certificates.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. package ca
  2. import (
  3. "bytes"
  4. "crypto"
  5. "crypto/ecdsa"
  6. "crypto/rand"
  7. "crypto/tls"
  8. "crypto/x509"
  9. "encoding/pem"
  10. "io"
  11. "io/ioutil"
  12. "os"
  13. "path/filepath"
  14. "time"
  15. cfcsr "github.com/cloudflare/cfssl/csr"
  16. "github.com/cloudflare/cfssl/helpers"
  17. "github.com/cloudflare/cfssl/initca"
  18. cflog "github.com/cloudflare/cfssl/log"
  19. cfsigner "github.com/cloudflare/cfssl/signer"
  20. "github.com/cloudflare/cfssl/signer/local"
  21. "github.com/docker/go-events"
  22. "github.com/docker/swarmkit/api"
  23. "github.com/docker/swarmkit/connectionbroker"
  24. "github.com/docker/swarmkit/ioutils"
  25. "github.com/opencontainers/go-digest"
  26. "github.com/pkg/errors"
  27. "golang.org/x/net/context"
  28. "google.golang.org/grpc"
  29. "google.golang.org/grpc/codes"
  30. "google.golang.org/grpc/credentials"
  31. )
  32. const (
  33. // Security Strength Equivalence
  34. //-----------------------------------
  35. //| ECC | DH/DSA/RSA |
  36. //| 256 | 3072 |
  37. //| 384 | 7680 |
  38. //-----------------------------------
  39. // RootKeySize is the default size of the root CA key
  40. // It would be ideal for the root key to use P-384, but in P-384 is not optimized in go yet :(
  41. RootKeySize = 256
  42. // RootKeyAlgo defines the default algorithm for the root CA Key
  43. RootKeyAlgo = "ecdsa"
  44. // PassphraseENVVar defines the environment variable to look for the
  45. // root CA private key material encryption key
  46. PassphraseENVVar = "SWARM_ROOT_CA_PASSPHRASE"
  47. // PassphraseENVVarPrev defines the alternate environment variable to look for the
  48. // root CA private key material encryption key. It can be used for seamless
  49. // KEK rotations.
  50. PassphraseENVVarPrev = "SWARM_ROOT_CA_PASSPHRASE_PREV"
  51. // RootCAExpiration represents the expiration for the root CA in seconds (20 years)
  52. RootCAExpiration = "630720000s"
  53. // DefaultNodeCertExpiration represents the default expiration for node certificates (3 months)
  54. DefaultNodeCertExpiration = 2160 * time.Hour
  55. // CertBackdate represents the amount of time each certificate is backdated to try to avoid
  56. // clock drift issues.
  57. CertBackdate = 1 * time.Hour
  58. // CertLowerRotationRange represents the minimum fraction of time that we will wait when randomly
  59. // choosing our next certificate rotation
  60. CertLowerRotationRange = 0.5
  61. // CertUpperRotationRange represents the maximum fraction of time that we will wait when randomly
  62. // choosing our next certificate rotation
  63. CertUpperRotationRange = 0.8
  64. // MinNodeCertExpiration represents the minimum expiration for node certificates
  65. MinNodeCertExpiration = 1 * time.Hour
  66. )
  67. // A recoverableErr is a non-fatal error encountered signing a certificate,
  68. // which means that the certificate issuance may be retried at a later time.
  69. type recoverableErr struct {
  70. err error
  71. }
  72. func (r recoverableErr) Error() string {
  73. return r.err.Error()
  74. }
  75. // ErrNoLocalRootCA is an error type used to indicate that the local root CA
  76. // certificate file does not exist.
  77. var ErrNoLocalRootCA = errors.New("local root CA certificate does not exist")
  78. // ErrNoValidSigner is an error type used to indicate that our RootCA doesn't have the ability to
  79. // sign certificates.
  80. var ErrNoValidSigner = recoverableErr{err: errors.New("no valid signer found")}
  81. func init() {
  82. cflog.Level = 5
  83. }
  84. // CertPaths is a helper struct that keeps track of the paths of a
  85. // Cert and corresponding Key
  86. type CertPaths struct {
  87. Cert, Key string
  88. }
  89. // RootCA is the representation of everything we need to sign certificates
  90. type RootCA struct {
  91. // Key will only be used by the original manager to put the private
  92. // key-material in raft, no signing operations depend on it.
  93. Key []byte
  94. // Cert includes the PEM encoded Certificate for the Root CA
  95. Cert []byte
  96. Pool *x509.CertPool
  97. // Digest of the serialized bytes of the certificate
  98. Digest digest.Digest
  99. // This signer will be nil if the node doesn't have the appropriate key material
  100. Signer cfsigner.Signer
  101. }
  102. // CanSign ensures that the signer has all three necessary elements needed to operate
  103. func (rca *RootCA) CanSign() bool {
  104. if rca.Cert == nil || rca.Pool == nil || rca.Signer == nil {
  105. return false
  106. }
  107. return true
  108. }
  109. // IssueAndSaveNewCertificates generates a new key-pair, signs it with the local root-ca, and returns a
  110. // tls certificate
  111. func (rca *RootCA) IssueAndSaveNewCertificates(kw KeyWriter, cn, ou, org string) (*tls.Certificate, error) {
  112. csr, key, err := GenerateNewCSR()
  113. if err != nil {
  114. return nil, errors.Wrap(err, "error when generating new node certs")
  115. }
  116. if !rca.CanSign() {
  117. return nil, ErrNoValidSigner
  118. }
  119. // Obtain a signed Certificate
  120. certChain, err := rca.ParseValidateAndSignCSR(csr, cn, ou, org)
  121. if err != nil {
  122. return nil, errors.Wrap(err, "failed to sign node certificate")
  123. }
  124. // Create a valid TLSKeyPair out of the PEM encoded private key and certificate
  125. tlsKeyPair, err := tls.X509KeyPair(certChain, key)
  126. if err != nil {
  127. return nil, err
  128. }
  129. if err := kw.Write(certChain, key, nil); err != nil {
  130. return nil, err
  131. }
  132. return &tlsKeyPair, nil
  133. }
  134. // Normally we can just call cert.Verify(opts), but since we actually want more information about
  135. // whether a certificate is not yet valid or expired, we also need to perform the expiry checks ourselves.
  136. func verifyCertificate(cert *x509.Certificate, opts x509.VerifyOptions, allowExpired bool) error {
  137. _, err := cert.Verify(opts)
  138. if invalidErr, ok := err.(x509.CertificateInvalidError); ok && invalidErr.Reason == x509.Expired {
  139. now := time.Now().UTC()
  140. if now.Before(cert.NotBefore) {
  141. return errors.Wrapf(err, "certificate not valid before %s, and it is currently %s",
  142. cert.NotBefore.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
  143. }
  144. if allowExpired {
  145. return nil
  146. }
  147. return errors.Wrapf(err, "certificate expires at %s, and it is currently %s",
  148. cert.NotAfter.UTC().Format(time.RFC1123), now.Format(time.RFC1123))
  149. }
  150. return err
  151. }
  152. // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is
  153. // available, or by requesting them from the remote server at remoteAddr.
  154. func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, kw KeyWriter, config CertificateRequestConfig) (*tls.Certificate, error) {
  155. // Create a new key/pair and CSR
  156. csr, key, err := GenerateNewCSR()
  157. if err != nil {
  158. return nil, errors.Wrap(err, "error when generating new node certs")
  159. }
  160. // Get the remote manager to issue a CA signed certificate for this node
  161. // Retry up to 5 times in case the manager we first try to contact isn't
  162. // responding properly (for example, it may have just been demoted).
  163. var signedCert []byte
  164. for i := 0; i != 5; i++ {
  165. signedCert, err = GetRemoteSignedCertificate(ctx, csr, rca.Pool, config)
  166. if err == nil {
  167. break
  168. }
  169. // If the first attempt fails, we should try a remote
  170. // connection. The local node may be a manager that was
  171. // demoted, so the local connection (which is preferred) may
  172. // not work. If we are successful in renewing the certificate,
  173. // the local connection will not be returned by the connection
  174. // broker anymore.
  175. config.ForceRemote = true
  176. }
  177. if err != nil {
  178. return nil, err
  179. }
  180. // Доверяй, но проверяй.
  181. // Before we overwrite our local key + certificate, let's make sure the server gave us one that is valid
  182. // Create an X509Cert so we can .Verify()
  183. certBlock, _ := pem.Decode(signedCert)
  184. if certBlock == nil {
  185. return nil, errors.New("failed to parse certificate PEM")
  186. }
  187. X509Cert, err := x509.ParseCertificate(certBlock.Bytes)
  188. if err != nil {
  189. return nil, err
  190. }
  191. // Include our current root pool
  192. opts := x509.VerifyOptions{
  193. Roots: rca.Pool,
  194. }
  195. // Check to see if this certificate was signed by our CA, and isn't expired
  196. if err := verifyCertificate(X509Cert, opts, false); err != nil {
  197. return nil, err
  198. }
  199. // Create a valid TLSKeyPair out of the PEM encoded private key and certificate
  200. tlsKeyPair, err := tls.X509KeyPair(signedCert, key)
  201. if err != nil {
  202. return nil, err
  203. }
  204. var kekUpdate *KEKData
  205. for i := 0; i < 5; i++ {
  206. kekUpdate, err = rca.getKEKUpdate(ctx, X509Cert, tlsKeyPair, config.ConnBroker)
  207. if err == nil {
  208. break
  209. }
  210. }
  211. if err != nil {
  212. return nil, err
  213. }
  214. if err := kw.Write(signedCert, key, kekUpdate); err != nil {
  215. return nil, err
  216. }
  217. return &tlsKeyPair, nil
  218. }
  219. func (rca *RootCA) getKEKUpdate(ctx context.Context, cert *x509.Certificate, keypair tls.Certificate, connBroker *connectionbroker.Broker) (*KEKData, error) {
  220. var managerRole bool
  221. for _, ou := range cert.Subject.OrganizationalUnit {
  222. if ou == ManagerRole {
  223. managerRole = true
  224. break
  225. }
  226. }
  227. if managerRole {
  228. mtlsCreds := credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rca.Pool, Certificates: []tls.Certificate{keypair}})
  229. conn, err := getGRPCConnection(mtlsCreds, connBroker, false)
  230. if err != nil {
  231. return nil, err
  232. }
  233. client := api.NewCAClient(conn.ClientConn)
  234. ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
  235. defer cancel()
  236. response, err := client.GetUnlockKey(ctx, &api.GetUnlockKeyRequest{})
  237. if err != nil {
  238. if grpc.Code(err) == codes.Unimplemented { // if the server does not support keks, return as if no encryption key was specified
  239. conn.Close(true)
  240. return &KEKData{}, nil
  241. }
  242. conn.Close(false)
  243. return nil, err
  244. }
  245. conn.Close(true)
  246. return &KEKData{KEK: response.UnlockKey, Version: response.Version.Index}, nil
  247. }
  248. // If this is a worker, set to never encrypt. We always want to set to the lock key to nil,
  249. // in case this was a manager that was demoted to a worker.
  250. return &KEKData{}, nil
  251. }
  252. // PrepareCSR creates a CFSSL Sign Request based on the given raw CSR and
  253. // overrides the Subject and Hosts with the given extra args.
  254. func PrepareCSR(csrBytes []byte, cn, ou, org string) cfsigner.SignRequest {
  255. // All managers get added the subject-alt-name of CA, so they can be
  256. // used for cert issuance.
  257. hosts := []string{ou, cn}
  258. if ou == ManagerRole {
  259. hosts = append(hosts, CARole)
  260. }
  261. return cfsigner.SignRequest{
  262. Request: string(csrBytes),
  263. // OU is used for Authentication of the node type. The CN has the random
  264. // node ID.
  265. Subject: &cfsigner.Subject{CN: cn, Names: []cfcsr.Name{{OU: ou, O: org}}},
  266. // Adding ou as DNS alt name, so clients can connect to ManagerRole and CARole
  267. Hosts: hosts,
  268. }
  269. }
  270. // ParseValidateAndSignCSR returns a signed certificate from a particular rootCA and a CSR.
  271. func (rca *RootCA) ParseValidateAndSignCSR(csrBytes []byte, cn, ou, org string) ([]byte, error) {
  272. if !rca.CanSign() {
  273. return nil, ErrNoValidSigner
  274. }
  275. signRequest := PrepareCSR(csrBytes, cn, ou, org)
  276. cert, err := rca.Signer.Sign(signRequest)
  277. if err != nil {
  278. return nil, errors.Wrap(err, "failed to sign node certificate")
  279. }
  280. return rca.AppendFirstRootPEM(cert)
  281. }
  282. // AppendFirstRootPEM appends the first certificate from this RootCA's cert
  283. // bundle to the given cert bundle (which should already be encoded as a series
  284. // of PEM-encoded certificate blocks).
  285. func (rca *RootCA) AppendFirstRootPEM(cert []byte) ([]byte, error) {
  286. // Append the first root CA Cert to the certificate, to create a valid chain
  287. // Get the first Root CA Cert on the bundle
  288. firstRootCA, _, err := helpers.ParseOneCertificateFromPEM(rca.Cert)
  289. if err != nil {
  290. return nil, err
  291. }
  292. if len(firstRootCA) < 1 {
  293. return nil, errors.New("no valid Root CA certificates found")
  294. }
  295. // Convert the first root CA back to PEM
  296. firstRootCAPEM := helpers.EncodeCertificatePEM(firstRootCA[0])
  297. if firstRootCAPEM == nil {
  298. return nil, errors.New("error while encoding the Root CA certificate")
  299. }
  300. // Append this Root CA to the certificate to make [Cert PEM]\n[Root PEM][EOF]
  301. certChain := append(cert, firstRootCAPEM...)
  302. return certChain, nil
  303. }
  304. // NewRootCA creates a new RootCA object from unparsed PEM cert bundle and key byte
  305. // slices. key may be nil, and in this case NewRootCA will return a RootCA
  306. // without a signer.
  307. func NewRootCA(certBytes, keyBytes []byte, certExpiry time.Duration) (RootCA, error) {
  308. // Parse all the certificates in the cert bundle
  309. parsedCerts, err := helpers.ParseCertificatesPEM(certBytes)
  310. if err != nil {
  311. return RootCA{}, err
  312. }
  313. // Check to see if we have at least one valid cert
  314. if len(parsedCerts) < 1 {
  315. return RootCA{}, errors.New("no valid Root CA certificates found")
  316. }
  317. // Create a Pool with all of the certificates found
  318. pool := x509.NewCertPool()
  319. for _, cert := range parsedCerts {
  320. // Check to see if all of the certificates are valid, self-signed root CA certs
  321. if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
  322. return RootCA{}, errors.Wrap(err, "error while validating Root CA Certificate")
  323. }
  324. pool.AddCert(cert)
  325. }
  326. // Calculate the digest for our Root CA bundle
  327. digest := digest.FromBytes(certBytes)
  328. if len(keyBytes) == 0 {
  329. // This RootCA does not have a valid signer.
  330. return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil
  331. }
  332. var (
  333. passphraseStr string
  334. passphrase, passphrasePrev []byte
  335. priv crypto.Signer
  336. )
  337. // Attempt two distinct passphrases, so we can do a hitless passphrase rotation
  338. if passphraseStr = os.Getenv(PassphraseENVVar); passphraseStr != "" {
  339. passphrase = []byte(passphraseStr)
  340. }
  341. if p := os.Getenv(PassphraseENVVarPrev); p != "" {
  342. passphrasePrev = []byte(p)
  343. }
  344. // Attempt to decrypt the current private-key with the passphrases provided
  345. priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrase)
  346. if err != nil {
  347. priv, err = helpers.ParsePrivateKeyPEMWithPassword(keyBytes, passphrasePrev)
  348. if err != nil {
  349. return RootCA{}, errors.Wrap(err, "malformed private key")
  350. }
  351. }
  352. // We will always use the first certificate inside of the root bundle as the active one
  353. if err := ensureCertKeyMatch(parsedCerts[0], priv.Public()); err != nil {
  354. return RootCA{}, err
  355. }
  356. signer, err := local.NewSigner(priv, parsedCerts[0], cfsigner.DefaultSigAlgo(priv), SigningPolicy(certExpiry))
  357. if err != nil {
  358. return RootCA{}, err
  359. }
  360. // If the key was loaded from disk unencrypted, but there is a passphrase set,
  361. // ensure it is encrypted, so it doesn't hit raft in plain-text
  362. keyBlock, _ := pem.Decode(keyBytes)
  363. if keyBlock == nil {
  364. // This RootCA does not have a valid signer.
  365. return RootCA{Cert: certBytes, Digest: digest, Pool: pool}, nil
  366. }
  367. if passphraseStr != "" && !x509.IsEncryptedPEMBlock(keyBlock) {
  368. keyBytes, err = EncryptECPrivateKey(keyBytes, passphraseStr)
  369. if err != nil {
  370. return RootCA{}, err
  371. }
  372. }
  373. return RootCA{Signer: signer, Key: keyBytes, Digest: digest, Cert: certBytes, Pool: pool}, nil
  374. }
  375. func ensureCertKeyMatch(cert *x509.Certificate, key crypto.PublicKey) error {
  376. switch certPub := cert.PublicKey.(type) {
  377. // TODO: Handle RSA keys.
  378. case *ecdsa.PublicKey:
  379. ecKey, ok := key.(*ecdsa.PublicKey)
  380. if ok && certPub.X.Cmp(ecKey.X) == 0 && certPub.Y.Cmp(ecKey.Y) == 0 {
  381. return nil
  382. }
  383. default:
  384. return errors.New("unknown or unsupported certificate public key algorithm")
  385. }
  386. return errors.New("certificate key mismatch")
  387. }
  388. // GetLocalRootCA validates if the contents of the file are a valid self-signed
  389. // CA certificate, and returns the PEM-encoded Certificate if so
  390. func GetLocalRootCA(paths CertPaths) (RootCA, error) {
  391. // Check if we have a Certificate file
  392. cert, err := ioutil.ReadFile(paths.Cert)
  393. if err != nil {
  394. if os.IsNotExist(err) {
  395. err = ErrNoLocalRootCA
  396. }
  397. return RootCA{}, err
  398. }
  399. key, err := ioutil.ReadFile(paths.Key)
  400. if err != nil {
  401. if !os.IsNotExist(err) {
  402. return RootCA{}, err
  403. }
  404. // There may not be a local key. It's okay to pass in a nil
  405. // key. We'll get a root CA without a signer.
  406. key = nil
  407. }
  408. return NewRootCA(cert, key, DefaultNodeCertExpiration)
  409. }
  410. func getGRPCConnection(creds credentials.TransportCredentials, connBroker *connectionbroker.Broker, forceRemote bool) (*connectionbroker.Conn, error) {
  411. dialOpts := []grpc.DialOption{
  412. grpc.WithTransportCredentials(creds),
  413. grpc.WithTimeout(5 * time.Second),
  414. grpc.WithBackoffMaxDelay(5 * time.Second),
  415. }
  416. if forceRemote {
  417. return connBroker.SelectRemote(dialOpts...)
  418. }
  419. return connBroker.Select(dialOpts...)
  420. }
  421. // GetRemoteCA returns the remote endpoint's CA certificate bundle
  422. func GetRemoteCA(ctx context.Context, d digest.Digest, connBroker *connectionbroker.Broker) (RootCA, error) {
  423. // This TLS Config is intentionally using InsecureSkipVerify. We use the
  424. // digest instead to check the integrity of the CA certificate.
  425. insecureCreds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
  426. conn, err := getGRPCConnection(insecureCreds, connBroker, false)
  427. if err != nil {
  428. return RootCA{}, err
  429. }
  430. client := api.NewCAClient(conn.ClientConn)
  431. ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
  432. defer cancel()
  433. defer func() {
  434. conn.Close(err == nil)
  435. }()
  436. response, err := client.GetRootCACertificate(ctx, &api.GetRootCACertificateRequest{})
  437. if err != nil {
  438. return RootCA{}, err
  439. }
  440. // If a bundle of certificates are provided, the digest covers the entire bundle and not just
  441. // one of the certificates in the bundle. Otherwise, a node can be MITMed while joining if
  442. // the MITM CA provides a single certificate which matches the digest, and providing arbitrary
  443. // other non-verified root certs that the manager certificate actually chains up to.
  444. if d != "" {
  445. verifier := d.Verifier()
  446. if err != nil {
  447. return RootCA{}, errors.Wrap(err, "unexpected error getting digest verifier")
  448. }
  449. io.Copy(verifier, bytes.NewReader(response.Certificate))
  450. if !verifier.Verified() {
  451. return RootCA{}, errors.Errorf("remote CA does not match fingerprint. Expected: %s", d.Hex())
  452. }
  453. }
  454. // NewRootCA will validate that the certificates are otherwise valid and create a RootCA object.
  455. // Since there is no key, the certificate expiry does not matter and will not be used.
  456. return NewRootCA(response.Certificate, nil, DefaultNodeCertExpiration)
  457. }
  458. // CreateRootCA creates a Certificate authority for a new Swarm Cluster, potentially
  459. // overwriting any existing CAs.
  460. func CreateRootCA(rootCN string, paths CertPaths) (RootCA, error) {
  461. // Create a simple CSR for the CA using the default CA validator and policy
  462. req := cfcsr.CertificateRequest{
  463. CN: rootCN,
  464. KeyRequest: &cfcsr.BasicKeyRequest{A: RootKeyAlgo, S: RootKeySize},
  465. CA: &cfcsr.CAConfig{Expiry: RootCAExpiration},
  466. }
  467. // Generate the CA and get the certificate and private key
  468. cert, _, key, err := initca.New(&req)
  469. if err != nil {
  470. return RootCA{}, err
  471. }
  472. rootCA, err := NewRootCA(cert, key, DefaultNodeCertExpiration)
  473. if err != nil {
  474. return RootCA{}, err
  475. }
  476. // save the cert to disk
  477. if err := saveRootCA(rootCA, paths); err != nil {
  478. return RootCA{}, err
  479. }
  480. return rootCA, nil
  481. }
  482. // GetRemoteSignedCertificate submits a CSR to a remote CA server address,
  483. // and that is part of a CA identified by a specific certificate pool.
  484. func GetRemoteSignedCertificate(ctx context.Context, csr []byte, rootCAPool *x509.CertPool, config CertificateRequestConfig) ([]byte, error) {
  485. if rootCAPool == nil {
  486. return nil, errors.New("valid root CA pool required")
  487. }
  488. creds := config.Credentials
  489. if creds == nil {
  490. // This is our only non-MTLS request, and it happens when we are boostraping our TLS certs
  491. // We're using CARole as server name, so an external CA doesn't also have to have ManagerRole in the cert SANs
  492. creds = credentials.NewTLS(&tls.Config{ServerName: CARole, RootCAs: rootCAPool})
  493. }
  494. conn, err := getGRPCConnection(creds, config.ConnBroker, config.ForceRemote)
  495. if err != nil {
  496. return nil, err
  497. }
  498. // Create a CAClient to retrieve a new Certificate
  499. caClient := api.NewNodeCAClient(conn.ClientConn)
  500. issueCtx, issueCancel := context.WithTimeout(ctx, 5*time.Second)
  501. defer issueCancel()
  502. // Send the Request and retrieve the request token
  503. issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Token: config.Token, Availability: config.Availability}
  504. issueResponse, err := caClient.IssueNodeCertificate(issueCtx, issueRequest)
  505. if err != nil {
  506. conn.Close(false)
  507. return nil, err
  508. }
  509. statusRequest := &api.NodeCertificateStatusRequest{NodeID: issueResponse.NodeID}
  510. expBackoff := events.NewExponentialBackoff(events.ExponentialBackoffConfig{
  511. Base: time.Second,
  512. Factor: time.Second,
  513. Max: 30 * time.Second,
  514. })
  515. // Exponential backoff with Max of 30 seconds to wait for a new retry
  516. for {
  517. // Send the Request and retrieve the certificate
  518. ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
  519. defer cancel()
  520. statusResponse, err := caClient.NodeCertificateStatus(ctx, statusRequest)
  521. if err != nil {
  522. conn.Close(false)
  523. return nil, err
  524. }
  525. // If the certificate was issued, return
  526. if statusResponse.Status.State == api.IssuanceStateIssued {
  527. if statusResponse.Certificate == nil {
  528. conn.Close(false)
  529. return nil, errors.New("no certificate in CertificateStatus response")
  530. }
  531. // The certificate in the response must match the CSR
  532. // we submitted. If we are getting a response for a
  533. // certificate that was previously issued, we need to
  534. // retry until the certificate gets updated per our
  535. // current request.
  536. if bytes.Equal(statusResponse.Certificate.CSR, csr) {
  537. conn.Close(true)
  538. return statusResponse.Certificate.Certificate, nil
  539. }
  540. }
  541. // If we're still pending, the issuance failed, or the state is unknown
  542. // let's continue trying.
  543. expBackoff.Failure(nil, nil)
  544. time.Sleep(expBackoff.Proceed(nil))
  545. }
  546. }
  547. // readCertValidity returns the certificate issue and expiration time
  548. func readCertValidity(kr KeyReader) (time.Time, time.Time, error) {
  549. var zeroTime time.Time
  550. // Read the Cert
  551. cert, _, err := kr.Read()
  552. if err != nil {
  553. return zeroTime, zeroTime, err
  554. }
  555. // Create an x509 certificate out of the contents on disk
  556. certBlock, _ := pem.Decode(cert)
  557. if certBlock == nil {
  558. return zeroTime, zeroTime, errors.New("failed to decode certificate block")
  559. }
  560. X509Cert, err := x509.ParseCertificate(certBlock.Bytes)
  561. if err != nil {
  562. return zeroTime, zeroTime, err
  563. }
  564. return X509Cert.NotBefore, X509Cert.NotAfter, nil
  565. }
  566. func saveRootCA(rootCA RootCA, paths CertPaths) error {
  567. // Make sure the necessary dirs exist and they are writable
  568. err := os.MkdirAll(filepath.Dir(paths.Cert), 0755)
  569. if err != nil {
  570. return err
  571. }
  572. // If the root certificate got returned successfully, save the rootCA to disk.
  573. return ioutils.AtomicWriteFile(paths.Cert, rootCA.Cert, 0644)
  574. }
  575. // GenerateNewCSR returns a newly generated key and CSR signed with said key
  576. func GenerateNewCSR() (csr, key []byte, err error) {
  577. req := &cfcsr.CertificateRequest{
  578. KeyRequest: cfcsr.NewBasicKeyRequest(),
  579. }
  580. csr, key, err = cfcsr.ParseRequest(req)
  581. if err != nil {
  582. return
  583. }
  584. return
  585. }
  586. // EncryptECPrivateKey receives a PEM encoded private key and returns an encrypted
  587. // AES256 version using a passphrase
  588. // TODO: Make this method generic to handle RSA keys
  589. func EncryptECPrivateKey(key []byte, passphraseStr string) ([]byte, error) {
  590. passphrase := []byte(passphraseStr)
  591. cipherType := x509.PEMCipherAES256
  592. keyBlock, _ := pem.Decode(key)
  593. if keyBlock == nil {
  594. // This RootCA does not have a valid signer.
  595. return nil, errors.New("error while decoding PEM key")
  596. }
  597. encryptedPEMBlock, err := x509.EncryptPEMBlock(rand.Reader,
  598. "EC PRIVATE KEY",
  599. keyBlock.Bytes,
  600. passphrase,
  601. cipherType)
  602. if err != nil {
  603. return nil, err
  604. }
  605. if encryptedPEMBlock.Headers == nil {
  606. return nil, errors.New("unable to encrypt key - invalid PEM file produced")
  607. }
  608. return pem.EncodeToMemory(encryptedPEMBlock), nil
  609. }