github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/ca/certificates.go (about) 1 package ca 2 3 import ( 4 "bytes" 5 "context" 6 "crypto" 7 "crypto/ecdsa" 8 "crypto/elliptic" 9 cryptorand "crypto/rand" 10 "crypto/rsa" 11 "crypto/tls" 12 "crypto/x509" 13 "encoding/asn1" 14 "encoding/pem" 15 "fmt" 16 "io" 17 "io/ioutil" 18 "os" 19 "path/filepath" 20 "time" 21 22 cfcsr "github.com/cloudflare/cfssl/csr" 23 "github.com/cloudflare/cfssl/helpers" 24 "github.com/cloudflare/cfssl/initca" 25 cflog "github.com/cloudflare/cfssl/log" 26 cfsigner "github.com/cloudflare/cfssl/signer" 27 "github.com/cloudflare/cfssl/signer/local" 28 "github.com/docker/go-events" 29 "github.com/docker/swarmkit/api" 30 "github.com/docker/swarmkit/ca/pkcs8" 31 "github.com/docker/swarmkit/connectionbroker" 32 "github.com/docker/swarmkit/ioutils" 33 "github.com/opencontainers/go-digest" 34 "github.com/pkg/errors" 35 "google.golang.org/grpc" 36 "google.golang.org/grpc/codes" 37 "google.golang.org/grpc/credentials" 38 "google.golang.org/grpc/status" 39 ) 40 41 const ( 42 // Security Strength Equivalence 43 //----------------------------------- 44 //| ECC | DH/DSA/RSA | 45 //| 256 | 3072 | 46 //| 384 | 7680 | 47 //----------------------------------- 48 49 // RootKeySize is the default size of the root CA key 50 // It would be ideal for the root key to use P-384, but in P-384 is not optimized in go yet :( 51 RootKeySize = 256 52 // RootKeyAlgo defines the default algorithm for the root CA Key 53 RootKeyAlgo = "ecdsa" 54 // RootCAExpiration represents the default expiration for the root CA in seconds (20 years) 55 RootCAExpiration = "630720000s" 56 // DefaultNodeCertExpiration represents the default expiration for node certificates (3 months) 57 DefaultNodeCertExpiration = 2160 * time.Hour 58 // CertBackdate represents the amount of time each certificate is backdated to try to avoid 59 // clock drift issues. 60 CertBackdate = 1 * time.Hour 61 // CertLowerRotationRange represents the minimum fraction of time that we will wait when randomly 62 // choosing our next certificate rotation 63 CertLowerRotationRange = 0.5 64 // CertUpperRotationRange represents the maximum fraction of time that we will wait when randomly 65 // choosing our next certificate rotation 66 CertUpperRotationRange = 0.8 67 // MinNodeCertExpiration represents the minimum expiration for node certificates 68 MinNodeCertExpiration = 1 * time.Hour 69 ) 70 71 // BasicConstraintsOID is the ASN1 Object ID indicating a basic constraints extension 72 var BasicConstraintsOID = asn1.ObjectIdentifier{2, 5, 29, 19} 73 74 // A recoverableErr is a non-fatal error encountered signing a certificate, 75 // which means that the certificate issuance may be retried at a later time. 76 type recoverableErr struct { 77 err error 78 } 79 80 func (r recoverableErr) Error() string { 81 return r.err.Error() 82 } 83 84 // ErrNoLocalRootCA is an error type used to indicate that the local root CA 85 // certificate file does not exist. 86 var ErrNoLocalRootCA = errors.New("local root CA certificate does not exist") 87 88 // ErrNoValidSigner is an error type used to indicate that our RootCA doesn't have the ability to 89 // sign certificates. 90 var ErrNoValidSigner = recoverableErr{err: errors.New("no valid signer found")} 91 92 func init() { 93 cflog.Level = 5 94 } 95 96 // CertPaths is a helper struct that keeps track of the paths of a 97 // Cert and corresponding Key 98 type CertPaths struct { 99 Cert, Key string 100 } 101 102 // IssuerInfo contains the subject and public key of the issuer of a certificate 103 type IssuerInfo struct { 104 Subject []byte 105 PublicKey []byte 106 } 107 108 // LocalSigner is a signer that can sign CSRs 109 type LocalSigner struct { 110 cfsigner.Signer 111 112 // Key will only be used by the original manager to put the private 113 // key-material in raft, no signing operations depend on it. 114 Key []byte 115 116 // Cert is one PEM encoded Certificate used as the signing CA. It must correspond to the key. 117 Cert []byte 118 119 // just cached parsed values for validation, etc. 120 parsedCert *x509.Certificate 121 cryptoSigner crypto.Signer 122 } 123 124 type x509UnknownAuthError struct { 125 error 126 failedLeafCert *x509.Certificate 127 } 128 129 // RootCA is the representation of everything we need to sign certificates and/or to verify certificates 130 // 131 // RootCA.Cert: [CA cert1][CA cert2] 132 // RootCA.Intermediates: [intermediate CA1][intermediate CA2][intermediate CA3] 133 // RootCA.signer.Cert: [signing CA cert] 134 // RootCA.signer.Key: [signing CA key] 135 // 136 // Requirements: 137 // 138 // - [signing CA key] must be the private key for [signing CA cert], and either both or none must be provided 139 // 140 // - [intermediate CA1] must have the same public key and subject as [signing CA cert], because otherwise when 141 // appended to a leaf certificate, the intermediates will not form a chain (because [intermediate CA1] won't because 142 // the signer of the leaf certificate) 143 // - [intermediate CA1] must be signed by [intermediate CA2], which must be signed by [intermediate CA3] 144 // 145 // - When we issue a certificate, the intermediates will be appended so that the certificate looks like: 146 // [leaf signed by signing CA cert][intermediate CA1][intermediate CA2][intermediate CA3] 147 // - [leaf signed by signing CA cert][intermediate CA1][intermediate CA2][intermediate CA3] is guaranteed to form a 148 // valid chain from [leaf signed by signing CA cert] to one of the root certs ([signing CA cert], [CA cert1], [CA cert2]) 149 // using zero or more of the intermediate certs ([intermediate CA1][intermediate CA2][intermediate CA3]) as intermediates 150 // 151 // Example 1: Simple root rotation 152 // - Initial state: 153 // - RootCA.Cert: [Root CA1 self-signed] 154 // - RootCA.Intermediates: [] 155 // - RootCA.signer.Cert: [Root CA1 self-signed] 156 // - Issued TLS cert: [leaf signed by Root CA1] 157 // 158 // - Intermediate state (during root rotation): 159 // - RootCA.Cert: [Root CA1 self-signed] 160 // - RootCA.Intermediates: [Root CA2 signed by Root CA1] 161 // - RootCA.signer.Cert: [Root CA2 signed by Root CA1] 162 // - Issued TLS cert: [leaf signed by Root CA2][Root CA2 signed by Root CA1] 163 // 164 // - Final state: 165 // - RootCA.Cert: [Root CA2 self-signed] 166 // - RootCA.Intermediates: [] 167 // - RootCA.signer.Cert: [Root CA2 self-signed] 168 // - Issued TLS cert: [leaf signed by Root CA2] 169 // 170 type RootCA struct { 171 // Certs contains a bundle of self-signed, PEM encoded certificates for the Root CA to be used 172 // as the root of trust. 173 Certs []byte 174 175 // Intermediates contains a bundle of PEM encoded intermediate CA certificates to append to any 176 // issued TLS (leaf) certificates. The first one must have the same public key and subject as the 177 // signing root certificate, and the rest must form a chain, each one certifying the one above it, 178 // as per RFC5246 section 7.4.2. 179 Intermediates []byte 180 181 // Pool is the root pool used to validate TLS certificates 182 Pool *x509.CertPool 183 184 // Digest of the serialized bytes of the certificate(s) 185 Digest digest.Digest 186 187 // This signer will be nil if the node doesn't have the appropriate key material 188 signer *LocalSigner 189 } 190 191 // Signer is an accessor for the local signer that returns an error if this root cannot sign. 192 func (rca *RootCA) Signer() (*LocalSigner, error) { 193 if rca.Pool == nil || rca.signer == nil || len(rca.signer.Cert) == 0 || rca.signer.Signer == nil { 194 return nil, ErrNoValidSigner 195 } 196 197 return rca.signer, nil 198 } 199 200 // IssueAndSaveNewCertificates generates a new key-pair, signs it with the local root-ca, and returns a 201 // TLS certificate and the issuer information for the certificate. 202 func (rca *RootCA) IssueAndSaveNewCertificates(kw KeyWriter, cn, ou, org string) (*tls.Certificate, *IssuerInfo, error) { 203 csr, key, err := GenerateNewCSR() 204 if err != nil { 205 return nil, nil, errors.Wrap(err, "error when generating new node certs") 206 } 207 208 // Obtain a signed Certificate 209 certChain, err := rca.ParseValidateAndSignCSR(csr, cn, ou, org) 210 if err != nil { 211 return nil, nil, errors.Wrap(err, "failed to sign node certificate") 212 } 213 signer, err := rca.Signer() 214 if err != nil { // should never happen, since if ParseValidateAndSignCSR did not fail this root CA must have a signer 215 return nil, nil, err 216 } 217 218 // Create a valid TLSKeyPair out of the PEM encoded private key and certificate 219 tlsKeyPair, err := tls.X509KeyPair(certChain, key) 220 if err != nil { 221 return nil, nil, err 222 } 223 224 if err := kw.Write(NormalizePEMs(certChain), key, nil); err != nil { 225 return nil, nil, err 226 } 227 228 return &tlsKeyPair, &IssuerInfo{ 229 PublicKey: signer.parsedCert.RawSubjectPublicKeyInfo, 230 Subject: signer.parsedCert.RawSubject, 231 }, nil 232 } 233 234 // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is 235 // available, or by requesting them from the remote server at remoteAddr. This function returns the TLS 236 // certificate and the issuer information for the certificate. 237 func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWriter, config CertificateRequestConfig) (*tls.Certificate, *IssuerInfo, error) { 238 // Create a new key/pair and CSR 239 csr, key, err := GenerateNewCSR() 240 if err != nil { 241 return nil, nil, errors.Wrap(err, "error when generating new node certs") 242 } 243 244 // Get the remote manager to issue a CA signed certificate for this node 245 // Retry up to 5 times in case the manager we first try to contact isn't 246 // responding properly (for example, it may have just been demoted). 247 var signedCert []byte 248 for i := 0; i != 5; i++ { 249 signedCert, err = GetRemoteSignedCertificate(ctx, csr, rca.Pool, config) 250 if err == nil { 251 break 252 } 253 254 // If the first attempt fails, we should try a remote 255 // connection. The local node may be a manager that was 256 // demoted, so the local connection (which is preferred) may 257 // not work. If we are successful in renewing the certificate, 258 // the local connection will not be returned by the connection 259 // broker anymore. 260 config.ForceRemote = true 261 262 // Wait a moment, in case a leader election was taking place. 263 select { 264 case <-time.After(config.RetryInterval): 265 case <-ctx.Done(): 266 return nil, nil, ctx.Err() 267 } 268 } 269 if err != nil { 270 return nil, nil, err 271 } 272 273 // Доверяй, но проверяй. 274 // Before we overwrite our local key + certificate, let's make sure the server gave us one that is valid 275 // Create an X509Cert so we can .Verify() 276 // Check to see if this certificate was signed by our CA, and isn't expired 277 parsedCerts, chains, err := ValidateCertChain(rca.Pool, signedCert, false) 278 // TODO(cyli): - right now we need the invalid certificate in order to determine whether or not we should 279 // download a new root, because we only want to do that in the case of workers. When we have a single 280 // codepath for updating the root CAs for both managers and workers, this snippet can go. 281 if _, ok := err.(x509.UnknownAuthorityError); ok { 282 if parsedCerts, parseErr := helpers.ParseCertificatesPEM(signedCert); parseErr == nil && len(parsedCerts) > 0 { 283 return nil, nil, x509UnknownAuthError{ 284 error: err, 285 failedLeafCert: parsedCerts[0], 286 } 287 } 288 } 289 if err != nil { 290 return nil, nil, err 291 } 292 293 // ValidateChain, if successful, will always return at least 1 parsed cert and at least 1 chain containing 294 // at least 2 certificates: the leaf and the root. 295 leafCert := parsedCerts[0] 296 issuer := chains[0][1] 297 298 // Create a valid TLSKeyPair out of the PEM encoded private key and certificate 299 tlsKeyPair, err := tls.X509KeyPair(signedCert, key) 300 if err != nil { 301 return nil, nil, err 302 } 303 304 var kekUpdate *KEKData 305 for i := 0; i < 5; i++ { 306 // ValidateCertChain will always return at least 1 cert, so indexing at 0 is safe 307 kekUpdate, err = rca.getKEKUpdate(ctx, leafCert, tlsKeyPair, config) 308 if err == nil { 309 break 310 } 311 312 config.ForceRemote = true 313 314 // Wait a moment, in case a leader election was taking place. 315 select { 316 case <-time.After(config.RetryInterval): 317 case <-ctx.Done(): 318 return nil, nil, ctx.Err() 319 } 320 } 321 if err != nil { 322 return nil, nil, err 323 } 324 325 if err := kw.Write(NormalizePEMs(signedCert), key, kekUpdate); err != nil { 326 return nil, nil, err 327 } 328 329 return &tlsKeyPair, &IssuerInfo{ 330 PublicKey: issuer.RawSubjectPublicKeyInfo, 331 Subject: issuer.RawSubject, 332 }, nil 333 } 334 335 func (rca *RootCA) getKEKUpdate(ctx context.Context, leafCert *x509.Certificate, keypair tls.Certificate, config CertificateRequestConfig) (*KEKData, error) { 336 var managerRole bool 337 for _, ou := range leafCert.Subject.OrganizationalUnit { 338 if ou == ManagerRole { 339 managerRole = true 340 break 341 } 342 } 343 344 if managerRole { 345 mtlsCreds := credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rca.Pool, Certificates: []tls.Certificate{keypair}}) 346 conn, err := getGRPCConnection(mtlsCreds, config.ConnBroker, config.ForceRemote) 347 if err != nil { 348 return nil, err 349 } 350 351 client := api.NewCAClient(conn.ClientConn) 352 ctx, cancel := context.WithTimeout(ctx, 5*time.Second) 353 defer cancel() 354 response, err := client.GetUnlockKey(ctx, &api.GetUnlockKeyRequest{}) 355 if err != nil { 356 s, _ := status.FromError(err) 357 if s.Code() == codes.Unimplemented { // if the server does not support keks, return as if no encryption key was specified 358 conn.Close(true) 359 return &KEKData{}, nil 360 } 361 362 conn.Close(false) 363 return nil, err 364 } 365 conn.Close(true) 366 return &KEKData{KEK: response.UnlockKey, Version: response.Version.Index}, nil 367 } 368 369 // If this is a worker, set to never encrypt. We always want to set to the lock key to nil, 370 // in case this was a manager that was demoted to a worker. 371 return &KEKData{}, nil 372 } 373 374 // PrepareCSR creates a CFSSL Sign Request based on the given raw CSR and 375 // overrides the Subject and Hosts with the given extra args. 376 func PrepareCSR(csrBytes []byte, cn, ou, org string) cfsigner.SignRequest { 377 // All managers get added the subject-alt-name of CA, so they can be 378 // used for cert issuance. 379 hosts := []string{ou, cn} 380 if ou == ManagerRole { 381 hosts = append(hosts, CARole) 382 } 383 384 return cfsigner.SignRequest{ 385 Request: string(csrBytes), 386 // OU is used for Authentication of the node type. The CN has the random 387 // node ID. 388 Subject: &cfsigner.Subject{CN: cn, Names: []cfcsr.Name{{OU: ou, O: org}}}, 389 // Adding ou as DNS alt name, so clients can connect to ManagerRole and CARole 390 Hosts: hosts, 391 } 392 } 393 394 // ParseValidateAndSignCSR returns a signed certificate from a particular rootCA and a CSR. 395 func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string) ([]byte, error) { 396 signRequest := PrepareCSR(csrBytes, cn, ou, org) 397 signer, err := rca.Signer() 398 if err != nil { 399 return nil, err 400 } 401 cert, err := signer.Sign(signRequest) 402 if err != nil { 403 return nil, errors.Wrap(err, "failed to sign node certificate") 404 } 405 406 return append(cert, rca.Intermediates...), nil 407 } 408 409 // CrossSignCACertificate takes a CA root certificate and generates an intermediate CA from it signed with the current root signer 410 func (rca *RootCA) CrossSignCACertificate(otherCAPEM []byte) ([]byte, error) { 411 signer, err := rca.Signer() 412 if err != nil { 413 return nil, err 414 } 415 416 // create a new cert with exactly the same parameters, including the public key and exact NotBefore and NotAfter 417 template, err := helpers.ParseCertificatePEM(otherCAPEM) 418 if err != nil { 419 return nil, errors.New("could not parse new CA certificate") 420 } 421 422 if !template.IsCA { 423 return nil, errors.New("certificate not a CA") 424 } 425 426 template.SignatureAlgorithm = signer.parsedCert.SignatureAlgorithm // make sure we can sign with the signer key 427 derBytes, err := x509.CreateCertificate(cryptorand.Reader, template, signer.parsedCert, template.PublicKey, signer.cryptoSigner) 428 if err != nil { 429 return nil, errors.Wrap(err, "could not cross-sign new CA certificate using old CA material") 430 } 431 432 return pem.EncodeToMemory(&pem.Block{ 433 Type: "CERTIFICATE", 434 Bytes: derBytes, 435 }), nil 436 } 437 438 func validateSignatureAlgorithm(cert *x509.Certificate) error { 439 switch cert.SignatureAlgorithm { 440 case x509.SHA256WithRSA, x509.SHA384WithRSA, x509.SHA512WithRSA, x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512: 441 return nil 442 default: 443 return fmt.Errorf("unsupported signature algorithm: %s", cert.SignatureAlgorithm.String()) 444 } 445 } 446 447 // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte 448 // slices. key may be nil, and in this case NewRootCA will return a RootCA 449 // without a signer. 450 func NewRootCA(rootCertBytes, signCertBytes, signKeyBytes []byte, certExpiry time.Duration, intermediates []byte) (RootCA, error) { 451 // Parse all the certificates in the cert bundle 452 parsedCerts, err := helpers.ParseCertificatesPEM(rootCertBytes) 453 if err != nil { 454 return RootCA{}, errors.Wrap(err, "invalid root certificates") 455 } 456 // Check to see if we have at least one valid cert 457 if len(parsedCerts) < 1 { 458 return RootCA{}, errors.New("no valid root CA certificates found") 459 } 460 461 // Create a Pool with all of the certificates found 462 pool := x509.NewCertPool() 463 for _, cert := range parsedCerts { 464 if err := validateSignatureAlgorithm(cert); err != nil { 465 return RootCA{}, err 466 } 467 // Check to see if all of the certificates are valid, self-signed root CA certs 468 selfpool := x509.NewCertPool() 469 selfpool.AddCert(cert) 470 if _, err := cert.Verify(x509.VerifyOptions{Roots: selfpool}); err != nil { 471 return RootCA{}, errors.Wrap(err, "error while validating Root CA Certificate") 472 } 473 pool.AddCert(cert) 474 } 475 476 // Calculate the digest for our Root CA bundle 477 digest := digest.FromBytes(rootCertBytes) 478 479 // The intermediates supplied must be able to chain up to the root certificates, so that when they are appended to 480 // a leaf certificate, the leaf certificate can be validated through the intermediates to the root certificates. 481 var intermediatePool *x509.CertPool 482 var parsedIntermediates []*x509.Certificate 483 if len(intermediates) > 0 { 484 parsedIntermediates, _, err = ValidateCertChain(pool, intermediates, false) 485 if err != nil { 486 return RootCA{}, errors.Wrap(err, "invalid intermediate chain") 487 } 488 intermediatePool = x509.NewCertPool() 489 for _, cert := range parsedIntermediates { 490 intermediatePool.AddCert(cert) 491 } 492 } 493 494 var localSigner *LocalSigner 495 if len(signKeyBytes) != 0 || len(signCertBytes) != 0 { 496 localSigner, err = newLocalSigner(signKeyBytes, signCertBytes, certExpiry, pool, intermediatePool) 497 if err != nil { 498 return RootCA{}, err 499 } 500 501 // If a signer is provided and there are intermediates, then either the first intermediate would be the signer CA 502 // certificate (in which case it'd have the same subject and public key), or it would be a cross-signed 503 // intermediate with the same subject and public key as our signing CA certificate (which could be either an 504 // intermediate cert or a self-signed root cert). 505 if len(parsedIntermediates) > 0 && (!bytes.Equal(parsedIntermediates[0].RawSubject, localSigner.parsedCert.RawSubject) || 506 !bytes.Equal(parsedIntermediates[0].RawSubjectPublicKeyInfo, localSigner.parsedCert.RawSubjectPublicKeyInfo)) { 507 return RootCA{}, errors.New( 508 "invalid intermediate chain - the first intermediate must have the same subject and public key as the signing cert") 509 } 510 } 511 512 return RootCA{signer: localSigner, Intermediates: intermediates, Digest: digest, Certs: rootCertBytes, Pool: pool}, nil 513 } 514 515 // ValidateCertChain checks checks that the certificates provided chain up to the root pool provided. In addition 516 // it also enforces that every cert in the bundle certificates form a chain, each one certifying the one above, 517 // as per RFC5246 section 7.4.2, and that every certificate (whether or not it is necessary to form a chain to the root 518 // pool) is currently valid and not yet expired (unless allowExpiry is set to true). 519 // This is additional validation not required by go's Certificate.Verify (which allows invalid certs in the 520 // intermediate pool), because this function is intended to be used when reading certs from untrusted locations such as 521 // from disk or over a network when a CSR is signed, so it is extra pedantic. 522 // This function always returns all the parsed certificates in the bundle in order, which means there will always be 523 // at least 1 certificate if there is no error, and the valid chains found by Certificate.Verify 524 func ValidateCertChain(rootPool *x509.CertPool, certs []byte, allowExpired bool) ([]*x509.Certificate, [][]*x509.Certificate, error) { 525 // Parse all the certificates in the cert bundle 526 parsedCerts, err := helpers.ParseCertificatesPEM(certs) 527 if err != nil { 528 return nil, nil, err 529 } 530 if len(parsedCerts) == 0 { 531 return nil, nil, errors.New("no certificates to validate") 532 } 533 now := time.Now() 534 // ensure that they form a chain, each one being signed by the one after it 535 var intermediatePool *x509.CertPool 536 for i, cert := range parsedCerts { 537 // Manual expiry validation because we want more information on which certificate in the chain is expired, and 538 // because this is an easier way to allow expired certs. 539 if now.Before(cert.NotBefore) { 540 return nil, nil, errors.Wrapf( 541 x509.CertificateInvalidError{ 542 Cert: cert, 543 Reason: x509.Expired, 544 }, 545 "certificate (%d - %s) not valid before %s, and it is currently %s", 546 i+1, cert.Subject.CommonName, cert.NotBefore.UTC().Format(time.RFC1123), now.Format(time.RFC1123)) 547 } 548 if !allowExpired && now.After(cert.NotAfter) { 549 return nil, nil, errors.Wrapf( 550 x509.CertificateInvalidError{ 551 Cert: cert, 552 Reason: x509.Expired, 553 }, 554 "certificate (%d - %s) not valid after %s, and it is currently %s", 555 i+1, cert.Subject.CommonName, cert.NotAfter.UTC().Format(time.RFC1123), now.Format(time.RFC1123)) 556 } 557 558 if i > 0 { 559 // check that the previous cert was signed by this cert 560 prevCert := parsedCerts[i-1] 561 if err := prevCert.CheckSignatureFrom(cert); err != nil { 562 return nil, nil, errors.Wrapf(err, "certificates do not form a chain: (%d - %s) is not signed by (%d - %s)", 563 i, prevCert.Subject.CommonName, i+1, cert.Subject.CommonName) 564 } 565 566 if intermediatePool == nil { 567 intermediatePool = x509.NewCertPool() 568 } 569 intermediatePool.AddCert(cert) 570 571 } 572 } 573 574 verifyOpts := x509.VerifyOptions{ 575 Roots: rootPool, 576 Intermediates: intermediatePool, 577 CurrentTime: now, 578 } 579 580 var chains [][]*x509.Certificate 581 582 // If we accept expired certs, try to build a valid cert chain using some subset of the certs. We start off using the 583 // first certificate's NotAfter as the current time, thus ensuring that the first cert is not expired. If the chain 584 // still fails to validate due to expiry issues, continue iterating over the rest of the certs. 585 // If any of the other certs has an earlier NotAfter time, use that time as the current time instead. This insures that 586 // particular cert, and any that came before it, are not expired. Note that the root that the certs chain up to 587 // should also not be expired at that "current" time. 588 if allowExpired { 589 verifyOpts.CurrentTime = parsedCerts[0].NotAfter.Add(time.Hour) 590 for _, cert := range parsedCerts { 591 if !cert.NotAfter.Before(verifyOpts.CurrentTime) { 592 continue 593 } 594 verifyOpts.CurrentTime = cert.NotAfter 595 596 chains, err = parsedCerts[0].Verify(verifyOpts) 597 if err == nil { 598 return parsedCerts, chains, nil 599 } 600 } 601 if invalid, ok := err.(x509.CertificateInvalidError); ok && invalid.Reason == x509.Expired { 602 return nil, nil, errors.New("there is no time span for which all of the certificates, including a root, are valid") 603 } 604 return nil, nil, err 605 } 606 607 chains, err = parsedCerts[0].Verify(verifyOpts) 608 if err != nil { 609 return nil, nil, err 610 } 611 return parsedCerts, chains, nil 612 } 613 614 // newLocalSigner validates the signing cert and signing key to create a local signer, which accepts a crypto signer and a cert 615 func newLocalSigner(keyBytes, certBytes []byte, certExpiry time.Duration, rootPool, intermediatePool *x509.CertPool) (*LocalSigner, error) { 616 if len(keyBytes) == 0 || len(certBytes) == 0 { 617 return nil, errors.New("must provide both a signing key and a signing cert, or neither") 618 } 619 620 parsedCerts, err := helpers.ParseCertificatesPEM(certBytes) 621 if err != nil { 622 return nil, errors.Wrap(err, "invalid signing CA cert") 623 } 624 if len(parsedCerts) == 0 { 625 return nil, errors.New("no valid signing CA certificates found") 626 } 627 if err := validateSignatureAlgorithm(parsedCerts[0]); err != nil { 628 return nil, err 629 } 630 opts := x509.VerifyOptions{ 631 Roots: rootPool, 632 Intermediates: intermediatePool, 633 } 634 if _, err := parsedCerts[0].Verify(opts); err != nil { 635 return nil, errors.Wrap(err, "error while validating signing CA certificate against roots and intermediates") 636 } 637 638 // The key should not be encrypted, but it could be in PKCS8 format rather than PKCS1 639 priv, err := helpers.ParsePrivateKeyPEM(keyBytes) 640 if err != nil { 641 return nil, errors.Wrap(err, "malformed private key") 642 } 643 644 // We will always use the first certificate inside of the root bundle as the active one 645 if err := ensureCertKeyMatch(parsedCerts[0], priv.Public()); err != nil { 646 return nil, err 647 } 648 649 signer, err := local.NewSigner(priv, parsedCerts[0], cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry)) 650 if err != nil { 651 return nil, err 652 } 653 654 return &LocalSigner{Cert: certBytes, Key: keyBytes, Signer: signer, parsedCert: parsedCerts[0], cryptoSigner: priv}, nil 655 } 656 657 func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error { 658 switch certPub := cert.PublicKey.(type) { 659 case *rsa.PublicKey: 660 if certPub.N.BitLen() < 2048 || certPub.E == 1 { 661 return errors.New("unsupported RSA key parameters") 662 } 663 rsaKey, ok := key.(*rsa.PublicKey) 664 if ok && certPub.E == rsaKey.E && certPub.N.Cmp(rsaKey.N) == 0 { 665 return nil 666 } 667 case *ecdsa.PublicKey: 668 switch certPub.Curve { 669 case elliptic.P256(), elliptic.P384(), elliptic.P521(): 670 break 671 default: 672 return errors.New("unsupported ECDSA key parameters") 673 } 674 675 ecKey, ok := key.(*ecdsa.PublicKey) 676 if ok && certPub.X.Cmp(ecKey.X) == 0 && certPub.Y.Cmp(ecKey.Y) == 0 { 677 return nil 678 } 679 default: 680 return errors.New("unknown or unsupported certificate public key algorithm") 681 } 682 683 return errors.New("certificate key mismatch") 684 } 685 686 // GetLocalRootCA validates if the contents of the file are a valid self-signed 687 // CA certificate, and returns the PEM-encoded Certificate if so 688 func GetLocalRootCA(paths CertPaths) (RootCA, error) { 689 // Check if we have a Certificate file 690 cert, err := ioutil.ReadFile(paths.Cert) 691 if err != nil { 692 if os.IsNotExist(err) { 693 err = ErrNoLocalRootCA 694 } 695 696 return RootCA{}, err 697 } 698 signingCert := cert 699 700 key, err := ioutil.ReadFile(paths.Key) 701 if err != nil { 702 if !os.IsNotExist(err) { 703 return RootCA{}, err 704 } 705 // There may not be a local key. It's okay to pass in a nil 706 // key. We'll get a root CA without a signer. 707 key = nil 708 signingCert = nil 709 } 710 711 return NewRootCA(cert, signingCert, key, DefaultNodeCertExpiration, nil) 712 } 713 714 func getGRPCConnection(creds credentials.TransportCredentials, connBroker *connectionbroker.Broker, forceRemote bool) (*connectionbroker.Conn, error) { 715 dialOpts := []grpc.DialOption{ 716 grpc.WithTransportCredentials(creds), 717 grpc.WithTimeout(5 * time.Second), 718 grpc.WithBackoffMaxDelay(5 * time.Second), 719 } 720 if forceRemote { 721 return connBroker.SelectRemote(dialOpts...) 722 } 723 return connBroker.Select(dialOpts...) 724 } 725 726 // GetRemoteCA returns the remote endpoint's CA certificate bundle 727 func GetRemoteCA(ctx context.Context, d digest.Digest, connBroker *connectionbroker.Broker) (RootCA, error) { 728 // This TLS Config is intentionally using InsecureSkipVerify. We use the 729 // digest instead to check the integrity of the CA certificate. 730 insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) 731 conn, err := getGRPCConnection(insecureCreds, connBroker, false) 732 if err != nil { 733 return RootCA{}, err 734 } 735 736 client := api.NewCAClient(conn.ClientConn) 737 ctx, cancel := context.WithTimeout(ctx, 5*time.Second) 738 defer cancel() 739 defer func() { 740 conn.Close(err == nil) 741 }() 742 response, err := client.GetRootCACertificate(ctx, &api.GetRootCACertificateRequest{}) 743 if err != nil { 744 return RootCA{}, err 745 } 746 747 // If a bundle of certificates are provided, the digest covers the entire bundle and not just 748 // one of the certificates in the bundle. Otherwise, a node can be MITMed while joining if 749 // the MITM CA provides a single certificate which matches the digest, and providing arbitrary 750 // other non-verified root certs that the manager certificate actually chains up to. 751 if d != "" { 752 verifier := d.Verifier() 753 if err != nil { 754 return RootCA{}, errors.Wrap(err, "unexpected error getting digest verifier") 755 } 756 757 io.Copy(verifier, bytes.NewReader(response.Certificate)) 758 759 if !verifier.Verified() { 760 return RootCA{}, errors.Errorf("remote CA does not match fingerprint. Expected: %s", d.Hex()) 761 } 762 } 763 764 // NewRootCA will validate that the certificates are otherwise valid and create a RootCA object. 765 // Since there is no key, the certificate expiry does not matter and will not be used. 766 return NewRootCA(response.Certificate, nil, nil, DefaultNodeCertExpiration, nil) 767 } 768 769 // CreateRootCA creates a Certificate authority for a new Swarm Cluster, potentially 770 // overwriting any existing CAs. 771 func CreateRootCA(rootCN string) (RootCA, error) { 772 // Create a simple CSR for the CA using the default CA validator and policy 773 req := cfcsr.CertificateRequest{ 774 CN: rootCN, 775 KeyRequest: &cfcsr.BasicKeyRequest{A: RootKeyAlgo, S: RootKeySize}, 776 CA: &cfcsr.CAConfig{Expiry: RootCAExpiration}, 777 } 778 779 // Generate the CA and get the certificate and private key 780 cert, _, key, err := initca.New(&req) 781 if err != nil { 782 return RootCA{}, err 783 } 784 785 rootCA, err := NewRootCA(cert, cert, key, DefaultNodeCertExpiration, nil) 786 if err != nil { 787 return RootCA{}, err 788 } 789 790 return rootCA, nil 791 } 792 793 // GetRemoteSignedCertificate submits a CSR to a remote CA server address, 794 // and that is part of a CA identified by a specific certificate pool. 795 func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x509.CertPool, config CertificateRequestConfig) ([]byte, error) { 796 if rootCAPool == nil { 797 return nil, errors.New("valid root CA pool required") 798 } 799 creds := config.Credentials 800 801 if creds == nil { 802 // This is our only non-MTLS request, and it happens when we are boostraping our TLS certs 803 // We're using CARole as server name, so an external CA doesn't also have to have ManagerRole in the cert SANs 804 creds = credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rootCAPool}) 805 } 806 807 conn, err := getGRPCConnection(creds, config.ConnBroker, config.ForceRemote) 808 if err != nil { 809 return nil, err 810 } 811 812 // Create a CAClient to retrieve a new Certificate 813 caClient := api.NewNodeCAClient(conn.ClientConn) 814 815 issueCtx, issueCancel := context.WithTimeout(ctx, 5*time.Second) 816 defer issueCancel() 817 818 // Send the Request and retrieve the request token 819 issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Token: config.Token, Availability: config.Availability} 820 issueResponse, err := caClient.IssueNodeCertificate(issueCtx, issueRequest) 821 if err != nil { 822 conn.Close(false) 823 return nil, err 824 } 825 826 statusRequest := &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID} 827 expBackoff := events.NewExponentialBackoff(events.ExponentialBackoffConfig{ 828 Base: time.Second, 829 Factor: time.Second, 830 Max: 30 * time.Second, 831 }) 832 833 // Exponential backoff with Max of 30 seconds to wait for a new retry 834 for { 835 timeout := 5 * time.Second 836 if config.NodeCertificateStatusRequestTimeout > 0 { 837 timeout = config.NodeCertificateStatusRequestTimeout 838 } 839 // Send the Request and retrieve the certificate 840 stateCtx, cancel := context.WithTimeout(ctx, timeout) 841 defer cancel() 842 statusResponse, err := caClient.NodeCertificateStatus(stateCtx, statusRequest) 843 s, _ := status.FromError(err) 844 switch { 845 case err != nil && s.Code() != codes.DeadlineExceeded: 846 conn.Close(false) 847 // Because IssueNodeCertificate succeeded, if this call failed likely it is due to an issue with this 848 // particular connection, so we need to get another. We should try a remote connection - the local node 849 // may be a manager that was demoted, so the local connection (which is preferred) may not work. 850 config.ForceRemote = true 851 conn, err = getGRPCConnection(creds, config.ConnBroker, config.ForceRemote) 852 if err != nil { 853 return nil, err 854 } 855 caClient = api.NewNodeCAClient(conn.ClientConn) 856 857 // If there was no deadline exceeded error, and the certificate was issued, return 858 case err == nil && (statusResponse.Status.State == api.IssuanceStateIssued || statusResponse.Status.State == api.IssuanceStateRotate): 859 if statusResponse.Certificate == nil { 860 conn.Close(false) 861 return nil, errors.New("no certificate in CertificateStatus response") 862 } 863 864 // The certificate in the response must match the CSR 865 // we submitted. If we are getting a response for a 866 // certificate that was previously issued, we need to 867 // retry until the certificate gets updated per our 868 // current request. 869 if bytes.Equal(statusResponse.Certificate.CSR, csr) { 870 conn.Close(true) 871 return statusResponse.Certificate.Certificate, nil 872 } 873 } 874 875 // If NodeCertificateStatus timed out, we're still pending, the issuance failed, or 876 // the state is unknown let's continue trying after an exponential backoff 877 expBackoff.Failure(nil, nil) 878 select { 879 case <-ctx.Done(): 880 conn.Close(true) 881 return nil, err 882 case <-time.After(expBackoff.Proceed(nil)): 883 } 884 } 885 } 886 887 // readCertValidity returns the certificate issue and expiration time 888 func readCertValidity(kr KeyReader) (time.Time, time.Time, error) { 889 var zeroTime time.Time 890 // Read the Cert 891 cert, _, err := kr.Read() 892 if err != nil { 893 return zeroTime, zeroTime, err 894 } 895 896 // Create an x509 certificate out of the contents on disk 897 certBlock, _ := pem.Decode(cert) 898 if certBlock == nil { 899 return zeroTime, zeroTime, errors.New("failed to decode certificate block") 900 } 901 X509Cert, err := x509.ParseCertificate(certBlock.Bytes) 902 if err != nil { 903 return zeroTime, zeroTime, err 904 } 905 906 return X509Cert.NotBefore, X509Cert.NotAfter, nil 907 908 } 909 910 // SaveRootCA saves a RootCA object to disk 911 func SaveRootCA(rootCA RootCA, paths CertPaths) error { 912 // Make sure the necessary dirs exist and they are writable 913 err := os.MkdirAll(filepath.Dir(paths.Cert), 0755) 914 if err != nil { 915 return err 916 } 917 918 // If the root certificate got returned successfully, save the rootCA to disk. 919 return ioutils.AtomicWriteFile(paths.Cert, rootCA.Certs, 0644) 920 } 921 922 // GenerateNewCSR returns a newly generated key and CSR signed with said key 923 func GenerateNewCSR() ([]byte, []byte, error) { 924 req := &cfcsr.CertificateRequest{ 925 KeyRequest: cfcsr.NewBasicKeyRequest(), 926 } 927 928 csr, key, err := cfcsr.ParseRequest(req) 929 if err != nil { 930 return nil, nil, err 931 } 932 933 key, err = pkcs8.ConvertECPrivateKeyPEM(key) 934 return csr, key, err 935 } 936 937 // NormalizePEMs takes a bundle of PEM-encoded certificates in a certificate bundle, 938 // decodes them, removes headers, and re-encodes them to make sure that they have 939 // consistent whitespace. Note that this is intended to normalize x509 certificates 940 // in PEM format, hence the stripping out of headers. 941 func NormalizePEMs(certs []byte) []byte { 942 var ( 943 results []byte 944 pemBlock *pem.Block 945 ) 946 for { 947 pemBlock, certs = pem.Decode(bytes.TrimSpace(certs)) 948 if pemBlock == nil { 949 return results 950 } 951 pemBlock.Headers = nil 952 results = append(results, pem.EncodeToMemory(pemBlock)...) 953 } 954 }