Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cosign: allow identity matching for keyless verification #1250

Merged
merged 2 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions api/v1beta2/ocirepository_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,28 @@ type OCIRepositoryVerification struct {
// trusted public keys.
// +optional
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`

// MatchOIDCIdentity specifies the identity matching criteria to use
// while verifying an OCI artifact which was signed using Cosign keyless
// signing. The artifact's identity is deemed to be verified if any of the
// specified matchers match against the identity.
// +optional
MatchOIDCIdentity []OIDCIdentityMatch `json:"matchOIDCIdentity,omitempty"`
}

// OIDCIdentityMatch specifies options for verifying the certificate identity,
// i.e. the issuer and the subject of the certificate.
type OIDCIdentityMatch struct {
// Issuer specifies the regex pattern to match against to verify
// the OIDC issuer in the Fulcio certificate. The pattern must be a
// valid Go regular expression.
// +required
Issuer string `json:"issuer"`
// Subject specifies the regex pattern to match against to verify
// the identity subject in the Fulcio certificate. The pattern must
// be a valid Go regular expression.
// +required
Subject string `json:"subject"`
}

// OCIRepositoryStatus defines the observed state of OCIRepository
Expand Down
20 changes: 20 additions & 0 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,32 @@ spec:
Chart dependencies, which are not bundled in the umbrella chart
artifact, are not verified.
properties:
matchOIDCIdentity:
description: MatchOIDCIdentity specifies the identity matching
criteria to use while verifying an OCI artifact which was signed
using Cosign keyless signing. The artifact's identity is deemed
to be verified if any of the specified matchers match against
the identity.
items:
description: OIDCIdentityMatch specifies options for verifying
the certificate identity, i.e. the issuer and the subject
of the certificate.
properties:
issuer:
description: Issuer specifies the regex pattern to match
against to verify the OIDC issuer in the Fulcio certificate.
The pattern must be a valid Go regular expression.
type: string
subject:
description: Subject specifies the regex pattern to match
against to verify the identity subject in the Fulcio certificate.
The pattern must be a valid Go regular expression.
type: string
required:
- issuer
- subject
type: object
type: array
provider:
default: cosign
description: Provider specifies the technology used to sign the
Expand Down
26 changes: 26 additions & 0 deletions config/crd/bases/source.toolkit.fluxcd.io_ocirepositories.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,32 @@ spec:
public keys used to verify the signature and specifies which provider
to use to check whether OCI image is authentic.
properties:
matchOIDCIdentity:
description: MatchOIDCIdentity specifies the identity matching
criteria to use while verifying an OCI artifact which was signed
using Cosign keyless signing. The artifact's identity is deemed
to be verified if any of the specified matchers match against
the identity.
items:
description: OIDCIdentityMatch specifies options for verifying
the certificate identity, i.e. the issuer and the subject
of the certificate.
properties:
issuer:
description: Issuer specifies the regex pattern to match
against to verify the OIDC issuer in the Fulcio certificate.
The pattern must be a valid Go regular expression.
type: string
subject:
description: Subject specifies the regex pattern to match
against to verify the identity subject in the Fulcio certificate.
The pattern must be a valid Go regular expression.
type: string
required:
- issuer
- subject
type: object
type: array
provider:
default: cosign
description: Provider specifies the technology used to sign the
Expand Down
65 changes: 65 additions & 0 deletions docs/api/v1beta2/source.md
Original file line number Diff line number Diff line change
Expand Up @@ -3319,6 +3319,71 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
trusted public keys.</p>
</td>
</tr>
<tr>
<td>
<code>matchOIDCIdentity</code><br>
<em>
<a href="#source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">
[]OIDCIdentityMatch
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>MatchOIDCIdentity specifies the identity matching criteria to use
while verifying an OCI artifact which was signed using Cosign keyless
signing. The artifact&rsquo;s identity is deemed to be verified if any of the
specified matchers match against the identity.</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<h3 id="source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">OIDCIdentityMatch
</h3>
<p>
(<em>Appears on:</em>
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">OCIRepositoryVerification</a>)
</p>
<p>OIDCIdentityMatch specifies options for verifying the certificate identity,
i.e. the issuer and the subject of the certificate.</p>
<div class="md-typeset__scrollwrap">
<div class="md-typeset__table">
<table>
<thead>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>issuer</code><br>
<em>
string
</em>
</td>
<td>
<p>Issuer specifies the regex pattern to match against to verify
the OIDC issuer in the Fulcio certificate. The pattern must be a
valid Go regular expression.</p>
</td>
</tr>
<tr>
<td>
<code>subject</code><br>
<em>
string
</em>
</td>
<td>
<p>Subject specifies the regex pattern to match against to verify
the identity subject in the Fulcio certificate. The pattern must
be a valid Go regular expression.</p>
</td>
</tr>
</tbody>
</table>
</div>
Expand Down
19 changes: 18 additions & 1 deletion docs/spec/v1beta2/helmcharts.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,13 @@ For practical information, see
**Note:** This feature is available only for Helm charts fetched from an OCI Registry.

`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign)
signatures. The field offers two subfields:
signatures. The field offers three subfields:

- `.provider`, to specify the verification provider. Only supports `cosign` at present.
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
the HelmChart, containing the Cosign public keys of trusted authors.
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers. Please see
[Keyless verification](#keyless-verification) for more details.

```yaml
---
Expand Down Expand Up @@ -307,6 +309,18 @@ For publicly available HelmCharts, which are signed using the
[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
you can enable the verification by omitting the `.verify.secretRef` field.

To verify the identity's subject and the OIDC issuer present in the Fulcio
certificate, you can specify a list of OIDC identity matchers using
`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:

- `.issuer`, to specify a regexp that matches against the OIDC issuer.
- `.subject`, to specify a regexp that matches against the subject identity in
the certificate.
Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).

The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
verified if any one matcher successfully matches against the identity.

Example of verifying HelmCharts signed by the
[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:

Expand All @@ -325,6 +339,9 @@ spec:
version: ">=6.1.6"
verify:
provider: cosign
matchOIDCIdentity:
- issuer: "^https://token.actions.githubusercontent.com$"
subject: "^https://github.com/stefanprodan/podinfo.*$"
```

```yaml
Expand Down
19 changes: 18 additions & 1 deletion docs/spec/v1beta2/ocirepositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -501,11 +501,13 @@ for more information.
### Verification

`.spec.verify` is an optional field to enable the verification of [Cosign](https://github.com/sigstore/cosign)
signatures. The field offers two subfields:
signatures. The field offers three subfields:

- `.provider`, to specify the verification provider. Only supports `cosign` at present.
- `.secretRef.name`, to specify a reference to a Secret in the same namespace as
the OCIRepository, containing the Cosign public keys of trusted authors.
- `.matchOIDCIdentity`, to specify a list of OIDC identity matchers. Please see
[Keyless verification](#keyless-verification) for more details.

```yaml
---
Expand Down Expand Up @@ -555,6 +557,18 @@ For publicly available OCI artifacts, which are signed using the
[Cosign Keyless](https://github.com/sigstore/cosign/blob/main/KEYLESS.md) procedure,
you can enable the verification by omitting the `.verify.secretRef` field.

To verify the identity's subject and the OIDC issuer present in the Fulcio
certificate, you can specify a list of OIDC identity matchers using
`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:
aryan9600 marked this conversation as resolved.
Show resolved Hide resolved

- `.issuer`, to specify a regexp that matches against the OIDC issuer.
- `.subject`, to specify a regexp that matches against the subject identity in
the certificate.
Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).

The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
verified if any one matcher successfully matches against the identity.

Example of verifying artifacts signed by the
[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:

Expand All @@ -568,6 +582,9 @@ spec:
url: oci://ghcr.io/stefanprodan/manifests/podinfo
verify:
provider: cosign
matchOIDCIdentity:
- issuer: "^https://token.actions.githubusercontent.com$"
subject: "^https://github.com/stefanprodan/podinfo.*$"
```

The controller verifies the signatures using the Fulcio root CA and the Rekor
Expand Down
10 changes: 10 additions & 0 deletions internal/controller/helmchart_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/opencontainers/go-digest"
"github.com/sigstore/cosign/v2/pkg/cosign"
helmgetter "helm.sh/helm/v3/pkg/getter"
helmreg "helm.sh/helm/v3/pkg/registry"
helmrepo "helm.sh/helm/v3/pkg/repo"
Expand Down Expand Up @@ -1338,6 +1339,15 @@ func (r *HelmChartReconciler) makeVerifiers(ctx context.Context, obj *helmv1.Hel
}

// if no secret is provided, add a keyless verifier
var identities []cosign.Identity
for _, match := range obj.Spec.Verify.MatchOIDCIdentity {
identities = append(identities, cosign.Identity{
IssuerRegExp: match.Issuer,
SubjectRegExp: match.Subject,
})
}
defaultCosignOciOpts = append(defaultCosignOciOpts, soci.WithIdentities(identities))

verifier, err := soci.NewCosignVerifier(ctx, defaultCosignOciOpts...)
if err != nil {
return nil, err
Expand Down
Loading