/
ssh.go
71 lines (64 loc) · 1.98 KB
/
ssh.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package cmd
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/metal-stack/metal-go/api/client/vpn"
"github.com/metal-stack/metal-go/api/models"
"github.com/metal-stack/metal-lib/pkg/pointer"
metalssh "github.com/metal-stack/metal-lib/pkg/ssh"
metalvpn "github.com/metal-stack/metal-lib/pkg/vpn"
"github.com/spf13/viper"
)
func (c *firewallCmd) firewallSSHViaVPN(firewall *models.V1FirewallResponse) (err error) {
if firewall.Allocation == nil || firewall.Allocation.Project == nil {
return fmt.Errorf("firewall allocation or allocation.project is nil")
}
projectID := firewall.Allocation.Project
fmt.Fprintf(c.out, "accessing firewall through vpn ")
authKeyResp, err := c.client.VPN().GetVPNAuthKey(vpn.NewGetVPNAuthKeyParams().WithBody(&models.V1VPNRequest{
Pid: projectID,
Ephemeral: pointer.Pointer(true),
}), nil)
if err != nil {
return fmt.Errorf("failed to get VPN auth key: %w", err)
}
ctx := context.Background()
v, err := metalvpn.Connect(ctx, *firewall.ID, *authKeyResp.Payload.Address, *authKeyResp.Payload.AuthKey)
if err != nil {
return err
}
defer v.Close()
privateKeyFile := viper.GetString("identity")
if strings.HasPrefix(privateKeyFile, "~/") {
home, _ := os.UserHomeDir()
privateKeyFile = filepath.Join(home, privateKeyFile[2:])
}
privateKey, err := os.ReadFile(privateKeyFile)
if err != nil {
return err
}
s, err := metalssh.NewClientWithConnection("metal", v.TargetIP, privateKey, v.Conn)
if err != nil {
return err
}
return s.Connect(nil)
}
// sshClient opens an interactive ssh session to the host on port with user, authenticated by the key.
func sshClient(user, keyfile, host string, port int, idToken *string) error {
privateKey, err := os.ReadFile(keyfile)
if err != nil {
return err
}
s, err := metalssh.NewClient(user, host, privateKey, port)
if err != nil {
return err
}
var env *metalssh.Env
if idToken != nil {
env = &metalssh.Env{"LC_METAL_STACK_OIDC_TOKEN": *idToken}
}
return s.Connect(env)
}