From ab85f2236f547011c4dba8ab300d567869685264 Mon Sep 17 00:00:00 2001 From: Sreejith Punnapuzha Date: Mon, 29 Mar 2021 11:55:31 -0500 Subject: [PATCH] Add function to generate SSH KeyPair via templater This commit adds functionality to generate SSH keypair via templater plugins. ssh keypairs can be generated via generate-secrets phase. Signed-off-by: Sreejith Punnapuzha Change-Id: I83720df5f934caf65dab201a1d0894ed3fee6cb5 --- go.mod | 1 + .../plugin/templater/extlib/crypto.go | 35 +++++++++++++++++++ .../plugin/templater/extlib/crypto_test.go | 9 +++++ .../plugin/templater/extlib/funcmap.go | 1 + 4 files changed, 46 insertions(+) diff --git a/go.mod b/go.mod index f3fde238a..f4332eaa0 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/cobra v1.0.0 github.com/stretchr/testify v1.6.1 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect k8s.io/api v0.17.9 diff --git a/pkg/document/plugin/templater/extlib/crypto.go b/pkg/document/plugin/templater/extlib/crypto.go index 38f5c0290..973d7a9c3 100644 --- a/pkg/document/plugin/templater/extlib/crypto.go +++ b/pkg/document/plugin/templater/extlib/crypto.go @@ -29,6 +29,8 @@ import ( "encoding/pem" "math/big" "time" + + "golang.org/x/crypto/ssh" ) func toUint32(i int) uint32 { return uint32(i) } @@ -41,6 +43,11 @@ type dnParser struct { dn []string } +type sshKey struct { + Private string + Public string +} + func (p *dnParser) startOver() { p.dn = append(p.dn, p.cur.String()) p.cur = bytes.Buffer{} @@ -218,6 +225,34 @@ func generateCertificateAuthorityEx( return generateCertificateAuthorityWithKeyInternalEx(subj, daysValid, priv) } +// genSSHKeyPair make a pair of public and private keys for SSH access. +// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file. +// Private Key generated is PEM encoded +func genSSHKeyPair(encryptionBit int) (sshKey, error) { + key := sshKey{} + privateKey, err := rsa.GenerateKey(rand.Reader, encryptionBit) + if err != nil { + return key, err + } + + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + var private bytes.Buffer + if err = pem.Encode(&private, privateKeyPEM); err != nil { + return key, err + } + + // generate public key + pub, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return key, err + } + + public := ssh.MarshalAuthorizedKey(pub) + key.Public = string(public) + key.Private = private.String() + return key, nil +} + func generateCertificateAuthorityWithPEMKeyEx( subj string, daysValid int, diff --git a/pkg/document/plugin/templater/extlib/crypto_test.go b/pkg/document/plugin/templater/extlib/crypto_test.go index 63072cab8..b0f4b9c6a 100644 --- a/pkg/document/plugin/templater/extlib/crypto_test.go +++ b/pkg/document/plugin/templater/extlib/crypto_test.go @@ -168,3 +168,12 @@ func TestNameFromString(t *testing.T) { assert.Equal(t, tc.expectedOut, *r) } } + +func TestGenSSHKeyPair(t *testing.T) { + key, err := genSSHKeyPair(2048) + assert.Nil(t, err) + assert.NotNil(t, key.Private) + assert.NotNil(t, key.Public) + assert.Contains(t, key.Private, "RSA PRIVATE KEY") + assert.Contains(t, key.Public, "ssh-rsa") +} diff --git a/pkg/document/plugin/templater/extlib/funcmap.go b/pkg/document/plugin/templater/extlib/funcmap.go index c6b5d1474..58d83fac4 100644 --- a/pkg/document/plugin/templater/extlib/funcmap.go +++ b/pkg/document/plugin/templater/extlib/funcmap.go @@ -32,6 +32,7 @@ var genericMap = map[string]interface{}{ "genCAWithKeyEx": generateCertificateAuthorityWithPEMKeyEx, "genSignedCertEx": generateSignedCertificateEx, "genSignedCertWithKeyEx": generateSignedCertificateWithPEMKeyEx, + "genSSHKeyPair": genSSHKeyPair, "regexGen": regexGen, "toYaml": toYaml, "toUint32": toUint32,