diff options
Diffstat (limited to 'vendor/k8s.io/client-go/util/cert')
-rw-r--r-- | vendor/k8s.io/client-go/util/cert/OWNERS | 9 | ||||
-rw-r--r-- | vendor/k8s.io/client-go/util/cert/cert.go | 157 | ||||
-rw-r--r-- | vendor/k8s.io/client-go/util/cert/io.go | 60 | ||||
-rw-r--r-- | vendor/k8s.io/client-go/util/cert/pem.go | 208 |
4 files changed, 68 insertions, 366 deletions
diff --git a/vendor/k8s.io/client-go/util/cert/OWNERS b/vendor/k8s.io/client-go/util/cert/OWNERS new file mode 100644 index 000000000..3cf036438 --- /dev/null +++ b/vendor/k8s.io/client-go/util/cert/OWNERS @@ -0,0 +1,9 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: +- sig-auth-certificates-approvers +reviewers: +- sig-auth-certificates-reviewers +labels: +- sig/auth + diff --git a/vendor/k8s.io/client-go/util/cert/cert.go b/vendor/k8s.io/client-go/util/cert/cert.go index fb7f5facc..9fd097af5 100644 --- a/vendor/k8s.io/client-go/util/cert/cert.go +++ b/vendor/k8s.io/client-go/util/cert/cert.go @@ -18,26 +18,25 @@ package cert import ( "bytes" - "crypto/ecdsa" - "crypto/elliptic" + "crypto" cryptorand "crypto/rand" "crypto/rsa" "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "errors" "fmt" - "math" + "io/ioutil" "math/big" "net" + "path" + "strings" "time" -) -const ( - rsaKeySize = 2048 - duration365d = time.Hour * 24 * 365 + "k8s.io/client-go/util/keyutil" ) +const duration365d = time.Hour * 24 * 365 + // Config contains the basic fields required for creating a certificate type Config struct { CommonName string @@ -54,13 +53,8 @@ type AltNames struct { IPs []net.IP } -// NewPrivateKey creates an RSA private key -func NewPrivateKey() (*rsa.PrivateKey, error) { - return rsa.GenerateKey(cryptorand.Reader, rsaKeySize) -} - // NewSelfSignedCACert creates a CA certificate -func NewSelfSignedCACert(cfg Config, key *rsa.PrivateKey) (*x509.Certificate, error) { +func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) { now := time.Now() tmpl := x509.Certificate{ SerialNumber: new(big.Int).SetInt64(0), @@ -72,7 +66,7 @@ func NewSelfSignedCACert(cfg Config, key *rsa.PrivateKey) (*x509.Certificate, er NotAfter: now.Add(duration365d * 10).UTC(), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, - IsCA: true, + IsCA: true, } certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key) @@ -82,62 +76,40 @@ func NewSelfSignedCACert(cfg Config, key *rsa.PrivateKey) (*x509.Certificate, er return x509.ParseCertificate(certDERBytes) } -// NewSignedCert creates a signed certificate using the given CA certificate and key -func NewSignedCert(cfg Config, key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) { - serial, err := cryptorand.Int(cryptorand.Reader, new(big.Int).SetInt64(math.MaxInt64)) - if err != nil { - return nil, err - } - if len(cfg.CommonName) == 0 { - return nil, errors.New("must specify a CommonName") - } - if len(cfg.Usages) == 0 { - return nil, errors.New("must specify at least one ExtKeyUsage") - } - - certTmpl := x509.Certificate{ - Subject: pkix.Name{ - CommonName: cfg.CommonName, - Organization: cfg.Organization, - }, - DNSNames: cfg.AltNames.DNSNames, - IPAddresses: cfg.AltNames.IPs, - SerialNumber: serial, - NotBefore: caCert.NotBefore, - NotAfter: time.Now().Add(duration365d).UTC(), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: cfg.Usages, - } - certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey) - if err != nil { - return nil, err - } - return x509.ParseCertificate(certDERBytes) +// GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host. +// Host may be an IP or a DNS name +// You may also specify additional subject alt names (either ip or dns names) for the certificate. +func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) { + return GenerateSelfSignedCertKeyWithFixtures(host, alternateIPs, alternateDNS, "") } -// MakeEllipticPrivateKeyPEM creates an ECDSA private key -func MakeEllipticPrivateKeyPEM() ([]byte, error) { - privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader) - if err != nil { - return nil, err - } - - derBytes, err := x509.MarshalECPrivateKey(privateKey) - if err != nil { - return nil, err +// GenerateSelfSignedCertKeyWithFixtures creates a self-signed certificate and key for the given host. +// Host may be an IP or a DNS name. You may also specify additional subject alt names (either ip or dns names) +// for the certificate. +// +// If fixtureDirectory is non-empty, it is a directory path which can contain pre-generated certs. The format is: +// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.crt +// <host>_<ip>-<ip>_<alternateDNS>-<alternateDNS>.key +// Certs/keys not existing in that directory are created. +func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, alternateDNS []string, fixtureDirectory string) ([]byte, []byte, error) { + validFrom := time.Now().Add(-time.Hour) // valid an hour earlier to avoid flakes due to clock skew + maxAge := time.Hour * 24 * 365 // one year self-signed certs + + baseName := fmt.Sprintf("%s_%s_%s", host, strings.Join(ipsToStrings(alternateIPs), "-"), strings.Join(alternateDNS, "-")) + certFixturePath := path.Join(fixtureDirectory, baseName+".crt") + keyFixturePath := path.Join(fixtureDirectory, baseName+".key") + if len(fixtureDirectory) > 0 { + cert, err := ioutil.ReadFile(certFixturePath) + if err == nil { + key, err := ioutil.ReadFile(keyFixturePath) + if err == nil { + return cert, key, nil + } + return nil, nil, fmt.Errorf("cert %s can be read, but key %s cannot: %v", certFixturePath, keyFixturePath, err) + } + maxAge = 100 * time.Hour * 24 * 365 // 100 years fixtures } - privateKeyPemBlock := &pem.Block{ - Type: ECPrivateKeyBlockType, - Bytes: derBytes, - } - return pem.EncodeToMemory(privateKeyPemBlock), nil -} - -// GenerateSelfSignedCertKey creates a self-signed certificate and key for the given host. -// Host may be an IP or a DNS name -// You may also specify additional subject alt names (either ip or dns names) for the certificate -func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS []string) ([]byte, []byte, error) { caKey, err := rsa.GenerateKey(cryptorand.Reader, 2048) if err != nil { return nil, nil, err @@ -148,12 +120,12 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS Subject: pkix.Name{ CommonName: fmt.Sprintf("%s-ca@%d", host, time.Now().Unix()), }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 365), + NotBefore: validFrom, + NotAfter: validFrom.Add(maxAge), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, - IsCA: true, + IsCA: true, } caDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &caTemplate, &caTemplate, &caKey.PublicKey, caKey) @@ -176,8 +148,8 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS Subject: pkix.Name{ CommonName: fmt.Sprintf("%s@%d", host, time.Now().Unix()), }, - NotBefore: time.Now(), - NotAfter: time.Now().Add(time.Hour * 24 * 365), + NotBefore: validFrom, + NotAfter: validFrom.Add(maxAge), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, @@ -209,37 +181,26 @@ func GenerateSelfSignedCertKey(host string, alternateIPs []net.IP, alternateDNS // Generate key keyBuffer := bytes.Buffer{} - if err := pem.Encode(&keyBuffer, &pem.Block{Type: RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { + if err := pem.Encode(&keyBuffer, &pem.Block{Type: keyutil.RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { return nil, nil, err } + if len(fixtureDirectory) > 0 { + if err := ioutil.WriteFile(certFixturePath, certBuffer.Bytes(), 0644); err != nil { + return nil, nil, fmt.Errorf("failed to write cert fixture to %s: %v", certFixturePath, err) + } + if err := ioutil.WriteFile(keyFixturePath, keyBuffer.Bytes(), 0644); err != nil { + return nil, nil, fmt.Errorf("failed to write key fixture to %s: %v", certFixturePath, err) + } + } + return certBuffer.Bytes(), keyBuffer.Bytes(), nil } -// FormatBytesCert receives byte array certificate and formats in human-readable format -func FormatBytesCert(cert []byte) (string, error) { - block, _ := pem.Decode(cert) - c, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return "", fmt.Errorf("failed to parse certificate [%v]", err) +func ipsToStrings(ips []net.IP) []string { + ss := make([]string, 0, len(ips)) + for _, ip := range ips { + ss = append(ss, ip.String()) } - return FormatCert(c), nil -} - -// FormatCert receives certificate and formats in human-readable format -func FormatCert(c *x509.Certificate) string { - var ips []string - for _, ip := range c.IPAddresses { - ips = append(ips, ip.String()) - } - altNames := append(ips, c.DNSNames...) - res := fmt.Sprintf( - "Issuer: CN=%s | Subject: CN=%s | CA: %t\n", - c.Issuer.CommonName, c.Subject.CommonName, c.IsCA, - ) - res += fmt.Sprintf("Not before: %s Not After: %s", c.NotBefore, c.NotAfter) - if len(altNames) > 0 { - res += fmt.Sprintf("\nAlternate Names: %v", altNames) - } - return res + return ss } diff --git a/vendor/k8s.io/client-go/util/cert/io.go b/vendor/k8s.io/client-go/util/cert/io.go index a41f8054a..5efb24894 100644 --- a/vendor/k8s.io/client-go/util/cert/io.go +++ b/vendor/k8s.io/client-go/util/cert/io.go @@ -69,38 +69,6 @@ func WriteCert(certPath string, data []byte) error { return ioutil.WriteFile(certPath, data, os.FileMode(0644)) } -// WriteKey writes the pem-encoded key data to keyPath. -// The key file will be created with file mode 0600. -// If the key file already exists, it will be overwritten. -// The parent directory of the keyPath will be created as needed with file mode 0755. -func WriteKey(keyPath string, data []byte) error { - if err := os.MkdirAll(filepath.Dir(keyPath), os.FileMode(0755)); err != nil { - return err - } - return ioutil.WriteFile(keyPath, data, os.FileMode(0600)) -} - -// LoadOrGenerateKeyFile looks for a key in the file at the given path. If it -// can't find one, it will generate a new key and store it there. -func LoadOrGenerateKeyFile(keyPath string) (data []byte, wasGenerated bool, err error) { - loadedData, err := ioutil.ReadFile(keyPath) - if err == nil { - return loadedData, false, err - } - if !os.IsNotExist(err) { - return nil, false, fmt.Errorf("error loading key from %s: %v", keyPath, err) - } - - generatedData, err := MakeEllipticPrivateKeyPEM() - if err != nil { - return nil, false, fmt.Errorf("error generating key: %v", err) - } - if err := WriteKey(keyPath, generatedData); err != nil { - return nil, false, fmt.Errorf("error writing key to %s: %v", keyPath, err) - } - return generatedData, true, nil -} - // NewPool returns an x509.CertPool containing the certificates in the given PEM-encoded file. // Returns an error if the file could not be read, a certificate could not be parsed, or if the file does not contain any certificates func NewPool(filename string) (*x509.CertPool, error) { @@ -128,31 +96,3 @@ func CertsFromFile(file string) ([]*x509.Certificate, error) { } return certs, nil } - -// PrivateKeyFromFile returns the private key in rsa.PrivateKey or ecdsa.PrivateKey format from a given PEM-encoded file. -// Returns an error if the file could not be read or if the private key could not be parsed. -func PrivateKeyFromFile(file string) (interface{}, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - key, err := ParsePrivateKeyPEM(data) - if err != nil { - return nil, fmt.Errorf("error reading private key file %s: %v", file, err) - } - return key, nil -} - -// PublicKeysFromFile returns the public keys in rsa.PublicKey or ecdsa.PublicKey format from a given PEM-encoded file. -// Reads public keys from both public and private key files. -func PublicKeysFromFile(file string) ([]interface{}, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - keys, err := ParsePublicKeysPEM(data) - if err != nil { - return nil, fmt.Errorf("error reading public key file %s: %v", file, err) - } - return keys, nil -} diff --git a/vendor/k8s.io/client-go/util/cert/pem.go b/vendor/k8s.io/client-go/util/cert/pem.go index b99e36651..9185e2e22 100644 --- a/vendor/k8s.io/client-go/util/cert/pem.go +++ b/vendor/k8s.io/client-go/util/cert/pem.go @@ -17,136 +17,18 @@ limitations under the License. package cert import ( - "crypto/ecdsa" - "crypto/rsa" "crypto/x509" "encoding/pem" "errors" - "fmt" ) const ( - // ECPrivateKeyBlockType is a possible value for pem.Block.Type. - ECPrivateKeyBlockType = "EC PRIVATE KEY" - // RSAPrivateKeyBlockType is a possible value for pem.Block.Type. - RSAPrivateKeyBlockType = "RSA PRIVATE KEY" - // PrivateKeyBlockType is a possible value for pem.Block.Type. - PrivateKeyBlockType = "PRIVATE KEY" - // PublicKeyBlockType is a possible value for pem.Block.Type. - PublicKeyBlockType = "PUBLIC KEY" // CertificateBlockType is a possible value for pem.Block.Type. CertificateBlockType = "CERTIFICATE" // CertificateRequestBlockType is a possible value for pem.Block.Type. CertificateRequestBlockType = "CERTIFICATE REQUEST" ) -// EncodePublicKeyPEM returns PEM-encoded public data -func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) { - der, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - return []byte{}, err - } - block := pem.Block{ - Type: PublicKeyBlockType, - Bytes: der, - } - return pem.EncodeToMemory(&block), nil -} - -// EncodePrivateKeyPEM returns PEM-encoded private key data -func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte { - block := pem.Block{ - Type: RSAPrivateKeyBlockType, - Bytes: x509.MarshalPKCS1PrivateKey(key), - } - return pem.EncodeToMemory(&block) -} - -// EncodeCertPEM returns PEM-endcoded certificate data -func EncodeCertPEM(cert *x509.Certificate) []byte { - block := pem.Block{ - Type: CertificateBlockType, - Bytes: cert.Raw, - } - return pem.EncodeToMemory(&block) -} - -// ParsePrivateKeyPEM returns a private key parsed from a PEM block in the supplied data. -// Recognizes PEM blocks for "EC PRIVATE KEY", "RSA PRIVATE KEY", or "PRIVATE KEY" -func ParsePrivateKeyPEM(keyData []byte) (interface{}, error) { - var privateKeyPemBlock *pem.Block - for { - privateKeyPemBlock, keyData = pem.Decode(keyData) - if privateKeyPemBlock == nil { - break - } - - switch privateKeyPemBlock.Type { - case ECPrivateKeyBlockType: - // ECDSA Private Key in ASN.1 format - if key, err := x509.ParseECPrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - case RSAPrivateKeyBlockType: - // RSA Private Key in PKCS#1 format - if key, err := x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - case PrivateKeyBlockType: - // RSA or ECDSA Private Key in unencrypted PKCS#8 format - if key, err := x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes); err == nil { - return key, nil - } - } - - // tolerate non-key PEM blocks for compatibility with things like "EC PARAMETERS" blocks - // originally, only the first PEM block was parsed and expected to be a key block - } - - // we read all the PEM blocks and didn't recognize one - return nil, fmt.Errorf("data does not contain a valid RSA or ECDSA private key") -} - -// ParsePublicKeysPEM is a helper function for reading an array of rsa.PublicKey or ecdsa.PublicKey from a PEM-encoded byte array. -// Reads public keys from both public and private key files. -func ParsePublicKeysPEM(keyData []byte) ([]interface{}, error) { - var block *pem.Block - keys := []interface{}{} - for { - // read the next block - block, keyData = pem.Decode(keyData) - if block == nil { - break - } - - // test block against parsing functions - if privateKey, err := parseRSAPrivateKey(block.Bytes); err == nil { - keys = append(keys, &privateKey.PublicKey) - continue - } - if publicKey, err := parseRSAPublicKey(block.Bytes); err == nil { - keys = append(keys, publicKey) - continue - } - if privateKey, err := parseECPrivateKey(block.Bytes); err == nil { - keys = append(keys, &privateKey.PublicKey) - continue - } - if publicKey, err := parseECPublicKey(block.Bytes); err == nil { - keys = append(keys, publicKey) - continue - } - - // tolerate non-key PEM blocks for backwards compatibility - // originally, only the first PEM block was parsed and expected to be a key block - } - - if len(keys) == 0 { - return nil, fmt.Errorf("data does not contain any valid RSA or ECDSA public keys") - } - return keys, nil -} - // ParseCertsPEM returns the x509.Certificates contained in the given PEM-encoded byte array // Returns an error if a certificate could not be parsed, or if the data does not contain any certificates func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { @@ -177,93 +59,3 @@ func ParseCertsPEM(pemCerts []byte) ([]*x509.Certificate, error) { } return certs, nil } - -// parseRSAPublicKey parses a single RSA public key from the provided data -func parseRSAPublicKey(data []byte) (*rsa.PublicKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { - if cert, err := x509.ParseCertificate(data); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - // Test if parsed key is an RSA Public Key - var pubKey *rsa.PublicKey - var ok bool - if pubKey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid RSA Public Key") - } - - return pubKey, nil -} - -// parseRSAPrivateKey parses a single RSA private key from the provided data -func parseRSAPrivateKey(data []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(data); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(data); err != nil { - return nil, err - } - } - - // Test if parsed key is an RSA Private Key - var privKey *rsa.PrivateKey - var ok bool - if privKey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid RSA Private Key") - } - - return privKey, nil -} - -// parseECPublicKey parses a single ECDSA public key from the provided data -func parseECPublicKey(data []byte) (*ecdsa.PublicKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(data); err != nil { - if cert, err := x509.ParseCertificate(data); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - // Test if parsed key is an ECDSA Public Key - var pubKey *ecdsa.PublicKey - var ok bool - if pubKey, ok = parsedKey.(*ecdsa.PublicKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid ECDSA Public Key") - } - - return pubKey, nil -} - -// parseECPrivateKey parses a single ECDSA private key from the provided data -func parseECPrivateKey(data []byte) (*ecdsa.PrivateKey, error) { - var err error - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParseECPrivateKey(data); err != nil { - return nil, err - } - - // Test if parsed key is an ECDSA Private Key - var privKey *ecdsa.PrivateKey - var ok bool - if privKey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { - return nil, fmt.Errorf("data doesn't contain valid ECDSA Private Key") - } - - return privKey, nil -} |