k8s.io/client-go@v0.22.2/util/certificate/certificate_manager.go (about)

     1  /*
     2  Copyright 2017 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 certificate
    18  
    19  import (
    20  	"context"
    21  	"crypto/ecdsa"
    22  	"crypto/elliptic"
    23  	cryptorand "crypto/rand"
    24  	"crypto/tls"
    25  	"crypto/x509"
    26  	"encoding/pem"
    27  	"fmt"
    28  	"reflect"
    29  	"sync"
    30  	"time"
    31  
    32  	"k8s.io/klog/v2"
    33  
    34  	certificates "k8s.io/api/certificates/v1"
    35  	"k8s.io/apimachinery/pkg/api/errors"
    36  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    37  	"k8s.io/apimachinery/pkg/util/sets"
    38  	"k8s.io/apimachinery/pkg/util/wait"
    39  	clientset "k8s.io/client-go/kubernetes"
    40  	"k8s.io/client-go/util/cert"
    41  	"k8s.io/client-go/util/certificate/csr"
    42  	"k8s.io/client-go/util/keyutil"
    43  )
    44  
    45  // certificateWaitTimeout controls the amount of time we wait for certificate
    46  // approval in one iteration.
    47  var certificateWaitTimeout = 15 * time.Minute
    48  
    49  // Manager maintains and updates the certificates in use by this certificate
    50  // manager. In the background it communicates with the API server to get new
    51  // certificates for certificates about to expire.
    52  type Manager interface {
    53  	// Start the API server status sync loop.
    54  	Start()
    55  	// Stop the cert manager loop.
    56  	Stop()
    57  	// Current returns the currently selected certificate from the
    58  	// certificate manager, as well as the associated certificate and key data
    59  	// in PEM format.
    60  	Current() *tls.Certificate
    61  	// ServerHealthy returns true if the manager is able to communicate with
    62  	// the server. This allows a caller to determine whether the cert manager
    63  	// thinks it can potentially talk to the API server. The cert manager may
    64  	// be very conservative and only return true if recent communication has
    65  	// occurred with the server.
    66  	ServerHealthy() bool
    67  }
    68  
    69  // Config is the set of configuration parameters available for a new Manager.
    70  type Config struct {
    71  	// ClientsetFn will be used to create a clientset for
    72  	// creating/fetching new certificate requests generated when a key rotation occurs.
    73  	// The function will never be invoked in parallel.
    74  	// It is passed the current client certificate if one exists.
    75  	ClientsetFn ClientsetFunc
    76  	// Template is the CertificateRequest that will be used as a template for
    77  	// generating certificate signing requests for all new keys generated as
    78  	// part of rotation. It follows the same rules as the template parameter of
    79  	// crypto.x509.CreateCertificateRequest in the Go standard libraries.
    80  	Template *x509.CertificateRequest
    81  	// GetTemplate returns the CertificateRequest that will be used as a template for
    82  	// generating certificate signing requests for all new keys generated as
    83  	// part of rotation. It follows the same rules as the template parameter of
    84  	// crypto.x509.CreateCertificateRequest in the Go standard libraries.
    85  	// If no template is available, nil may be returned, and no certificate will be requested.
    86  	// If specified, takes precedence over Template.
    87  	GetTemplate func() *x509.CertificateRequest
    88  	// SignerName is the name of the certificate signer that should sign certificates
    89  	// generated by the manager.
    90  	SignerName string
    91  	// RequestedCertificateLifetime is the requested lifetime length for certificates generated by the manager.
    92  	// Optional.
    93  	// This will set the spec.expirationSeconds field on the CSR.  Controlling the lifetime of
    94  	// the issued certificate is not guaranteed as the signer may choose to ignore the request.
    95  	RequestedCertificateLifetime *time.Duration
    96  	// Usages is the types of usages that certificates generated by the manager
    97  	// can be used for.
    98  	Usages []certificates.KeyUsage
    99  	// CertificateStore is a persistent store where the current cert/key is
   100  	// kept and future cert/key pairs will be persisted after they are
   101  	// generated.
   102  	CertificateStore Store
   103  	// BootstrapCertificatePEM is the certificate data that will be returned
   104  	// from the Manager if the CertificateStore doesn't have any cert/key pairs
   105  	// currently available and has not yet had a chance to get a new cert/key
   106  	// pair from the API. If the CertificateStore does have a cert/key pair,
   107  	// this will be ignored. If there is no cert/key pair available in the
   108  	// CertificateStore, as soon as Start is called, it will request a new
   109  	// cert/key pair from the CertificateSigningRequestClient. This is intended
   110  	// to allow the first boot of a component to be initialized using a
   111  	// generic, multi-use cert/key pair which will be quickly replaced with a
   112  	// unique cert/key pair.
   113  	BootstrapCertificatePEM []byte
   114  	// BootstrapKeyPEM is the key data that will be returned from the Manager
   115  	// if the CertificateStore doesn't have any cert/key pairs currently
   116  	// available. If the CertificateStore does have a cert/key pair, this will
   117  	// be ignored. If the bootstrap cert/key pair are used, they will be
   118  	// rotated at the first opportunity, possibly well in advance of expiring.
   119  	// This is intended to allow the first boot of a component to be
   120  	// initialized using a generic, multi-use cert/key pair which will be
   121  	// quickly replaced with a unique cert/key pair.
   122  	BootstrapKeyPEM []byte `datapolicy:"security-key"`
   123  	// CertificateRotation will record a metric showing the time in seconds
   124  	// that certificates lived before being rotated. This metric is a histogram
   125  	// because there is value in keeping a history of rotation cadences. It
   126  	// allows one to setup monitoring and alerting of unexpected rotation
   127  	// behavior and track trends in rotation frequency.
   128  	CertificateRotation Histogram
   129  	// CertifcateRenewFailure will record a metric that keeps track of
   130  	// certificate renewal failures.
   131  	CertificateRenewFailure Counter
   132  	// Name is an optional string that will be used when writing log output
   133  	// or returning errors from manager methods. If not set, SignerName will
   134  	// be used, if SignerName is not set, if Usages includes client auth the
   135  	// name will be "client auth", otherwise the value will be "server".
   136  	Name string
   137  	// Logf is an optional function that log output will be sent to from the
   138  	// certificate manager. If not set it will use klog.V(2)
   139  	Logf func(format string, args ...interface{})
   140  }
   141  
   142  // Store is responsible for getting and updating the current certificate.
   143  // Depending on the concrete implementation, the backing store for this
   144  // behavior may vary.
   145  type Store interface {
   146  	// Current returns the currently selected certificate, as well as the
   147  	// associated certificate and key data in PEM format. If the Store doesn't
   148  	// have a cert/key pair currently, it should return a NoCertKeyError so
   149  	// that the Manager can recover by using bootstrap certificates to request
   150  	// a new cert/key pair.
   151  	Current() (*tls.Certificate, error)
   152  	// Update accepts the PEM data for the cert/key pair and makes the new
   153  	// cert/key pair the 'current' pair, that will be returned by future calls
   154  	// to Current().
   155  	Update(cert, key []byte) (*tls.Certificate, error)
   156  }
   157  
   158  // Gauge will record the remaining lifetime of the certificate each time it is
   159  // updated.
   160  type Gauge interface {
   161  	Set(float64)
   162  }
   163  
   164  // Histogram will record the time a rotated certificate was used before being
   165  // rotated.
   166  type Histogram interface {
   167  	Observe(float64)
   168  }
   169  
   170  // Counter will wrap a counter with labels
   171  type Counter interface {
   172  	Inc()
   173  }
   174  
   175  // NoCertKeyError indicates there is no cert/key currently available.
   176  type NoCertKeyError string
   177  
   178  // ClientsetFunc returns a new clientset for discovering CSR API availability and requesting CSRs.
   179  // It is passed the current certificate if one is available and valid.
   180  type ClientsetFunc func(current *tls.Certificate) (clientset.Interface, error)
   181  
   182  func (e *NoCertKeyError) Error() string { return string(*e) }
   183  
   184  type manager struct {
   185  	getTemplate func() *x509.CertificateRequest
   186  
   187  	// lastRequestLock guards lastRequestCancel and lastRequest
   188  	lastRequestLock   sync.Mutex
   189  	lastRequestCancel context.CancelFunc
   190  	lastRequest       *x509.CertificateRequest
   191  
   192  	dynamicTemplate              bool
   193  	signerName                   string
   194  	requestedCertificateLifetime *time.Duration
   195  	usages                       []certificates.KeyUsage
   196  	forceRotation                bool
   197  
   198  	certStore Store
   199  
   200  	certificateRotation     Histogram
   201  	certificateRenewFailure Counter
   202  
   203  	// the following variables must only be accessed under certAccessLock
   204  	certAccessLock sync.RWMutex
   205  	cert           *tls.Certificate
   206  	serverHealth   bool
   207  
   208  	// the clientFn must only be accessed under the clientAccessLock
   209  	clientAccessLock sync.Mutex
   210  	clientsetFn      ClientsetFunc
   211  	stopCh           chan struct{}
   212  	stopped          bool
   213  
   214  	// Set to time.Now but can be stubbed out for testing
   215  	now func() time.Time
   216  
   217  	name string
   218  	logf func(format string, args ...interface{})
   219  }
   220  
   221  // NewManager returns a new certificate manager. A certificate manager is
   222  // responsible for being the authoritative source of certificates in the
   223  // Kubelet and handling updates due to rotation.
   224  func NewManager(config *Config) (Manager, error) {
   225  	cert, forceRotation, err := getCurrentCertificateOrBootstrap(
   226  		config.CertificateStore,
   227  		config.BootstrapCertificatePEM,
   228  		config.BootstrapKeyPEM)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  
   233  	getTemplate := config.GetTemplate
   234  	if getTemplate == nil {
   235  		getTemplate = func() *x509.CertificateRequest { return config.Template }
   236  	}
   237  
   238  	m := manager{
   239  		stopCh:                       make(chan struct{}),
   240  		clientsetFn:                  config.ClientsetFn,
   241  		getTemplate:                  getTemplate,
   242  		dynamicTemplate:              config.GetTemplate != nil,
   243  		signerName:                   config.SignerName,
   244  		requestedCertificateLifetime: config.RequestedCertificateLifetime,
   245  		usages:                       config.Usages,
   246  		certStore:                    config.CertificateStore,
   247  		cert:                         cert,
   248  		forceRotation:                forceRotation,
   249  		certificateRotation:          config.CertificateRotation,
   250  		certificateRenewFailure:      config.CertificateRenewFailure,
   251  		now:                          time.Now,
   252  	}
   253  
   254  	name := config.Name
   255  	if len(name) == 0 {
   256  		name = m.signerName
   257  	}
   258  	if len(name) == 0 {
   259  		switch {
   260  		case hasKeyUsage(config.Usages, certificates.UsageClientAuth):
   261  			name = string(certificates.UsageClientAuth)
   262  		default:
   263  			name = "certificate"
   264  		}
   265  	}
   266  
   267  	m.name = name
   268  	m.logf = config.Logf
   269  	if m.logf == nil {
   270  		m.logf = func(format string, args ...interface{}) { klog.V(2).Infof(format, args...) }
   271  	}
   272  
   273  	return &m, nil
   274  }
   275  
   276  // Current returns the currently selected certificate from the certificate
   277  // manager. This can be nil if the manager was initialized without a
   278  // certificate and has not yet received one from the
   279  // CertificateSigningRequestClient, or if the current cert has expired.
   280  func (m *manager) Current() *tls.Certificate {
   281  	m.certAccessLock.RLock()
   282  	defer m.certAccessLock.RUnlock()
   283  	if m.cert != nil && m.cert.Leaf != nil && m.now().After(m.cert.Leaf.NotAfter) {
   284  		m.logf("%s: Current certificate is expired", m.name)
   285  		return nil
   286  	}
   287  	return m.cert
   288  }
   289  
   290  // ServerHealthy returns true if the cert manager believes the server
   291  // is currently alive.
   292  func (m *manager) ServerHealthy() bool {
   293  	m.certAccessLock.RLock()
   294  	defer m.certAccessLock.RUnlock()
   295  	return m.serverHealth
   296  }
   297  
   298  // Stop terminates the manager.
   299  func (m *manager) Stop() {
   300  	m.clientAccessLock.Lock()
   301  	defer m.clientAccessLock.Unlock()
   302  	if m.stopped {
   303  		return
   304  	}
   305  	close(m.stopCh)
   306  	m.stopped = true
   307  }
   308  
   309  // Start will start the background work of rotating the certificates.
   310  func (m *manager) Start() {
   311  	// Certificate rotation depends on access to the API server certificate
   312  	// signing API, so don't start the certificate manager if we don't have a
   313  	// client.
   314  	if m.clientsetFn == nil {
   315  		m.logf("%s: Certificate rotation is not enabled, no connection to the apiserver", m.name)
   316  		return
   317  	}
   318  	m.logf("%s: Certificate rotation is enabled", m.name)
   319  
   320  	templateChanged := make(chan struct{})
   321  	go wait.Until(func() {
   322  		deadline := m.nextRotationDeadline()
   323  		if sleepInterval := deadline.Sub(m.now()); sleepInterval > 0 {
   324  			m.logf("%s: Waiting %v for next certificate rotation", m.name, sleepInterval)
   325  
   326  			timer := time.NewTimer(sleepInterval)
   327  			defer timer.Stop()
   328  
   329  			select {
   330  			case <-timer.C:
   331  				// unblock when deadline expires
   332  			case <-templateChanged:
   333  				_, lastRequestTemplate := m.getLastRequest()
   334  				if reflect.DeepEqual(lastRequestTemplate, m.getTemplate()) {
   335  					// if the template now matches what we last requested, restart the rotation deadline loop
   336  					return
   337  				}
   338  				m.logf("%s: Certificate template changed, rotating", m.name)
   339  			}
   340  		}
   341  
   342  		// Don't enter rotateCerts and trigger backoff if we don't even have a template to request yet
   343  		if m.getTemplate() == nil {
   344  			return
   345  		}
   346  
   347  		backoff := wait.Backoff{
   348  			Duration: 2 * time.Second,
   349  			Factor:   2,
   350  			Jitter:   0.1,
   351  			Steps:    5,
   352  		}
   353  		if err := wait.ExponentialBackoff(backoff, m.rotateCerts); err != nil {
   354  			utilruntime.HandleError(fmt.Errorf("%s: Reached backoff limit, still unable to rotate certs: %v", m.name, err))
   355  			wait.PollInfinite(32*time.Second, m.rotateCerts)
   356  		}
   357  	}, time.Second, m.stopCh)
   358  
   359  	if m.dynamicTemplate {
   360  		go wait.Until(func() {
   361  			// check if the current template matches what we last requested
   362  			lastRequestCancel, lastRequestTemplate := m.getLastRequest()
   363  
   364  			if !m.certSatisfiesTemplate() && !reflect.DeepEqual(lastRequestTemplate, m.getTemplate()) {
   365  				// if the template is different, queue up an interrupt of the rotation deadline loop.
   366  				// if we've requested a CSR that matches the new template by the time the interrupt is handled, the interrupt is disregarded.
   367  				if lastRequestCancel != nil {
   368  					// if we're currently waiting on a submitted request that no longer matches what we want, stop waiting
   369  					lastRequestCancel()
   370  				}
   371  				select {
   372  				case templateChanged <- struct{}{}:
   373  				case <-m.stopCh:
   374  				}
   375  			}
   376  		}, time.Second, m.stopCh)
   377  	}
   378  }
   379  
   380  func getCurrentCertificateOrBootstrap(
   381  	store Store,
   382  	bootstrapCertificatePEM []byte,
   383  	bootstrapKeyPEM []byte) (cert *tls.Certificate, shouldRotate bool, errResult error) {
   384  
   385  	currentCert, err := store.Current()
   386  	if err == nil {
   387  		// if the current cert is expired, fall back to the bootstrap cert
   388  		if currentCert.Leaf != nil && time.Now().Before(currentCert.Leaf.NotAfter) {
   389  			return currentCert, false, nil
   390  		}
   391  	} else {
   392  		if _, ok := err.(*NoCertKeyError); !ok {
   393  			return nil, false, err
   394  		}
   395  	}
   396  
   397  	if bootstrapCertificatePEM == nil || bootstrapKeyPEM == nil {
   398  		return nil, true, nil
   399  	}
   400  
   401  	bootstrapCert, err := tls.X509KeyPair(bootstrapCertificatePEM, bootstrapKeyPEM)
   402  	if err != nil {
   403  		return nil, false, err
   404  	}
   405  	if len(bootstrapCert.Certificate) < 1 {
   406  		return nil, false, fmt.Errorf("no cert/key data found")
   407  	}
   408  
   409  	certs, err := x509.ParseCertificates(bootstrapCert.Certificate[0])
   410  	if err != nil {
   411  		return nil, false, fmt.Errorf("unable to parse certificate data: %v", err)
   412  	}
   413  	if len(certs) < 1 {
   414  		return nil, false, fmt.Errorf("no cert data found")
   415  	}
   416  	bootstrapCert.Leaf = certs[0]
   417  
   418  	if _, err := store.Update(bootstrapCertificatePEM, bootstrapKeyPEM); err != nil {
   419  		utilruntime.HandleError(fmt.Errorf("Unable to set the cert/key pair to the bootstrap certificate: %v", err))
   420  	}
   421  
   422  	return &bootstrapCert, true, nil
   423  }
   424  
   425  func (m *manager) getClientset() (clientset.Interface, error) {
   426  	current := m.Current()
   427  	m.clientAccessLock.Lock()
   428  	defer m.clientAccessLock.Unlock()
   429  	return m.clientsetFn(current)
   430  }
   431  
   432  // RotateCerts is exposed for testing only and is not a part of the public interface.
   433  // Returns true if it changed the cert, false otherwise. Error is only returned in
   434  // exceptional cases.
   435  func (m *manager) RotateCerts() (bool, error) {
   436  	return m.rotateCerts()
   437  }
   438  
   439  // rotateCerts attempts to request a client cert from the server, wait a reasonable
   440  // period of time for it to be signed, and then update the cert on disk. If it cannot
   441  // retrieve a cert, it will return false. It will only return error in exceptional cases.
   442  // This method also keeps track of "server health" by interpreting the responses it gets
   443  // from the server on the various calls it makes.
   444  // TODO: return errors, have callers handle and log them correctly
   445  func (m *manager) rotateCerts() (bool, error) {
   446  	m.logf("%s: Rotating certificates", m.name)
   447  
   448  	template, csrPEM, keyPEM, privateKey, err := m.generateCSR()
   449  	if err != nil {
   450  		utilruntime.HandleError(fmt.Errorf("%s: Unable to generate a certificate signing request: %v", m.name, err))
   451  		if m.certificateRenewFailure != nil {
   452  			m.certificateRenewFailure.Inc()
   453  		}
   454  		return false, nil
   455  	}
   456  
   457  	// request the client each time
   458  	clientSet, err := m.getClientset()
   459  	if err != nil {
   460  		utilruntime.HandleError(fmt.Errorf("%s: Unable to load a client to request certificates: %v", m.name, err))
   461  		if m.certificateRenewFailure != nil {
   462  			m.certificateRenewFailure.Inc()
   463  		}
   464  		return false, nil
   465  	}
   466  
   467  	// Call the Certificate Signing Request API to get a certificate for the
   468  	// new private key.
   469  	reqName, reqUID, err := csr.RequestCertificate(clientSet, csrPEM, "", m.signerName, m.requestedCertificateLifetime, m.usages, privateKey)
   470  	if err != nil {
   471  		utilruntime.HandleError(fmt.Errorf("%s: Failed while requesting a signed certificate from the control plane: %v", m.name, err))
   472  		if m.certificateRenewFailure != nil {
   473  			m.certificateRenewFailure.Inc()
   474  		}
   475  		return false, m.updateServerError(err)
   476  	}
   477  
   478  	ctx, cancel := context.WithTimeout(context.Background(), certificateWaitTimeout)
   479  	defer cancel()
   480  
   481  	// Once we've successfully submitted a CSR for this template, record that we did so
   482  	m.setLastRequest(cancel, template)
   483  
   484  	// Wait for the certificate to be signed. This interface and internal timout
   485  	// is a remainder after the old design using raw watch wrapped with backoff.
   486  	crtPEM, err := csr.WaitForCertificate(ctx, clientSet, reqName, reqUID)
   487  	if err != nil {
   488  		utilruntime.HandleError(fmt.Errorf("%s: certificate request was not signed: %v", m.name, err))
   489  		if m.certificateRenewFailure != nil {
   490  			m.certificateRenewFailure.Inc()
   491  		}
   492  		return false, nil
   493  	}
   494  
   495  	cert, err := m.certStore.Update(crtPEM, keyPEM)
   496  	if err != nil {
   497  		utilruntime.HandleError(fmt.Errorf("%s: Unable to store the new cert/key pair: %v", m.name, err))
   498  		if m.certificateRenewFailure != nil {
   499  			m.certificateRenewFailure.Inc()
   500  		}
   501  		return false, nil
   502  	}
   503  
   504  	if old := m.updateCached(cert); old != nil && m.certificateRotation != nil {
   505  		m.certificateRotation.Observe(m.now().Sub(old.Leaf.NotBefore).Seconds())
   506  	}
   507  
   508  	return true, nil
   509  }
   510  
   511  // Check that the current certificate on disk satisfies the requests from the
   512  // current template.
   513  //
   514  // Note that extra items in the certificate's SAN or orgs that don't exist in
   515  // the template will not trigger a renewal.
   516  //
   517  // Requires certAccessLock to be locked.
   518  func (m *manager) certSatisfiesTemplateLocked() bool {
   519  	if m.cert == nil {
   520  		return false
   521  	}
   522  
   523  	if template := m.getTemplate(); template != nil {
   524  		if template.Subject.CommonName != m.cert.Leaf.Subject.CommonName {
   525  			m.logf("%s: Current certificate CN (%s) does not match requested CN (%s)", m.name, m.cert.Leaf.Subject.CommonName, template.Subject.CommonName)
   526  			return false
   527  		}
   528  
   529  		currentDNSNames := sets.NewString(m.cert.Leaf.DNSNames...)
   530  		desiredDNSNames := sets.NewString(template.DNSNames...)
   531  		missingDNSNames := desiredDNSNames.Difference(currentDNSNames)
   532  		if len(missingDNSNames) > 0 {
   533  			m.logf("%s: Current certificate is missing requested DNS names %v", m.name, missingDNSNames.List())
   534  			return false
   535  		}
   536  
   537  		currentIPs := sets.NewString()
   538  		for _, ip := range m.cert.Leaf.IPAddresses {
   539  			currentIPs.Insert(ip.String())
   540  		}
   541  		desiredIPs := sets.NewString()
   542  		for _, ip := range template.IPAddresses {
   543  			desiredIPs.Insert(ip.String())
   544  		}
   545  		missingIPs := desiredIPs.Difference(currentIPs)
   546  		if len(missingIPs) > 0 {
   547  			m.logf("%s: Current certificate is missing requested IP addresses %v", m.name, missingIPs.List())
   548  			return false
   549  		}
   550  
   551  		currentOrgs := sets.NewString(m.cert.Leaf.Subject.Organization...)
   552  		desiredOrgs := sets.NewString(template.Subject.Organization...)
   553  		missingOrgs := desiredOrgs.Difference(currentOrgs)
   554  		if len(missingOrgs) > 0 {
   555  			m.logf("%s: Current certificate is missing requested orgs %v", m.name, missingOrgs.List())
   556  			return false
   557  		}
   558  	}
   559  
   560  	return true
   561  }
   562  
   563  func (m *manager) certSatisfiesTemplate() bool {
   564  	m.certAccessLock.RLock()
   565  	defer m.certAccessLock.RUnlock()
   566  	return m.certSatisfiesTemplateLocked()
   567  }
   568  
   569  // nextRotationDeadline returns a value for the threshold at which the
   570  // current certificate should be rotated, 80%+/-10% of the expiration of the
   571  // certificate.
   572  func (m *manager) nextRotationDeadline() time.Time {
   573  	// forceRotation is not protected by locks
   574  	if m.forceRotation {
   575  		m.forceRotation = false
   576  		return m.now()
   577  	}
   578  
   579  	m.certAccessLock.RLock()
   580  	defer m.certAccessLock.RUnlock()
   581  
   582  	if !m.certSatisfiesTemplateLocked() {
   583  		return m.now()
   584  	}
   585  
   586  	notAfter := m.cert.Leaf.NotAfter
   587  	totalDuration := float64(notAfter.Sub(m.cert.Leaf.NotBefore))
   588  	deadline := m.cert.Leaf.NotBefore.Add(jitteryDuration(totalDuration))
   589  
   590  	m.logf("%s: Certificate expiration is %v, rotation deadline is %v", m.name, notAfter, deadline)
   591  	return deadline
   592  }
   593  
   594  // jitteryDuration uses some jitter to set the rotation threshold so each node
   595  // will rotate at approximately 70-90% of the total lifetime of the
   596  // certificate.  With jitter, if a number of nodes are added to a cluster at
   597  // approximately the same time (such as cluster creation time), they won't all
   598  // try to rotate certificates at the same time for the rest of the life of the
   599  // cluster.
   600  //
   601  // This function is represented as a variable to allow replacement during testing.
   602  var jitteryDuration = func(totalDuration float64) time.Duration {
   603  	return wait.Jitter(time.Duration(totalDuration), 0.2) - time.Duration(totalDuration*0.3)
   604  }
   605  
   606  // updateCached sets the most recent retrieved cert and returns the old cert.
   607  // It also sets the server as assumed healthy.
   608  func (m *manager) updateCached(cert *tls.Certificate) *tls.Certificate {
   609  	m.certAccessLock.Lock()
   610  	defer m.certAccessLock.Unlock()
   611  	m.serverHealth = true
   612  	old := m.cert
   613  	m.cert = cert
   614  	return old
   615  }
   616  
   617  // updateServerError takes an error returned by the server and infers
   618  // the health of the server based on the error. It will return nil if
   619  // the error does not require immediate termination of any wait loops,
   620  // and otherwise it will return the error.
   621  func (m *manager) updateServerError(err error) error {
   622  	m.certAccessLock.Lock()
   623  	defer m.certAccessLock.Unlock()
   624  	switch {
   625  	case errors.IsUnauthorized(err):
   626  		// SSL terminating proxies may report this error instead of the master
   627  		m.serverHealth = true
   628  	case errors.IsUnexpectedServerError(err):
   629  		// generally indicates a proxy or other load balancer problem, rather than a problem coming
   630  		// from the master
   631  		m.serverHealth = false
   632  	default:
   633  		// Identify known errors that could be expected for a cert request that
   634  		// indicate everything is working normally
   635  		m.serverHealth = errors.IsNotFound(err) || errors.IsForbidden(err)
   636  	}
   637  	return nil
   638  }
   639  
   640  func (m *manager) generateCSR() (template *x509.CertificateRequest, csrPEM []byte, keyPEM []byte, key interface{}, err error) {
   641  	// Generate a new private key.
   642  	privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
   643  	if err != nil {
   644  		return nil, nil, nil, nil, fmt.Errorf("%s: unable to generate a new private key: %v", m.name, err)
   645  	}
   646  	der, err := x509.MarshalECPrivateKey(privateKey)
   647  	if err != nil {
   648  		return nil, nil, nil, nil, fmt.Errorf("%s: unable to marshal the new key to DER: %v", m.name, err)
   649  	}
   650  
   651  	keyPEM = pem.EncodeToMemory(&pem.Block{Type: keyutil.ECPrivateKeyBlockType, Bytes: der})
   652  
   653  	template = m.getTemplate()
   654  	if template == nil {
   655  		return nil, nil, nil, nil, fmt.Errorf("%s: unable to create a csr, no template available", m.name)
   656  	}
   657  	csrPEM, err = cert.MakeCSRFromTemplate(privateKey, template)
   658  	if err != nil {
   659  		return nil, nil, nil, nil, fmt.Errorf("%s: unable to create a csr from the private key: %v", m.name, err)
   660  	}
   661  	return template, csrPEM, keyPEM, privateKey, nil
   662  }
   663  
   664  func (m *manager) getLastRequest() (context.CancelFunc, *x509.CertificateRequest) {
   665  	m.lastRequestLock.Lock()
   666  	defer m.lastRequestLock.Unlock()
   667  	return m.lastRequestCancel, m.lastRequest
   668  }
   669  
   670  func (m *manager) setLastRequest(cancel context.CancelFunc, r *x509.CertificateRequest) {
   671  	m.lastRequestLock.Lock()
   672  	defer m.lastRequestLock.Unlock()
   673  	m.lastRequestCancel = cancel
   674  	m.lastRequest = r
   675  }
   676  
   677  func hasKeyUsage(usages []certificates.KeyUsage, usage certificates.KeyUsage) bool {
   678  	for _, u := range usages {
   679  		if u == usage {
   680  			return true
   681  		}
   682  	}
   683  	return false
   684  }