pki_helpers.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package pkiutil
  14. import (
  15. "crypto"
  16. "crypto/ecdsa"
  17. cryptorand "crypto/rand"
  18. "crypto/rsa"
  19. "crypto/x509"
  20. "crypto/x509/pkix"
  21. "encoding/pem"
  22. "fmt"
  23. "io/ioutil"
  24. "math"
  25. "math/big"
  26. "net"
  27. "os"
  28. "path/filepath"
  29. "time"
  30. "github.com/pkg/errors"
  31. "k8s.io/apimachinery/pkg/util/validation"
  32. certutil "k8s.io/client-go/util/cert"
  33. "k8s.io/client-go/util/keyutil"
  34. kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
  35. kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
  36. kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
  37. "k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
  38. )
  39. const (
  40. // PrivateKeyBlockType is a possible value for pem.Block.Type.
  41. PrivateKeyBlockType = "PRIVATE KEY"
  42. // PublicKeyBlockType is a possible value for pem.Block.Type.
  43. PublicKeyBlockType = "PUBLIC KEY"
  44. // CertificateBlockType is a possible value for pem.Block.Type.
  45. CertificateBlockType = "CERTIFICATE"
  46. // RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
  47. RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
  48. rsaKeySize = 2048
  49. )
  50. // NewCertificateAuthority creates new certificate and private key for the certificate authority
  51. func NewCertificateAuthority(config *certutil.Config) (*x509.Certificate, crypto.Signer, error) {
  52. key, err := NewPrivateKey()
  53. if err != nil {
  54. return nil, nil, errors.Wrap(err, "unable to create private key while generating CA certificate")
  55. }
  56. cert, err := certutil.NewSelfSignedCACert(*config, key)
  57. if err != nil {
  58. return nil, nil, errors.Wrap(err, "unable to create self-signed CA certificate")
  59. }
  60. return cert, key, nil
  61. }
  62. // NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key
  63. func NewCertAndKey(caCert *x509.Certificate, caKey crypto.Signer, config *certutil.Config) (*x509.Certificate, crypto.Signer, error) {
  64. key, err := NewPrivateKey()
  65. if err != nil {
  66. return nil, nil, errors.Wrap(err, "unable to create private key")
  67. }
  68. cert, err := NewSignedCert(config, key, caCert, caKey)
  69. if err != nil {
  70. return nil, nil, errors.Wrap(err, "unable to sign certificate")
  71. }
  72. return cert, key, nil
  73. }
  74. // NewCSRAndKey generates a new key and CSR and that could be signed to create the given certificate
  75. func NewCSRAndKey(config *certutil.Config) (*x509.CertificateRequest, crypto.Signer, error) {
  76. key, err := NewPrivateKey()
  77. if err != nil {
  78. return nil, nil, errors.Wrap(err, "unable to create private key")
  79. }
  80. csr, err := NewCSR(*config, key)
  81. if err != nil {
  82. return nil, nil, errors.Wrap(err, "unable to generate CSR")
  83. }
  84. return csr, key, nil
  85. }
  86. // HasServerAuth returns true if the given certificate is a ServerAuth
  87. func HasServerAuth(cert *x509.Certificate) bool {
  88. for i := range cert.ExtKeyUsage {
  89. if cert.ExtKeyUsage[i] == x509.ExtKeyUsageServerAuth {
  90. return true
  91. }
  92. }
  93. return false
  94. }
  95. // WriteCertAndKey stores certificate and key at the specified location
  96. func WriteCertAndKey(pkiPath string, name string, cert *x509.Certificate, key crypto.Signer) error {
  97. if err := WriteKey(pkiPath, name, key); err != nil {
  98. return errors.Wrap(err, "couldn't write key")
  99. }
  100. return WriteCert(pkiPath, name, cert)
  101. }
  102. // WriteCert stores the given certificate at the given location
  103. func WriteCert(pkiPath, name string, cert *x509.Certificate) error {
  104. if cert == nil {
  105. return errors.New("certificate cannot be nil when writing to file")
  106. }
  107. certificatePath := pathForCert(pkiPath, name)
  108. if err := certutil.WriteCert(certificatePath, EncodeCertPEM(cert)); err != nil {
  109. return errors.Wrapf(err, "unable to write certificate to file %s", certificatePath)
  110. }
  111. return nil
  112. }
  113. // WriteKey stores the given key at the given location
  114. func WriteKey(pkiPath, name string, key crypto.Signer) error {
  115. if key == nil {
  116. return errors.New("private key cannot be nil when writing to file")
  117. }
  118. privateKeyPath := pathForKey(pkiPath, name)
  119. encoded, err := keyutil.MarshalPrivateKeyToPEM(key)
  120. if err != nil {
  121. return errors.Wrapf(err, "unable to marshal private key to PEM")
  122. }
  123. if err := keyutil.WriteKey(privateKeyPath, encoded); err != nil {
  124. return errors.Wrapf(err, "unable to write private key to file %s", privateKeyPath)
  125. }
  126. return nil
  127. }
  128. // WriteCSR writes the pem-encoded CSR data to csrPath.
  129. // The CSR file will be created with file mode 0644.
  130. // If the CSR file already exists, it will be overwritten.
  131. // The parent directory of the csrPath will be created as needed with file mode 0755.
  132. func WriteCSR(csrDir, name string, csr *x509.CertificateRequest) error {
  133. if csr == nil {
  134. return errors.New("certificate request cannot be nil when writing to file")
  135. }
  136. csrPath := pathForCSR(csrDir, name)
  137. if err := os.MkdirAll(filepath.Dir(csrPath), os.FileMode(0755)); err != nil {
  138. return errors.Wrapf(err, "failed to make directory %s", filepath.Dir(csrPath))
  139. }
  140. if err := ioutil.WriteFile(csrPath, EncodeCSRPEM(csr), os.FileMode(0644)); err != nil {
  141. return errors.Wrapf(err, "unable to write CSR to file %s", csrPath)
  142. }
  143. return nil
  144. }
  145. // WritePublicKey stores the given public key at the given location
  146. func WritePublicKey(pkiPath, name string, key crypto.PublicKey) error {
  147. if key == nil {
  148. return errors.New("public key cannot be nil when writing to file")
  149. }
  150. publicKeyBytes, err := EncodePublicKeyPEM(key)
  151. if err != nil {
  152. return err
  153. }
  154. publicKeyPath := pathForPublicKey(pkiPath, name)
  155. if err := keyutil.WriteKey(publicKeyPath, publicKeyBytes); err != nil {
  156. return errors.Wrapf(err, "unable to write public key to file %s", publicKeyPath)
  157. }
  158. return nil
  159. }
  160. // CertOrKeyExist returns a boolean whether the cert or the key exists
  161. func CertOrKeyExist(pkiPath, name string) bool {
  162. certificatePath, privateKeyPath := PathsForCertAndKey(pkiPath, name)
  163. _, certErr := os.Stat(certificatePath)
  164. _, keyErr := os.Stat(privateKeyPath)
  165. if os.IsNotExist(certErr) && os.IsNotExist(keyErr) {
  166. // The cert or the key did not exist
  167. return false
  168. }
  169. // Both files exist or one of them
  170. return true
  171. }
  172. // CSROrKeyExist returns true if one of the CSR or key exists
  173. func CSROrKeyExist(csrDir, name string) bool {
  174. csrPath := pathForCSR(csrDir, name)
  175. keyPath := pathForKey(csrDir, name)
  176. _, csrErr := os.Stat(csrPath)
  177. _, keyErr := os.Stat(keyPath)
  178. return !(os.IsNotExist(csrErr) && os.IsNotExist(keyErr))
  179. }
  180. // TryLoadCertAndKeyFromDisk tries to load a cert and a key from the disk and validates that they are valid
  181. func TryLoadCertAndKeyFromDisk(pkiPath, name string) (*x509.Certificate, crypto.Signer, error) {
  182. cert, err := TryLoadCertFromDisk(pkiPath, name)
  183. if err != nil {
  184. return nil, nil, errors.Wrap(err, "failed to load certificate")
  185. }
  186. key, err := TryLoadKeyFromDisk(pkiPath, name)
  187. if err != nil {
  188. return nil, nil, errors.Wrap(err, "failed to load key")
  189. }
  190. return cert, key, nil
  191. }
  192. // TryLoadCertFromDisk tries to load the cert from the disk and validates that it is valid
  193. func TryLoadCertFromDisk(pkiPath, name string) (*x509.Certificate, error) {
  194. certificatePath := pathForCert(pkiPath, name)
  195. certs, err := certutil.CertsFromFile(certificatePath)
  196. if err != nil {
  197. return nil, errors.Wrapf(err, "couldn't load the certificate file %s", certificatePath)
  198. }
  199. // We are only putting one certificate in the certificate pem file, so it's safe to just pick the first one
  200. // TODO: Support multiple certs here in order to be able to rotate certs
  201. cert := certs[0]
  202. // Check so that the certificate is valid now
  203. now := time.Now()
  204. if now.Before(cert.NotBefore) {
  205. return nil, errors.New("the certificate is not valid yet")
  206. }
  207. if now.After(cert.NotAfter) {
  208. return nil, errors.New("the certificate has expired")
  209. }
  210. return cert, nil
  211. }
  212. // TryLoadKeyFromDisk tries to load the key from the disk and validates that it is valid
  213. func TryLoadKeyFromDisk(pkiPath, name string) (crypto.Signer, error) {
  214. privateKeyPath := pathForKey(pkiPath, name)
  215. // Parse the private key from a file
  216. privKey, err := keyutil.PrivateKeyFromFile(privateKeyPath)
  217. if err != nil {
  218. return nil, errors.Wrapf(err, "couldn't load the private key file %s", privateKeyPath)
  219. }
  220. // Allow RSA and ECDSA formats only
  221. var key crypto.Signer
  222. switch k := privKey.(type) {
  223. case *rsa.PrivateKey:
  224. key = k
  225. case *ecdsa.PrivateKey:
  226. key = k
  227. default:
  228. return nil, errors.Errorf("the private key file %s is neither in RSA nor ECDSA format", privateKeyPath)
  229. }
  230. return key, nil
  231. }
  232. // TryLoadCSRAndKeyFromDisk tries to load the CSR and key from the disk
  233. func TryLoadCSRAndKeyFromDisk(pkiPath, name string) (*x509.CertificateRequest, crypto.Signer, error) {
  234. csrPath := pathForCSR(pkiPath, name)
  235. csr, err := CertificateRequestFromFile(csrPath)
  236. if err != nil {
  237. return nil, nil, errors.Wrapf(err, "couldn't load the certificate request %s", csrPath)
  238. }
  239. key, err := TryLoadKeyFromDisk(pkiPath, name)
  240. if err != nil {
  241. return nil, nil, errors.Wrap(err, "couldn't load key file")
  242. }
  243. return csr, key, nil
  244. }
  245. // TryLoadPrivatePublicKeyFromDisk tries to load the key from the disk and validates that it is valid
  246. func TryLoadPrivatePublicKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, *rsa.PublicKey, error) {
  247. privateKeyPath := pathForKey(pkiPath, name)
  248. // Parse the private key from a file
  249. privKey, err := keyutil.PrivateKeyFromFile(privateKeyPath)
  250. if err != nil {
  251. return nil, nil, errors.Wrapf(err, "couldn't load the private key file %s", privateKeyPath)
  252. }
  253. publicKeyPath := pathForPublicKey(pkiPath, name)
  254. // Parse the public key from a file
  255. pubKeys, err := keyutil.PublicKeysFromFile(publicKeyPath)
  256. if err != nil {
  257. return nil, nil, errors.Wrapf(err, "couldn't load the public key file %s", publicKeyPath)
  258. }
  259. // Allow RSA format only
  260. k, ok := privKey.(*rsa.PrivateKey)
  261. if !ok {
  262. return nil, nil, errors.Errorf("the private key file %s isn't in RSA format", privateKeyPath)
  263. }
  264. p := pubKeys[0].(*rsa.PublicKey)
  265. return k, p, nil
  266. }
  267. // PathsForCertAndKey returns the paths for the certificate and key given the path and basename.
  268. func PathsForCertAndKey(pkiPath, name string) (string, string) {
  269. return pathForCert(pkiPath, name), pathForKey(pkiPath, name)
  270. }
  271. func pathForCert(pkiPath, name string) string {
  272. return filepath.Join(pkiPath, fmt.Sprintf("%s.crt", name))
  273. }
  274. func pathForKey(pkiPath, name string) string {
  275. return filepath.Join(pkiPath, fmt.Sprintf("%s.key", name))
  276. }
  277. func pathForPublicKey(pkiPath, name string) string {
  278. return filepath.Join(pkiPath, fmt.Sprintf("%s.pub", name))
  279. }
  280. func pathForCSR(pkiPath, name string) string {
  281. return filepath.Join(pkiPath, fmt.Sprintf("%s.csr", name))
  282. }
  283. // GetAPIServerAltNames builds an AltNames object for to be used when generating apiserver certificate
  284. func GetAPIServerAltNames(cfg *kubeadmapi.InitConfiguration) (*certutil.AltNames, error) {
  285. // advertise address
  286. advertiseAddress := net.ParseIP(cfg.LocalAPIEndpoint.AdvertiseAddress)
  287. if advertiseAddress == nil {
  288. return nil, errors.Errorf("error parsing LocalAPIEndpoint AdvertiseAddress %v: is not a valid textual representation of an IP address",
  289. cfg.LocalAPIEndpoint.AdvertiseAddress)
  290. }
  291. // internal IP address for the API server
  292. _, svcSubnet, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
  293. if err != nil {
  294. return nil, errors.Wrapf(err, "error parsing CIDR %q", cfg.Networking.ServiceSubnet)
  295. }
  296. internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(svcSubnet, 1)
  297. if err != nil {
  298. return nil, errors.Wrapf(err, "unable to get first IP address from the given CIDR (%s)", svcSubnet.String())
  299. }
  300. // create AltNames with defaults DNSNames/IPs
  301. altNames := &certutil.AltNames{
  302. DNSNames: []string{
  303. cfg.NodeRegistration.Name,
  304. "kubernetes",
  305. "kubernetes.default",
  306. "kubernetes.default.svc",
  307. fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain),
  308. },
  309. IPs: []net.IP{
  310. internalAPIServerVirtualIP,
  311. advertiseAddress,
  312. },
  313. }
  314. // add cluster controlPlaneEndpoint if present (dns or ip)
  315. if len(cfg.ControlPlaneEndpoint) > 0 {
  316. if host, _, err := kubeadmutil.ParseHostPort(cfg.ControlPlaneEndpoint); err == nil {
  317. if ip := net.ParseIP(host); ip != nil {
  318. altNames.IPs = append(altNames.IPs, ip)
  319. } else {
  320. altNames.DNSNames = append(altNames.DNSNames, host)
  321. }
  322. } else {
  323. return nil, errors.Wrapf(err, "error parsing cluster controlPlaneEndpoint %q", cfg.ControlPlaneEndpoint)
  324. }
  325. }
  326. appendSANsToAltNames(altNames, cfg.APIServer.CertSANs, kubeadmconstants.APIServerCertName)
  327. return altNames, nil
  328. }
  329. // GetEtcdAltNames builds an AltNames object for generating the etcd server certificate.
  330. // `advertise address` and localhost are included in the SAN since this is the interfaces the etcd static pod listens on.
  331. // The user can override the listen address with `Etcd.ExtraArgs` and add SANs with `Etcd.ServerCertSANs`.
  332. func GetEtcdAltNames(cfg *kubeadmapi.InitConfiguration) (*certutil.AltNames, error) {
  333. return getAltNames(cfg, kubeadmconstants.EtcdServerCertName)
  334. }
  335. // GetEtcdPeerAltNames builds an AltNames object for generating the etcd peer certificate.
  336. // Hostname and `API.AdvertiseAddress` are included if the user chooses to promote the single node etcd cluster into a multi-node one (stacked etcd).
  337. // The user can override the listen address with `Etcd.ExtraArgs` and add SANs with `Etcd.PeerCertSANs`.
  338. func GetEtcdPeerAltNames(cfg *kubeadmapi.InitConfiguration) (*certutil.AltNames, error) {
  339. return getAltNames(cfg, kubeadmconstants.EtcdPeerCertName)
  340. }
  341. // getAltNames builds an AltNames object with the cfg and certName.
  342. func getAltNames(cfg *kubeadmapi.InitConfiguration, certName string) (*certutil.AltNames, error) {
  343. // advertise address
  344. advertiseAddress := net.ParseIP(cfg.LocalAPIEndpoint.AdvertiseAddress)
  345. if advertiseAddress == nil {
  346. return nil, errors.Errorf("error parsing LocalAPIEndpoint AdvertiseAddress %v: is not a valid textual representation of an IP address",
  347. cfg.LocalAPIEndpoint.AdvertiseAddress)
  348. }
  349. // create AltNames with defaults DNSNames/IPs
  350. altNames := &certutil.AltNames{
  351. DNSNames: []string{cfg.NodeRegistration.Name, "localhost"},
  352. IPs: []net.IP{advertiseAddress, net.IPv4(127, 0, 0, 1), net.IPv6loopback},
  353. }
  354. if cfg.Etcd.Local != nil {
  355. if certName == kubeadmconstants.EtcdServerCertName {
  356. appendSANsToAltNames(altNames, cfg.Etcd.Local.ServerCertSANs, kubeadmconstants.EtcdServerCertName)
  357. } else if certName == kubeadmconstants.EtcdPeerCertName {
  358. appendSANsToAltNames(altNames, cfg.Etcd.Local.PeerCertSANs, kubeadmconstants.EtcdPeerCertName)
  359. }
  360. }
  361. return altNames, nil
  362. }
  363. // appendSANsToAltNames parses SANs from as list of strings and adds them to altNames for use on a specific cert
  364. // altNames is passed in with a pointer, and the struct is modified
  365. // valid IP address strings are parsed and added to altNames.IPs as net.IP's
  366. // RFC-1123 compliant DNS strings are added to altNames.DNSNames as strings
  367. // RFC-1123 compliant wildcard DNS strings are added to altNames.DNSNames as strings
  368. // certNames is used to print user facing warnings and should be the name of the cert the altNames will be used for
  369. func appendSANsToAltNames(altNames *certutil.AltNames, SANs []string, certName string) {
  370. for _, altname := range SANs {
  371. if ip := net.ParseIP(altname); ip != nil {
  372. altNames.IPs = append(altNames.IPs, ip)
  373. } else if len(validation.IsDNS1123Subdomain(altname)) == 0 {
  374. altNames.DNSNames = append(altNames.DNSNames, altname)
  375. } else if len(validation.IsWildcardDNS1123Subdomain(altname)) == 0 {
  376. altNames.DNSNames = append(altNames.DNSNames, altname)
  377. } else {
  378. fmt.Printf(
  379. "[certificates] WARNING: '%s' was not added to the '%s' SAN, because it is not a valid IP or RFC-1123 compliant DNS entry\n",
  380. altname,
  381. certName,
  382. )
  383. }
  384. }
  385. }
  386. // EncodeCSRPEM returns PEM-encoded CSR data
  387. func EncodeCSRPEM(csr *x509.CertificateRequest) []byte {
  388. block := pem.Block{
  389. Type: certutil.CertificateRequestBlockType,
  390. Bytes: csr.Raw,
  391. }
  392. return pem.EncodeToMemory(&block)
  393. }
  394. func parseCSRPEM(pemCSR []byte) (*x509.CertificateRequest, error) {
  395. block, _ := pem.Decode(pemCSR)
  396. if block == nil {
  397. return nil, errors.New("data doesn't contain a valid certificate request")
  398. }
  399. if block.Type != certutil.CertificateRequestBlockType {
  400. var block *pem.Block
  401. return nil, errors.Errorf("expected block type %q, but PEM had type %v", certutil.CertificateRequestBlockType, block.Type)
  402. }
  403. return x509.ParseCertificateRequest(block.Bytes)
  404. }
  405. // CertificateRequestFromFile returns the CertificateRequest from a given PEM-encoded file.
  406. // Returns an error if the file could not be read or if the CSR could not be parsed.
  407. func CertificateRequestFromFile(file string) (*x509.CertificateRequest, error) {
  408. pemBlock, err := ioutil.ReadFile(file)
  409. if err != nil {
  410. return nil, errors.Wrap(err, "failed to read file")
  411. }
  412. csr, err := parseCSRPEM(pemBlock)
  413. if err != nil {
  414. return nil, errors.Wrapf(err, "error reading certificate request file %s", file)
  415. }
  416. return csr, nil
  417. }
  418. // NewCSR creates a new CSR
  419. func NewCSR(cfg certutil.Config, key crypto.Signer) (*x509.CertificateRequest, error) {
  420. template := &x509.CertificateRequest{
  421. Subject: pkix.Name{
  422. CommonName: cfg.CommonName,
  423. Organization: cfg.Organization,
  424. },
  425. DNSNames: cfg.AltNames.DNSNames,
  426. IPAddresses: cfg.AltNames.IPs,
  427. }
  428. csrBytes, err := x509.CreateCertificateRequest(cryptorand.Reader, template, key)
  429. if err != nil {
  430. return nil, errors.Wrap(err, "failed to create a CSR")
  431. }
  432. return x509.ParseCertificateRequest(csrBytes)
  433. }
  434. // EncodeCertPEM returns PEM-endcoded certificate data
  435. func EncodeCertPEM(cert *x509.Certificate) []byte {
  436. block := pem.Block{
  437. Type: CertificateBlockType,
  438. Bytes: cert.Raw,
  439. }
  440. return pem.EncodeToMemory(&block)
  441. }
  442. // EncodePublicKeyPEM returns PEM-encoded public data
  443. func EncodePublicKeyPEM(key crypto.PublicKey) ([]byte, error) {
  444. der, err := x509.MarshalPKIXPublicKey(key)
  445. if err != nil {
  446. return []byte{}, err
  447. }
  448. block := pem.Block{
  449. Type: PublicKeyBlockType,
  450. Bytes: der,
  451. }
  452. return pem.EncodeToMemory(&block), nil
  453. }
  454. // NewPrivateKey creates an RSA private key
  455. func NewPrivateKey() (crypto.Signer, error) {
  456. return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
  457. }
  458. // NewSignedCert creates a signed certificate using the given CA certificate and key
  459. func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
  460. serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64))
  461. if err != nil {
  462. return nil, err
  463. }
  464. if len(cfg.CommonName) == 0 {
  465. return nil, errors.New("must specify a CommonName")
  466. }
  467. if len(cfg.Usages) == 0 {
  468. return nil, errors.New("must specify at least one ExtKeyUsage")
  469. }
  470. certTmpl := x509.Certificate{
  471. Subject: pkix.Name{
  472. CommonName: cfg.CommonName,
  473. Organization: cfg.Organization,
  474. },
  475. DNSNames: cfg.AltNames.DNSNames,
  476. IPAddresses: cfg.AltNames.IPs,
  477. SerialNumber: serial,
  478. NotBefore: caCert.NotBefore,
  479. NotAfter: time.Now().Add(kubeadmconstants.CertificateValidity).UTC(),
  480. KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
  481. ExtKeyUsage: cfg.Usages,
  482. }
  483. certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
  484. if err != nil {
  485. return nil, err
  486. }
  487. return x509.ParseCertificate(certDERBytes)
  488. }