package policy import ( "fmt" "github.com/docker/attest/pkg/config" ) type matchType string const ( matchTypePolicy matchType = "policy" matchTypeMatchNoPolicy matchType = "match_no_policy" matchTypeNoMatch matchType = "no_match" ) type policyMatch struct { matchType matchType policy *config.PolicyMapping rule *config.PolicyRule matchedName string } func findPolicyMatch(imageName string, mappings *config.PolicyMappings) (*policyMatch, error) { if mappings == nil { return &policyMatch{matchType: matchTypeNoMatch, matchedName: imageName}, nil } return findPolicyMatchImpl(imageName, mappings, make(map[*config.PolicyRule]bool)) } func findPolicyMatchImpl(imageName string, mappings *config.PolicyMappings, matched map[*config.PolicyRule]bool) (*policyMatch, error) { for _, rule := range mappings.Rules { if rule.Pattern.MatchString(imageName) { switch { case rule.PolicyID == "" && rule.Replacement == "": return nil, fmt.Errorf("rule %s has neither policy-id nor rewrite", rule.Pattern) case rule.PolicyID != "" && rule.Replacement != "": return nil, fmt.Errorf("rule %s has both policy-id and rewrite", rule.Pattern) case rule.PolicyID != "": policy := mappings.Policies[rule.PolicyID] if policy != nil { return &policyMatch{ matchType: matchTypePolicy, policy: policy, rule: rule, matchedName: imageName, }, nil } return &policyMatch{ matchType: matchTypeMatchNoPolicy, rule: rule, matchedName: imageName, }, nil case rule.Replacement != "": if matched[rule] { return nil, fmt.Errorf("rewrite loop detected") } matched[rule] = true imageName = rule.Pattern.ReplaceAllString(imageName, rule.Replacement) return findPolicyMatchImpl(imageName, mappings, matched) } } } return &policyMatch{matchType: matchTypeNoMatch, matchedName: imageName}, nil }