Ideally, it's best to provision everyone with their own ssh keypair, their own login account and use sudo
to track who's doing what, and where. If you don't have centralized authentication and more than a couple servers, maintaining all those login accounts can be a mess (note: see ansible
for an easier way without LDAP) not to mention maintaining password changes.
What I've done in the past, is require the remote user to export a variable on their system named LC_SSH_USER
. This variable can be accepted by the sshd config via the AcceptEnv LANG LC_*
setting. A script in /etc/profile.d
runs on login and "sanitizes" the variable and/or terminates the connection if the variable is not found. Additionally, the readonly
attribute is set on the variable so inadvertent changes to the variable cannot easily be made. This way, no matter what account the remote user had logged into (www-data
, passenger
, admin
) the originating user is logged. The system can be circumvented easily enough by the user setting their variable to whatever they want however an HR policy can be put in place to deal with it.
sample script to place in /etc/profile.d/lc-ssh-user.sh which will log LC_SSH_USER to /var/log/auth.log (on Ubuntu) :
# only allow letters, numbers and underscores in passed LC_SSH_USER variable
lc_ssh_user_sanitize()
{
arg="{$1}"
# first, strip underscores
clean="${arg//_/}"
# next, replace spaces with underscores
clean="${clean// /_}"
# now, clean out anything that's not alphanumeric or an underscore
ret="${clean//[^a-zA-Z0-9_]/}"
echo "${ret}"
}
# if SSH_CLIENT is not set, and LC_SSH_USER is not set, then this is a local login or a new shell opened by same user
if [ -z "${SSH_CLIENT}" ] && [ -z "${LC_SSH_USER}" ]; then
export LC_SSH_USER=${USER}
else
# otherwise, this is an ssh session - extract the connecting IP from env
con=`echo "${SSH_CLIENT}" | cut -d'=' -f2 | cut -d' ' -f1`
# export some variables needed for the user environment
# when using "su --preserve-environment userxxx --login" be sure to fixup needed variables
export USER=`whoami`
export LOGNAME=${USER}
export HOME=$( getent passwd "$USER" | cut -d: -f6 )
cd ${HOME}
# user login without LC_SSH_USER set on their local machine
if [ -z "${LC_SSH_USER}" ]; then
echo "Error: LC_SSH_USER not set in connection from ${con} as user $USER" | logger -p auth.info
#
# connection could probably be terminated here to enforce the use of LC_SSH_USER
#
# since there is no LC_SSH_USER in the connection, just use whatever the user logged in as
export LC_SSH_USER=${USER}
echo "Notice: LC_SSH_USER set from login ${USER} from ${con}" | logger -p auth.info
else
# user has LC_SSH_USER set, so sanitize it (just in case) and log the sanitized version to syslog via logger
u_sanitized=$(lc_ssh_user_sanitize "${LC_SSH_USER}")
echo "Notice: LC_SSH_USER ${u_sanitized} login from ${con} as user $USER" | logger -p auth.info
fi
fi
# always make LC_SSH_USER readonly in the users environment
readonly LC_SSH_USER
Update: git commit hook to use $LC_SSH_USER
:
#!/bin/sh
# To enable this hook drop this in ".git/hooks/pre-commit" (chmod 0755)
# It will create .commit_template if it does not exist
# add these lines to .git/config:
# [commit]
# template = .commit_template
#
test -f .commit_template && exit
echo "
Fix :
Issue :
Author: $LC_SSH_USER
" > .commit_template