73 lines
3.1 KiB
Go
73 lines
3.1 KiB
Go
package verification
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/sigstore/sigstore-go/pkg/fulcio/certificate"
|
|
)
|
|
|
|
var (
|
|
GitHubOIDCIssuer = "https://token.actions.githubusercontent.com"
|
|
GitHubTenantOIDCIssuer = "https://token.actions.%s.ghe.com"
|
|
)
|
|
|
|
// VerifyCertExtensions allows us to perform case insensitive comparisons of certificate extensions
|
|
func VerifyCertExtensions(results []*AttestationProcessingResult, ec EnforcementCriteria) ([]*AttestationProcessingResult, error) {
|
|
if len(results) == 0 {
|
|
return nil, errors.New("no attestations processing results")
|
|
}
|
|
|
|
verified := make([]*AttestationProcessingResult, 0, len(results))
|
|
var lastErr error
|
|
for _, attestation := range results {
|
|
if err := verifyCertExtensions(*attestation.VerificationResult.Signature.Certificate, ec.Certificate); err != nil {
|
|
lastErr = err
|
|
// move onto the next attestation in the for loop if verification fails
|
|
continue
|
|
}
|
|
// otherwise, add the result to the results slice and increment verifyCount
|
|
verified = append(verified, attestation)
|
|
}
|
|
|
|
// if we have exited the for loop without verifying any attestations,
|
|
// return the last error found
|
|
if len(verified) == 0 {
|
|
return nil, lastErr
|
|
}
|
|
|
|
return verified, nil
|
|
}
|
|
|
|
func verifyCertExtensions(given, expected certificate.Summary) error {
|
|
if !strings.EqualFold(expected.SourceRepositoryOwnerURI, given.SourceRepositoryOwnerURI) {
|
|
return fmt.Errorf("expected SourceRepositoryOwnerURI to be %s, got %s", expected.SourceRepositoryOwnerURI, given.SourceRepositoryOwnerURI)
|
|
}
|
|
|
|
// if repo is set, compare the SourceRepositoryURI fields
|
|
if expected.SourceRepositoryURI != "" && !strings.EqualFold(expected.SourceRepositoryURI, given.SourceRepositoryURI) {
|
|
return fmt.Errorf("expected SourceRepositoryURI to be %s, got %s", expected.SourceRepositoryURI, given.SourceRepositoryURI)
|
|
}
|
|
|
|
// compare the OIDC issuers. If not equal, return an error depending
|
|
// on if there is a partial match
|
|
if !strings.EqualFold(expected.Issuer, given.Issuer) {
|
|
if strings.Index(given.Issuer, expected.Issuer+"/") == 0 {
|
|
return fmt.Errorf("expected Issuer to be %s, got %s -- if you have a custom OIDC issuer policy for your enterprise, use the --cert-oidc-issuer flag with your expected issuer", expected.Issuer, given.Issuer)
|
|
}
|
|
return fmt.Errorf("expected Issuer to be %s, got %s", expected.Issuer, given.Issuer)
|
|
}
|
|
|
|
if expected.BuildSignerDigest != "" && !strings.EqualFold(expected.BuildSignerDigest, given.BuildSignerDigest) {
|
|
return fmt.Errorf("expected BuildSignerDigest to be %s, got %s", expected.BuildSignerDigest, given.BuildSignerDigest)
|
|
}
|
|
if expected.SourceRepositoryDigest != "" && !strings.EqualFold(expected.SourceRepositoryDigest, given.SourceRepositoryDigest) {
|
|
return fmt.Errorf("expected SourceRepositoryDigest to be %s, got %s", expected.SourceRepositoryDigest, given.SourceRepositoryDigest)
|
|
}
|
|
if expected.SourceRepositoryRef != "" && !strings.EqualFold(expected.SourceRepositoryRef, given.SourceRepositoryRef) {
|
|
return fmt.Errorf("expected SourceRepositoryRef to be %s, got %s", expected.SourceRepositoryRef, given.SourceRepositoryRef)
|
|
}
|
|
|
|
return nil
|
|
}
|