mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +00:00 
			
		
		
		
	Allow vault ssh to accept ssh commands in any ssh compatible format (#4710)
* Allow vault ssh to accept ssh commands in any ssh compatible format Previously vault ssh required ssh commands to be in the format `username@hostname <flags> command`. While this works just fine for human users this breaks a lot of automation workflows and is not compatible with the options that the ssh client supports. Motivation We currently run ansible which uses vault ssh to connect to hosts. Ansible generates ssh commands with the format `ssh <flags> -o User=username hostname command`. While this is a valid ssh command it currently breaks with vault because vault expects the format to be `username@hostname`. To work around this we currently use a wrapper script to parse the correct username being set by ansible and translate this into a vault ssh compatible `username@hostname` format Changes * You can now specify arguments in any order that ssh client allows. All arguments are passed directly to the ssh command and the format isn't modified in any way. * The username and port are parsed from the specified ssh command. It will accept all of the options supported by the ssh command and also will properly prefer `-p` and `user@` if both options are specified. * The ssh port is only added from the vault credentials if it hasn't been specified on the command line
This commit is contained in:
		 Michael Russell
					Michael Russell
				
			
				
					committed by
					
						 Jeff Mitchell
						Jeff Mitchell
					
				
			
			
				
	
			
			
			 Jeff Mitchell
						Jeff Mitchell
					
				
			
						parent
						
							b5c0f5b1c5
						
					
				
				
					commit
					caf3b94335
				
			| @@ -21,3 +21,136 @@ func TestSSHCommand_Run(t *testing.T) { | ||||
| 	t.Parallel() | ||||
| 	t.Skip("Need a way to setup target infrastructure") | ||||
| } | ||||
|  | ||||
| func TestParseSSHCommand(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	_, cmd := testSSHCommand(t) | ||||
| 	var tests = []struct { | ||||
| 		name     string | ||||
| 		args     []string | ||||
| 		hostname string | ||||
| 		username string | ||||
| 		port     string | ||||
| 		err      error | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"Parse just a hostname", | ||||
| 			[]string{ | ||||
| 				"hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Parse the standard username@hostname", | ||||
| 			[]string{ | ||||
| 				"username@hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"username", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Parse the username out of -o User=username", | ||||
| 			[]string{ | ||||
| 				"-o", "User=username", | ||||
| 				"hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"username", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"If the username is specified with -o User=username and realname@hostname prefer realname@", | ||||
| 			[]string{ | ||||
| 				"-o", "User=username", | ||||
| 				"realname@hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"realname", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Parse the port out of -o Port=2222", | ||||
| 			[]string{ | ||||
| 				"-o", "Port=2222", | ||||
| 				"hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"", | ||||
| 			"2222", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Parse the port out of -p 2222", | ||||
| 			[]string{ | ||||
| 				"-p", "2222", | ||||
| 				"hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"", | ||||
| 			"2222", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"If port is defined with -o Port=2222 and -p 2244 prefer -p", | ||||
| 			[]string{ | ||||
| 				"-p", "2244", | ||||
| 				"-o", "Port=2222", | ||||
| 				"hostname", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"", | ||||
| 			"2244", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Ssh args with a command", | ||||
| 			[]string{ | ||||
| 				"hostname", | ||||
| 				"command", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"Flags after the ssh command are not pased because they are part of the command", | ||||
| 			[]string{ | ||||
| 				"username@hostname", | ||||
| 				"command", | ||||
| 				"-p 22", | ||||
| 			}, | ||||
| 			"hostname", | ||||
| 			"username", | ||||
| 			"", | ||||
| 			nil, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, test := range tests { | ||||
| 		t.Run(test.name, func(t *testing.T) { | ||||
|  | ||||
| 			hostname, username, port, err := cmd.parseSSHCommand(test.args) | ||||
| 			if err != test.err { | ||||
| 				t.Errorf("got error: %q want %q", err, test.err) | ||||
| 			} | ||||
| 			if hostname != test.hostname { | ||||
| 				t.Errorf("got hostname: %q want %q", hostname, test.hostname) | ||||
| 			} | ||||
| 			if username != test.username { | ||||
| 				t.Errorf("got username: %q want %q", username, test.username) | ||||
| 			} | ||||
| 			if port != test.port { | ||||
| 				t.Errorf("got port: %q want %q", port, test.port) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user