...

Source file src/edge-infra.dev/pkg/edge/edge-issuer/signer/policies.go

Documentation: edge-infra.dev/pkg/edge/edge-issuer/signer

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

View as plain text