Skip to content

Commit a8a8196

Browse files
authored
Merge pull request #1250 from fluxcd/cosign-identity-matching
cosign: allow identity matching for keyless verification
2 parents 8c63fba + fcaf86e commit a8a8196

13 files changed

+604
-15
lines changed

api/v1beta2/ocirepository_types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,28 @@ type OCIRepositoryVerification struct {
190190
// trusted public keys.
191191
// +optional
192192
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
193+
194+
// MatchOIDCIdentity specifies the identity matching criteria to use
195+
// while verifying an OCI artifact which was signed using Cosign keyless
196+
// signing. The artifact's identity is deemed to be verified if any of the
197+
// specified matchers match against the identity.
198+
// +optional
199+
MatchOIDCIdentity []OIDCIdentityMatch `json:"matchOIDCIdentity,omitempty"`
200+
}
201+
202+
// OIDCIdentityMatch specifies options for verifying the certificate identity,
203+
// i.e. the issuer and the subject of the certificate.
204+
type OIDCIdentityMatch struct {
205+
// Issuer specifies the regex pattern to match against to verify
206+
// the OIDC issuer in the Fulcio certificate. The pattern must be a
207+
// valid Go regular expression.
208+
// +required
209+
Issuer string `json:"issuer"`
210+
// Subject specifies the regex pattern to match against to verify
211+
// the identity subject in the Fulcio certificate. The pattern must
212+
// be a valid Go regular expression.
213+
// +required
214+
Subject string `json:"subject"`
193215
}
194216

195217
// OCIRepositoryStatus defines the observed state of OCIRepository

api/v1beta2/zz_generated.deepcopy.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/source.toolkit.fluxcd.io_helmcharts.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,32 @@ spec:
411411
Chart dependencies, which are not bundled in the umbrella chart
412412
artifact, are not verified.
413413
properties:
414+
matchOIDCIdentity:
415+
description: MatchOIDCIdentity specifies the identity matching
416+
criteria to use while verifying an OCI artifact which was signed
417+
using Cosign keyless signing. The artifact's identity is deemed
418+
to be verified if any of the specified matchers match against
419+
the identity.
420+
items:
421+
description: OIDCIdentityMatch specifies options for verifying
422+
the certificate identity, i.e. the issuer and the subject
423+
of the certificate.
424+
properties:
425+
issuer:
426+
description: Issuer specifies the regex pattern to match
427+
against to verify the OIDC issuer in the Fulcio certificate.
428+
The pattern must be a valid Go regular expression.
429+
type: string
430+
subject:
431+
description: Subject specifies the regex pattern to match
432+
against to verify the identity subject in the Fulcio certificate.
433+
The pattern must be a valid Go regular expression.
434+
type: string
435+
required:
436+
- issuer
437+
- subject
438+
type: object
439+
type: array
414440
provider:
415441
default: cosign
416442
description: Provider specifies the technology used to sign the

config/crd/bases/source.toolkit.fluxcd.io_ocirepositories.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,32 @@ spec:
164164
public keys used to verify the signature and specifies which provider
165165
to use to check whether OCI image is authentic.
166166
properties:
167+
matchOIDCIdentity:
168+
description: MatchOIDCIdentity specifies the identity matching
169+
criteria to use while verifying an OCI artifact which was signed
170+
using Cosign keyless signing. The artifact's identity is deemed
171+
to be verified if any of the specified matchers match against
172+
the identity.
173+
items:
174+
description: OIDCIdentityMatch specifies options for verifying
175+
the certificate identity, i.e. the issuer and the subject
176+
of the certificate.
177+
properties:
178+
issuer:
179+
description: Issuer specifies the regex pattern to match
180+
against to verify the OIDC issuer in the Fulcio certificate.
181+
The pattern must be a valid Go regular expression.
182+
type: string
183+
subject:
184+
description: Subject specifies the regex pattern to match
185+
against to verify the identity subject in the Fulcio certificate.
186+
The pattern must be a valid Go regular expression.
187+
type: string
188+
required:
189+
- issuer
190+
- subject
191+
type: object
192+
type: array
167193
provider:
168194
default: cosign
169195
description: Provider specifies the technology used to sign the

docs/api/v1beta2/source.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3319,6 +3319,71 @@ github.com/fluxcd/pkg/apis/meta.LocalObjectReference
33193319
trusted public keys.</p>
33203320
</td>
33213321
</tr>
3322+
<tr>
3323+
<td>
3324+
<code>matchOIDCIdentity</code><br>
3325+
<em>
3326+
<a href="#source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">
3327+
[]OIDCIdentityMatch
3328+
</a>
3329+
</em>
3330+
</td>
3331+
<td>
3332+
<em>(Optional)</em>
3333+
<p>MatchOIDCIdentity specifies the identity matching criteria to use
3334+
while verifying an OCI artifact which was signed using Cosign keyless
3335+
signing. The artifact&rsquo;s identity is deemed to be verified if any of the
3336+
specified matchers match against the identity.</p>
3337+
</td>
3338+
</tr>
3339+
</tbody>
3340+
</table>
3341+
</div>
3342+
</div>
3343+
<h3 id="source.toolkit.fluxcd.io/v1beta2.OIDCIdentityMatch">OIDCIdentityMatch
3344+
</h3>
3345+
<p>
3346+
(<em>Appears on:</em>
3347+
<a href="#source.toolkit.fluxcd.io/v1beta2.OCIRepositoryVerification">OCIRepositoryVerification</a>)
3348+
</p>
3349+
<p>OIDCIdentityMatch specifies options for verifying the certificate identity,
3350+
i.e. the issuer and the subject of the certificate.</p>
3351+
<div class="md-typeset__scrollwrap">
3352+
<div class="md-typeset__table">
3353+
<table>
3354+
<thead>
3355+
<tr>
3356+
<th>Field</th>
3357+
<th>Description</th>
3358+
</tr>
3359+
</thead>
3360+
<tbody>
3361+
<tr>
3362+
<td>
3363+
<code>issuer</code><br>
3364+
<em>
3365+
string
3366+
</em>
3367+
</td>
3368+
<td>
3369+
<p>Issuer specifies the regex pattern to match against to verify
3370+
the OIDC issuer in the Fulcio certificate. The pattern must be a
3371+
valid Go regular expression.</p>
3372+
</td>
3373+
</tr>
3374+
<tr>
3375+
<td>
3376+
<code>subject</code><br>
3377+
<em>
3378+
string
3379+
</em>
3380+
</td>
3381+
<td>
3382+
<p>Subject specifies the regex pattern to match against to verify
3383+
the identity subject in the Fulcio certificate. The pattern must
3384+
be a valid Go regular expression.</p>
3385+
</td>
3386+
</tr>
33223387
</tbody>
33233388
</table>
33243389
</div>

docs/spec/v1beta2/helmcharts.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,13 @@ For practical information, see
253253
**Note:** This feature is available only for Helm charts fetched from an OCI Registry.
254254

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

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

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

312+
To verify the identity's subject and the OIDC issuer present in the Fulcio
313+
certificate, you can specify a list of OIDC identity matchers using
314+
`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:
315+
316+
- `.issuer`, to specify a regexp that matches against the OIDC issuer.
317+
- `.subject`, to specify a regexp that matches against the subject identity in
318+
the certificate.
319+
Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).
320+
321+
The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
322+
verified if any one matcher successfully matches against the identity.
323+
310324
Example of verifying HelmCharts signed by the
311325
[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:
312326

@@ -325,6 +339,9 @@ spec:
325339
version: ">=6.1.6"
326340
verify:
327341
provider: cosign
342+
matchOIDCIdentity:
343+
- issuer: "^https://token.actions.githubusercontent.com$"
344+
subject: "^https://github.com/stefanprodan/podinfo.*$"
328345
```
329346

330347
```yaml

docs/spec/v1beta2/ocirepositories.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,11 +501,13 @@ for more information.
501501
### Verification
502502

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

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

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

560+
To verify the identity's subject and the OIDC issuer present in the Fulcio
561+
certificate, you can specify a list of OIDC identity matchers using
562+
`.spec.verify.matchOIDCIdentity`. The matcher provides two required fields:
563+
564+
- `.issuer`, to specify a regexp that matches against the OIDC issuer.
565+
- `.subject`, to specify a regexp that matches against the subject identity in
566+
the certificate.
567+
Both values should follow the [Go regular expression syntax](https://golang.org/s/re2syntax).
568+
569+
The matchers are evaluated in an OR fashion, i.e. the identity is deemed to be
570+
verified if any one matcher successfully matches against the identity.
571+
558572
Example of verifying artifacts signed by the
559573
[Cosign GitHub Action](https://github.com/sigstore/cosign-installer) with GitHub OIDC Token:
560574

@@ -568,6 +582,9 @@ spec:
568582
url: oci://ghcr.io/stefanprodan/manifests/podinfo
569583
verify:
570584
provider: cosign
585+
matchOIDCIdentity:
586+
- issuer: "^https://token.actions.githubusercontent.com$"
587+
subject: "^https://github.com/stefanprodan/podinfo.*$"
571588
```
572589

573590
The controller verifies the signatures using the Fulcio root CA and the Rekor

internal/controller/helmchart_controller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

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

13401341
// if no secret is provided, add a keyless verifier
1342+
var identities []cosign.Identity
1343+
for _, match := range obj.Spec.Verify.MatchOIDCIdentity {
1344+
identities = append(identities, cosign.Identity{
1345+
IssuerRegExp: match.Issuer,
1346+
SubjectRegExp: match.Subject,
1347+
})
1348+
}
1349+
defaultCosignOciOpts = append(defaultCosignOciOpts, soci.WithIdentities(identities))
1350+
13411351
verifier, err := soci.NewCosignVerifier(ctx, defaultCosignOciOpts...)
13421352
if err != nil {
13431353
return nil, err

0 commit comments

Comments
 (0)