...

Source file src/k8s.io/kubernetes/pkg/controller/certificates/authority/policies.go

Documentation: k8s.io/kubernetes/pkg/controller/certificates/authority

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package authority
    18  
    19  import (
    20  	"crypto/x509"
    21  	"fmt"
    22  	"sort"
    23  	"time"
    24  
    25  	capi "k8s.io/api/certificates/v1"
    26  )
    27  
    28  // SigningPolicy validates a CertificateRequest before it's signed by the
    29  // CertificateAuthority. It may default or otherwise mutate a certificate
    30  // template.
    31  type SigningPolicy interface {
    32  	// not-exporting apply forces signing policy implementations to be internal
    33  	// to this package.
    34  	apply(template *x509.Certificate, signerNotAfter time.Time) error
    35  }
    36  
    37  // PermissiveSigningPolicy is the signing policy historically used by the local
    38  // signer.
    39  //
    40  //   - It forwards all SANs from the original signing request.
    41  //   - It sets allowed usages as configured in the policy.
    42  //   - It zeros all extensions.
    43  //   - It sets BasicConstraints to true.
    44  //   - It sets IsCA to false.
    45  //   - It validates that the signer has not expired.
    46  //   - It sets NotBefore and NotAfter:
    47  //     All certificates set NotBefore = Now() - Backdate.
    48  //     Long-lived certificates set NotAfter = Now() + TTL - Backdate.
    49  //     Short-lived certificates set NotAfter = Now() + TTL.
    50  //     All certificates truncate NotAfter to the expiration date of the signer.
    51  type PermissiveSigningPolicy struct {
    52  	// TTL is used in certificate NotAfter calculation as described above.
    53  	TTL time.Duration
    54  
    55  	// Usages are the allowed usages of a certificate.
    56  	Usages []capi.KeyUsage
    57  
    58  	// Backdate is used in certificate NotBefore calculation as described above.
    59  	Backdate time.Duration
    60  
    61  	// Short is the duration used to determine if the lifetime of a certificate should be considered short.
    62  	Short time.Duration
    63  
    64  	// Now defaults to time.Now but can be stubbed for testing
    65  	Now func() time.Time
    66  }
    67  
    68  func (p PermissiveSigningPolicy) apply(tmpl *x509.Certificate, signerNotAfter time.Time) error {
    69  	var now time.Time
    70  	if p.Now != nil {
    71  		now = p.Now()
    72  	} else {
    73  		now = time.Now()
    74  	}
    75  
    76  	ttl := p.TTL
    77  
    78  	usage, extUsages, err := keyUsagesFromStrings(p.Usages)
    79  	if err != nil {
    80  		return err
    81  	}
    82  	tmpl.KeyUsage = usage
    83  	tmpl.ExtKeyUsage = extUsages
    84  
    85  	tmpl.ExtraExtensions = nil
    86  	tmpl.Extensions = nil
    87  	tmpl.BasicConstraintsValid = true
    88  	tmpl.IsCA = false
    89  
    90  	tmpl.NotBefore = now.Add(-p.Backdate)
    91  
    92  	if ttl < p.Short {
    93  		// do not backdate the end time if we consider this to be a short lived certificate
    94  		tmpl.NotAfter = now.Add(ttl)
    95  	} else {
    96  		tmpl.NotAfter = now.Add(ttl - p.Backdate)
    97  	}
    98  
    99  	if !tmpl.NotAfter.Before(signerNotAfter) {
   100  		tmpl.NotAfter = signerNotAfter
   101  	}
   102  
   103  	if !tmpl.NotBefore.Before(signerNotAfter) {
   104  		return fmt.Errorf("the signer has expired: NotAfter=%v", signerNotAfter)
   105  	}
   106  
   107  	if !now.Before(signerNotAfter) {
   108  		return fmt.Errorf("refusing to sign a certificate that expired in the past: NotAfter=%v", signerNotAfter)
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  var keyUsageDict = map[capi.KeyUsage]x509.KeyUsage{
   115  	capi.UsageSigning:           x509.KeyUsageDigitalSignature,
   116  	capi.UsageDigitalSignature:  x509.KeyUsageDigitalSignature,
   117  	capi.UsageContentCommitment: x509.KeyUsageContentCommitment,
   118  	capi.UsageKeyEncipherment:   x509.KeyUsageKeyEncipherment,
   119  	capi.UsageKeyAgreement:      x509.KeyUsageKeyAgreement,
   120  	capi.UsageDataEncipherment:  x509.KeyUsageDataEncipherment,
   121  	capi.UsageCertSign:          x509.KeyUsageCertSign,
   122  	capi.UsageCRLSign:           x509.KeyUsageCRLSign,
   123  	capi.UsageEncipherOnly:      x509.KeyUsageEncipherOnly,
   124  	capi.UsageDecipherOnly:      x509.KeyUsageDecipherOnly,
   125  }
   126  
   127  var extKeyUsageDict = map[capi.KeyUsage]x509.ExtKeyUsage{
   128  	capi.UsageAny:             x509.ExtKeyUsageAny,
   129  	capi.UsageServerAuth:      x509.ExtKeyUsageServerAuth,
   130  	capi.UsageClientAuth:      x509.ExtKeyUsageClientAuth,
   131  	capi.UsageCodeSigning:     x509.ExtKeyUsageCodeSigning,
   132  	capi.UsageEmailProtection: x509.ExtKeyUsageEmailProtection,
   133  	capi.UsageSMIME:           x509.ExtKeyUsageEmailProtection,
   134  	capi.UsageIPsecEndSystem:  x509.ExtKeyUsageIPSECEndSystem,
   135  	capi.UsageIPsecTunnel:     x509.ExtKeyUsageIPSECTunnel,
   136  	capi.UsageIPsecUser:       x509.ExtKeyUsageIPSECUser,
   137  	capi.UsageTimestamping:    x509.ExtKeyUsageTimeStamping,
   138  	capi.UsageOCSPSigning:     x509.ExtKeyUsageOCSPSigning,
   139  	capi.UsageMicrosoftSGC:    x509.ExtKeyUsageMicrosoftServerGatedCrypto,
   140  	capi.UsageNetscapeSGC:     x509.ExtKeyUsageNetscapeServerGatedCrypto,
   141  }
   142  
   143  // keyUsagesFromStrings will translate a slice of usage strings from the
   144  // certificates API ("pkg/apis/certificates".KeyUsage) to x509.KeyUsage and
   145  // x509.ExtKeyUsage types.
   146  func keyUsagesFromStrings(usages []capi.KeyUsage) (x509.KeyUsage, []x509.ExtKeyUsage, error) {
   147  	var keyUsage x509.KeyUsage
   148  	var unrecognized []capi.KeyUsage
   149  	extKeyUsages := make(map[x509.ExtKeyUsage]struct{})
   150  	for _, usage := range usages {
   151  		if val, ok := keyUsageDict[usage]; ok {
   152  			keyUsage |= val
   153  		} else if val, ok := extKeyUsageDict[usage]; ok {
   154  			extKeyUsages[val] = struct{}{}
   155  		} else {
   156  			unrecognized = append(unrecognized, usage)
   157  		}
   158  	}
   159  
   160  	var sorted sortedExtKeyUsage
   161  	for eku := range extKeyUsages {
   162  		sorted = append(sorted, eku)
   163  	}
   164  	sort.Sort(sorted)
   165  
   166  	if len(unrecognized) > 0 {
   167  		return 0, nil, fmt.Errorf("unrecognized usage values: %q", unrecognized)
   168  	}
   169  
   170  	return keyUsage, sorted, nil
   171  }
   172  
   173  type sortedExtKeyUsage []x509.ExtKeyUsage
   174  
   175  func (s sortedExtKeyUsage) Len() int {
   176  	return len(s)
   177  }
   178  
   179  func (s sortedExtKeyUsage) Swap(i, j int) {
   180  	s[i], s[j] = s[j], s[i]
   181  }
   182  
   183  func (s sortedExtKeyUsage) Less(i, j int) bool {
   184  	return s[i] < s[j]
   185  }
   186  

View as plain text