Last active
June 6, 2018 13:52
-
-
Save icy/36a728d8764fc5638a5d848bc025e150 to your computer and use it in GitHub Desktop.
challenge6.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Purpose : Grant/Revoke SSH access | |
# Author : Ky-Anh Huynh | |
# License : MIT | |
# Date : 2018-May-20 | |
_err() { | |
echo >&2 ":: $(date -u): ERR: ${FUNCNAME[1]:-$0}: $*" | |
return 1 | |
} | |
_warn() { | |
echo >&2 ":: $(date -u): WARN: ${FUNCNAME[1]:-$0}: $*" | |
} | |
_download_github_keys() { | |
local _fuser | |
_fuser="${1:-}" | |
_check_username "$_fuser" || return 1 | |
_warn "Attempt to download public SSH key from Github for user $_fuser" | |
curl -Lso- "https://github.com/$_fuser.keys" \ | |
| awk ' | |
BEGIN { | |
error = 0 | |
} | |
{ | |
printf("<github key> %s\n", $0) > "/dev/stderr" | |
if ($0 ~ /Not Found/) { | |
error = 1 | |
} | |
else { | |
} | |
} | |
END { | |
if (error == 1) { | |
exit(1) | |
} | |
} | |
' | |
} | |
_create_user() { | |
local _fuser | |
_fuser="${1:-}" | |
_check_username "$_fuser" || return 1 | |
useradd "$_fuser" | |
mkdir -pv "/home/$_fuser/.ssh/" | |
chown "$_fuser" "/home/$_fuser/" "/home/$_fuser/.ssh/" | |
chmod 700 "/home/$_fuser/" "/home/$_fuser/.ssh/" | |
usermod -s /bin/bash "$_fuser" | |
usermod -d "/home/$_fuser/" "$_fuser" | |
_download_github_keys "$_fuser" \ | |
> "/home/$_fuser/.ssh/authorized_keys" | |
} | |
_revoke_user() { | |
local _fuser= | |
local _fkey= | |
_fuser="${1:-1}" | |
_fkey="/home/${_fuser}/.ssh/authorized_keys" | |
_check_username "$_fuser" || return 1 | |
usermod "$_fuser" -s /bin/true | |
if [[ -f "$_fkey" ]]; then | |
mv -fv "$_fkey" "$_fkey.revoked.$(date -u "+%Y%m%d-%H%M%S")" | |
else | |
_warn "File not found '$_fkey'" | |
fi | |
if [[ -f "$_fkey" ]]; then | |
_err "Unable to revoke '$_fkey'" | |
else | |
: | |
fi | |
} | |
_check_username() { | |
if [[ -z "${1:-}" ]]; then | |
_err "Missing user information as the first argument." | |
return 1 | |
fi | |
case "${1:-}" in | |
"root"|"ubuntu"|"admin") | |
_err "Are you shooting yourself in the foot?" | |
return 1 | |
;; | |
esac | |
echo "${1:-}" | grep -Eqs -e ' +' | |
# shellcheck disable=2181 | |
if [[ $? -eq 0 ]]; then | |
_err "Unable to have space in username '${1:-}'." | |
return 1 | |
else | |
: | |
fi | |
} | |
_main() { | |
set -u | |
_warn "This is ${FUNCNAME[*]} running as user = $(id -un)" | |
if [[ "$(id -un)" != "root" ]]; then | |
_warn "Switching to root environment thanks to sudo" | |
_script_contents \ | |
| sudo -H \ | |
"USERNAME=$USERNAME" \ | |
"ACTION=$ACTION" \ | |
bash -s | |
exit | |
fi | |
_check_username "$USERNAME" || return 1 | |
_warn "Running script as root account. USERNAME=$USERNAME, ACTION=$ACTION" | |
case "$ACTION" in | |
"grant") _create_user "$USERNAME" ;; | |
"revoke") _revoke_user "$USERNAME" ;; | |
*) _err "Unknown action '$ACTION'" ;; | |
esac | |
} | |
_script_contents() { | |
declare -f _err | |
declare -f _warn | |
declare -f _create_user | |
declare -f _download_github_keys | |
declare -f _revoke_user | |
declare -f _script_contents | |
declare -f _check_username | |
declare -f _main | |
echo "export USERNAME=$USERNAME" | |
echo "export ACTION=$ACTION" | |
echo "_main" | |
} | |
_help() { | |
cat 2>&1 <<-'EOF' | |
challenge6.sh -- Grant or Revoke ssh user on Linux servers | |
Syntax: | |
challenge6.sh username host1 [host2...] | |
challenge6.sh +username host1 [host2...] | |
challenge6.sh -username host1 [host2...] | |
Given a Github `username` and a list of hosts, the script will create | |
new shell account or revoke them from the Linux servers. When `username` | |
is prefixed with a plug sign (`-`), the `revoke` action is instructed. | |
Public SSH key is fetched from public Github service, e.g., | |
https://github.com/username.keys | |
For `revoke` action, the `authorized_keys` file is renamed, and the user's | |
shell is changed to `/usr/bin/true`. | |
NOTES: | |
* If there is a running programs on system, revoke action may not be able | |
to update user's shell. | |
* The script will not continue if the input user is `root`, `ubuntu` or `admin` | |
* The script requires `sudo` on remote machine to create/revoke user. | |
TODO: | |
* Logging support | |
* Dry-run mode support | |
EOF | |
} | |
# Print help message for details | |
case "x${1:-}" in | |
"x") _err "Please try -h or --help for details" ; exit ;; | |
"x-h"|"x--help") _help ; exit ;; | |
esac | |
# $0 user host_1 host_2 host_3... | |
USERNAME="${1:-}"; shift | |
if [[ "${USERNAME:0:1}" == "+" ]]; then | |
USERNAME="${USERNAME:1}" | |
fi | |
if [[ "${USERNAME:0:1}" == "-" ]]; then | |
ACTION="revoke" | |
USERNAME="${USERNAME:1}" | |
else | |
ACTION="grant" | |
fi | |
export ACTION | |
export USERNAME | |
_check_username "$USERNAME" || exit 1 | |
while (( $# )); do | |
HOST="${1:-}"; shift | |
_warn "Attempt to $ACTION user '$USERNAME' on $HOST" | |
ssh "$HOST" bash -s < <(_script_contents) | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment