Skip to content

Commit

Permalink
Implement ssh --forward-agent | -x functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy van Baekel committed Jan 22, 2025
1 parent 4dbc32e commit b7621d9
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 1 deletion.
8 changes: 8 additions & 0 deletions bin/shell/osh.pl
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ sub main_exit {
"interactive|i" => \my $interactive,
"netconf" => \my $netconf,
"wait" => \my $wait,
"forward-agent|x" => \my $sshAddKeysToAgent,
"ssh-as=s" => \my $sshAs,
"use-key=s" => \my $useKey,
"kbd-interactive" => \my $userKbdInteractive,
Expand Down Expand Up @@ -1411,6 +1412,8 @@ sub main_exit {
# also set password if allowed in bastion config (to allow users to enter a remote password interactively)
push @preferredAuths, 'password' if $config->{'passwordAllowed'};

# If sshAddKeystoAgent is set, run 'ssh-agent' first and let it spawn 'ssh'
push @command, 'ssh-agent', '-t', '60' if ($config->{'sshAddKeysToAgentAllowed'} && $sshAddKeysToAgent);
push @command, '/usr/bin/ssh', $ip, '-l', $user, '-p', $port;

$fnret = get_details_from_access_array(
Expand Down Expand Up @@ -1459,6 +1462,10 @@ sub main_exit {
}
}

# -x flag is set and allowed, as such set the -A flag (enable agent forwarding) and '-o AddKeysToAgent=yes' to automatically add the egress sshkey to the agent, so that it can be used
if ($config->{'sshAddKeysToAgentAllowed'} && $sshAddKeysToAgent) {
push @command, '-A', '-o', 'AddKeysToAgent=yes';
}
push @command, '-o', 'PreferredAuthentications=' . (join(',', @preferredAuths));

if ($config->{'sshClientHasOptionE'}) {
Expand Down Expand Up @@ -2053,6 +2060,7 @@ sub long_help {
--always-escape Bypass config and force the bugged behavior of old bastions for REMOTE_COMMAND escaping. Don't use.
--never-escape Bypass config and force the new behavior of new bastions for REMOTE_COMMAND escaping. Don't use.
--wait Ping the host before connecting to it (useful to ssh just after a reboot!)
--forward-agent, -x Enables ssh agent forwarding on the egress connection
--long-help Print this
[REMOTE_COMMAND]
Expand Down
12 changes: 12 additions & 0 deletions doc/sphinx/administration/configuration/bastion_conf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ These options are either discouraged (in which case this is explained in the des
- `remoteCommandEscapeByDefault`_
- `sshClientDebugLevel`_
- `sshClientHasOptionE`_
- `sshAddKeysToAgentAllowed`_

Option Reference
================
Expand Down Expand Up @@ -1064,3 +1065,14 @@ sshClientHasOptionE

Set to ``true`` if your ssh client supports the ``-E`` option and you want to use it to log debug info on opened sessions. **Discouraged** because it has some annoying side effects (some ssh errors then go silent from the user perspective).

.. _sshAddKeysToAgentAllowed:

sshAddKeysToAgentAllowed
************************

:Type: ``boolean``

:Default: ``false``

Set to ``true`` if you want to allow to spawn an ssh-agent and forward it over the egress session when specifically requested with the '--forward-agent' or '-x' flag, with the egress key added to the agent. Useful if you need the ssh-key for authentication on other systems (another jumpserver for example).

1 change: 1 addition & 0 deletions doc/sphinx/presentation/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Features
splitting the authentication and authorization phases while still enforcing local policies
- Supports SSH password autologin on the egress side for legacy devices not supporting pubkey authentication,
while still forcing proper pubkey authentication on the ingress side
- Supports ssh-agent forwarding with the egress ssh key added to the agent
- Supports telnet password autologin on the egress side for ancient devices not supporting SSH,
while still forcing proper SSH pubkey authentication on the ingress side
- Supports HTTPS proxying with man-in-the-middle authentication and authorization handling,
Expand Down
7 changes: 6 additions & 1 deletion etc/bastion/bastion.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -492,5 +492,10 @@
# sshClientHasOptionE (boolean)
# DESC: Set to ``true`` if your ssh client supports the ``-E`` option and you want to use it to log debug info on opened sessions. **Discouraged** because it has some annoying side effects (some ssh errors then go silent from the user perspective).
# DEFAULT: false
"sshClientHasOptionE": false
"sshClientHasOptionE": false,
#
# sshAddKeysToAgentAllowed (boolean)
# DESC: Set to ``true`` if you want to allow to spawn an ssh-agent and forward it over the egress session when specifically requested with the '--forward-agent' or '-x' flag, with the egress key added to the agent. Useful if you need the ssh-key for authentication on other systems (another jumpserver for example).
# DEFAULT: false
"sshAddKeysToAgentAllowed": false
}
77 changes: 77 additions & 0 deletions tests/functional/tests.d/346-testagentforward.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# vim: set filetype=sh ts=4 sw=4 sts=4 et:
# shellcheck shell=bash
# shellcheck disable=SC2086,SC2016,SC2046
# below: convoluted way that forces shellcheck to source our caller
# shellcheck source=tests/functional/launch_tests_on_instance.sh
. "$(dirname "${BASH_SOURCE[0]}")"/dummy

testsuite_agent_forwarding()
{
#create account1
success accountCreate $a0 --osh accountCreate --always-active --account $account1 --uid $uid1 --public-key "\"$(cat $account1key1file.pub)\""
json .error_code OK .command accountCreate .value null

# Add access to $remote_ip for $shellaccount
success mustwork $a0 -osh selfAddPersonalAccess -h $remote_ip -u $shellaccount -p 22 --kbd-interactive
nocontain "already"
json .command selfAddPersonalAccess .error_code OK .value.user $shellaccount .value.port 22

# Patch sshd to allow Agent Forwarding, else all other steps are useless to test
success sshd_config_backup $r0 "\"cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak\""
success sshd_config_patch $r0 "\"sed -i 's/^AllowAgentForwarding no/AllowAgentForwarding yes/' /etc/ssh/sshd_config\""
success sshd_reload $r0 "\"pkill -SIGHUP -f '^(/usr/sbin/sshd\\\$|sshd.+listener)'\""

# Test if ssh-agent is spawned without requesting it; it shouldn't
run shellaccount_noagent $a0 $shellaccount@$remote_ip --kbd-interactive -- ssh-add -L
retvalshouldbe 2
contain REGEX "$shellaccount@[a-zA-Z0-9._-]+:22"
contain "allowed ... log on"
nocontain "Permission denied"
contain "Could not open a connection to your authentication agent."

# test if ssh-agent is spawned whilst requesting it but with the addkeystoagentallowed-config directive set to false
run shellaccount_with_fwd_cfg_disallowed_noagent $a0 $shellaccount@$remote_ip --kbd-interactive -- ssh-add -L
retvalshouldbe 2
contain REGEX "$shellaccount@[a-zA-Z0-9._-]+:22"
contain "allowed ... log on"
nocontain "Permission denied"
contain "Could not open a connection to your authentication agent."


# test if ssh-agent is spawned whilst requesting it, with the addkeystoagentallowed-config directive set to True
# Change config
configchg 's=^\\\\x22sshAddKeysToAgentAllowed\\\\x22.+=\\\\x22sshAddKeysToAgentAllowed\\\\x22:\\\\x20true='


# Run test with --forward-agent; agent should spawn
run shellaccount_with_fwd_cfg_longarg $a0 --forward-agent $shellaccount@$remote_ip -- ssh-add -L
retvalshouldbe 0
contain REGEX "$shellaccount@[a-zA-Z0-9._-]+:22"
contain "allowed ... log on"
nocontain "Permission denied"
nocontain "Could not open a connection to your authentication agent."

# Run test with -x; agent should spawn
run shellaccount_with_fwd_cfg_shortarg $a0 -x $shellaccount@$remote_ip -- ssh-add -L
retvalshouldbe 0
contain REGEX "$shellaccount@[a-zA-Z0-9._-]+:22"
contain "allowed ... log on"
nocontain "Permission denied"
nocontain "Could not open a connection to your authentication agent."

# Patch sshd to allow Agent Forwarding, else all other steps are useless to test
success sshd_config_backup $r0 "\"cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config\""
success sshd_reload $r0 "\"pkill -SIGHUP -f '^(/usr/sbin/sshd\\\$|sshd.+listener)'\""

# Remove access for our testaccount first...
success removeaccess $a0 -osh selfDelPersonalAccess -h $remote_ip -u $shellaccount -p 22
contain "Access to $shellaccount"
json .command selfDelPersonalAccess .error_code OK .value.port 22

# delete account1
script cleanup $a0 --osh accountDelete --account $account1 "<<< \"Yes, do as I say and delete $account1, kthxbye\""
retvalshouldbe 0
}

testsuite_agent_forwarding
unset -f testsuite_agent_forwarding

0 comments on commit b7621d9

Please sign in to comment.