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 }