Skip to content

feat: add OCI 1.1 Referrers API support with configurable encoding format#1691

Merged
tekton-robot merged 1 commit into
tektoncd:mainfrom
anithapriyanatarajan:oci-referrer-api-enablement
Jul 24, 2026
Merged

feat: add OCI 1.1 Referrers API support with configurable encoding format#1691
tekton-robot merged 1 commit into
tektoncd:mainfrom
anithapriyanatarajan:oci-referrer-api-enablement

Conversation

@anithapriyanatarajan

@anithapriyanatarajan anithapriyanatarajan commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

NOTE TO REVIEWERS: Originally this PR intended to allow a user-configurable approach for both distribution and serialization. During later review and iterative testing it became clear this adds needless complexity for users, and we additionally discovered via sigstore/cosign#4841 that the sigstore-bundle + DSSE combination is not supported in cosign. The PR therefore distills to two simple scenarios behind a single config knob, summarized below.

Changes

Chains currently stores all OCI signatures and attestations using a tag-based scheme (sha256-<digest>.sig / .att). This creates extra tags in the registry for every signed artifact. This PR adds support for the OCI 1.1 Referrers API as an alternative storage mechanism.

New configuration key

A single new key controls both the serialization format and the distribution mechanism. They are intentionally coupled — not separately configurable:

Key Values Default
storage.oci.encoding-format dsse, sigstore-bundle dsse

Possible Scenarios:

encoding-format Encoding Behaviour
dsse DSSE envelope Tag-based storage (.sig / .att tags) — unchanged default
sigstore-bundle Sigstore protobuf bundle OCI 1.1 Referrers API — no .sig / .att tags

dsse + protobuf-bundle and sigstore-bundle + DSSE are intentionally not offered: cosign's verification for referrer-stored attestations expects the protobuf bundle, and sigstore-bundle exists precisely to move away from the legacy tag layout, which has downsides:

  • The registry fills up with extra tags that aren't real images.
  • These tags are easy to confuse with actual image tags.
  • No OCI standard describes this layout, so every tool has to special-case it.

This keeps the surface to one knob and avoids a confusing matrix of combinations, some of which no tool can verify.

Backward compatibility

All existing deployments with no OCI encoding format config set continue to behave identically (dsse + tag-based). No action required.

Implementation

  • config.goOCIStorageConfig gains an EncodingFormat field; new constants (OCIEncodingFormatDSSE, OCIEncodingFormatSigstoreBundle) and a validateOCIEncodingFormat validator. Defaults to dsse when unset.
  • options.go — New WithEncodingFormat() option function; houses the referrersRepoOverrideIgnored helper.
  • attestation.go / simple.go — Dispatch keys off encodingFormat; sigstore-bundle writes attestations as a protobuf bundle via ociremote.WriteAttestationNewBundleFormat, while signatures use cosign's native signature referrer.
  • legacy.go — Backend passes WithEncodingFormat when constructing storers.
  • signing.go / signing/iface.gosigning.Bundle and StorageOpts gain a PublicKey crypto.PublicKey field; PublicKey() extraction after signing is non-fatal (logs a warning, storage continues) so KMS signers don't break the default path. Also wires up Rekor bundle population before storage so the bundle annotation is available for offline verification.

Tests

  • config_test.go — Tests the default, valid/invalid values for encoding-format, and the validateOCIEncodingFormat validator.
  • oci_test.go — Tests WithEncodingFormat, empty defaults, the Backend config, and that storage.oci.repository override is ignored in sigstore-bundle mode.
  • store_test.go — Updated defaultStorage to reflect the struct field rename.
  • attestation_test.go / simple_test.go — Tests for the sigstore-bundle store path including dedup.
  • referrers_api_e2e_test.go (new) — E2E tests for TestOCIStorageSigstoreBundle_TaskRun and TestOCIStorageSigstoreBundle_PipelineRun.

Docs

  • oci-artifact-distribution-format-referrers-schema.md (new) — Tutorial-style page explaining the Referrers schema, how cosign and Chains enable it, why referrers + protobuf bundle (not DSSE), registry compatibility, and verification examples.
  • config.md — New storage.oci.encoding-format row in the storage configuration table.

Submitter Checklist

As the author of this PR, please check off the items in this checklist:

  • Has Docs included if any changes are user facing
  • Has Tests included if any functionality added or changed
  • Follows the commit message standard
  • Meets the Tekton contributor standards (including functionality, content, code)
  • Release notes block below has been updated with any user facing changes (API changes, bug fixes, changes requiring upgrade notices or deprecation warnings)
  • Release notes contains the string "action required" if the change requires additional action from users switching to the new release

Release Notes

feat: OCI storage now supports the OCI 1.1 Referrers API via a new config key:

Set `storage.oci.encoding-format: sigstore-bundle` in the `chains-config` ConfigMap
to store signatures and attestations as Sigstore protobuf bundles (v0.3) via the
OCI 1.1 Referrers API instead of `.sig`/`.att` tags.

- Default value `dsse` preserves existing tag-based behavior (backward compatible).
- `sigstore-bundle` mode: both signatures and attestations are pushed as OCI 1.1 referrers with `artifactType: application/vnd.dev.sigstore.bundle.v0.3+json`, discoverable via `oras discover` or `cosign download`.
- Transparency log entries (Rekor) are embedded in the bundle when
  `transparency.enabled: "true"`.
- Verification: `cosign verify` and `cosign verify-attestation` work with both modes.
- Re-signing in `sigstore-bundle` mode accumulates referrers (one per signing invocation) because ECDSA is non-deterministic; the dedup only coalesces exact crash-recovery retries.
- Invalid values for `storage.oci.encoding-format` are rejected by the controller at config-load time; the last valid config continues to be used.

/kind feature

Co-Authored-by: Copilot (Claude Sonnet 4.6)

@tekton-robot

Copy link
Copy Markdown

@anithapriyanatarajan: The label(s) kind/enhancement cannot be applied, because the repository doesn't have them.

Details

In response to this:

Changes

Chains currently stores all OCI signatures and attestations using a tag-based scheme (sha256-.sig / .att). This creates extra tags in the registry for every signed artifact. This PR introduces support for the OCI 1.1 Referrers API as an alternative storage mechanism, plus independent control over payload serialization format, making both dimensions separately configurable.

New configuration keys

Two new keys introduced to replace the old monolithic approach:

Key Values Default
storage.oci.distribution-method legacy, referrers-api legacy
storage.oci.serialization-format dsse, protobuf-bundle dsse

Valid combinations:

distribution-method serialization-format Behaviour
legacy dsse Tag-based storage, DSSE encoding — unchanged default
referrers-api dsse OCI 1.1 Referrers API, DSSE encoding — fewer tags
referrers-api protobuf-bundle OCI 1.1 Referrers API, Sigstore protobuf bundle (experimental)

legacy + protobuf-bundle is rejected at startup with a clear error.

Backward compatibility

All existing deployments with no OCI config set continue to behave identically.

Implementation

  • config.goOCIStorageConfig gains DistributionMethod and SerializationFormat fields; new constants (OCIDistribution*, OCISerialization*); independent validators plus a combination validator.
  • options.go — New WithDistributionMethod() and WithSerializationFormat() option functions replacing the former WithFormat().
  • attestation.go / simple.go — Dispatch logic updated; new storeWithReferrersAPI() and storeWithProtobufBundle() methods on both storers using ociremote.WriteAttestationsReferrer / ociremote.WriteAttestationNewBundleFormat.
  • legacy.go — Backend passes both new options when constructing storers.
  • signing.go / signing/iface.gosigning.Bundle and StorageOpts gain a PublicKey crypto.PublicKey field; PublicKey() extraction after signing is non-fatal (logs a warning, storage continues) so KMS signers don't break the legacy path.
  • options.goStorageOpts.PublicKey field added.

Tests

  • config_referrers_test.go (new) — Tests defaults, valid/invalid values for each key, the invalid combination, and backward-compat migration.
  • referrers_test.go (new) — Tests WithDistributionMethod, WithSerializationFormat, empty defaults, and the Backend two-field config.
  • store_test.go — Updated defaultStorage to reflect the two-field struct.

Docs

  • oci-storage-formats.md (new) — Full reference page explaining both keys, the valid combination matrix, per-format details, registry compatibility, and verification examples.
  • config.md — Two new rows in the storage configuration table.

Submitter Checklist

As the author of this PR, please check off the items in this checklist:

  • Has Docs included if any changes are user facing
  • Has Tests included if any functionality added or changed
  • Follows the commit message standard
  • Meets the Tekton contributor standards (including
    functionality, content, code)
  • Release notes block below has been updated with any user facing changes (API changes, bug fixes, changes requiring upgrade notices or deprecation warnings)
  • Release notes contains the string "action required" if the change requires additional action from users switching to the new release

Release Notes

feat: OCI storage now supports the OCI 1.1 Referrers API and Sigstore protobuf bundle serialization via two new independent config keys:
 storage.oci.distribution-method: legacy / referrers-api   (default: legacy)
 storage.oci.serialization-format: dsse / protobuf-bundle  (default: dsse)
Setting distribution-method: referrers-api eliminates the sha256-*.sig / *.att tag proliferation in your registry. The default (legacy + dsse) is unchanged - no action required for existing deployments.

NOTE: This original PR that attempted to address this scenario was #1409. With consensus from the author @arewm this PR is being progressed to address the same functionality. If this PR is merged, #1409 could be closed.

/kind enhancement

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@tekton-robot
tekton-robot requested review from enarha and lcarva June 2, 2026 17:58
@tekton-robot tekton-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Jun 2, 2026
@anithapriyanatarajan anithapriyanatarajan added the kind/feature Categorizes issue or PR as related to a new feature. label Jun 2, 2026
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from 7ff8190 to d757d46 Compare June 2, 2026 18:05
@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

@tektoncd/chains-collaborators @arewm - Please review and share your comments. Thank you

@vdemeester vdemeester self-assigned this Jun 3, 2026
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from d757d46 to c429a7e Compare June 3, 2026 09:31
@anithapriyanatarajan

anithapriyanatarajan commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

Detailed steps to test and observations are captured here for reference - https://gist.github.com/anithapriyanatarajan/b112638e7b3d78ee6638c6fec4f51bc8

Observed Gaps, which would be analyzed further with appropriate follow ups:

  1. cosign verify discoverability (used cosign 3.0.3): the signature path uses the low-level WriteReferrer. Switching to cosign-native WriteSignaturesExperimentalOCI would let cosign verify reverse-discover signatures directly. Scoped as a follow-up to keep the storage PR focused. Update NOTE: Fixed in [commit] (4d43d45) - this should no more be a problem

  2. quay.io read path: write succeeds but referrers aren't returned on read. Registry-side bug, not a Chains issue. The functionality was completely verifiable if we target ghcr.io. we may need to check the status of other registries and add to the release notes.

Registry readiness for OCI 1.1 is much critical to realize the benefit of this PR for users.

@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from c429a7e to 4d43d45 Compare June 4, 2026 03:13
Comment thread pkg/chains/storage/oci/legacy.go Outdated
Comment thread pkg/chains/storage/oci/attestation.go Outdated
if err != nil {
return nil, errors.Wrap(err, "attaching attestation to entity")
}
if err := ociremote.WriteAttestationsReferrer(req.Artifact, newImage, ociremote.WithRemoteOptions(s.remoteOpts...)); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to confirm, here we are using req.Artifact, which drops the override of repo and ignores the storage.oci.repository. Should we use the overridden repo instead?

@anithapriyanatarajan

anithapriyanatarajan commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

More details on why we are doing this change - sigstore/docs#411 & kubernetes-sigs/tejolote#639

Comment thread pkg/config/config.go Outdated
Comment thread pkg/chains/storage/oci/attestation.go Outdated
@jkhelil

jkhelil commented Jun 8, 2026

Copy link
Copy Markdown
Member

@anithapriyanatarajan
Does the PR handles automatically fall back to the legacy tag schema when a registry does not support the OCI 1.1 Referrers API, so that storage.oci.format=referrers can be safely configured without knowing the registry's OCI 1.1 support status.

@jkhelil

jkhelil commented Jun 8, 2026

Copy link
Copy Markdown
Member

@anithapriyanatarajan can you add e2e tests ?

@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from ee93f82 to 904528b Compare June 11, 2026 16:22
@anithapriyanatarajan anithapriyanatarajan added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jun 11, 2026
Comment thread docs/config.md Outdated
@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

@anithapriyanatarajan Does the PR handles automatically fall back to the legacy tag schema when a registry does not support the OCI 1.1 Referrers API, so that storage.oci.format=referrers can be safely configured without knowing the registry's OCI 1.1 support status.

@jkhelil - Yes, storage.oci.format=referrers-api can be safely configured without knowing the registry's OCI 1.1 support status. The fallback to the Referrers Tag Schema is handled automatically by go-containerregistry (the underlying library used by cosign and vendored in Chains). If the registry natively supports the Referrers API (e.g., Quay), it is used directly. If not, go-containerregistry automatically falls back to storing referrers as an OCI Image Index tag, per the OCI distribution spec mandate (spec lines 777–806). Since this fallback is transparent at the library level, Chains does not need to implement its own fallback logic, and users do not need to manually revert to the legacy storage format based on registry capability. I have verified this behavior with quay and ghcr. For quay it takes the referrers API path while for ghcr it takes the referrers tag path. Will share evidences after fixing a few other findings. Thank you

@anithapriyanatarajan
anithapriyanatarajan marked this pull request as draft June 11, 2026 17:58
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from 904528b to 78d47da Compare June 12, 2026 04:27
@tekton-robot tekton-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Jun 12, 2026
@anithapriyanatarajan anithapriyanatarajan changed the title feat: add OCI 1.1 Referrers API support with configurable distribution and serialization feat: add OCI 1.1 Referrers API support with configurable distribution Jun 12, 2026
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from 78d47da to 276c83e Compare June 12, 2026 04:48
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch 2 times, most recently from f1937ed to 8a74fdb Compare July 9, 2026 13:07
@tekton-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: arewm, jkhelil

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

/hold until sigstore/cosign#4997 (comment) is resolved

@tekton-robot tekton-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 14, 2026
Comment thread pkg/chains/storage/oci/attestation.go Outdated
@codecov-commenter

codecov-commenter commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.93%. Comparing base (a172538) to head (18342c4).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1691      +/-   ##
==========================================
- Coverage   61.96%   61.93%   -0.03%     
==========================================
  Files          64       64              
  Lines        3899     4067     +168     
==========================================
+ Hits         2416     2519     +103     
- Misses       1222     1266      +44     
- Partials      261      282      +21     
Flag Coverage Δ
unit-tests 61.93% <ø> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch 2 times, most recently from 195e676 to 4187a96 Compare July 23, 2026 07:00
@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

/hold cancel

@tekton-robot tekton-robot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 23, 2026
@anithapriyanatarajan
anithapriyanatarajan requested review from Copilot and removed request for lcarva July 23, 2026 07:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a single OCI storage configuration knob to switch Chains between the existing tag-based .sig/.att layout and OCI 1.1 Referrers-based storage using Sigstore protobuf bundles, enabling referrer-native registries to avoid signature/attestation tag proliferation while preserving backward-compatible defaults.

Changes:

  • Introduces storage.oci.encoding-format (dsse default, sigstore-bundle) with validation + defaults in config parsing.
  • Implements sigstore-bundle storage paths for OCI signatures/attestations using referrers + protobuf bundle writing, including referrer deduplication.
  • Adds unit + e2e coverage and documentation for the new encoding/storage behavior; bumps vendored cosign to v2.6.4.

Reviewed changes

Copilot reviewed 17 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
vendor/modules.txt Updates vendored module listing for cosign version bump.
vendor/github.com/sigstore/cosign/v2/pkg/oci/remote/write.go Vendored cosign changes related to referrer manifest handling.
vendor/github.com/sigstore/cosign/v2/pkg/cosign/fetch.go Vendored cosign behavior change when no attestations are present.
go.mod Bumps github.com/sigstore/cosign/v2 to v2.6.4 and makes protobuf-specs a direct dependency.
go.sum Updates sums for the cosign bump.
pkg/config/config.go Adds storage.oci.encoding-format key, constants, defaulting, and validation.
pkg/config/config_test.go Tests default/valid/invalid encoding-format config values and validator behavior.
pkg/config/store_test.go Updates config parsing expectations to include the new default OCI encoding format.
pkg/config/options.go Extends storage options with PublicKey and raw Rekor entry fields for bundle construction.
pkg/chains/signing/iface.go Extends signing.Bundle to carry PublicKey and raw Rekor entry for downstream storage.
pkg/chains/signing.go Captures Rekor entry + signer public key (non-fatal) and threads them into StorageOpts.
pkg/chains/storage/oci/options.go Adds WithEncodingFormat and helper for referrers repo override behavior.
pkg/chains/storage/oci/legacy.go Threads encoding format + bundle-related fields into signature/attestation upload logic.
pkg/chains/storage/oci/simple.go Implements sigstore-bundle signature storage via referrers + protobuf bundle (with dedup).
pkg/chains/storage/oci/simple_test.go Adds unit tests for sigstore-bundle signature referrer writes, repo override behavior, and dedup.
pkg/chains/storage/oci/attestation.go Implements sigstore-bundle attestation storage via referrers + protobuf bundle (with dedup).
pkg/chains/storage/oci/attestation_test.go Adds unit tests for sigstore-bundle attestation referrer writes and dedup.
pkg/chains/storage/oci/oci_test.go Adds tests for WithEncodingFormat, default behavior, backend config wiring, and payload preservation regression.
test/oci_sigstore_bundle_e2e_test.go Adds e2e coverage ensuring .sig/.att tags are not created in sigstore-bundle mode.
docs/oci-encoding-format.md New doc explaining encoding-format behavior, referrers layout, compatibility, and verification.
docs/config.md Documents the new storage.oci.encoding-format config key and links to the new doc.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/oci_sigstore_bundle_e2e_test.go
Comment thread docs/oci-encoding-format.md
Comment thread pkg/chains/storage/oci/attestation.go
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from 4187a96 to 91193f7 Compare July 23, 2026 07:37
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch 2 times, most recently from 9f92193 to 295461d Compare July 23, 2026 14:52
… format

Adds a new storage.oci.encoding-format config key that controls both
the serialization format and distribution mechanism for OCI artifacts:

  storage.oci.encoding-format: dsse (default) | sigstore-bundle

- dsse: unchanged tag-based storage with DSSE envelopes (default)
- sigstore-bundle: Sigstore protobuf bundle via OCI 1.1 Referrers API,
  eliminating sha256-*.sig / *.att tag proliferation in the registry

Both signatures and attestations are stored as
application/vnd.dev.sigstore.bundle.v0.3+json referrer manifests,
distinguished by the dev.sigstore.bundle.predicateType annotation.
Signatures use CosignSignPredicateType; attestations use the in-toto
predicate type. This matches the manifest layout produced by cosign 3.x
`cosign sign` and `cosign attest`.

Also fixes a bug where the raw Rekor transparency log entry was never
forwarded to MakeNewBundle in the sigstore-bundle attestation path.
The entry was converted to a RekorBundle in signing.go and then
discarded; the OCI attestation storer always passed a nil rekorEntry to
MakeNewBundle, so bundles shipped without a tlog entry and would be
rejected by cosign verify-attestation (which checks for one by default
since v2). Fixed by carrying *models.LogEntryAnon through StorageOpts
and signing.Bundle to the storer.

Bumps cosign from v2.6.3 to v2.6.4 to include:
- PR #4997: correct artifactType in OCI 1.1 signature referrer manifests
- PR #4996: cosign download attestation now returns bundle-format
  referrers alongside legacy .att tag attestations

Signed-off-by: Anitha Natarajan <anataraj@redhat.com>
Assisted-by: Claude Sonnet 4.6 (via GitHub Copilot)
@anithapriyanatarajan
anithapriyanatarajan force-pushed the oci-referrer-api-enablement branch from 295461d to 18342c4 Compare July 23, 2026 15:17
@jkhelil

jkhelil commented Jul 24, 2026

Copy link
Copy Markdown
Member

/lgtm

@tekton-robot tekton-robot added the lgtm Indicates that a PR is ready to be merged. label Jul 24, 2026
@tekton-robot
tekton-robot merged commit b5ecaf7 into tektoncd:main Jul 24, 2026
19 checks passed
@anithapriyanatarajan

Copy link
Copy Markdown
Contributor Author

Test prompt used for this PR : pr1691-test-prompt.md
Test Results: pr1691-test-results-v2.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants