@@ -22,23 +22,44 @@ modified to work independently of kubeadm internals like the configuration.
2222package pkiutil
2323
2424import (
25+ "crypto"
26+ cryptorand "crypto/rand"
2527 "crypto/rsa"
2628 "crypto/x509"
29+ "crypto/x509/pkix"
30+ "encoding/pem"
2731 "fmt"
2832 "net"
2933 "os"
3034 "path/filepath"
3135 "time"
3236
37+ "github.com/pkg/errors"
3338 "k8s.io/apimachinery/pkg/util/validation"
3439 certutil "k8s.io/client-go/util/cert"
40+ "k8s.io/client-go/util/keyutil"
41+ "math"
42+ "math/big"
3543 "sigs.k8s.io/etcdadm/apis"
3644 "sigs.k8s.io/etcdadm/constants"
3745)
3846
47+ const (
48+ // PrivateKeyBlockType is a possible value for pem.Block.Type.
49+ PrivateKeyBlockType = "PRIVATE KEY"
50+ // PublicKeyBlockType is a possible value for pem.Block.Type.
51+ PublicKeyBlockType = "PUBLIC KEY"
52+ // CertificateBlockType is a possible value for pem.Block.Type.
53+ CertificateBlockType = "CERTIFICATE"
54+ // RSAPrivateKeyBlockType is a possible value for pem.Block.Type.
55+ RSAPrivateKeyBlockType = "RSA PRIVATE KEY"
56+ rsaKeySize = 2048
57+ certificateValidity = time .Hour * 24 * 365
58+ )
59+
3960// NewCertificateAuthority creates new certificate and private key for the certificate authority
4061func NewCertificateAuthority () (* x509.Certificate , * rsa.PrivateKey , error ) {
41- key , err := certutil . NewPrivateKey ()
62+ key , err := NewPrivateKey ()
4263 if err != nil {
4364 return nil , nil , fmt .Errorf ("unable to create private key [%v]" , err )
4465 }
@@ -56,12 +77,12 @@ func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) {
5677
5778// NewCertAndKey creates new certificate and key by passing the certificate authority certificate and key
5879func NewCertAndKey (caCert * x509.Certificate , caKey * rsa.PrivateKey , config certutil.Config ) (* x509.Certificate , * rsa.PrivateKey , error ) {
59- key , err := certutil . NewPrivateKey ()
80+ key , err := NewPrivateKey ()
6081 if err != nil {
6182 return nil , nil , fmt .Errorf ("unable to create private key [%v]" , err )
6283 }
6384
64- cert , err := certutil . NewSignedCert (config , key , caCert , caKey )
85+ cert , err := NewSignedCert (& config , key , caCert , caKey )
6586 if err != nil {
6687 return nil , nil , fmt .Errorf ("unable to sign certificate [%v]" , err )
6788 }
@@ -95,7 +116,7 @@ func WriteCert(pkiPath, name string, cert *x509.Certificate) error {
95116 }
96117
97118 certificatePath := pathForCert (pkiPath , name )
98- if err := certutil .WriteCert (certificatePath , certutil . EncodeCertPEM (cert )); err != nil {
119+ if err := certutil .WriteCert (certificatePath , EncodeCertPEM (cert )); err != nil {
99120 return fmt .Errorf ("unable to write certificate to file %q: [%v]" , certificatePath , err )
100121 }
101122
@@ -109,7 +130,7 @@ func WriteKey(pkiPath, name string, key *rsa.PrivateKey) error {
109130 }
110131
111132 privateKeyPath := pathForKey (pkiPath , name )
112- if err := certutil .WriteKey (privateKeyPath , certutil . EncodePrivateKeyPEM (key )); err != nil {
133+ if err := keyutil .WriteKey (privateKeyPath , EncodePrivateKeyPEM (key )); err != nil {
113134 return fmt .Errorf ("unable to write private key to file %q: [%v]" , privateKeyPath , err )
114135 }
115136
@@ -122,12 +143,12 @@ func WritePublicKey(pkiPath, name string, key *rsa.PublicKey) error {
122143 return fmt .Errorf ("public key cannot be nil when writing to file" )
123144 }
124145
125- publicKeyBytes , err := certutil . EncodePublicKeyPEM (key )
146+ publicKeyBytes , err := EncodePublicKeyPEM (key )
126147 if err != nil {
127148 return err
128149 }
129150 publicKeyPath := pathForPublicKey (pkiPath , name )
130- if err := certutil .WriteKey (publicKeyPath , publicKeyBytes ); err != nil {
151+ if err := keyutil .WriteKey (publicKeyPath , publicKeyBytes ); err != nil {
131152 return fmt .Errorf ("unable to write public key to file %q: [%v]" , publicKeyPath , err )
132153 }
133154
@@ -194,7 +215,7 @@ func TryLoadKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, error) {
194215 privateKeyPath := pathForKey (pkiPath , name )
195216
196217 // Parse the private key from a file
197- privKey , err := certutil .PrivateKeyFromFile (privateKeyPath )
218+ privKey , err := keyutil .PrivateKeyFromFile (privateKeyPath )
198219 if err != nil {
199220 return nil , fmt .Errorf ("couldn't load the private key file %s: %v" , privateKeyPath , err )
200221 }
@@ -216,15 +237,15 @@ func TryLoadPrivatePublicKeyFromDisk(pkiPath, name string) (*rsa.PrivateKey, *rs
216237 privateKeyPath := pathForKey (pkiPath , name )
217238
218239 // Parse the private key from a file
219- privKey , err := certutil .PrivateKeyFromFile (privateKeyPath )
240+ privKey , err := keyutil .PrivateKeyFromFile (privateKeyPath )
220241 if err != nil {
221242 return nil , nil , fmt .Errorf ("couldn't load the private key file %s: %v" , privateKeyPath , err )
222243 }
223244
224245 publicKeyPath := pathForPublicKey (pkiPath , name )
225246
226247 // Parse the public key from a file
227- pubKeys , err := certutil .PublicKeysFromFile (publicKeyPath )
248+ pubKeys , err := keyutil .PublicKeysFromFile (publicKeyPath )
228249 if err != nil {
229250 return nil , nil , fmt .Errorf ("couldn't load the public key file %s: %v" , publicKeyPath , err )
230251 }
@@ -296,3 +317,72 @@ func appendSANsToAltNames(altNames *certutil.AltNames, SANs []string, certName s
296317 }
297318 }
298319}
320+
321+ // NewPrivateKey creates an RSA private key
322+ func NewPrivateKey () (* rsa.PrivateKey , error ) {
323+ return rsa .GenerateKey (cryptorand .Reader , rsaKeySize )
324+ }
325+
326+ // NewSignedCert creates a signed certificate using the given CA certificate and key
327+ func NewSignedCert (cfg * certutil.Config , key crypto.Signer , caCert * x509.Certificate , caKey crypto.Signer ) (* x509.Certificate , error ) {
328+ serial , err := cryptorand .Int (cryptorand .Reader , new (big.Int ).SetInt64 (math .MaxInt64 ))
329+ if err != nil {
330+ return nil , err
331+ }
332+ if len (cfg .CommonName ) == 0 {
333+ return nil , errors .New ("must specify a CommonName" )
334+ }
335+ if len (cfg .Usages ) == 0 {
336+ return nil , errors .New ("must specify at least one ExtKeyUsage" )
337+ }
338+
339+ certTmpl := x509.Certificate {
340+ Subject : pkix.Name {
341+ CommonName : cfg .CommonName ,
342+ Organization : cfg .Organization ,
343+ },
344+ DNSNames : cfg .AltNames .DNSNames ,
345+ IPAddresses : cfg .AltNames .IPs ,
346+ SerialNumber : serial ,
347+ NotBefore : caCert .NotBefore ,
348+ NotAfter : time .Now ().Add (certificateValidity ).UTC (),
349+ KeyUsage : x509 .KeyUsageKeyEncipherment | x509 .KeyUsageDigitalSignature ,
350+ ExtKeyUsage : cfg .Usages ,
351+ }
352+ certDERBytes , err := x509 .CreateCertificate (cryptorand .Reader , & certTmpl , caCert , key .Public (), caKey )
353+ if err != nil {
354+ return nil , err
355+ }
356+ return x509 .ParseCertificate (certDERBytes )
357+ }
358+
359+ // EncodeCertPEM returns PEM-endcoded certificate data
360+ func EncodeCertPEM (cert * x509.Certificate ) []byte {
361+ block := pem.Block {
362+ Type : CertificateBlockType ,
363+ Bytes : cert .Raw ,
364+ }
365+ return pem .EncodeToMemory (& block )
366+ }
367+
368+ // EncodePublicKeyPEM returns PEM-encoded public data
369+ func EncodePublicKeyPEM (key crypto.PublicKey ) ([]byte , error ) {
370+ der , err := x509 .MarshalPKIXPublicKey (key )
371+ if err != nil {
372+ return []byte {}, err
373+ }
374+ block := pem.Block {
375+ Type : PublicKeyBlockType ,
376+ Bytes : der ,
377+ }
378+ return pem .EncodeToMemory (& block ), nil
379+ }
380+
381+ // EncodePrivateKeyPEM returns PEM-encoded private key data
382+ func EncodePrivateKeyPEM (key * rsa.PrivateKey ) []byte {
383+ block := pem.Block {
384+ Type : RSAPrivateKeyBlockType , // "RSA PRIVATE KEY"
385+ Bytes : x509 .MarshalPKCS1PrivateKey (key ),
386+ }
387+ return pem .EncodeToMemory (& block )
388+ }
0 commit comments