Ssh – Allow regular users to SSH using a private key they cannot read

key-authenticationprivilegesSecurityssh

Let's say I have a set of machines (called here the customers' machines) that only a small list of people (called the support staff) is allowed to SSH into, using only one account by machine (the support access account).

The support staff are only supposed to log into the customers' machines using keys. Moreover, the support staff can evolve, so someone who leaves the support staff is not permitted to log in to any customer machine. Therefore, staff people are prohibited from reading the private keys used to log into the customers' machines. Also, it is forbidden to modify the authorized_keys file on the customers' machines.

To realize that configuration, I had the idea to use an SSH proxy that the support staff will log into (with LDAP authentication, but that's another problem) and that contains the private keys.

The question is: How do I allow support staff to use the SSH private key without being able to read it?

I believe that I have to make a daemon running as root on the proxy machine that will accept a user's request and open an SSH session for them, but I have no idea how to do it. Any ideas?

Best Answer

I would suggest a couple of options.

  1. Protect the ssh key and require the use of sudo on your support team's side. You could do this transparently with a wrapper. Call the wrapper, say, /usr/local/bin/ssh-support and have it contain something like this (untested):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1
    

    This would require an entry in the sudoers file that permitted users in the support group to use the tool. This command allows them to run the ssh-support tool as the ssupport user - which you must create. It does not confer any root privilege.

    %support ALL = (ssupport) /usr/local/bin/ssh-support
    

    If you are happy that the support users should not need to provider their own password to run the tool (as requested by the sudo invocation within the script itself) you can amend the sudoers definition thus:

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support
    

    Assuming PATH contained /usr/local/bin/ you would then call it with ssh-support clientname. Also assuming you had created the ssupport user as /home/ssupport you would create /home/ssupport/.ssh/id_rsa_clientname and /home/ssupport/.ssh/id_rsa_clientname.pub as the certificate pair, and have a host entry in /home/ssupport/.ssh/config for clientname that defined the user, host, port, etc. for the target machine. You would probably disable X11 forwarding, port forwarding, etc. explicitly. As usual, the /home/ssupport/.ssh directory would need to be protected with permissions 0700.

  2. Give each member of support their own local user account, and have each person use their own private ssh key to access the client's servers. When a person leaves the support group you remove their ssh key from the client's servers. This means that you no longer need to worry about preventing your staff from knowing the private ssh key.

Related Question