Skip to content

feat: add keyless signature verification for Zarf packages - #1393

Merged
emoskito merged 26 commits into
mainfrom
fix/zarf-dep-v0.77.0-with-keyless-signature-verification
Jun 3, 2026
Merged

feat: add keyless signature verification for Zarf packages#1393
emoskito merged 26 commits into
mainfrom
fix/zarf-dep-v0.77.0-with-keyless-signature-verification

Conversation

@emoskito

@emoskito emoskito commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Description

  • Updates Zarf dependency to v0.77.0
  • Adds keyless (OIDC/Sigstore) signature verification support for Zarf packages in bundle definitions,
    resolving the inability to reference the Zarf init package at v0.77.0 which is signed with a keyless
    identity
  • Migrates cosign signing types from utils to Zarf's signing package introduced in v0.77.0

New bundle YAML fields (per package)

Field Description
keylessVerification.certificateIdentity Required identity claim in the signing certificate.
keylessVerification.certificateIdentityRegexp Regex-based alternative to certificateIdentity for pattern matching.
keylessVerification.certificateOIDCIssuer Required OIDC issuer claim in the signing certificate.
keylessVerification.certificateOIDCIssuerRegexp Regex-based variant of certificateOIDCIssuer.
keylessVerification.trustedRoot Sigstore TrustedRoot JSON content for keyless signature verification. Omit to use Zarf's embedded TrustedRoot.
keylessVerification.insecureIgnoreTlog Skip Rekor transparency log inclusion verification. Set to true only for air-gapped or private Sigstore infrastructure.
keylessVerification.useSignedTimestamps Verify RFC3161 signed timestamps in the bundle. Use when signing was done with a TSA and Rekor was not used.

publicKey and keylessVerification are mutually exclusive.

Example usage

  packages:
  - name: init
    repository: ghcr.io/zarf-dev/packages/init
    ref: v0.77.0
    keylessVerification:
      certificateIdentityRegexp: https://github.com/zarf-dev/zarf/.github/workflows/release.yml@refs/tags/v\d+\.\d+.\d+
      certificateOIDCIssuer: https://token.actions.githubusercontent.com

Related Issue

Completes CLI-201

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Other (security config, docs update, etc)

Checklist before merging

@emoskito

emoskito commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review this draft

@greptile-apps

greptile-apps Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds keyless (OIDC/Sigstore) signature verification support for Zarf packages in bundle definitions and bumps the Zarf dependency to v0.77.0, which requires it. Signing types are migrated from zarfUtils to Zarf's new signing package.

  • Introduces a keylessVerification struct on Package with mutual-exclusion enforcement against publicKey, full identity/issuer constraint validation, and support for custom trusted roots, tlog skipping, and signed timestamps.
  • Adds BuildVerifyBlobOptions / ValidateVerifyBlobConfig helpers and propagates *signing.VerifyBlobOptions through all fetch, deploy, and inspect code paths, replacing the previous raw public-key-path approach.
  • Extends both the remote and tarball sources to fetch/extract the zarf.bundle.sig layer alongside the legacy zarf.yaml.sig, and introduces selectPackageVerifyOpts to pick the right file at verification time.

Confidence Score: 5/5

Safe to merge; all verification paths fail closed and the keyless feature is fully additive with no changes to existing key-based flows.

The validation logic in ValidateVerifyBlobConfig correctly prevents empty or conflicting signing configs, and the mutual-exclusion check runs before any file I/O. All temp directories holding key material are cleaned up via defer os.RemoveAll. The asymmetry in selectPackageVerifyOpts results in a less-informative error in a rare edge case but does not compromise verification correctness.

src/pkg/bundle/inspect.go for the selectPackageVerifyOpts keyless branch; src/pkg/utils/utils_test.go for the shared tmpDir in TestBuildVerifyBlobOptions

Important Files Changed

Filename Overview
src/pkg/bundle/inspect.go Refactors signature verification to use BuildVerifyBlobOptions; adds selectPackageVerifyOpts helper; keyless branch sets BundlePath unconditionally without an existence check unlike the key-based branch
src/pkg/utils/utils.go Adds ValidateVerifyBlobConfig and BuildVerifyBlobOptions; migrates from zarfUtils to signing package; mutual-exclusion and identity-constraint validation are thorough
src/types/bundle.go Adds KeylessVerification struct and helper methods to Package; clean design with pointer field for optional keyless config
src/pkg/sources/tarball.go Adds layout.Bundle extraction alongside legacy layout.Signature; replaces PublicKeyPath with VerifyBlobOptions; correctly handles both signature formats
src/pkg/sources/remote.go Refactors to fetch both layout.Signature and layout.Bundle OCI layers; replaces PublicKeyPath field with VerifyBlobOptions
src/pkg/utils/utils_test.go Adds comprehensive tests for BuildVerifyBlobOptions and ValidateVerifyBlobConfig; shared tmpDir across subtests means written files persist

Sequence Diagram

sequenceDiagram
    participant User
    participant Bundle
    participant utils as utils.BuildVerifyBlobOptions
    participant Source as sources Remote or Tarball
    participant Inspect as bundle.verifyPackageSignature
    participant Cosign as signing.CosignVerifyBlobWithOptions

    User->>Bundle: deploy or inspect
    Bundle->>utils: BuildVerifyBlobOptions(pkg, tmpDir)
    utils-->>utils: ValidateVerifyBlobConfig
    alt publicKey set
        utils-->>Bundle: VerifyBlobOptions with Key
    else keylessVerification set
        utils-->>Bundle: VerifyBlobOptions with CertIdentity and OIDC
    else no config
        utils-->>Bundle: nil
    end
    Bundle->>Source: NewFromLocation with verifyOpts
    Source-->>Source: LoadPackageMetadata downloads zarf.yaml.sig and zarf.bundle.sig
    Bundle->>Inspect: verifyPackageSignature(pkgDir, verifyOpts, zarfPkg)
    Inspect-->>Inspect: detect signed via Build.Signed or sig files on disk
    Inspect-->>Inspect: selectPackageVerifyOpts picks BundlePath or Signature
    Inspect->>Cosign: CosignVerifyBlobWithOptions(ctx, zarf.yaml, opts)
    Cosign-->>Bundle: verified or error
Loading

Reviews (5): Last reviewed commit: "chore: prefer zarf.bundle.sig for key-ba..." | Re-trigger Greptile

Comment thread src/pkg/utils/utils.go Outdated
Comment thread src/pkg/bundle/common.go Outdated
Comment thread src/pkg/bundle/inspect.go Outdated
@emoskito

emoskito commented Jun 1, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai review this draft

Comment thread src/pkg/bundle/inspect.go Outdated
@emoskito
emoskito marked this pull request as ready for review June 2, 2026 00:13
@emoskito
emoskito requested a review from a team as a code owner June 2, 2026 00:13
@emoskito
emoskito requested a review from brandtkeller June 2, 2026 00:13
@emoskito

emoskito commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai

@slaskawi

slaskawi commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 28bd18721e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pkg/bundle/inspect.go Outdated

@slaskawi slaskawi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good in general. Worth check the Codex comment and then I'm happy to approve.

Comment thread src/types/bundle_test.go Outdated
Comment thread src/pkg/bundle/inspect.go Outdated

@joelmccoy joelmccoy left a comment

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.

Haven't done a super deep dive yet but looking good on the approach. However can we add a very small how-to guide here for specifying signing in your bundle packages?

@emoskito

emoskito commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Addressed in 99fcc5f. Added how-to guide for verifying keyless package signatures. Intentionally left out public keys per our discussion, @joelmccoy .

@joelmccoy

Copy link
Copy Markdown
Member

@greptileai review

@greptile-apps

greptile-apps Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@emoskito
emoskito requested review from joelmccoy and slaskawi June 2, 2026 18:46
joelmccoy
joelmccoy previously approved these changes Jun 2, 2026

@joelmccoy joelmccoy left a comment

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.

Generally LGTM - One comment for consideration

Comment thread src/pkg/bundle/inspect.go Outdated
joelmccoy
joelmccoy previously approved these changes Jun 2, 2026
@emoskito
emoskito merged commit 0f8c26c into main Jun 3, 2026
34 of 35 checks passed
@emoskito
emoskito deleted the fix/zarf-dep-v0.77.0-with-keyless-signature-verification branch June 3, 2026 14:38
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.

4 participants