Shell out to ssh-keygen for creating ed25519 keys

Go's crypto modules can't generate ed25519 keys in the openssh format, so we rely on ssh-keygen instead
This commit is contained in:
Peter Rifel 2022-04-20 18:36:09 -05:00
parent 3242dc3cb4
commit f9c0487fbf
No known key found for this signature in database
GPG Key ID: BC6469E5B16DB2B6
2 changed files with 7 additions and 50 deletions

View File

@ -7,7 +7,6 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/octago/sflags v0.2.0
github.com/spf13/pflag v1.0.5
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
k8s.io/api v0.23.5
k8s.io/apimachinery v0.23.5
k8s.io/client-go v9.0.0+incompatible
@ -123,6 +122,7 @@ require (
github.com/xanzy/ssh-agent v0.3.1 // indirect
go.opencensus.io v0.23.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect

View File

@ -17,72 +17,29 @@ limitations under the License.
package util
import (
"crypto/ed25519"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"os"
"path/filepath"
"golang.org/x/crypto/ssh"
"sigs.k8s.io/kubetest2/pkg/exec"
)
// CreateSSHKeyPair creates a key pair in a temp directory
// and returns the paths to the private and public keys respectively.
// The file paths are deterministic from the clusterName.
func CreateSSHKeyPair(clusterName string) (string, string, error) {
_, privateKey, err := ed25519.GenerateKey(nil)
if err != nil {
return "", "", err
}
publicKey, err := ssh.NewPublicKey(privateKey.Public())
if err != nil {
return "", "", err
}
publicKeyContents := ssh.MarshalAuthorizedKey(publicKey)
user := os.Getenv("USER")
if user == "" {
user = "user"
}
comment := fmt.Sprintf(" %v\n", user)
// AWS requires a comment on the SSH public key but MarshalAuthorizedKey doesn't create one
publicKeyContents = publicKeyContents[:len(publicKeyContents)-1]
publicKeyContents = append(publicKeyContents, []byte(comment)...)
privateKeyContents, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return "", "", err
}
tmp := os.TempDir()
dir := filepath.Join(tmp, "kops", clusterName)
err = os.MkdirAll(dir, 0700)
if err != nil {
if err := os.MkdirAll(dir, 0700); err != nil {
return "", "", err
}
publicKeyPath := filepath.Join(dir, "id_ed25519.pub")
privateKeyPath := filepath.Join(dir, "id_ed25519")
publicKeyPath := filepath.Join(dir, "id_ed25519.pub")
if _, err := os.Stat(privateKeyPath); errors.Is(err, os.ErrNotExist) {
if err := os.WriteFile(publicKeyPath, publicKeyContents, 0644); err != nil {
return "", "", err
}
f, err := os.OpenFile(privateKeyPath, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return "", "", err
}
defer f.Close()
err = pem.Encode(f, &pem.Block{
Type: "PRIVATE KEY",
Bytes: privateKeyContents,
})
if err != nil {
cmd := exec.Command("ssh-keygen", "-t", "ed25519", "-N", "", "-q", "-f", privateKeyPath)
exec.InheritOutput(cmd)
if err := cmd.Run(); err != nil {
return "", "", err
}
}