mirror of https://github.com/kubernetes/kops.git
kubetest2-kops - Create ephemeral SSH keys
This commit is contained in:
parent
91bce6627e
commit
fdad5cf9e5
|
|
@ -7,6 +7,7 @@ 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
|
||||
|
|
@ -122,7 +123,6 @@ 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
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/kops/tests/e2e/kubetest2-kops/gce"
|
||||
"k8s.io/kops/tests/e2e/pkg/kops"
|
||||
"k8s.io/kops/tests/e2e/pkg/target"
|
||||
"k8s.io/kops/tests/e2e/pkg/util"
|
||||
"sigs.k8s.io/kubetest2/pkg/boskos"
|
||||
)
|
||||
|
||||
|
|
@ -66,13 +67,13 @@ func (d *deployer) initialize() error {
|
|||
|
||||
switch d.CloudProvider {
|
||||
case "aws":
|
||||
// These environment variables are defined by the "preset-aws-ssh" prow preset
|
||||
// https://github.com/kubernetes/test-infra/blob/3d3b325c98b739b526ba5d93ce21c90a05e1f46d/config/prow/config.yaml#L653-L670
|
||||
if d.SSHPrivateKeyPath == "" {
|
||||
d.SSHPrivateKeyPath = os.Getenv("AWS_SSH_PRIVATE_KEY_FILE")
|
||||
}
|
||||
if d.SSHPublicKeyPath == "" {
|
||||
d.SSHPublicKeyPath = os.Getenv("AWS_SSH_PUBLIC_KEY_FILE")
|
||||
if d.SSHPrivateKeyPath == "" || d.SSHPublicKeyPath == "" {
|
||||
publicKeyPath, privateKeyPath, err := util.CreateSSHKeyPair(d.ClusterName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.SSHPublicKeyPath = publicKeyPath
|
||||
d.SSHPrivateKeyPath = privateKeyPath
|
||||
}
|
||||
case "digitalocean":
|
||||
if d.SSHPrivateKeyPath == "" {
|
||||
|
|
@ -185,6 +186,9 @@ func (d *deployer) env() []string {
|
|||
vars = append(vars, k+"="+v)
|
||||
}
|
||||
}
|
||||
// Recognized by the e2e framework
|
||||
// https://github.com/kubernetes/kubernetes/blob/a750d8054a6cb3167f495829ce3e77ab0ccca48e/test/e2e/framework/ssh/ssh.go#L59-L62
|
||||
vars = append(vars, fmt.Sprintf("KUBE_SSH_KEY_PATH=%v", d.SSHPrivateKeyPath))
|
||||
} else if d.CloudProvider == "digitalocean" {
|
||||
// Pass through some env vars if set
|
||||
for _, k := range []string{"DIGITALOCEAN_ACCESS_TOKEN", "S3_ACCESS_KEY_ID", "S3_SECRET_ACCESS_KEY"} {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright 2022 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
publicKeyPath := filepath.Join(dir, "id_ed25519.pub")
|
||||
privateKeyPath := filepath.Join(dir, "id_ed25519")
|
||||
|
||||
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 {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
|
||||
return publicKeyPath, privateKeyPath, nil
|
||||
}
|
||||
Loading…
Reference in New Issue