Chainloop Documentation

repository·main·Indexed 20 days ago

https://github.com/chainloop-dev/chainloop

Chainloop is an open-source evidence store for Software Supply Chain attestations, SBOMs, and security reports. It features an Artifact Content Addressable Storage (CAS) Proxy for immutable artifact management via gRPC, a Go-based CLI for operator tasks and attestation crafting, and a plugin system with integrations for Dependency-Track, Discord webhooks, and GUAC.

Tokens
186K
Snippets
535
Records
680
Agent score
68%

What's inside Chainloop

  1. Overview of Chainloop WASM Policy SDKs

    main
    Chainloop WASM Policy SDKs allow you to write validation rules (policies) in Go or JavaScript/TypeScript that compile to WebAssembly (WASM). These policies run automatically when artifacts—such as SBOMs, attestations, or evidence files—are uploaded to Chainloop. The SDKs provide a secure execution environment and high-level APIs to access uploaded material, make HTTP calls, and explore the artifact graph.
  2. Overview of Artifact Content Addressable Storage (CAS) Proxy

    main

    The Artifact CAS Proxy is a service that sits in front of storage backends (currently supporting OCI storage) to ensure that uploaded artifacts are immutable and uniquely identifiable by their content digest (sha256sum).

    Key technical details:

    • API: Implements a bytestream gRPC service for efficient streaming over HTTP/2.
    • Architecture: Built with Go, leveraging protocol buffers, gRPC, wire for dependency injection, and the Kratos framework for middleware and configuration.
    • Multi-tenancy: Achieved by retrieving OCI repository credentials (path + key pair) from a secret storage backend at runtime.
  3. Use the Artifact Content Addressable Storage (CAS) Client

    main

    The CAS Client is a bytestream gRPC client used to communicate with the Artifact Storage Proxy (/app/artifact-cas/). It allows for managing artifacts using content-addressable storage principles. Currently, the client supports two primary operations:

    1. Download: Retrieve artifacts using their content digest (specifically sha256).
    2. Upload: Send artifact data to the storage proxy.

    The client implements the google.golang.org/api/transport/bytestream interface for efficient data transfer.

    // The client is a bytestream gRPC client supporting:
    // - Download by content digest (sha256)
    // - Upload methods
  4. Use the Chainloop CLI for management and attestation

    main

    The Chainloop CLI is a Go-based client used for two primary workflows:

    1. Operator Management Tasks: Operating on the control plane and uploading/downloading artifacts to the artifact proxy (CAS).
    2. Attestation Crafting Process: Performing the attestation process within a CI/CD system.

    The CLI communicates with the control plane and Artifact CAS APIs via gRPC and integrates with cosign, in-toto, DSEE, and SLSA for attestation tasks.

  5. Configure AuthN/AuthZ for the Artifact CAS Proxy

    main

    The Artifact CAS API requires a JSON Web Token (JWT) for every request. The token must contain:

    1. The allowed operation (e.g., download or upload).
    2. A reference to the location where the CAS can find the target OCI credentials.

    Tokens are signed by the Control Plane using a private key and verified by the CAS using a pre-configured public key. Future support for JWKS endpoints is planned to facilitate credential rotation.

  6. Identify Control Plane system dependencies

    main

    The Control Plane relies on four primary external components:

    • OpenID Connect (OIDC) provider: Used for authentication (e.g., Google, GitHub, or Auth0).
    • PostgreSQL: Used as the persistence layer.
    • Secret Storage Backend: Used for sensitive information like OCI registry credentials. Supported backends include Hashicorp Vault, AWS Secret Manager, and GCP Secret Manager.
    • Artifact CAS: Chainloop's own Artifact Content Addressable Storage, used to forward attestations to the user's storage backend (e.g., an OCI registry).

    Note: The control plane does not store artifacts directly; it forwards them via the Artifact CAS.

  7. Understanding Chainloop FanOut plugins

    main

    Chainloop currently supports a single plugin type called fanOut plugins. These plugins implement logic that is triggered whenever attestations or materials are received by the system.

    Common use cases for FanOut plugins include:

    • Sending notifications (e.g., to Slack).
    • Uploading attestations to a storage backend.
    • Sending Software Bill of Materials (SBOMs) to external analysis tools like Dependency-Track.
  8. Core concepts of the WASM Policy SDK

    main

    When developing policies using the WASM SDK, you will interact with several key patterns and functions:

    • ExecutePolicyTyped: The primary type-safe policy function that handles automatic I/O for your policy logic.
    • Result Builders: Used to construct the outcome of a policy evaluation:
      • Success(): Indicates the policy passed without issues.
      • AddViolation(): Records a specific policy violation.
      • AddViolationf(): Records a formatted policy violation.
    • Logging: Provides debug output during policy execution via LogInfo() and LogError().
    • Result Checking: Use HasViolations() to inspect the state of the result and determine if the policy failed.
  9. Follow TinyGo compatibility constraints for policies

    main

    Because the SDK runs in a WASM environment via TinyGo, you must adhere to specific type constraints to avoid runtime panics (like wasm error: unreachable).

    Supported Types:

    • Flat structs with simple types.
    • Slices and maps with string keys.
    • json.Unmarshal for parsing.

    Unsupported/Avoid:

    • Generics (limited support).
    • Complex nested types containing interfaces.
    • Maps with any values.

    Recommended Pattern: Use simple, flat structs for data modeling.

    // Good: Simple struct
    type Component struct {
        Name    string `json:"name"`
        Version string `json:"version"`
        Hashes  []Hash `json:"hashes"`
    }
    
    // Avoid: Complex types
    type Complex struct {
        Metadata any              `json:"metadata"`
        Data     map[string]any   `json:"data"`
    }
  10. Use global variables for credentials in complex deployments

    main

    In scenarios where multiple sub-charts need to connect to the same PostgreSQL instance, instead of repeating credentials for every sub-chart (e.g., subchart1.postgresql.auth.password), use the global object. This makes the credentials available to all sub-charts automatically.

    global.postgresql.auth.username=testuser
    global.postgresql.auth.password=testpass
    global.postgresql.auth.database=testdb