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  }