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

Implement ssh --forward-agent | -x functionality #521

Merged
merged 1 commit into from
Feb 6, 2025
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
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
}
2 changes: 1 addition & 1 deletion lib/perl/OVH/Bastion/configuration.inc
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ sub load_configuration {
qw{
interactiveModeAllowed readOnlySlaveMode sshClientHasOptionE ingressKeysFromAllowOverride
moshAllowed debug keyboardInteractiveAllowed passwordAllowed telnetAllowed remoteCommandEscapeByDefault
accountExternalValidationDenyOnFailure ingressRequirePIV IPv6Allowed
accountExternalValidationDenyOnFailure ingressRequirePIV IPv6Allowed sshAddKeysToAgentAllowed
}
],
}
Expand Down
79 changes: 79 additions & 0 deletions tests/functional/tests.d/346-testagentforward.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 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 "\"command -v freebsd-version >/dev/null && sed -I '' 's=^AllowAgentForwarding no=AllowAgentForwarding yes=' /etc/ssh/sshd_config || sed -i 's=^AllowAgentForwarding no=AllowAgentForwarding yes=' /etc/ssh/sshd_config\""
# pkill doesn't work well under FreeBSD, so do it ourselves for all OSes
success sshd_reload $r0 "\"ps -U 0 -o pid,command | grep -E '/usr/sbin/sshd\\\$|sshd:.+liste[n]er' | awk '{print \\\$1}' | xargs -r kill -SIGHUP\""
# during tests, under some OSes it takes some time for sshd to accept new connections again after the SIGHUP
[ "$COUNTONLY" != 1 ] && sleep 1

# 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\""
# pkill doesn't work well under FreeBSD, so do it ourselves for all OSes
success sshd_reload $r0 "\"ps -U 0 -o pid,command | grep -E '/usr/sbin/sshd\\\$|sshd:.+liste[n]er' | awk '{print \\\$1}' | xargs -r kill -SIGHUP\""

# 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