local-server/cmd/dkl-local-server/ssh-secrets.go
2019-12-03 14:39:42 +01:00

168 lines
2.7 KiB
Go

package main
import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/ed25519"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/asn1"
"fmt"
"io/ioutil"
"os"
"os/exec"
)
type SSHKeyPair struct {
Type string
Public string
Private string
}
func (sd *SecretData) SSHKeyPairs(cluster, host string) (pairs []SSHKeyPair, err error) {
cs := sd.cluster(cluster)
if cs.SSHKeyPairs == nil {
cs.SSHKeyPairs = map[string][]SSHKeyPair{}
}
outFile, err := ioutil.TempFile("/tmp", "dls-key.")
if err != nil {
return
}
outPath := outFile.Name()
removeTemp := func() {
os.Remove(outPath)
os.Remove(outPath + ".pub")
}
defer removeTemp()
pairs = cs.SSHKeyPairs[host]
didGenerate := false
genLoop:
for _, keyType := range []string{
"rsa",
"dsa",
"ecdsa",
"ed25519",
} {
for _, pair := range pairs {
if pair.Type == keyType {
continue genLoop
}
}
didGenerate = true
removeTemp()
var out, privKey, pubKey []byte
out, err = exec.Command("ssh-keygen",
"-N", "",
"-C", "root@"+host,
"-f", outPath,
"-t", keyType).CombinedOutput()
if err != nil {
err = fmt.Errorf("ssh-keygen failed: %v: %s", err, string(out))
return
}
privKey, err = ioutil.ReadFile(outPath)
if err != nil {
return
}
os.Remove(outPath)
pubKey, err = ioutil.ReadFile(outPath + ".pub")
if err != nil {
return
}
os.Remove(outPath + ".pub")
pairs = append(pairs, SSHKeyPair{
Type: keyType,
Public: string(pubKey),
Private: string(privKey),
})
}
if didGenerate {
cs.SSHKeyPairs[host] = pairs
err = sd.Save()
}
return
}
func sshKeyGenDSA() (data []byte, pubKey interface{}, err error) {
privKey := &dsa.PrivateKey{}
err = dsa.GenerateParameters(&privKey.Parameters, rand.Reader, dsa.L1024N160)
if err != nil {
return
}
err = dsa.GenerateKey(privKey, rand.Reader)
if err != nil {
return
}
data, err = asn1.Marshal(*privKey)
//data, err = x509.MarshalPKCS8PrivateKey(privKey)
if err != nil {
return
}
pubKey = privKey.PublicKey
return
}
func sshKeyGenRSA() (data []byte, pubKey interface{}, err error) {
privKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return
}
data = x509.MarshalPKCS1PrivateKey(privKey)
pubKey = privKey.Public()
return
}
func sshKeyGenECDSA() (data []byte, pubKey interface{}, err error) {
privKey, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
if err != nil {
return
}
data, err = x509.MarshalPKCS8PrivateKey(privKey)
if err != nil {
return
}
pubKey = privKey.Public()
return
}
func sshKeyGenED25519() (data []byte, pubKey interface{}, err error) {
pubKey, privKey, err := ed25519.GenerateKey(rand.Reader)
data, err = x509.MarshalPKCS8PrivateKey(privKey)
if err != nil {
return
}
return
}