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:
- the expected registry and immutable artifact digest;
- the signature or signed attestation associated with that digest;
- the approved signer identity, certificate constraints, or public trust material;
- required transparency or timestamp evidence, where applicable; and
- 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.