github.com/boxboat/in-toto-golang@v0.0.3-0.20210303203820-2fa16ecbe6f6/in_toto/certconstraint.go (about) 1 package in_toto 2 3 import ( 4 "crypto/x509" 5 "net/url" 6 ) 7 8 const ( 9 AllowAllConstraint = "*" 10 ) 11 12 // CertificateConstraint defines the attributes a certificate must have to act as a functionary. 13 // A wildcard `*` allows any value in the specified attribute, where as an empty array or value 14 // asserts that the certificate must have nothing for that attribute. A certificate must have 15 // every value defined in a constraint to match. 16 type CertificateConstraint struct { 17 CommonName string `json:"common_name"` 18 URIs []string `json:"uris"` 19 } 20 21 // Check tests the provided certificate against the constraint. True is returned if the certificate 22 // satisifies the constraint, false will be returned otherwise. 23 func (cc CertificateConstraint) Check(cert *x509.Certificate) bool { 24 if cc.CommonName != AllowAllConstraint && cc.CommonName != cert.Subject.CommonName { 25 return false 26 } 27 28 return checkConstraintAttribute(cc.URIs, urisToStrings(cert.URIs)) 29 } 30 31 // urisToStrings is a helper that converts a list of URL objects to the string that represents them 32 func urisToStrings(uris []*url.URL) []string { 33 res := make([]string, 0, len(uris)) 34 for _, uri := range uris { 35 res = append(res, uri.String()) 36 } 37 38 return res 39 } 40 41 // checkConstraintAttribute tests that the provided test values match the allowed values of the constraint. 42 // All allowed values must be met one-to-one to be considered a successful match. 43 func checkConstraintAttribute(allowed, test []string) bool { 44 if len(allowed) == 1 && allowed[0] == AllowAllConstraint { 45 return true 46 } 47 48 unmet := NewSet(allowed...) 49 for _, t := range test { 50 // if our test has a value we didn't expect, fail early 51 if !unmet.Has(t) { 52 return false 53 } 54 55 // consider the constraint met 56 unmet.Remove(t) 57 } 58 59 // if we have any unmet left after going through each test value, fail. 60 return len(unmet) == 0 61 }