File: //usr/sbin/turnkey-sudoadmin
#!/bin/bash -e
#
# Copyright (c) 2015 Alon Swartz <alon@turnkeylinux.org>
#
# This file is part of InitHooks.
#
# InitHooks is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
SUDOADMIN_STATE=/etc/sudoadmin/state
fatal() { echo "FATAL [$(basename $0)]: $@" 1>&2; exit 1; }
warn() { echo "WARN [$(basename $0)]: $@"; }
info() { echo "INFO [$(basename $0)]: $@"; }
usage() {
cat<<EOF
Syntax: $(basename $0) on|off|status [--disable-setpass]
Configure system to use admin user with sudo, or root
On:
- installs sudo package
- creates admin user and sets random password
- configures passwordless sudo for admin user
- configures inithooks and init-fence for admin user
- updates confconsole services for admin user
- merges root .ssh/authorized_keys with admin
- locks the root user
- disables root ssh access
- sets root ssh login banner
- restarts ssh daemon, if it is running
- sets admin password interactively (unless --disable-setpass)
Off:
- configures inithooks and init-fence for root
- updates confconsole services for root
- merges admin .ssh/authorized_keys with root
- enables root ssh access
- locks admin user
- unsets root ssh login banner
- restarts ssh daemon, if it is running
- sets root password interactively (unless --disable-setpass)
Status:
- checks turnkey-sudoadmin status, returns one of the following:
- unconfigured
- on
- off
EOF
exit 1
}
install_sudo() {
info $FUNCNAME $@
which sudo >/dev/null && return
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get -y install sudo
}
create_user() {
info $FUNCNAME $@
username=$1
grep -q ^${username}: /etc/passwd && return
useradd --create-home --skel /etc/skel --shell /bin/bash ${username}
echo ${username}:$(mcookie) | chpasswd
}
passwordless_sudo() {
info $FUNCNAME $@
username=$1
cfg="/etc/sudoers.d/99_${username}"
str="${username} ALL=(ALL) NOPASSWD:ALL"
touch $cfg
grep -q "^${str}$" $cfg && return
echo "$str" >> $cfg
chmod 0440 $cfg
}
inithooks_sudoadmin() {
info $FUNCNAME $@
val=$1
key="SUDOADMIN"
cfg="/etc/default/inithooks"
[ -e $cfg ] || return 0
grep -q ^${key}= $cfg || (echo "$key=$val" >> $cfg; return)
sed -i "s/^${key}=.*/$key=$val/" $cfg
}
setup_initfence() {
info $FUNCNAME $@
username=$1
root_profiled=/root/.profile.d/turnkey-init-fence
user_profiled=/home/${username}/.profile.d/turnkey-init-fence
if [ -e $root_profiled ]; then
if [ $username != "root" ]; then
mkdir -p $(dirname $user_profiled)
cp $root_profiled $user_profiled
sed -i "s|^|sudo |" $user_profiled
sed -i "s|/root|/home\/${username}|g" $user_profiled
chown -R $username:$username $(dirname $user_profiled)
fi
fi
return 0
}
update_confconsole_services() {
info $FUNCNAME $@
new_uname=$1
old_uname=$2
cfg="/etc/confconsole/services.txt"
[ -e $cfg ] || return 0
sed -i "s|${old_uname}@|${new_uname}@|g" $cfg
}
ssh_authorizedkeys_inithook() {
info $FUNCNAME $@
username=$1
sshkeys_inithook=/usr/lib/inithooks/firstboot.d/40ec2-sshkeys
[ -e $sshkeys_inithook ] || return 0
sed -i "s|^USERNAME.*|USERNAME = \'${username}\'|" $sshkeys_inithook
}
ssh_authorizedkeys_merge() {
info $FUNCNAME $@
user1=$1
user2=$2
grep -q ^${user1}: /etc/passwd || return 0
grep -q ^${user2}: /etc/passwd || return 0
auth1="$(eval printf ~$user1)/.ssh/authorized_keys"
mkdir -p $(dirname $auth1)
chmod 0700 $(dirname $auth1)
touch $auth1
auth2="$(eval printf ~$user2)/.ssh/authorized_keys"
mkdir -p $(dirname $auth2)
chmod 0700 $(dirname $auth2)
touch $auth2
cat $auth1 $auth2 | sort | uniq > $auth1.new
echo $auth1 $auth2 | xargs -n 1 cp $auth1.new
rm $auth1.new
chown -R $user1:$user1 $(dirname $auth1)
chown -R $user2:$user2 $(dirname $auth2)
}
permitrootlogin_ssh() {
info $FUNCNAME $@
val=$1
key="PermitRootLogin"
cfg="/etc/ssh/sshd_config"
grep -q ^${key} $cfg || (echo "$key $val" >> $cfg; return)
sed -i "s/^${key} .*/$key $val/" $cfg
}
set_sshrootbanner() {
info $FUNCNAME $@
content=$1
banner_path="/root/.ssh/banner"
mkdir -p $(dirname $banner_path)
echo $content > $banner_path
}
user_state() {
info $FUNCNAME $@
username=$1
action=$2
grep -q ^${username}: /etc/passwd || return 0
passwd --${action} $username
if [ $username != "root" ]; then
[ $action == "lock" ] && usermod --expiredate "1" $username
[ $action == "unlock" ] && usermod --expiredate "" $username
fi
return 0
}
restart_sshd() {
info $FUNCNAME $@
if [ -e /var/run/sshd.pid ]; then
/etc/init.d/ssh restart
fi
}
setpass() {
info $FUNCNAME $@
username=$1
script=/usr/lib/inithooks/bin/setpass.py
if [ -x $script ]; then
$script $username
else
echo "Set password for $username"
passwd $username
fi
}
set_status() {
if [ ! -d $(dirname $SUDOADMIN_STATE) ]; then
mkdir $(dirname $SUDOADMIN_STATE)
fi
cat > $SUDOADMIN_STATE <<EOF
# This is an automatically generated file, do not edit manually
state=$1
EOF
}
check_status() {
if [ ! -f $SUDOADMIN_STATE ]; then
echo 'unconfigured'
else
sed -rn 's/state=(.*)/\1/p' "$SUDOADMIN_STATE"
fi
}
case $1 in
on)
[ "$(id -u)" != "0" ] && fatal "must be run with root permissions"
install_sudo;
create_user "admin";
passwordless_sudo "admin";
inithooks_sudoadmin "true";
setup_initfence "admin";
update_confconsole_services "admin" "root";
ssh_authorizedkeys_inithook "admin";
ssh_authorizedkeys_merge "admin" "root";
user_state "admin" "unlock";
user_state "root" "lock";
permitrootlogin_ssh "no";
set_sshrootbanner 'Please login as user "admin" rather than user "root".';
restart_sshd;
set_status "on"
[ "$2" == "--disable-setpass" ] || setpass "admin";
;;
off)
[ "$(id -u)" != "0" ] && fatal "must be run with root permissions"
inithooks_sudoadmin "false";
setup_initfence "root";
update_confconsole_services "root" "admin";
ssh_authorizedkeys_inithook "root";
ssh_authorizedkeys_merge "root" "admin";
permitrootlogin_ssh "yes";
user_state "root" "unlock";
user_state "admin" "lock";
set_sshrootbanner "";
restart_sshd;
set_status "off"
[ "$2" == "--disable-setpass" ] || setpass "root";
;;
status)
check_status;
;;
*)
usage;;
esac