mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 11:03:34 +00:00
feat: auto-accept only new SSH host keys using "-o StrictHostKeyChecking: accept-new" (#303)
* feat: add "StrictHostKeyChecking no" to ssh Disable host key checking to prevent interaction with ssh. Fixes: #297 Signed-off-by: Miek Gieben <miek@miek.nl> * use accept-new instead of no Signed-off-by: Miek Gieben <miek@miek.nl> * fix tests Signed-off-by: Miek Gieben <miek@miek.nl> * Fix tests here as well Signed-off-by: Miek Gieben <miek@miek.nl> --------- Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
@@ -33,6 +33,7 @@ func NewSSHCLIRemote(user, host string, port int, keyPath string) *SSHCLIRemote
|
||||
func (r *SSHCLIRemote) newSSHCommand(ctx context.Context, cmd string) *exec.Cmd {
|
||||
args := []string{
|
||||
"-o", "ConnectTimeout=5",
|
||||
"-o", "StrictHostKeyChecking=accept-new",
|
||||
// Disable pseudo-terminal allocation to prevent SSH from executing as a login shell.
|
||||
"-T",
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
host: "example.com",
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -33,7 +33,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
host: "example.com",
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "root@example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "root@example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -42,7 +42,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
port: 2222,
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-p", "2222", "example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "2222", "example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -51,7 +51,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
keyPath: "/path/to/key",
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-i", "/path/to/key", "example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-i", "/path/to/key", "example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -61,7 +61,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
port: 2222,
|
||||
cmd: "ls -la",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-p", "2222", "ubuntu@192.168.1.10", "ls -la",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "2222", "ubuntu@192.168.1.10", "ls -la",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -71,7 +71,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
keyPath: "/path/to/key",
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-i", "/path/to/key", "root@example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-i", "/path/to/key", "root@example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -81,7 +81,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
keyPath: "~/.ssh/id_rsa",
|
||||
cmd: "whoami",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-p", "22", "-i", "~/.ssh/id_rsa", "example.com", "whoami",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "22", "-i", "~/.ssh/id_rsa", "example.com", "whoami",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -92,7 +92,7 @@ func TestSSHCLIRemote_newSSHCommand(t *testing.T) {
|
||||
keyPath: "~/.ssh/id_rsa",
|
||||
cmd: "sudo bash -c 'echo hello'",
|
||||
expected: []string{
|
||||
"ssh", "-o", "ConnectTimeout=5", "-T", "-p", "2222", "-i", "~/.ssh/id_rsa",
|
||||
"ssh", "-o", "ConnectTimeout=5", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "2222", "-i", "~/.ssh/id_rsa",
|
||||
"admin@server.local", "sudo bash -c 'echo hello'",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -131,6 +131,8 @@ func (c *SSHCLIConnector) buildSSHArgs() []string {
|
||||
// Disable interactive prompts (e.g., passphrase input) to prevent interference with the TUI.
|
||||
// Authentication must succeed non-interactively via SSH agent or unencrypted key.
|
||||
args = append(args, "-o", "BatchMode=yes")
|
||||
// Disable host key checking for parity with go+ssh.
|
||||
args = append(args, "-o", "StrictHostKeyChecking=accept-new")
|
||||
// Disable pseudo-terminal allocation to prevent SSH from executing as a login shell.
|
||||
args = append(args, "-T")
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
Host: "example.com",
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "basic connection without control socket",
|
||||
@@ -32,7 +32,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
Host: "example.com",
|
||||
},
|
||||
controlSockPath: "",
|
||||
expected: []string{"-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "root@example.com"},
|
||||
expected: []string{"-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "with custom port",
|
||||
@@ -42,7 +42,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
Port: 2222,
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "-p", "2222", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "2222", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "with identity file",
|
||||
@@ -52,7 +52,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
KeyPath: "/path/to/key",
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "-i", "/path/to/key", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "-i", "/path/to/key", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "all options combined",
|
||||
@@ -64,7 +64,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
SockPath: "/custom/path/uncloud.sock",
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "-p", "2222", "-i", "/path/to/key", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "2222", "-i", "/path/to/key", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "port 0 not included",
|
||||
@@ -74,7 +74,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
Port: 0,
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "root@example.com"},
|
||||
},
|
||||
{
|
||||
name: "port 22 included when explicit",
|
||||
@@ -84,7 +84,7 @@ func TestSSHCLIConnector_buildSSHArgs(t *testing.T) {
|
||||
Port: 22,
|
||||
},
|
||||
controlSockPath: "/tmp/test.sock",
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-T", "-p", "22", "root@example.com"},
|
||||
expected: []string{"-o", "ControlMaster=auto", "-o", "ControlPath=/tmp/test.sock", "-o", "ControlPersist=10m", "-o", "ConnectTimeout=5", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=accept-new", "-T", "-p", "22", "root@example.com"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user