Repository: cli/cli
File: pkg/cmd/attestation/verification/extensions.go (Go)

Code before:
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"
)

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)
	}

Review comment (security):
yesterday we had a conversation where we realized it's not obvious WHY we verifyCertExtensions separately from the CertificateIdentity provided in sigstore-go (and frankly, maybe we should just upstream how we've done it here) and

after some mild effort,

we discovered it's so we can support case insensitivity around repo & owner names.

given that conversation let's add a wee comment to `func verifyCertExtensiosn` denoting that - "this func exists so we can do case insensitive comparisons"

Code after:
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)