The signing identity is:
helm-expt-package-signer@nth-fort-499605-q5.iam.gserviceaccount.com
It is a dedicated Google service account. The publisher uses a short-lived Google identity token with Sigstore. The repository does not contain a private signing key, a service-account key file, or a registry credential.
Verify A Package
Install cosign v3.1.3, then use the immutable reference and the two annotations from the package's catalog record. For Redis 25.5.3, the command has this shape:
cosign verify \
--certificate-identity helm-expt-package-signer@nth-fort-499605-q5.iam.gserviceaccount.com \
--certificate-oidc-issuer https://accounts.google.com \
--annotations confighub.com/package-path=packages/bitnami/redis/25.5.3 \
--annotations confighub.com/package-sha256=<package-sha256> \
europe-west1-docker.pkg.dev/nth-fort-499605-q5/helm-expt/bitnami-redis:25.5.3@sha256:<manifest-digest>
The generated package catalog and each chart-version page provide the complete command with the recorded digests filled in.
Verify The Catalog Index
The downloadable package index is dated and signed separately. This checks that the list of package references, manifest digests, package signatures, and commands is the list published by ConfigHub Workshop:
curl -fsSLo packages.json \
https://raw.githubusercontent.com/confighub/helm-expt/main/data/installer-oci-packages/packages.json
curl -fsSLo packages.sigstore.json \
https://raw.githubusercontent.com/confighub/helm-expt/main/runs/installer-oci-index-signature/packages.sigstore.json
cosign verify-blob \
--bundle packages.sigstore.json \
--certificate-identity helm-expt-package-signer@nth-fort-499605-q5.iam.gserviceaccount.com \
--certificate-oidc-issuer https://accounts.google.com \
packages.json
The index date comes from the newest package publication or signature receipt. It does not change merely because a generator was rerun.
What A Valid Signature Shows
A successful verification shows that:
- the named service account signed the exact OCI manifest digest;
- the signed payload records the expected package path and package SHA-256;
- the public registry served the signature without credentials when the receipt was written;
- Sigstore accepted the Google identity and recorded the signing event.
It does not show that a selected preset is suitable for a particular cluster. It also does not prove that a hook, CRD, Secret, setup Job, or later rollout will succeed. Use the chart page for the render checks, lifecycle instructions, destination requirements, and live receipts that answer those questions.
Repository Evidence
Each signed package has five committed files under runs/installer-oci-signatures/<package>/<version>/:
signature.sigstore.json: the Sigstore verification bundle written while signing the immutable manifest;signature-payload.json: the exact signed image payload, including the OCI manifest digest and the package annotations;verification.json: the result of runningcosign verifyagainst the public registry with an empty private Docker configuration and the expected identity, issuer, and annotations;payload-verification.txt: the result of runningcosign verify-blobover the committed payload and bundle;signature-receipt.yaml: the binding from the package publication receipt to those four files.
The generated index is at data/installer-package-signatures/summary.md. The receipt schema is schemas/installer-package-signature-receipt.schema.json.
The repository consistency gate checks that every published package has exactly one signature receipt and that all paths, digests, annotations, identities, and file hashes agree. The cryptographic gate then runs Cosign over every committed payload and bundle:
npm run installer-oci:signatures:verify
npm run installer-oci:signatures:self-test
npm run installer-oci:signatures:verify-crypto
npm run installer-oci:signatures:crypto-self-test
The consistency self-test changes the digest, signer, bundle hash, and transparency-log material in turn. The cryptographic self-test changes the signed payload bytes and requires Cosign to reject them. The public cosign verify command above remains the direct check against the registry attachment.
The index has the same consistency checks:
npm run installer-oci:index-signature:verify
npm run installer-oci:index-signature:self-test
npm run installer-oci:index-signature:verify-crypto
npm run installer-oci:index-signature:crypto-self-test
The index signature files are committed under runs/installer-oci-index-signature/. Its receipt schema is schemas/installer-oci-index-signature-receipt.schema.json.
Maintainer Procedure
One-time Google Cloud setup:
PROJECT=nth-fort-499605-q5
LOCATION=europe-west1
REPOSITORY=helm-expt
SIGNER=helm-expt-package-signer@$PROJECT.iam.gserviceaccount.com
OPERATOR=$(gcloud config get account)
gcloud iam service-accounts create helm-expt-package-signer \
--project "$PROJECT" \
--display-name "helm-expt package signer"
gcloud artifacts repositories add-iam-policy-binding "$REPOSITORY" \
--project "$PROJECT" \
--location "$LOCATION" \
--member "serviceAccount:$SIGNER" \
--role roles/artifactregistry.writer
gcloud iam service-accounts add-iam-policy-binding "$SIGNER" \
--project "$PROJECT" \
--member "user:$OPERATOR" \
--role roles/iam.serviceAccountTokenCreator
The service account has package-write access only on the public catalog repository. The operator may mint a short-lived token for that account. No service-account key file is created.
Test impersonation before signing:
gcloud auth print-identity-token \
--impersonate-service-account "$SIGNER" \
--include-email \
--audiences sigstore >/dev/null
The live signing command is deliberately separate from ordinary generation:
npm run installer-oci:sign:plan
HELM_EXPT_ALLOW_REGISTRY_SIGNING=1 \
npm run installer-oci:sign -- \
--package packages/bitnami/redis/25.5.3
Maintainer signing is pinned to cosign v3.1.3. A different version is refused until the repository contract and self-tests are reviewed for that version.
The operator must be able to impersonate the dedicated signer. The script asks for a short-lived identity token for Sigstore and a short-lived access token for Artifact Registry. It places both in a private temporary Docker configuration and identity-token file, then removes the directory before the command exits. SIGSTORE_ID_TOKEN and HELM_EXPT_REGISTRY_ACCESS_TOKEN may instead be supplied by a controlled CI system. Neither token belongs in Git.
After signing, regenerate the two indexes and the public site:
npm run installer-oci:signatures:generate
npm run installer-oci:catalog
HELM_EXPT_ALLOW_INDEX_SIGNING=1 \
npm run installer-oci:index-signature:sign
npm run installer-oci:catalog
npm run site:generate
Do not sign a tag. The script always signs the immutable manifest digest from the existing publication receipt.