111 lines
2.9 KiB
Bash
111 lines
2.9 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Create a Linux user and install an SSH public key.
|
|
#
|
|
# This script is designed for repeatable server onboarding. It creates the user
|
|
# if missing, prepares ~/.ssh, writes the authorized key, and can optionally add
|
|
# the user to a sudo-capable group.
|
|
#
|
|
# Usage:
|
|
# sudo bash linux_user_bootstrap.sh --user deploy --ssh-key "ssh-ed25519 AAAA..."
|
|
# sudo bash linux_user_bootstrap.sh --user deploy --ssh-key-file ./deploy.pub --sudo
|
|
#
|
|
# Options:
|
|
# --user NAME Linux username to create or update.
|
|
# --ssh-key KEY Public SSH key content.
|
|
# --ssh-key-file FILE File containing the public SSH key.
|
|
# --sudo Add the user to sudo or wheel group.
|
|
# --help Show this help message.
|
|
|
|
set -Eeuo pipefail
|
|
|
|
target_user=""
|
|
ssh_key=""
|
|
ssh_key_file=""
|
|
grant_sudo=false
|
|
|
|
usage() {
|
|
sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//'
|
|
}
|
|
|
|
log() {
|
|
printf '[%s] %s\n' "$(date -Is)" "$*"
|
|
}
|
|
|
|
while [[ "$#" -gt 0 ]]; do
|
|
case "$1" in
|
|
--user)
|
|
target_user="${2:-}"
|
|
shift 2
|
|
;;
|
|
--ssh-key)
|
|
ssh_key="${2:-}"
|
|
shift 2
|
|
;;
|
|
--ssh-key-file)
|
|
ssh_key_file="${2:-}"
|
|
shift 2
|
|
;;
|
|
--sudo)
|
|
grant_sudo=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
printf 'ERROR: unknown option: %s\n' "$1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
[[ "$(id -u)" -eq 0 ]] || { printf 'ERROR: this script must run as root.\n' >&2; exit 1; }
|
|
[[ "$target_user" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]] || { printf 'ERROR: invalid Linux username: %s\n' "$target_user" >&2; exit 1; }
|
|
|
|
if [[ -n "$ssh_key_file" ]]; then
|
|
[[ -f "$ssh_key_file" ]] || { printf 'ERROR: SSH key file not found: %s\n' "$ssh_key_file" >&2; exit 1; }
|
|
ssh_key="$(< "$ssh_key_file")"
|
|
fi
|
|
|
|
[[ "$ssh_key" == ssh-* || "$ssh_key" == ecdsa-* ]] || { printf 'ERROR: a valid public SSH key is required.\n' >&2; exit 1; }
|
|
|
|
if id "$target_user" >/dev/null 2>&1; then
|
|
log "User already exists: ${target_user}"
|
|
else
|
|
log "Creating user: ${target_user}"
|
|
useradd --create-home --shell /bin/bash "$target_user"
|
|
fi
|
|
|
|
home_dir="$(getent passwd "$target_user" | cut -d: -f6)"
|
|
ssh_dir="${home_dir}/.ssh"
|
|
authorized_keys="${ssh_dir}/authorized_keys"
|
|
|
|
install -d -m 700 -o "$target_user" -g "$target_user" "$ssh_dir"
|
|
touch "$authorized_keys"
|
|
chmod 600 "$authorized_keys"
|
|
chown "$target_user:$target_user" "$authorized_keys"
|
|
|
|
if ! grep -qxF "$ssh_key" "$authorized_keys"; then
|
|
log "Installing SSH public key for ${target_user}"
|
|
printf '%s\n' "$ssh_key" >> "$authorized_keys"
|
|
fi
|
|
|
|
if [[ "$grant_sudo" == true ]]; then
|
|
if getent group sudo >/dev/null 2>&1; then
|
|
usermod -aG sudo "$target_user"
|
|
log "Added ${target_user} to sudo group."
|
|
elif getent group wheel >/dev/null 2>&1; then
|
|
usermod -aG wheel "$target_user"
|
|
log "Added ${target_user} to wheel group."
|
|
else
|
|
printf 'ERROR: no sudo or wheel group found.\n' >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
log "User bootstrap completed successfully."
|
|
|