Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Luke Yang <[email protected]>
  • Loading branch information
lukewarmtemp committed May 30, 2024
1 parent ce0305f commit 7cfeed6
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 10 deletions.
21 changes: 15 additions & 6 deletions signature/fulcio_cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"slices"
"strings"
"time"

"github.com/containers/image/v5/signature/internal"
Expand All @@ -24,14 +25,15 @@ type fulcioTrustRoot struct {
caCertificates *x509.CertPool
oidcIssuer string
subjectEmail string
URI string
}

func (f *fulcioTrustRoot) validate() error {
if f.oidcIssuer == "" {
return errors.New("Internal inconsistency: Fulcio use set up without OIDC issuer")
}
if f.subjectEmail == "" {
return errors.New("Internal inconsistency: Fulcio use set up without subject email")
if f.subjectEmail == "" && f.URI == "" {
return errors.New("Internal inconsistency: Fulcio use set up without subject email or URI")
}
return nil
}
Expand Down Expand Up @@ -177,10 +179,17 @@ func (f *fulcioTrustRoot) verifyFulcioCertificateAtTime(relevantTime time.Time,
}

// == Validate the OIDC subject
if !slices.Contains(untrustedCertificate.EmailAddresses, f.subjectEmail) {
return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Required email %q not found (got %q)",
f.subjectEmail,
untrustedCertificate.EmailAddresses))
if !slices.Contains(untrustedCertificate.EmailAddresses, f.subjectEmail) && !strings.Contains(untrustedCertificate.URIs[0].String(), f.URI) {
if len(untrustedCertificate.EmailAddresses) > 0 {
return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Required email %s not found (got %#v)",
f.subjectEmail,
untrustedCertificate.EmailAddresses))
}
if len(untrustedCertificate.URIs) > 0 {
return nil, internal.NewInvalidSignatureError(fmt.Sprintf("Required URI %s not found (got %#v)",
f.URI,
untrustedCertificate.URIs))
}
}
// FIXME: Match more subject types? Cosign does:
// - .DNSNames (can’t be issued by Fulcio)
Expand Down
25 changes: 21 additions & 4 deletions signature/policy_config_sigstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ func PRSigstoreSignedFulcioWithSubjectEmail(subjectEmail string) PRSigstoreSigne
}
}

// PRSigstoreSignedFulcioWithURI specifies a value for the "URI" field when calling NewPRSigstoreSignedFulcio
func PRSigstoreSignedFulcioWithURI(URI string) PRSigstoreSignedFulcioOption {
return func(f *prSigstoreSignedFulcio) error {
if f.URI != "" {
return errors.New(`"URI" already specified`)
}
f.URI = URI
return nil
}
}

// newPRSigstoreSignedFulcio is NewPRSigstoreSignedFulcio, except it returns the private type
func newPRSigstoreSignedFulcio(options ...PRSigstoreSignedFulcioOption) (*prSigstoreSignedFulcio, error) {
res := prSigstoreSignedFulcio{}
Expand All @@ -279,8 +290,8 @@ func newPRSigstoreSignedFulcio(options ...PRSigstoreSignedFulcioOption) (*prSigs
if res.OIDCIssuer == "" {
return nil, InvalidPolicyFormatError("oidcIssuer not specified")
}
if res.SubjectEmail == "" {
return nil, InvalidPolicyFormatError("subjectEmail not specified")
if res.SubjectEmail == "" && res.URI == "" {
return nil, InvalidPolicyFormatError("subjectEmail and URI not specified")
}

return &res, nil
Expand All @@ -297,7 +308,7 @@ var _ json.Unmarshaler = (*prSigstoreSignedFulcio)(nil)
func (f *prSigstoreSignedFulcio) UnmarshalJSON(data []byte) error {
*f = prSigstoreSignedFulcio{}
var tmp prSigstoreSignedFulcio
var gotCAPath, gotCAData, gotOIDCIssuer, gotSubjectEmail bool // = false...
var gotCAPath, gotCAData, gotOIDCIssuer, gotSubjectEmail, gotURI bool // = false...
if err := internal.ParanoidUnmarshalJSONObject(data, func(key string) any {
switch key {
case "caPath":
Expand All @@ -312,6 +323,9 @@ func (f *prSigstoreSignedFulcio) UnmarshalJSON(data []byte) error {
case "subjectEmail":
gotSubjectEmail = true
return &tmp.SubjectEmail
case "URI":
gotURI = true
return &tmp.URI
default:
return nil
}
Expand All @@ -329,9 +343,12 @@ func (f *prSigstoreSignedFulcio) UnmarshalJSON(data []byte) error {
if gotOIDCIssuer {
opts = append(opts, PRSigstoreSignedFulcioWithOIDCIssuer(tmp.OIDCIssuer))
}
if gotSubjectEmail {
if gotSubjectEmail && !gotURI {
opts = append(opts, PRSigstoreSignedFulcioWithSubjectEmail(tmp.SubjectEmail))
}
if !gotSubjectEmail && gotURI {
opts = append(opts, PRSigstoreSignedFulcioWithURI(tmp.URI))
}

res, err := newPRSigstoreSignedFulcio(opts...)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions signature/policy_eval_sigstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func (f *prSigstoreSignedFulcio) prepareTrustRoot() (*fulcioTrustRoot, error) {
caCertificates: certs,
oidcIssuer: f.OIDCIssuer,
subjectEmail: f.SubjectEmail,
URI: f.URI,
}
if err := fulcio.validate(); err != nil {
return nil, err
Expand Down
2 changes: 2 additions & 0 deletions signature/policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ type prSigstoreSignedFulcio struct {
OIDCIssuer string `json:"oidcIssuer,omitempty"`
// SubjectEmail specifies the expected email address of the authenticated OIDC identity, recorded by Fulcio into the generated certificates.
SubjectEmail string `json:"subjectEmail,omitempty"`
// URI specifies the expected URI of the authenticated OIDC identity, recorded by Fulcio into the generated certificates.
URI string `json:"URI,omitempty"`
}

// PolicyReferenceMatch specifies a set of image identities accepted in PolicyRequirement.
Expand Down

0 comments on commit 7cfeed6

Please sign in to comment.