Skip to content

sigstore: add Rekor v2 opt-in for cosign signing#1176

Open
crazy-max wants to merge 2 commits into
mainfrom
cosign-rekor-v2
Open

sigstore: add Rekor v2 opt-in for cosign signing#1176
crazy-max wants to merge 2 commits into
mainfrom
cosign-rekor-v2

Conversation

@crazy-max

@crazy-max crazy-max commented Jun 11, 2026

Copy link
Copy Markdown
Member

needs #1208

This updates the Sigstore signing flow for cosign 3.1.1 while keeping older cosign versions working with their existing flags.

The signing config creation now supports Rekor v2 as an explicit opt-in through rekorV2. When that option is enabled, transparency log upload is enabled, and cosign is 3.1.1 or newer, the toolkit uses --with-default-rekor-v2=true. The default path continues to use --with-default-services=true, so cosign 3.1.1 does not switch to Rekor v2 unless callers request it.

The cosign command arguments now omit --new-bundle-format for cosign 3.1.1 and newer because that bundle format is already the default and the flag is deprecated. Older cosign 3.0.x versions still receive --new-bundle-format, which keeps the existing signing and verification flows compatible.

The Rekor upload log now avoids linking to search.sigstore.dev when Rekor v2 is used, because there is no Rekor v2 UI there yet. In that case the log reports the Rekor v2 transparency log index directly.

This intentionally keeps --experimental-oci11 for verification because cosign 3.1.1 still needs that flag for the OCI referrer behavior used by these signatures. Removing it now would be premature even though upstream marks it as deprecated for future versions.

The integration coverage now runs the default signing path across the supported cosign versions and adds Rekor v2 opt-in coverage for cosign versions that support it. This applies to both attestation manifest signing and provenance blob signing.

@crazy-max

Copy link
Copy Markdown
Member Author

With cosign 3.1.1 it creates this signing config: https://github.com/docker/actions-toolkit/actions/runs/27343642457/job/80786588245?pr=1176#step:10:376

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign signing-config create --with-default-rekor-v2=true --out=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json
  {
    "mediaType": "application/vnd.dev.sigstore.signingconfig.v0.2+json",
    "caUrls": [
      {
        "url": "https://fulcio.sigstore.dev/",
        "majorApiVersion": 1,
        "validFor": {
          "start": "2022-04-13T20:06:15Z"
        },
        "operator": "sigstore.dev"
      }
    ],
    "oidcUrls": [
      {
        "url": "https://oauth2.sigstore.dev/auth",
        "majorApiVersion": 1,
        "validFor": {
          "start": "2022-04-13T20:06:15Z"
        },
        "operator": "sigstore.dev"
      }
    ],
    "rekorTlogUrls": [
      {
        "url": "https://log2025-1.rekor.sigstore.dev/",
        "majorApiVersion": 2,
        "validFor": {
          "start": "2026-01-01T00:00:00Z"
        },
        "operator": "sigstore.dev"
      },
      {
        "url": "https://rekor.sigstore.dev/",
        "majorApiVersion": 1,
        "validFor": {
          "start": "2021-01-12T11:53:27Z"
        },
        "operator": "sigstore.dev"
      }
    ],
    "rekorTlogConfig": {
      "selector": "ANY"
    },
    "tsaUrls": [
      {
        "url": "https://timestamp.sigstore.dev/api/v1/timestamp",
        "majorApiVersion": 1,
        "validFor": {
          "start": "2025-07-04T00:00:00Z"
        },
        "operator": "sigstore.dev"
      }
    ],
    "tsaConfig": {
      "selector": "ANY"
    }
  }

Example of signed attestation manifest:

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign sign --yes --oidc-provider github-actions --registry-referrers-mode oci-1-1 --signing-config=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab
  Uploaded to Rekor transparency log: [https://search.sigstore.dev?logIndex=5035492](https://search.sigstore.dev/?logIndex=5035492)
  Signature manifest pushed: https://oci.dag.dev/?referrers=ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab

The https://search.sigstore.dev?logIndex=5035492 is wrong for rekor v2 though. Don't think there is a Rekor v2 search UI yet

@crazy-max

Copy link
Copy Markdown
Member Author

Example of signed attestation manifest:

/home/runner/work/_temp/sigstore-cosign-v3-1-1-VceUAw/cosign-bin/cosign sign --yes --oidc-provider github-actions --registry-referrers-mode oci-1-1 --signing-config=/home/runner/work/_temp/docker-actions-toolkit-elp37s/signing-config-Z7X0zp.json ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab
  Uploaded to Rekor transparency log: [https://search.sigstore.dev?logIndex=5035492](https://search.sigstore.dev/?logIndex=5035492)
  Signature manifest pushed: https://oci.dag.dev/?referrers=ghcr.io/docker/actions-toolkit-test@sha256:6a5e1f9bc5ca5e63ede973e6540dd3129b14712e52c8591ab136961aa7dcd2ab

The https://search.sigstore.dev?logIndex=5035492 is wrong for rekor v2 though. Don't think there is a Rekor v2 search UI

So for the rekor log entry 5035492 we need the Tessera tiled path encoding and Rekor v2 stores entries in bundles of 256 entries so for this log index:

bundle_number = floor(5035492 / 256)
              = 19669

Then 19669 formatted as 3-digit decimal groups from left to right:

19669  ->  019 / 669

Which gives: https://log2025-1.rekor.sigstore.dev/api/v2/tile/entries/x019/669

I attached the output here.

bundle.zip

Decoding is tricky so I used an agent for this:

{
  "logIndex": 5035492,
  "rekorV2BundlePath": "x019/669",
  "bundleIndex": 19669,
  "offsetZeroBased": 228,
  "offsetOneBased": 229,
  "apiVersion": "0.0.2",
  "kind": "hashedrekord",
  "data": {
    "algorithm": "SHA2_256",
    "digestBase64": "bL9f6pc9Nq5yzruKYA+iboF6MVhXK6Gfx5vflh1PMLU=",
    "digestHex": "6cbf5fea973d36ae72cebb8a600fa26e817a3158572ba19fc79bdf961d4f30b5"
  },
  "signature": {
    "keyDetails": "PKIX_ECDSA_P256_SHA_256",
    "signatureBase64": "MEQCIAS2+PKs/J3v27PLfHSM0SdAoX7GU3l5Ybd3MwWl4BguAiBBPzJfhgIWvjFuyVcyoYWj/O8uwKV/yjDrgZIeAdEtnA==",
    "ecdsaR": "04b6f8f2acfc9defdbb3cb7c748cd12740a17ec653797961b7773305a5e0182e",
    "ecdsaS": "413f325f860216be316ec95732a185a3fcef2ec0a57fca30eb81921e01d12d9c"
  },
  "certificate": {
    "subject": "(empty)",
    "issuer": "CN=sigstore-intermediate,O=sigstore.dev",
    "serialHex": "0x1c16ae92f16578fda09f0d1b34127f48c2004f0c",
    "validFromUtc": "2026-06-11T11:32:09+00:00",
    "validUntilUtc": "2026-06-11T11:42:09+00:00",
    "fingerprintSha256": "35477077f6f33a8ec2217cf620b3bad2818929db96193363a945e05fa596f6ea",
    "subjectAltNameUri": "https://github.com/docker/actions-toolkit/.github/workflows/test.yml@refs/pull/1176/merge"
  },
  "githubOidcIdentity": {
    "oidcIssuer": "https://token.actions.githubusercontent.com",
    "workflowTrigger": "pull_request",
    "workflowSha": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
    "workflowName": "test",
    "workflowRepository": "docker/actions-toolkit",
    "workflowRef": "refs/pull/1176/merge",
    "runnerEnvironment": "github-hosted",
    "sourceRepositoryUri": "https://github.com/docker/actions-toolkit",
    "sourceRepositoryDigest": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
    "sourceRepositoryRef": "refs/pull/1176/merge",
    "sourceRepositoryIdentifier": "589268852",
    "sourceRepositoryOwnerUri": "https://github.com/docker",
    "sourceRepositoryOwnerIdentifier": "5429470",
    "buildConfigUri": "https://github.com/docker/actions-toolkit/.github/workflows/test.yml@refs/pull/1176/merge",
    "buildConfigDigest": "8a7f0a5cc407ca261a94d48a7f2b950f22660724",
    "buildTrigger": "pull_request",
    "runInvocationUri": "https://github.com/docker/actions-toolkit/actions/runs/27343642457/attempts/1",
    "sourceRepositoryVisibilityAtSigning": "public",
    "subject": "repo:docker/actions-toolkit:pull_request"
  }
}

Original Rekor entry, with the large cert decoded separately above:

{
  "apiVersion": "0.0.2",
  "kind": "hashedrekord",
  "spec": {
    "hashedRekordV002": {
      "data": {
        "algorithm": "SHA2_256",
        "digest": "bL9f6pc9Nq5yzruKYA+iboF6MVhXK6Gfx5vflh1PMLU="
      },
      "signature": {
        "content": "MEQCIAS2+PKs/J3v27PLfHSM0SdAoX7GU3l5Ybd3MwWl4BguAiBBPzJfhgIWvjFuyVcyoYWj/O8uwKV/yjDrgZIeAdEtnA==",
        "verifier": {
          "keyDetails": "PKIX_ECDSA_P256_SHA_256",
          "x509Certificate": {
            "rawBytes": "<base64 DER certificate; decoded above>"
          }
        }
      }
    }
  }
}

@Hayden-IO For Rekor v2, it looks like entries are now exposed through Tessera entry bundles. I understand Rekor v2 removed the old search/index API and that entries are served as bundles, so I'm not asking for the old backend behavior necessarily. I'm mainly asking whether there will be a supported web UI or shareable permalink for inspecting a Rekor v2 entry by log index.

@crazy-max crazy-max requested a review from tonistiigi June 29, 2026 10:16
@crazy-max crazy-max marked this pull request as ready for review June 29, 2026 10:16
@crazy-max crazy-max marked this pull request as draft June 29, 2026 10:18
@crazy-max crazy-max force-pushed the cosign-rekor-v2 branch 2 times, most recently from 213df1d to 069a00a Compare July 1, 2026 07:52
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
@crazy-max crazy-max marked this pull request as ready for review July 1, 2026 08:31
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
@crazy-max crazy-max changed the title sigstore: handle cosign 3.1.1 signing defaults sigstore: add Rekor v2 opt-in for cosign signing Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant