generate ssh secrets
This commit is contained in:
parent
6ef93489bd
commit
f43f4fcec4
@ -13,7 +13,7 @@ run apt-get update \
|
|||||||
run yes |apt-get install -y grub2 grub-pc-bin grub-efi-amd64-bin \
|
run yes |apt-get install -y grub2 grub-pc-bin grub-efi-amd64-bin \
|
||||||
&& apt-get clean
|
&& apt-get clean
|
||||||
|
|
||||||
run apt-get install -y ca-certificates curl \
|
run apt-get install -y ca-certificates curl openssh-client \
|
||||||
&& apt-get clean
|
&& apt-get clean
|
||||||
|
|
||||||
run curl -L https://github.com/vmware/govmomi/releases/download/v0.21.0/govc_linux_amd64.gz | gunzip > /bin/govc && chmod +x /bin/govc
|
run curl -L https://github.com/vmware/govmomi/releases/download/v0.21.0/govc_linux_amd64.gz | gunzip > /bin/govc && chmod +x /bin/govc
|
||||||
|
@ -257,6 +257,11 @@ func (ctx *renderContext) templateFuncs(ctxMap map[string]interface{}) map[strin
|
|||||||
return getKeyCert(name, "tls_dir")
|
return getKeyCert(name, "tls_dir")
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"ssh_host_keys": func(dir string) (s string) {
|
||||||
|
return fmt.Sprintf("{{ ssh_host_keys %q %q %q}}",
|
||||||
|
dir, cluster, ctx.Host.Name)
|
||||||
|
},
|
||||||
|
|
||||||
"hosts_of_group": func() (hosts []interface{}) {
|
"hosts_of_group": func() (hosts []interface{}) {
|
||||||
hosts = make([]interface{}, 0)
|
hosts = make([]interface{}, 0)
|
||||||
|
|
||||||
|
@ -239,6 +239,33 @@ func (ctx *renderContext) templateFuncs() map[string]interface{} {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"ssh_host_keys": func(dir, cluster, host string) (s string, err error) {
|
||||||
|
pairs, err := secretData.SSHKeyPairs(cluster, host)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
files := make([]config.FileDef, 0, len(pairs)*2)
|
||||||
|
|
||||||
|
for _, pair := range pairs {
|
||||||
|
basePath := path.Join(dir, "ssh_host_"+pair.Type+"_key")
|
||||||
|
files = append(files, []config.FileDef{
|
||||||
|
{
|
||||||
|
Path: basePath,
|
||||||
|
Mode: 0600,
|
||||||
|
Content: pair.Private,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: basePath + ".pub",
|
||||||
|
Mode: 0644,
|
||||||
|
Content: pair.Public,
|
||||||
|
},
|
||||||
|
}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return asYaml(files)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
secretData *SecretData
|
secretData *SecretData
|
||||||
|
DontSave = false
|
||||||
)
|
)
|
||||||
|
|
||||||
type SecretData struct {
|
type SecretData struct {
|
||||||
@ -40,6 +41,7 @@ type ClusterSecrets struct {
|
|||||||
CAs map[string]*CA
|
CAs map[string]*CA
|
||||||
Tokens map[string]string
|
Tokens map[string]string
|
||||||
Passwords map[string]string
|
Passwords map[string]string
|
||||||
|
SSHKeyPairs map[string][]SSHKeyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
type CA struct {
|
type CA struct {
|
||||||
@ -92,6 +94,10 @@ func (sd *SecretData) Changed() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sd *SecretData) Save() error {
|
func (sd *SecretData) Save() error {
|
||||||
|
if DontSave {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
sd.l.Lock()
|
sd.l.Lock()
|
||||||
defer sd.l.Unlock()
|
defer sd.l.Unlock()
|
||||||
|
|
||||||
|
167
cmd/dkl-local-server/ssh-secrets.go
Normal file
167
cmd/dkl-local-server/ssh-secrets.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
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
|
||||||
|
}
|
17
cmd/dkl-local-server/ssh-secrets_test.go
Normal file
17
cmd/dkl-local-server/ssh-secrets_test.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
DontSave = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSSHKeyGet(t *testing.T) {
|
||||||
|
sd := &SecretData{
|
||||||
|
clusters: make(map[string]*ClusterSecrets),
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := sd.SSHKeyPairs("test", "host"); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
3
go.mod
3
go.mod
@ -1,6 +1,7 @@
|
|||||||
module novit.nc/direktil/local-server
|
module novit.nc/direktil/local-server
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412
|
||||||
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e
|
github.com/cavaliercoder/go-cpio v0.0.0-20180626203310-925f9528c45e
|
||||||
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e
|
github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e
|
||||||
github.com/emicklei/go-restful v2.10.0+incompatible
|
github.com/emicklei/go-restful v2.10.0+incompatible
|
||||||
@ -14,7 +15,7 @@ require (
|
|||||||
github.com/mcluseau/go-swagger-ui v0.0.0-20191019002626-fd9128c24a34
|
github.com/mcluseau/go-swagger-ui v0.0.0-20191019002626-fd9128c24a34
|
||||||
github.com/oklog/ulid v1.3.1
|
github.com/oklog/ulid v1.3.1
|
||||||
github.com/pierrec/lz4 v2.3.0+incompatible
|
github.com/pierrec/lz4 v2.3.0+incompatible
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||||
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
|
golang.org/x/net v0.0.0-20191014212845-da9a3fd4c582 // indirect
|
||||||
golang.org/x/sys v0.0.0-20191018095205-727590c5006e // indirect
|
golang.org/x/sys v0.0.0-20191018095205-727590c5006e // indirect
|
||||||
gopkg.in/src-d/go-billy.v4 v4.3.2
|
gopkg.in/src-d/go-billy.v4 v4.3.2
|
||||||
|
2
go.sum
2
go.sum
@ -8,6 +8,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
|||||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
|
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI=
|
||||||
|
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0=
|
||||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||||
|
Loading…
Reference in New Issue
Block a user