mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-04-20 07:25:51 -04:00
add ssh subcommand
This commit is contained in:
parent
e6048e093b
commit
1850d4b327
@ -61,6 +61,7 @@ func NewRootCmd() *cobra.Command {
|
||||
rootCmd.AddCommand(cmd.NewIAMCmd())
|
||||
rootCmd.AddCommand(cmd.NewVersionCmd())
|
||||
rootCmd.AddCommand(cmd.NewInitCmd())
|
||||
rootCmd.AddCommand(cmd.NewSSHCmd())
|
||||
rootCmd.AddCommand(cmd.NewMaaPatchCmd())
|
||||
|
||||
return rootCmd
|
||||
|
@ -46,6 +46,7 @@ go_library(
|
||||
"validargs.go",
|
||||
"verify.go",
|
||||
"version.go",
|
||||
"ssh.go",
|
||||
],
|
||||
importpath = "github.com/edgelesssys/constellation/v2/cli/internal/cmd",
|
||||
visibility = ["//cli:__subpackages__"],
|
||||
@ -116,6 +117,8 @@ go_library(
|
||||
"//internal/attestation/azure/tdx",
|
||||
"@com_github_google_go_sev_guest//proto/sevsnp",
|
||||
"@com_github_google_go_tpm_tools//proto/attest",
|
||||
"@org_golang_x_crypto//hkdf",
|
||||
"@org_golang_x_crypto//ssh",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:android_amd64": [
|
||||
"@org_golang_x_sys//unix",
|
||||
|
108
cli/internal/cmd/ssh.go
Normal file
108
cli/internal/cmd/ssh.go
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
Copyright (c) Edgeless Systems GmbH
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/file"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"golang.org/x/crypto/hkdf"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type secret struct {
|
||||
Key []byte `json:"key,omitempty"`
|
||||
Salt []byte `json:"salt,omitempty"`
|
||||
}
|
||||
|
||||
var permissions = ssh.Permissions{
|
||||
Extensions: map[string]string{
|
||||
"permit-port-forwarding": "yes",
|
||||
"permit-pty": "yes",
|
||||
},
|
||||
}
|
||||
|
||||
// NewSSHCmd returns a new cobra.Command for the ssh command.
|
||||
func NewSSHCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "ssh",
|
||||
Short: "Prepare your cluster for emergency ssh access",
|
||||
Long: "Prepare your cluster for emergency ssh access and sign a given key pair for authorization.",
|
||||
Args: cobra.ExactArgs(0),
|
||||
RunE: runSSH,
|
||||
}
|
||||
cmd.Flags().String("key", "", "The path to an existing ssh public key.")
|
||||
cmd.MarkFlagRequired("key")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runSSH(cmd *cobra.Command, _ []string) error {
|
||||
fh := file.NewHandler(afero.NewOsFs())
|
||||
debugLogger, err := newDebugFileLogger(cmd, fh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var mastersecret secret
|
||||
if err = fh.ReadJSON(fmt.Sprintf("%s.json", constants.ConstellationMasterSecretStoreName), &mastersecret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
hkdf := hkdf.New(sha256.New, mastersecret.Key, mastersecret.Salt, []byte("ssh-ca"))
|
||||
_, priv, err := ed25519.GenerateKey(hkdf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ca, err := ssh.NewSignerFromSigner(priv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
debugLogger.Debug("CA KEY generated", "key", string(ssh.MarshalAuthorizedKey(ca.PublicKey())))
|
||||
|
||||
key_path, err := cmd.Flags().GetString("key")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key_buf, err := fh.Read(key_path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pub, _, _, _, err := ssh.ParseAuthorizedKey(key_buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
certificate := ssh.Certificate{
|
||||
Key: pub,
|
||||
CertType: ssh.UserCert,
|
||||
ValidAfter: uint64(time.Now().Unix()),
|
||||
ValidBefore: uint64(time.Now().Add(24 * time.Hour).Unix()),
|
||||
ValidPrincipals: []string{"root"},
|
||||
Permissions: permissions,
|
||||
}
|
||||
if err := certificate.SignCert(rand.Reader, ca); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
debugLogger.Debug("Signed certificate", "certificate", string(ssh.MarshalAuthorizedKey(&certificate)))
|
||||
fh.Write(fmt.Sprintf("%s/ca_cert.pub", constants.TerraformWorkingDir), ssh.MarshalAuthorizedKey(&certificate), file.OptOverwrite, file.OptMkdirAll)
|
||||
fmt.Printf("You can now connect to a node using 'ssh -F %s/ssh_config -i <your private key> <node ip>'.\nYou can obtain the private node IP via the web UI of your CSP.\n", constants.TerraformWorkingDir)
|
||||
|
||||
return nil
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user