Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 3 additions & 40 deletions cmd/admin/v2/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ If ~/.ssh/[id_ed25519.pub | id_rsa.pub | id_dsa.pub] is present it will be picke
},
ValidArgsFunction: c.Completion.AdminMachine,
}
consoleCmd.Flags().Bool("ipmi", false, "if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present)")
consoleCmd.Flags().Int("metal-console-port", 5222, "port open on our control-plane to connect via ssh to get machine console access")
consoleCmd.Flags().Bool("ipmi", false, "if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present and the machine bmc being accessible from the local machine)")
consoleCmd.Flags().Int("metal-console-port", 5222, "the metal-console tcp port in the control-plane to connect via ssh to get machine console access")

consolePasswordCmd := &cobra.Command{
Use: "consolepassword",
Expand Down Expand Up @@ -452,7 +452,7 @@ func (c *machine) console(ctx context.Context, args []string) error {
return err
}

err = sshClient(id, viper.GetString("sshidentity"), parsedurl.Host, viper.GetInt("metal-console-port"), &c.c.Context.Token, true)
err = helpers.SSHClient(id, viper.GetString("sshidentity"), parsedurl.Host, viper.GetInt("metal-console-port"), c.c.Context.Token, nil)
if err != nil {
return fmt.Errorf("machine console error:%w", err)
}
Expand Down Expand Up @@ -592,40 +592,3 @@ func (c *machine) firewallSSH(ctx context.Context, args []string) (err error) {
}
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, passwordAuth bool) error {
var opts []metalssh.ConnectOpt

if passwordAuth {
opts = append(opts, metalssh.ConnectOptOutputPassword(*idToken))
} else {
if keyfile == "" {
var err error
keyfile, err = helpers.SearchSSHKey()
if err != nil {
return err
}
}

privateKey, err := os.ReadFile(keyfile)
if err != nil {
return err
}

opts = append(opts, metalssh.ConnectOptOutputPrivateKey(privateKey))
}

s, err := metalssh.NewClient(user, host, port, opts...)
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)
}
40 changes: 39 additions & 1 deletion cmd/api/v2/machine.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package v2

import (
"fmt"
"net/url"

"github.com/metal-stack/api/go/errorutil"
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/cli/cmd/config"
"github.com/metal-stack/cli/cmd/sorters"
"github.com/metal-stack/cli/pkg/helpers"
"github.com/metal-stack/metal-lib/pkg/genericcli"
"github.com/metal-stack/metal-lib/pkg/genericcli/printers"
"github.com/metal-stack/metal-lib/pkg/pointer"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -72,7 +76,22 @@ If ~/.ssh/[id_ed25519.pub | id_rsa.pub | id_dsa.pub] is present it will be picke
ValidArgsFn: c.Completion.Machine,
}

return genericcli.NewCmds(cmdsConfig)
consoleCmd := &cobra.Command{
Use: "console",
Short: "establishes a connection to the serial console of a machine. for authentication at the metal-console it uses the token and the machine ssh key that was used when creating the machine.",
RunE: func(cmd *cobra.Command, args []string) error {
return w.console(args)
},
ValidArgsFunction: c.Completion.Machine,
}
consoleCmd.Flags().Bool("ipmi", false, "if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present and the machine bmc being accessible from the local machine)")
consoleCmd.Flags().Int("metal-console-port", 5222, "the metal-console tcp port in the control-plane to connect via ssh to get machine console access")
consoleCmd.Flags().StringP("project", "p", "", "project of the machine")
consoleCmd.Flags().StringP("sshidentity", "i", "", "the ssh private key used when creating the machine")
genericcli.Must(consoleCmd.RegisterFlagCompletionFunc("project", c.Completion.Project))
genericcli.Must(consoleCmd.MarkFlagRequired("project"))

return genericcli.NewCmds(cmdsConfig, consoleCmd)
}

func (c *machine) Create(rq *apiv2.MachineServiceCreateRequest) (*apiv2.Machine, error) {
Expand Down Expand Up @@ -176,3 +195,22 @@ func (c *machine) Convert(r *apiv2.Machine) (string, *apiv2.MachineServiceCreate

return helpers.EncodeProject(r.Uuid, r.Allocation.Project), create, update, err
}

func (c *machine) console(args []string) error {
id, err := genericcli.GetExactlyOneArg(args)
if err != nil {
return err
}

parsedurl, err := url.Parse(pointer.SafeDeref(c.c.Context.ApiURL))
if err != nil {
return err
}

err = helpers.SSHClient(id, viper.GetString("sshidentity"), parsedurl.Host, viper.GetInt("metal-console-port"), c.c.Context.Token, new(viper.GetString("project")))
if err != nil {
return fmt.Errorf("machine console error: %w", err)
}

return nil
}
2 changes: 1 addition & 1 deletion docs/admin/metalctlv2_admin_component_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ metalctlv2 admin component list [flags]
```
-h, --help help for list
--identifier string lists only component with this identifier
--sort-by strings sort by (comma separated) column(s), sort direction can be changed by appending :asc or :desc behind the column identifier. possible values: identifier|started|type
--sort-by strings sort by (comma separated) column(s), sort direction can be changed by appending :asc or :desc behind the column identifier. possible values: expiration|identifier|started|type
--type string lists only component of this type
--uuid string lists only component with this uuid
```
Expand Down
4 changes: 2 additions & 2 deletions docs/admin/metalctlv2_admin_machine_console.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ metalctlv2 admin machine console [flags]

```
-h, --help help for console
--ipmi if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present)
--metal-console-port int port open on our control-plane to connect via ssh to get machine console access (default 5222)
--ipmi if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present and the machine bmc being accessible from the local machine)
--metal-console-port int the metal-console tcp port in the control-plane to connect via ssh to get machine console access (default 5222)
```

### Options inherited from parent commands
Expand Down
1 change: 1 addition & 0 deletions docs/metalctlv2_machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ allocate a machine

* [metalctlv2](metalctlv2.md) - cli for managing entities in metal-stack
* [metalctlv2 machine apply](metalctlv2_machine_apply.md) - applies one or more machines from a given file
* [metalctlv2 machine console](metalctlv2_machine_console.md) - establishes a connection to the serial console of a machine. for authentication at the metal-console it uses the token and the machine ssh key that was used when creating the machine.
* [metalctlv2 machine create](metalctlv2_machine_create.md) - creates the machine
* [metalctlv2 machine delete](metalctlv2_machine_delete.md) - deletes the machine
* [metalctlv2 machine describe](metalctlv2_machine_describe.md) - describes the machine
Expand Down
35 changes: 35 additions & 0 deletions docs/metalctlv2_machine_console.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## metalctlv2 machine console

establishes a connection to the serial console of a machine. for authentication at the metal-console it uses the token and the machine ssh key that was used when creating the machine.

```
metalctlv2 machine console [flags]
```

### Options

```
-h, --help help for console
--ipmi if set to true, the serial console will be opened using ipmitool (requires ipmitool to be present and the machine bmc being accessible from the local machine)
--metal-console-port int the metal-console tcp port in the control-plane to connect via ssh to get machine console access (default 5222)
-p, --project string project of the machine
-i, --sshidentity string the ssh private key used when creating the machine
```

### Options inherited from parent commands

```
--api-token string the token used for api requests
--api-url string the url to the metal-stack.io api
-c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml)
--debug debug output
--force-color force colored output even without tty
-o, --output-format string output format (table|wide|markdown|json|yaml|template), wide is a table with more columns. (default "table")
--template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference.
--timeout duration request timeout used for api requests
```

### SEE ALSO

* [metalctlv2 machine](metalctlv2_machine.md) - manage machine entities

11 changes: 6 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ require (
github.com/fatih/color v1.19.0
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/metal-stack/api v0.5.1
github.com/metal-stack/api v0.5.5
github.com/metal-stack/metal-console v0.7.7-0.20260909095012-75ec3d1e3e1a
github.com/metal-stack/metal-lib v0.26.3
github.com/metal-stack/v v1.0.3
github.com/spf13/afero v1.15.0
Expand All @@ -22,7 +23,7 @@ require (
)

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1 // indirect
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.2 // indirect
buf.build/go/protovalidate v1.3.0 // indirect
buf.build/go/protoyaml v0.7.0 // indirect
cel.dev/expr v0.25.3 // indirect
Expand All @@ -43,7 +44,7 @@ require (
github.com/gaissmai/bart v0.29.0 // indirect
github.com/go-json-experiment/json v0.0.0-20260820222146-c27c302e5fc3 // indirect
github.com/go-openapi/errors v0.22.8 // indirect
github.com/go-openapi/strfmt v0.27.0 // indirect
github.com/go-openapi/strfmt v0.27.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/goccy/go-json v0.10.6 // indirect
Expand All @@ -57,7 +58,7 @@ require (
github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.2 // indirect
github.com/klauspost/compress v1.19.2 // indirect
github.com/klauspost/compress v1.20.0 // indirect
github.com/klauspost/connect-compress/v2 v2.1.1 // indirect
github.com/mattn/go-colorable v0.1.15 // indirect
github.com/mattn/go-isatty v0.0.24 // indirect
Expand Down Expand Up @@ -91,7 +92,7 @@ require (
go.yaml.in/yaml/v3 v3.0.5 // indirect
go4.org/mem v0.0.0-20240501181205-ae6ca9944745 // indirect
go4.org/netipx v0.0.0-20260823151212-3075585bcbeb // indirect
golang.org/x/crypto v0.55.0 // indirect
golang.org/x/crypto v0.56.0 // indirect
golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa // indirect
golang.org/x/net v0.58.0 // indirect
golang.org/x/oauth2 v0.36.0 // indirect
Expand Down
30 changes: 16 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
9fans.net/go v0.0.8-0.20250307142834-96bdba94b63f h1:1C7nZuxUMNz7eiQALRfiqNOm04+m3edWlRff/BYHf0Q=
9fans.net/go v0.0.8-0.20250307142834-96bdba94b63f/go.mod h1:hHyrZRryGqVdqrknjq5OWDLGCTJ2NeEvtrpR96mjraM=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1 h1:Slv0uGxx219srASyiaI5C9cDlyG8kNDcXpTSYcuAeE4=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.1/go.mod h1:TCt1lluMFnctISJXvkIQ4x3ABrPuUKCWKyjKdkJNBpw=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.2 h1:NbnlmV26O7oZ1iM5tsCI+GEx+3ZSdrhvnKQ/eWSrLiY=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.2/go.mod h1:TCt1lluMFnctISJXvkIQ4x3ABrPuUKCWKyjKdkJNBpw=
buf.build/go/protovalidate v1.3.0 h1:8ITcnZGkAHx6TyhZvro+iET/AyqU8gEWQJK2WsT62ms=
buf.build/go/protovalidate v1.3.0/go.mod h1:82s5g+rFRj1CZPiLv6OTA31jBu2fpq7mLXHwa9mZfEs=
buf.build/go/protoyaml v0.7.0 h1:z4oVoFicbpPefhT7WAykxUdfp0yEQlhMQ2mCZOY5V38=
Expand Down Expand Up @@ -113,10 +113,10 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/errors v0.22.8 h1:oP7sW7TWc3wFFjrzzj0nI83H2qMBkNjNfSd+XRejk/I=
github.com/go-openapi/errors v0.22.8/go.mod h1:BuUoHcYrU6E7V9gfj1I5wLQqgtIHnup/alXZ8KdgQ0w=
github.com/go-openapi/strfmt v0.27.0 h1:kbcTeaD9TXuXD0hhMXzuYa1sdTo6+dWGvwjW93E80IM=
github.com/go-openapi/strfmt v0.27.0/go.mod h1:s/qhDqfY72irigXUGJmtgid2Rm+3tnz3k8hZaRmvWYc=
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
github.com/go-openapi/strfmt v0.27.2 h1:SG32SlbwNy92s0KJiVxt2joJeFdqIYHvwrA0OU6HqzQ=
github.com/go-openapi/strfmt v0.27.2/go.mod h1:M4CKsMO0Fb8qR10+1Ra75wCKNNquy+Vj+4LWZrhTo2E=
github.com/go-openapi/testify/v2 v2.7.0 h1:bycOreEj6wfBvijg3YFogZ/sFjTCDmQnwSodSzHa3X8=
github.com/go-openapi/testify/v2 v2.7.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
Expand Down Expand Up @@ -165,8 +165,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jsimonetti/rtnetlink v1.4.2 h1:Df9w9TZ3npHTyDn0Ev9e1uzmN2odmXd0QX+J5GTEn90=
github.com/jsimonetti/rtnetlink v1.4.2/go.mod h1:92s6LJdE+1iOrw+F2/RO7LYI2Qd8pPpFNNUYW06gcoM=
github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8=
github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
github.com/klauspost/compress v1.20.0 h1:a3C1ke2ohxFymNlb2HWAHjDeKCI90scRskErZkR0ezA=
github.com/klauspost/compress v1.20.0/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI=
github.com/klauspost/connect-compress/v2 v2.1.1 h1:ycZNp4rWOZBodVE2Ls5AzK4aHkyK+GteEfzRZgKNs+c=
github.com/klauspost/connect-compress/v2 v2.1.1/go.mod h1:9oilsPHJMzGKkjafSBk9J7iVo4mO+dw0G0KSdVpnlVE=
github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ=
Expand All @@ -191,8 +191,10 @@ github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
github.com/mdlayher/socket v0.6.1 h1:M7uj2NtuujUY4mYr1C57NmfNiRHbkKpnBxO856lsc3A=
github.com/mdlayher/socket v0.6.1/go.mod h1:+/SGtqc9V+5dAuRgQsU0fGBI+oRDiW7O2Obx10OIWfg=
github.com/metal-stack/api v0.5.1 h1:cA4i56RYXwcda/EkEWb2MG/YGQAEqJ4RvwxS7RtdUaA=
github.com/metal-stack/api v0.5.1/go.mod h1:QbDG4YRFIkDf1z6cGmeu0m/791IAMyk8/9U/lsrxH8E=
github.com/metal-stack/api v0.5.5 h1:AzPjTKi8Y4XNiJaEcRDCAjuOmIaLuuOEhKXVWliTtWc=
github.com/metal-stack/api v0.5.5/go.mod h1:U8c+awSMxXaRJjzWpo1IMcvlNxOi1ewu/fk1BzDM7hI=
github.com/metal-stack/metal-console v0.7.7-0.20260909095012-75ec3d1e3e1a h1:zFB1a0PMyzgBGtJU3HID75pEsD6l694BViuxJxKDdLg=
github.com/metal-stack/metal-console v0.7.7-0.20260909095012-75ec3d1e3e1a/go.mod h1:ZkselOaxF/iELFL9Tku3maXgpX4DM0CHjoG7CGuky6E=
github.com/metal-stack/metal-lib v0.26.3 h1:K5gLoD65m6p3l6qCPrfavIdvNdWfmF2QdXrvU2URaZs=
github.com/metal-stack/metal-lib v0.26.3/go.mod h1:cNXjPBs8SFnjqfBobuSbm5mDk6E/jS8PVeIOrV/7POE=
github.com/metal-stack/v v1.0.3 h1:Sh2oBlnxrCUD+mVpzfC8HiqL045YWkxs0gpTvkjppqs=
Expand Down Expand Up @@ -300,8 +302,8 @@ go4.org/mem v0.0.0-20240501181205-ae6ca9944745 h1:Tl++JLUCe4sxGu8cTpDzRLd3tN7US4
go4.org/mem v0.0.0-20240501181205-ae6ca9944745/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
go4.org/netipx v0.0.0-20260823151212-3075585bcbeb h1:XBM4hvfwGAttkkiTIFfeigdfcL1xIfdKXqFdgiHGtDs=
go4.org/netipx v0.0.0-20260823151212-3075585bcbeb/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y=
golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I=
golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa h1:QSyA8ishJCyT21kER9KwNt0b7BM3iRK4x9QXhjN5Fdk=
golang.org/x/exp v0.0.0-20260824195058-e88cd73687aa/go.mod h1:zeBbvyFKDaLwa7CH/zI8KXt7gTl14SF7sO08Pl5jBCM=
golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f h1:phY1HzDcf18Aq9A8KkmRtY9WvOFIxN8wgfvy6Zm1DV8=
Expand Down Expand Up @@ -342,8 +344,8 @@ google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsok
google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc=
google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
46 changes: 46 additions & 0 deletions pkg/helpers/ssh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package helpers

import (
"os"

consoleapi "github.com/metal-stack/metal-console/api"
metalssh "github.com/metal-stack/metal-lib/pkg/ssh"
)

// 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, project *string) error {
var opts []metalssh.ConnectOpt

opts = append(opts, metalssh.ConnectOptOutputPassword(idToken))

if keyfile == "" {
var err error
keyfile, err = SearchSSHKey()
if err != nil {
return err
}
}

privateKey, err := os.ReadFile(keyfile)
if err != nil {
return err
}

opts = append(opts, metalssh.ConnectOptOutputPrivateKey(privateKey))

s, err := metalssh.NewClient(user, host, port, opts...)
if err != nil {
return err
}

env := map[string]string{
consoleapi.OidcTokenEnv: idToken,
}
if project != nil {
env[consoleapi.ProjectEnv] = *project
}

sshEnv := metalssh.Env(env)

return s.Connect(&sshEnv)
}