Skip to content

Artifact Signing

Artifact signing enables consumers to verify identity and integrity: that an artifact is the exact content identified by its digest and that an approved signing identity authorized the signature under a defined policy.

Indian Hill Labs uses the Sigstore Cosign verification model for the engineering implementation described below. Keyless verification checks both the expected OIDC issuer and certificate identity; trusting a signature without constraining identity is not the release policy.

Verification model

A complete verification procedure should establish:

  1. the expected registry and immutable artifact digest;
  2. the signature or signed attestation associated with that digest;
  3. the approved signer identity, certificate constraints, or public trust material;
  4. required transparency or timestamp evidence, where applicable; and
  5. the policy result and verification time.

Current candidate and protected-lab implementation

Protected Secure, Hardened, and Validated lab publications use Sigstore keyless signing. The short-lived certificate must have issuer https://gitlab.com and identity https://gitlab.com/indianhilllabs/indian-hill-secure-containers//.gitlab-ci.yml@refs/heads/main. Verification also requires the expected assurance-tier, source-revision, and assurance-manifest-sha256 annotations and targets the immutable digest rather than a tag.

The controlled policy is compliance/supply-chain/cosign-keyless-policy.json. The pipeline retains Cosign's JSON verification output and hashes that output into the release-evidence boundary.

The protected ACR promotion repeats signing against each imported ACR digest. It obtains an ACR data-plane token from the branch-bound Azure workload identity, writes the signature as an OCI referrer, verifies the destination digest, certificate identity, issuer, and required annotations, records the ACR referrer graph, and then locks both the release tag and manifest. Promotion fails closed if any destination verification or lock check fails. The ACR evidence is uploaded to a separate Generic Package Registry version named acr-<tier>-<pipeline-id>-<assurance-manifest-sha256>.

Existing ACR lab releases are admitted through protected backfill:<tier>-acr-signatures jobs. Each job first downloads the original durable evidence metadata and requires an exact match for the source revision, source image digests, tier, manifest hash, package URL, and export job before signing the corresponding ACR digests. Backfill jobs have no build-stage dependencies, so they can be approved without publishing a replacement image; the protected production environment remains their mandatory authorization boundary.

What a signature does not prove

A valid signature does not prove that software is vulnerability-free, correctly configured, suitable for a particular mission, or authorized by a government or third party. It must be evaluated with provenance, assessment results, product behavior, and deployment controls.

Key-material boundary

Private signing keys, credentials, runner tokens, and internal trust-architecture details are not public documentation. They must not be embedded in an image, committed to this repository, included in an assurance bundle, or copied into verification examples.

Keyless signing avoids a stored private signing key. GitLab issues a job-specific OIDC token; Cosign obtains an ephemeral certificate and records transparency evidence. Registry and Azure credentials remain short-lived job inputs and are not included in the retained bundle.

The ACR signing job installs a version-pinned Cosign binary only after verifying its controlled SHA-256. Azure tokens and the temporary registry client configuration are removed when the job exits.

Deployment-time enforcement

The restricted lab deployment wrapper applies the same keyless policy before it pulls an image. It accepts only a fixed repository and immutable digest, then requires the deployment request to include the exact source revision and assurance-manifest SHA-256. A root-owned, checksum-pinned Cosign binary verifies the GitLab issuer, protected-main signing identity, and all three required annotations before Docker is allowed to pull or start the image. The host persists the verification output and hash alongside its current deployment record.

Re-run deploy/lab/bootstrap-host.sh from an authenticated administrator session whenever the deployment wrapper or controlled verifier changes. The bootstrap verifies the pinned Cosign binary SHA-256 before it installs the verifier; the restricted deployment account cannot update either component.

This is an execution-time control for the lab host, not a substitute for an admission controller. Every future production runtime must enforce the same digest, issuer, identity, and annotation policy before it pulls or starts an ACR image; ACR storage alone is not a runtime admission controller.