104 lines
3.3 KiB
Go
104 lines
3.3 KiB
Go
package verification
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/cli/cli/v2/pkg/cmd/attestation/artifact"
|
|
|
|
"github.com/sigstore/sigstore-go/pkg/fulcio/certificate"
|
|
"github.com/sigstore/sigstore-go/pkg/verify"
|
|
)
|
|
|
|
// represents the GitHub hosted runner in the certificate RunnerEnvironment extension
|
|
const GitHubRunner = "github-hosted"
|
|
|
|
// BuildDigestPolicyOption builds a verify.ArtifactPolicyOption
|
|
// from the given artifact digest and digest algorithm
|
|
func BuildDigestPolicyOption(a artifact.DigestedArtifact) (verify.ArtifactPolicyOption, error) {
|
|
// sigstore-go expects the artifact digest to be decoded from hex
|
|
decoded, err := hex.DecodeString(a.Digest())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return verify.WithArtifactDigest(a.Algorithm(), decoded), nil
|
|
}
|
|
|
|
type EnforcementCriteria struct {
|
|
Certificate certificate.Summary
|
|
PredicateType string
|
|
SANRegex string
|
|
SAN string
|
|
}
|
|
|
|
func (c EnforcementCriteria) Valid() error {
|
|
if c.Certificate.Issuer == "" {
|
|
return fmt.Errorf("Issuer must be set")
|
|
}
|
|
if c.Certificate.RunnerEnvironment != "" && c.Certificate.RunnerEnvironment != GitHubRunner {
|
|
return fmt.Errorf("RunnerEnvironment must be set to either \"\" or %s", GitHubRunner)
|
|
}
|
|
if c.Certificate.SourceRepositoryOwnerURI == "" {
|
|
return fmt.Errorf("SourceRepositoryOwnerURI must be set")
|
|
}
|
|
if c.PredicateType == "" {
|
|
return fmt.Errorf("PredicateType must be set")
|
|
}
|
|
if c.SANRegex == "" && c.SAN == "" {
|
|
return fmt.Errorf("SANRegex or SAN must be set")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c EnforcementCriteria) BuildPolicyInformation() string {
|
|
policyAttr := [][]string{}
|
|
|
|
policyAttr = appendStr(policyAttr, "- Predicate type must match", c.PredicateType)
|
|
|
|
policyAttr = appendStr(policyAttr, "- Source Repository Owner URI must match", c.Certificate.SourceRepositoryOwnerURI)
|
|
|
|
if c.Certificate.SourceRepositoryURI != "" {
|
|
policyAttr = appendStr(policyAttr, "- Source Repository URI must match", c.Certificate.SourceRepositoryURI)
|
|
}
|
|
|
|
if c.Certificate.BuildSignerDigest != "" {
|
|
policyAttr = appendStr(policyAttr, "- Build signer digest must match", c.Certificate.BuildSignerDigest)
|
|
}
|
|
if c.Certificate.SourceRepositoryDigest != "" {
|
|
policyAttr = appendStr(policyAttr, "- Source repo digest digest must match", c.Certificate.SourceRepositoryDigest)
|
|
}
|
|
if c.Certificate.SourceRepositoryRef != "" {
|
|
policyAttr = appendStr(policyAttr, "- Source repo ref must match", c.Certificate.SourceRepositoryRef)
|
|
}
|
|
|
|
if c.SAN != "" {
|
|
policyAttr = appendStr(policyAttr, "- Subject Alternative Name must match", c.SAN)
|
|
} else if c.SANRegex != "" {
|
|
policyAttr = appendStr(policyAttr, "- Subject Alternative Name must match regex", c.SANRegex)
|
|
}
|
|
|
|
policyAttr = appendStr(policyAttr, "- OIDC Issuer must match", c.Certificate.Issuer)
|
|
if c.Certificate.RunnerEnvironment == GitHubRunner {
|
|
policyAttr = appendStr(policyAttr, "- Action workflow Runner Environment must match ", GitHubRunner)
|
|
}
|
|
|
|
maxColLen := 0
|
|
for _, attr := range policyAttr {
|
|
if len(attr[0]) > maxColLen {
|
|
maxColLen = len(attr[0])
|
|
}
|
|
}
|
|
|
|
policyInfo := ""
|
|
for _, attr := range policyAttr {
|
|
dots := strings.Repeat(".", maxColLen-len(attr[0]))
|
|
policyInfo += fmt.Sprintf("%s:%s %s\n", attr[0], dots, attr[1])
|
|
}
|
|
|
|
return policyInfo
|
|
}
|
|
|
|
func appendStr(arr [][]string, a, b string) [][]string {
|
|
return append(arr, []string{a, b})
|
|
}
|