Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sshuser flag #335

Merged
merged 5 commits into from
Sep 11, 2023
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
1 change: 1 addition & 0 deletions docs/help/gardenctl_ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ gardenctl ssh --keep-bastion --bastion-name cli-xxxxxxxx --public-key-file /path
--seed string target the given seed cluster
--shoot string target the given shoot cluster
--skip-availability-check Skip checking for SSH bastion host availability.
--user string user is the name of the Shoot cluster node ssh login username. (default "gardener")
--wait-timeout duration Maximum duration to wait for the bastion to become available. (default 10m0s)
```

Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/ssh/arguments.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func sshCommandArguments(
bastionUserKnownHostsFiles []string,
nodeHostname string,
nodePrivateKeyFiles []PrivateKeyFile,
user string,
) arguments {
bastionUserKnownHostsFilesArg := userKnownHostsFilesArgument(bastionUserKnownHostsFiles)

Expand All @@ -87,7 +88,7 @@ func sshCommandArguments(

args = append(args, argument{value: fmt.Sprintf("-oProxyCommand=%s", proxyCmdArgs.String())})

args = append(args, argument{value: fmt.Sprintf("%s@%s", SSHNodeUsername, nodeHostname)})
args = append(args, argument{value: fmt.Sprintf("%s@%s", user, nodeHostname)})

return arguments{list: args}
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/cmd/ssh/arguments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type testCase struct {
nodeHostname string
nodePrivateKeyFiles []ssh.PrivateKeyFile
expectedArgs []string
user string
}

func newTestCase() testCase {
Expand All @@ -32,6 +33,7 @@ func newTestCase() testCase {
sshPrivateKeyFile: "path/to/private/key",
nodeHostname: "node.example.com",
nodePrivateKeyFiles: []ssh.PrivateKeyFile{"path/to/node/private/key"},
user: "gardener",
}
}

Expand All @@ -46,6 +48,7 @@ var _ = Describe("Arguments", func() {
tc.bastionUserKnownHostsFiles,
tc.nodeHostname,
tc.nodePrivateKeyFiles,
tc.user,
)
Expect(args.String()).To(Equal(strings.Join(tc.expectedArgs, " ")))
},
Expand All @@ -60,6 +63,18 @@ var _ = Describe("Arguments", func() {
}
return tc
}()),
Entry("basic case with other ssh username", func() testCase {
tc := newTestCase()
tc.user = "aaa"
tc.expectedArgs = []string{
"-oStrictHostKeyChecking=no",
"-oIdentitiesOnly=yes",
"'-ipath/to/node/private/key'",
`'-oProxyCommand=ssh -W%h:%p -oStrictHostKeyChecking=no -oIdentitiesOnly=yes '"'"'-ipath/to/private/key'"'"' '"'"'gardener@bastion.example.com'"'"' '"'"'-p22'"'"''`,
"'aaa@node.example.com'",
}
return tc
}()),
Entry("no bastion port", func() testCase {
tc := newTestCase()
tc.bastionPort = ""
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/ssh/connect_information.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ type ConnectInformation struct {

// Nodes is a list of Node objects containing information about the worker nodes.
Nodes []Node `json:"nodes"`

// User is the name of the Shoot cluster node ssh login username
User string
tedteng marked this conversation as resolved.
Show resolved Hide resolved
}

var _ fmt.Stringer = &ConnectInformation{}
Expand Down Expand Up @@ -84,6 +87,7 @@ func NewConnectInformation(
sshPrivateKeyFile PrivateKeyFile,
nodePrivateKeyFiles []PrivateKeyFile,
nodes []corev1.Node,
user string,
) (*ConnectInformation, error) {
var nodeList []Node

Expand Down Expand Up @@ -140,6 +144,7 @@ func NewConnectInformation(
NodeHostname: nodeHostname,
NodePrivateKeyFiles: nodePrivateKeyFiles,
Nodes: nodeList,
User: user,
}, nil
}

Expand Down Expand Up @@ -200,6 +205,7 @@ func (p *ConnectInformation) String() string {
p.Bastion.UserKnownHostsFiles,
nodeHostname,
p.NodePrivateKeyFiles,
p.User,
tedteng marked this conversation as resolved.
Show resolved Hide resolved
)

fmt.Fprintf(&buf, "> Connect to shoot nodes by using the bastion as a proxy/jump host.\n")
Expand Down
2 changes: 2 additions & 0 deletions pkg/cmd/ssh/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func SSHCommandArguments(
bastionUserKnownHostsFiles []string,
nodeHostname string,
nodePrivateKeyFiles []PrivateKeyFile,
user string,
) TestArguments {
return TestArguments{
sshCommandArguments(
Expand All @@ -69,6 +70,7 @@ func SSHCommandArguments(
bastionUserKnownHostsFiles,
nodeHostname,
nodePrivateKeyFiles,
user,
),
}
}
18 changes: 15 additions & 3 deletions pkg/cmd/ssh/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ import (
const (
// SSHBastionUsername is the system username on the bastion host.
SSHBastionUsername = "gardener"
// SSHNodeUsername is the system username on any of the shoot cluster nodes.
SSHNodeUsername = "gardener"
// DefaultUsername is the default Shoot cluster node ssh login username.
DefaultUsername = "gardener"
// SSHPort is the TCP port on a bastion instance that allows incoming SSH.
SSHPort = 22
)
Expand Down Expand Up @@ -194,6 +194,9 @@ type SSHOptions struct {
// bastion host, but leave it up to the user to SSH themselves.
NodeName string

// User is the name of the Shoot cluster node ssh login username
User string

// SSHPublicKeyFile is the full path to the file containing the user's
// public SSH key. If not given, gardenctl will create a new temporary keypair.
SSHPublicKeyFile PublicKeyFile
Expand Down Expand Up @@ -242,6 +245,7 @@ func NewSSHOptions(ioStreams util.IOStreams) *SSHOptions {
SkipAvailabilityCheck: false,
NoKeepalive: false,
BastionPort: strconv.Itoa(SSHPort),
User: DefaultUsername,
}
}

Expand All @@ -258,7 +262,7 @@ func (o *SSHOptions) AddFlags(flagSet *pflag.FlagSet) {
flagSet.StringVar(&o.BastionPort, "bastion-port", o.BastionPort, "SSH port of the bastion used for the SSH client command. Defaults to port 22")
flagSet.StringSliceVar(&o.BastionUserKnownHostsFiles, "bastion-user-known-hosts-file", o.BastionUserKnownHostsFiles, "Path to a custom known hosts file for the SSH connection to the bastion. This file is used to verify the public keys of remote hosts when establishing a secure connection.")
flagSet.BoolVarP(&o.ConfirmAccessRestriction, "confirm-access-restriction", "y", o.ConfirmAccessRestriction, "Bypasses the need for confirmation of any access restrictions. Set this flag only if you are fully aware of the access restrictions.")

flagSet.StringVar(&o.User, "user", o.User, "user is the name of the Shoot cluster node ssh login username.")
o.Options.AddFlags(flagSet)
}

Expand Down Expand Up @@ -368,6 +372,10 @@ func (o *SSHOptions) Validate() error {
}
}

if o.User == "" {
return errors.New("user must not be empty")
}

content, err := os.ReadFile(o.SSHPublicKeyFile.String())
if err != nil {
return fmt.Errorf("invalid SSH public key file: %w", err)
Expand Down Expand Up @@ -655,6 +663,7 @@ func (o *SSHOptions) Run(f util.Factory) error {
o.SSHPrivateKeyFile,
nodePrivateKeyFiles,
nodes,
o.User,
)
if err != nil {
return err
Expand Down Expand Up @@ -682,6 +691,7 @@ func (o *SSHOptions) Run(f util.Factory) error {
o.BastionUserKnownHostsFiles,
nodeHostname,
nodePrivateKeyFiles,
o.User,
)
}

Expand Down Expand Up @@ -946,6 +956,7 @@ func remoteShell(
bastionUserKnownHostsFiles []string,
nodeHostname string,
nodePrivateKeyFiles []PrivateKeyFile,
user string,
) error {
commandArgs := sshCommandArguments(
bastionHost,
Expand All @@ -954,6 +965,7 @@ func remoteShell(
bastionUserKnownHostsFiles,
nodeHostname,
nodePrivateKeyFiles,
user,
)

fmt.Fprintf(ioStreams.Out, "> You can open additional SSH sessions by running the following command in a separate terminal:\n\n")
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/ssh/ssh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ var _ = Describe("SSH Command", func() {
ssh.SSHBastionUsername,
bastionIP,
),
fmt.Sprintf("%s@%s", ssh.SSHNodeUsername, nodeHostname),
fmt.Sprintf("%s@%s", options.User, nodeHostname),
}))

return nil
Expand Down Expand Up @@ -407,7 +407,7 @@ var _ = Describe("SSH Command", func() {
ssh.SSHBastionUsername,
bastionIP,
),
fmt.Sprintf("%s@%s", ssh.SSHNodeUsername, nodeName),
fmt.Sprintf("%s@%s", options.User, nodeName),
}))

return nil
Expand Down