istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pkg/test/csrctrl/authority/policies.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package authority 16 17 import ( 18 "crypto/x509" 19 "fmt" 20 "sort" 21 "time" 22 23 capi "k8s.io/api/certificates/v1" 24 ) 25 26 // SigningPolicy validates a CertificateRequest before it's signed by the 27 // CertificateAuthority. It may default or otherwise mutate a certificate 28 // template. 29 type SigningPolicy interface { 30 // not-exporting apply forces signing policy implementations to be internal 31 // to this package. 32 apply(template *x509.Certificate) error 33 } 34 35 // PermissiveSigningPolicy is the signing policy historically used by the local 36 // signer. 37 // 38 // - It forwards all SANs from the original signing request. 39 // - It sets allowed usages as configured in the policy. 40 // - It sets NotAfter based on the TTL configured in the policy. 41 // - It zeros all extensions. 42 // - It sets BasicConstraints to true. 43 // - It sets IsCA to false. 44 type PermissiveSigningPolicy struct { 45 // TTL is the certificate TTL. It's used to calculate the NotAfter value of 46 // the certificate. 47 TTL time.Duration 48 // Usages are the allowed usages of a certificate. 49 Usages []capi.KeyUsage 50 } 51 52 func (p PermissiveSigningPolicy) apply(tmpl *x509.Certificate) error { 53 usage, extUsages, err := keyUsagesFromStrings(p.Usages) 54 if err != nil { 55 return err 56 } 57 tmpl.KeyUsage = usage 58 tmpl.ExtKeyUsage = extUsages 59 tmpl.NotAfter = tmpl.NotBefore.Add(p.TTL) 60 61 tmpl.ExtraExtensions = nil 62 tmpl.Extensions = nil 63 tmpl.BasicConstraintsValid = true 64 tmpl.IsCA = false 65 66 return nil 67 } 68 69 var keyUsageDict = map[capi.KeyUsage]x509.KeyUsage{ 70 capi.UsageSigning: x509.KeyUsageDigitalSignature, 71 capi.UsageDigitalSignature: x509.KeyUsageDigitalSignature, 72 capi.UsageContentCommitment: x509.KeyUsageContentCommitment, 73 capi.UsageKeyEncipherment: x509.KeyUsageKeyEncipherment, 74 capi.UsageKeyAgreement: x509.KeyUsageKeyAgreement, 75 capi.UsageDataEncipherment: x509.KeyUsageDataEncipherment, 76 capi.UsageCertSign: x509.KeyUsageCertSign, 77 capi.UsageCRLSign: x509.KeyUsageCRLSign, 78 capi.UsageEncipherOnly: x509.KeyUsageEncipherOnly, 79 capi.UsageDecipherOnly: x509.KeyUsageDecipherOnly, 80 } 81 82 var extKeyUsageDict = map[capi.KeyUsage]x509.ExtKeyUsage{ 83 capi.UsageAny: x509.ExtKeyUsageAny, 84 capi.UsageServerAuth: x509.ExtKeyUsageServerAuth, 85 capi.UsageClientAuth: x509.ExtKeyUsageClientAuth, 86 capi.UsageCodeSigning: x509.ExtKeyUsageCodeSigning, 87 capi.UsageEmailProtection: x509.ExtKeyUsageEmailProtection, 88 capi.UsageSMIME: x509.ExtKeyUsageEmailProtection, 89 capi.UsageIPsecEndSystem: x509.ExtKeyUsageIPSECEndSystem, 90 capi.UsageIPsecTunnel: x509.ExtKeyUsageIPSECTunnel, 91 capi.UsageIPsecUser: x509.ExtKeyUsageIPSECUser, 92 capi.UsageTimestamping: x509.ExtKeyUsageTimeStamping, 93 capi.UsageOCSPSigning: x509.ExtKeyUsageOCSPSigning, 94 capi.UsageMicrosoftSGC: x509.ExtKeyUsageMicrosoftServerGatedCrypto, 95 capi.UsageNetscapeSGC: x509.ExtKeyUsageNetscapeServerGatedCrypto, 96 } 97 98 // keyUsagesFromStrings will translate a slice of usage strings from the 99 // certificates API ("pkg/apis/certificates".KeyUsage) to x509.KeyUsage and 100 // x509.ExtKeyUsage types. 101 func keyUsagesFromStrings(usages []capi.KeyUsage) (x509.KeyUsage, []x509.ExtKeyUsage, error) { 102 var keyUsage x509.KeyUsage 103 var unrecognized []capi.KeyUsage 104 extKeyUsages := make(map[x509.ExtKeyUsage]struct{}) 105 for _, usage := range usages { 106 if val, ok := keyUsageDict[usage]; ok { 107 keyUsage |= val 108 } else if val, ok := extKeyUsageDict[usage]; ok { 109 extKeyUsages[val] = struct{}{} 110 } else { 111 unrecognized = append(unrecognized, usage) 112 } 113 } 114 115 var sorted sortedExtKeyUsage 116 for eku := range extKeyUsages { 117 sorted = append(sorted, eku) 118 } 119 sort.Sort(sorted) 120 121 if len(unrecognized) > 0 { 122 return 0, nil, fmt.Errorf("unrecognized usage values: %q", unrecognized) 123 } 124 125 return keyUsage, []x509.ExtKeyUsage(sorted), nil 126 } 127 128 type sortedExtKeyUsage []x509.ExtKeyUsage 129 130 func (s sortedExtKeyUsage) Len() int { 131 return len(s) 132 } 133 134 func (s sortedExtKeyUsage) Swap(i, j int) { 135 s[i], s[j] = s[j], s[i] 136 } 137 138 func (s sortedExtKeyUsage) Less(i, j int) bool { 139 return s[i] < s[j] 140 }