Skip to content

Commit

Permalink
Add support for PKCS8 private keys in CA certs
Browse files Browse the repository at this point in the history
  • Loading branch information
maelk committed Jun 17, 2020
1 parent c97bdd7 commit 8338a6d
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
3 changes: 2 additions & 1 deletion controlplane/kubeadm/internal/workload_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package internal

import (
"context"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/tls"
Expand Down Expand Up @@ -311,7 +312,7 @@ func generateClientCert(caCertEncoded, caKeyEncoded []byte) (tls.Certificate, er
return tls.X509KeyPair(certs.EncodeCertPEM(x509Cert), certs.EncodePrivateKeyPEM(privKey))
}

func newClientCert(caCert *x509.Certificate, key *rsa.PrivateKey, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
func newClientCert(caCert *x509.Certificate, key *rsa.PrivateKey, caKey crypto.Signer) (*x509.Certificate, error) {
cfg := certs.Config{
CommonName: "cluster-api.x-k8s.io",
}
Expand Down
32 changes: 30 additions & 2 deletions util/certs/certs.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ limitations under the License.
package certs

import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"

"github.com/pkg/errors"
kerrors "k8s.io/apimachinery/pkg/util/errors"
)

// NewPrivateKey creates an RSA private key
Expand Down Expand Up @@ -76,11 +78,37 @@ func DecodeCertPEM(encoded []byte) (*x509.Certificate, error) {

// DecodePrivateKeyPEM attempts to return a decoded key or nil
// if the encoded input does not contain a private key.
func DecodePrivateKeyPEM(encoded []byte) (*rsa.PrivateKey, error) {
func DecodePrivateKeyPEM(encoded []byte) (crypto.Signer, error) {
block, _ := pem.Decode(encoded)
if block == nil {
return nil, nil
}

return x509.ParsePKCS1PrivateKey(block.Bytes)
errs := []error{}
pkcs1Key, pkcs1Err := x509.ParsePKCS1PrivateKey(block.Bytes)
if pkcs1Err == nil {
return crypto.Signer(pkcs1Key), nil
}
errs = append(errs, pkcs1Err)

// ParsePKCS1PrivateKey will fail with errors.New for many reasons
// including if the format is wrong, so we can retry with PKCS8 or EC
// https://golang.org/src/crypto/x509/pkcs1.go#L58
pkcs8Key, pkcs8Err := x509.ParsePKCS8PrivateKey(block.Bytes)
if pkcs8Err == nil {
pkcs8Signer, ok := pkcs8Key.(crypto.Signer)
if !ok {
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
return pkcs8Signer, nil
}
errs = append(errs, pkcs8Err)

ecKey, ecErr := x509.ParseECPrivateKey(block.Bytes)
if ecErr == nil {
return crypto.Signer(ecKey), nil
}
errs = append(errs, ecErr)

return nil, kerrors.NewAggregate(errs)
}
3 changes: 2 additions & 1 deletion util/certs/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package certs

import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
Expand Down Expand Up @@ -48,7 +49,7 @@ type Config struct {
}

// NewSignedCert creates a signed certificate using the given CA certificate and key.
func (cfg *Config) NewSignedCert(key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) {
func (cfg *Config) NewSignedCert(key *rsa.PrivateKey, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
if err != nil {
return nil, errors.Wrap(err, "failed to generate random integer for signed cerficate")
Expand Down
5 changes: 3 additions & 2 deletions util/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package kubeconfig

import (
"context"
"crypto/rsa"
"crypto"
"crypto/x509"
"fmt"
"time"
Expand Down Expand Up @@ -50,7 +50,8 @@ func FromSecret(ctx context.Context, c client.Reader, cluster client.ObjectKey)
}

// New creates a new Kubeconfig using the cluster name and specified endpoint.
func New(clusterName, endpoint string, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*api.Config, error) {
func New(clusterName, endpoint string, caCert *x509.Certificate, caKey crypto.Signer) (*api.Config, error) {

cfg := &certs.Config{
CommonName: "kubernetes-admin",
Organization: []string{"system:masters"},
Expand Down

0 comments on commit 8338a6d

Please sign in to comment.