Skip to content

Commit

Permalink
Support PKCS1 and PKCS8 private keys
Browse files Browse the repository at this point in the history
For server ca cert
  • Loading branch information
lkysow committed Nov 4, 2021
1 parent a08ddb0 commit 3010ad2
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 35 deletions.
19 changes: 19 additions & 0 deletions control-plane/helper/cert/tls_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"time"
)

// NOTE: A lot of this code is taken from
// https://github.com/hashicorp/consul/blob/44c023a3020fdd139c5be330f318a3c12339f08e/agent/connect/parsing.go.

// GenerateCA generates a CA with the provided
// common name valid for 10 years. It returns the private key as
// a crypto.Signer and a PEM string and certificate
Expand Down Expand Up @@ -162,6 +165,22 @@ func ParseSigner(pemValue string) (crypto.Signer, error) {
switch block.Type {
case "EC PRIVATE KEY":
return x509.ParseECPrivateKey(block.Bytes)

case "RSA PRIVATE KEY":
return x509.ParsePKCS1PrivateKey(block.Bytes)

case "PRIVATE KEY":
signer, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
pk, ok := signer.(crypto.Signer)
if !ok {
return nil, fmt.Errorf("private key is not a valid format")
}

return pk, nil

default:
return nil, fmt.Errorf("unknown PEM block type for signing key: %s", block.Type)
}
Expand Down
176 changes: 141 additions & 35 deletions control-plane/subcommand/tls-init/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,50 +58,78 @@ func TestRun_FlagValidation(t *testing.T) {
}

func TestRun_CreatesServerCertificatesWithExistingCAAsFiles(t *testing.T) {
ui := cli.NewMockUi()
cmd := Command{UI: ui}
k8s := fake.NewSimpleClientset()
cmd.clientset = k8s

ca, err := ioutil.TempFile("", "")
require.NoError(t, err)
defer os.RemoveAll(ca.Name())
err = ioutil.WriteFile(ca.Name(), []byte(caCert), 0644)
require.NoError(t, err)
cases := []struct {
caCert string
caKey string
algorithm string
}{
{
caCert: caCert,
caKey: caKey,
algorithm: "ec",
},
{
caCert: caCertRSA,
caKey: caKeyRSA,
algorithm: "rsa",
},
{
caCert: caCertRSA,
caKey: caKeyPKCS8,
algorithm: "pkcs8",
},
}

key, err := ioutil.TempFile("", "")
require.NoError(t, err)
defer os.RemoveAll(key.Name())
err = ioutil.WriteFile(key.Name(), []byte(caKey), 0644)
require.NoError(t, err)
for _, c := range cases {
t.Run(c.algorithm, func(t *testing.T) {
ui := cli.NewMockUi()
cmd := Command{UI: ui}
k8s := fake.NewSimpleClientset()
cmd.clientset = k8s

flags := []string{"-name-prefix", "consul", "-ca", ca.Name(), "-key", key.Name()}
ca, err := ioutil.TempFile("", "")
require.NoError(t, err)
defer os.RemoveAll(ca.Name())
err = ioutil.WriteFile(ca.Name(), []byte(c.caCert), 0644)
require.NoError(t, err)

exitCode := cmd.Run(flags)
require.Equal(t, 0, exitCode)
key, err := ioutil.TempFile("", "")
require.NoError(t, err)
defer os.RemoveAll(key.Name())
err = ioutil.WriteFile(key.Name(), []byte(c.caKey), 0644)
require.NoError(t, err)

caCertBlock, _ := pem.Decode([]byte(caCert))
caCertificate, err := x509.ParseCertificate(caCertBlock.Bytes)
require.NoError(t, err)
flags := []string{"-name-prefix", "consul", "-ca", ca.Name(), "-key", key.Name()}

serverCertSecret, err := k8s.CoreV1().Secrets("default").Get(context.Background(), "consul-server-cert", metav1.GetOptions{})
require.NoError(t, err)
serverCert := serverCertSecret.Data[corev1.TLSCertKey]
serverKey := serverCertSecret.Data[corev1.TLSPrivateKeyKey]
exitCode := cmd.Run(flags)
require.Equal(t, 0, exitCode)

certBlock, _ := pem.Decode(serverCert)
certificate, err := x509.ParseCertificate(certBlock.Bytes)
require.NoError(t, err)
require.False(t, certificate.IsCA)
require.Equal(t, []string{"server.dc1.consul", "localhost"}, certificate.DNSNames)
require.Equal(t, []net.IP{net.ParseIP("127.0.0.1").To4()}, certificate.IPAddresses)
caCertBlock, _ := pem.Decode([]byte(c.caCert))
caCertificate, err := x509.ParseCertificate(caCertBlock.Bytes)
require.NoError(t, err)

keyBlock, _ := pem.Decode(serverKey)
privateKey, err := x509.ParseECPrivateKey(keyBlock.Bytes)
require.NoError(t, err)
require.Equal(t, &privateKey.PublicKey, certificate.PublicKey)
serverCertSecret, err := k8s.CoreV1().Secrets("default").Get(context.Background(), "consul-server-cert", metav1.GetOptions{})
require.NoError(t, err)
serverCert := serverCertSecret.Data[corev1.TLSCertKey]
serverKey := serverCertSecret.Data[corev1.TLSPrivateKeyKey]

require.NoError(t, certificate.CheckSignatureFrom(caCertificate))
certBlock, _ := pem.Decode(serverCert)
certificate, err := x509.ParseCertificate(certBlock.Bytes)
require.NoError(t, err)
require.False(t, certificate.IsCA)
require.Equal(t, []string{"server.dc1.consul", "localhost"}, certificate.DNSNames)
require.Equal(t, []net.IP{net.ParseIP("127.0.0.1").To4()}, certificate.IPAddresses)

keyBlock, _ := pem.Decode(serverKey)
privateKey, err := x509.ParseECPrivateKey(keyBlock.Bytes)
require.NoError(t, err)
require.Equal(t, &privateKey.PublicKey, certificate.PublicKey)

require.NoError(t, certificate.CheckSignatureFrom(caCertificate))

})
}
}

func TestRun_UpdatesServerCertificatesWithExistingCertsAsFiles(t *testing.T) {
Expand Down Expand Up @@ -560,4 +588,82 @@ MHcCAQEEINVuQ1fmOWH5HDG7wEqB1KObSs7q26czY7P+WLhtLDZPoAoGCCqGSM49
AwEHoUQDQgAEu6FUB4WbJpJmXe9cXC2vf9xlvLB5aj9lfAzg4uPL+yXHUpHMYyZy
tdsZa0jHMVkDIrNoL8nmxu6X578xNY304w==
-----END EC PRIVATE KEY-----`

caCertRSA string = `-----BEGIN CERTIFICATE-----
MIIDGjCCAgICCQC9IJfDAbKSIjANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQGEwJD
QTEZMBcGA1UECAwQQnJpdGlzaCBDb2x1bWJpYTERMA8GA1UEBwwIVmFuY292ZXIx
EjAQBgNVBAoMCUhhc2hpQ29ycDAeFw0yMTExMDQyMjQ0MjJaFw0yMTEyMDQyMjQ0
MjJaME8xCzAJBgNVBAYTAkNBMRkwFwYDVQQIDBBCcml0aXNoIENvbHVtYmlhMREw
DwYDVQQHDAhWYW5jb3ZlcjESMBAGA1UECgwJSGFzaGlDb3JwMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxTVd5sFGuVOZxkPv3tE69khUToVcRb85NRWW
eWBSyrTE4UWr06kG4reSTVrGgR2hojrP4nzVynu7EslCJITb6Df5sn34bKVDpqWJ
gDFJoEYoTzajRxEDjSkwau+iPhuaJ6pB97+JimOg0Jnqe0QVZ2NtjwgpXYSGkevn
iVxZHaurLxnhDry5KyDJ79p48c7aKNxAxU2syrhKkrWNJaCg4WVTOc/eQU4elUZb
TwYIZ/Zi4gOkS+vz0ceggRmXg5MzYT6cBlccHRrA7BaSRkoD7bNbDh+mRTz67UgO
KUjIi+o1TsUhmvO2Know+zIGd1mfAf9qFT+4KXPFh3yN5DeMkQIDAQABMA0GCSqG
SIb3DQEBCwUAA4IBAQC6LAK0NnmnxuWvKZano3hI9DPRlktB4LVfYSBNFnQllxUC
ZYBIouJXFKK4dTccMkgLlQU7hFXj/YWdSRmf78w/w0GbWYAnUDnGfYro7+ZRUtFV
v7FT+xV2hFe+2cp4+btux5kfqD6OC58Gp9FWXMzRhJCWSDAk2rIYJ2MM7og+ad+Q
mJAYoOBLuY1rXc080v0Vdcl3tQ24UvvvLhuyOyL795OaZZl3uVvbaNHpM8lfJNEg
XfsbHpePEKd9ORLV6jUirl0YheqY8Mdx5hfwFHi1FL4eH6vzRm6GF2hUkkfjOUGO
x8JijLHx5rnkFyNOynhoH8QlwYeMPZbc4js7DWuG
-----END CERTIFICATE-----`

caKeyRSA string = `-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAxTVd5sFGuVOZxkPv3tE69khUToVcRb85NRWWeWBSyrTE4UWr
06kG4reSTVrGgR2hojrP4nzVynu7EslCJITb6Df5sn34bKVDpqWJgDFJoEYoTzaj
RxEDjSkwau+iPhuaJ6pB97+JimOg0Jnqe0QVZ2NtjwgpXYSGkevniVxZHaurLxnh
Dry5KyDJ79p48c7aKNxAxU2syrhKkrWNJaCg4WVTOc/eQU4elUZbTwYIZ/Zi4gOk
S+vz0ceggRmXg5MzYT6cBlccHRrA7BaSRkoD7bNbDh+mRTz67UgOKUjIi+o1TsUh
mvO2Know+zIGd1mfAf9qFT+4KXPFh3yN5DeMkQIDAQABAoH/E0Ii6WX2giKn4bTA
uAG2wFZP5Vsgp68E5yo0h6Xgb+s3Tsh+/yyCf6FtqCA1QmaiYjVcF8IZHqz2l98P
loFi+Ep/F+81U2bQNHX1947Yoc44IYQ0bbw7nI1pLQg5z9biNv1pc8hApkMUcUqW
m3MKpA4RpOYnI/rNKXLgKYnbKgptyniJSyFm+pOLgpSnwZIiSIBqHnppHS1b8Bjq
H2ZYqEYNB7dHLu0HpHB1zGVC4CAzmBqtLw4fNDp1lsHTis0SJpRuBiD5IZU6+1TS
QvgkmfJKStRFIT+0YRap0J+rSYtqwPalPPbV4ePfZTpj4d9Ll0Xx97Pn3oinUQgl
auhBAoGBAOIeH5tEaj3U8DTNGGMWmMBVediJEhqDITyjPVGoKZAt+29tqwlDg+aw
hEEGgaIOPE+mQ3CEbvJnRC4Z/ntYRJpv1arBziRQKfznyb3yyFvy/JBSkNEkyFhz
KHYv/uQyg8XHIAIE41IpKdUk9MZ6BVvHjFdBbU01KerPl8Dfm7aJAoGBAN9FNFyv
A61q44oCwGRTxpYzRshHkk7GsO4Jg/vMKpU8bOCvz8GLD7cx38Xt1bV+uUlNGZc6
4EZxKrv0P9Fsj//WREc+0K11U3aN6HIYNdVV9Vel2v6Bis8+zTzNY6fSF4sx1Dw9
5q1BkE6sP3IPHz58Tt0pWNW8lmucZS7Q3KPJAoGBAJuy0GKytlFDOe+xtfQtEBuH
//GpWMzmtFEzujprB8uezf6JTnd/hOipbTf1SfgTw1W5D8D/gAHsN5djEMdQHVUW
YtNExjRc+ryJwnHIJkyiQWUDZXKN2GKHUToojGQHoJLkLVcWlIzziTmaS+4LAXuU
KT+/7op2bBmivkTx9B+5AoGBALyJxhPWPra8onSyqiCOlg3UMxuBRM18/3+jTW7e
E79+DTsXe8smURkT5rFPi739yx1ZHBkWwLj7a2jYcuO4V0lleLbpFnLDtr1QTE+8
ngkO02U2S13LqpojoFCN6G+Y/ASxCVXtt9Pqn5+v2MvKdUng0v/zoG6tGCC7Kr6D
5S3xAoGAZTYnX/rV1n2YuVvd12T9Xs2EBD9Q3FfL/oDfchU2nWiXyQA8HXhb8aBw
5Mw4BOuo0JgkSTqIxqda10tAViNeqlNiQKvOMt9y8Ugl4eEd4SdutmdTZuVPwK4/
yLi0ot+KP/8sbKAZjcAiJJIZFsqVY4wRdhSo3jzI72Zsx9CqJvE=
-----END RSA PRIVATE KEY-----`

// caKeyPKCS8 is caKeyRSA converted to PKCS8 form.
caKeyPKCS8 string = `-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDFNV3mwUa5U5nG
Q+/e0Tr2SFROhVxFvzk1FZZ5YFLKtMThRavTqQbit5JNWsaBHaGiOs/ifNXKe7sS
yUIkhNvoN/myffhspUOmpYmAMUmgRihPNqNHEQONKTBq76I+G5onqkH3v4mKY6DQ
mep7RBVnY22PCCldhIaR6+eJXFkdq6svGeEOvLkrIMnv2njxztoo3EDFTazKuEqS
tY0loKDhZVM5z95BTh6VRltPBghn9mLiA6RL6/PRx6CBGZeDkzNhPpwGVxwdGsDs
FpJGSgPts1sOH6ZFPPrtSA4pSMiL6jVOxSGa87YqejD7MgZ3WZ8B/2oVP7gpc8WH
fI3kN4yRAgMBAAECgf8TQiLpZfaCIqfhtMC4AbbAVk/lWyCnrwTnKjSHpeBv6zdO
yH7/LIJ/oW2oIDVCZqJiNVwXwhkerPaX3w+WgWL4Sn8X7zVTZtA0dfX3jtihzjgh
hDRtvDucjWktCDnP1uI2/WlzyECmQxRxSpabcwqkDhGk5icj+s0pcuApidsqCm3K
eIlLIWb6k4uClKfBkiJIgGoeemkdLVvwGOofZlioRg0Ht0cu7QekcHXMZULgIDOY
Gq0vDh80OnWWwdOKzRImlG4GIPkhlTr7VNJC+CSZ8kpK1EUhP7RhFqnQn6tJi2rA
9qU89tXh499lOmPh30uXRfH3s+feiKdRCCVq6EECgYEA4h4fm0RqPdTwNM0YYxaY
wFV52IkSGoMhPKM9UagpkC37b22rCUOD5rCEQQaBog48T6ZDcIRu8mdELhn+e1hE
mm/VqsHOJFAp/OfJvfLIW/L8kFKQ0STIWHModi/+5DKDxccgAgTjUikp1ST0xnoF
W8eMV0FtTTUp6s+XwN+btokCgYEA30U0XK8DrWrjigLAZFPGljNGyEeSTsaw7gmD
+8wqlTxs4K/PwYsPtzHfxe3VtX65SU0ZlzrgRnEqu/Q/0WyP/9ZERz7QrXVTdo3o
chg11VX1V6Xa/oGKzz7NPM1jp9IXizHUPD3mrUGQTqw/cg8fPnxO3SlY1byWa5xl
LtDco8kCgYEAm7LQYrK2UUM577G19C0QG4f/8alYzOa0UTO6OmsHy57N/olOd3+E
6KltN/VJ+BPDVbkPwP+AAew3l2MQx1AdVRZi00TGNFz6vInCccgmTKJBZQNlco3Y
YodROiiMZAegkuQtVxaUjPOJOZpL7gsBe5QpP7/uinZsGaK+RPH0H7kCgYEAvInG
E9Y+tryidLKqII6WDdQzG4FEzXz/f6NNbt4Tv34NOxd7yyZRGRPmsU+Lvf3LHVkc
GRbAuPtraNhy47hXSWV4tukWcsO2vVBMT7yeCQ7TZTZLXcuqmiOgUI3ob5j8BLEJ
Ve230+qfn6/Yy8p1SeDS//Ogbq0YILsqvoPlLfECgYBlNidf+tXWfZi5W93XZP1e
zYQEP1DcV8v+gN9yFTadaJfJADwdeFvxoHDkzDgE66jQmCRJOojGp1rXS0BWI16q
U2JAq84y33LxSCXh4R3hJ262Z1Nm5U/Arj/IuLSi34o//yxsoBmNwCIkkhkWypVj
jBF2FKjePMjvZmzH0Kom8Q==
-----END PRIVATE KEY-----`
)

0 comments on commit 3010ad2

Please sign in to comment.