Files
janus/scripts/ssh-server-check.sh
John Lancaster 7f634bf0ba more prompts
2026-01-04 11:48:01 -06:00

217 lines
5.2 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Env vars
#
# SSH config paths
SSH_CFG_DIR="/etc/ssh"
SSH_USER_CA="$SSH_CFG_DIR/ssh_user_ca.pub"
SSH_HOST_KEY="$SSH_CFG_DIR/ssh_host_ed25519_key"
SSH_HOST_PUBLIC_KEY="$SSH_HOST_KEY.pub"
SSH_HOST_CERT="$SSH_HOST_KEY-cert.pub"
GREEN_CHECK="\e[32m✔\e[0m"
RED_X="\e[31m✗\e[0m"
YELLOW_BANG="\e[33m!\e[0m"
#
# Function Definition
#
# This test loads the sshd config to see what values actually get parsed.
ssh_config_val() {
local field="$1"
local val
if [[ -z "$field" ]]; then
echo "usage: ssh_config_val <config name>" >&2
return 2
fi
echo $(sshd -T 2>/dev/null | grep -i "^$field " | head -1 | awk '{print $2}')
}
prompt_user() {
local title="\e[1m${1:-Title}\e[0m"
local prompt="${2:-Prompt for the user}"
full_prompt_msg="$title: $prompt"
echo -n -e "$YELLOW_BANG $full_prompt_msg"
read -p " (y/n) " -n 1 -r
echo
}
update_prompt() {
local icon="$1"
local msg="${2:-$full_prompt_msg}"
# \e[1A: Move up one line
# \r: Move to start of line
# \e[K: Clear to end of line
echo -en "\e[1A\r\e[K"
if [[ "$msg" != "$full_prompt_msg" ]]; then
echo -e "$icon $msg"
else
echo -e "$icon $msg $REPLY"
fi
}
auto_update_prompt() {
if [[ $REPLY =~ ^[Yy]$ ]]; then
update_prompt $GREEN_CHECK
elif [[ $REPLY =~ ^[Nn]$ ]]; then
update_prompt $RED_X
fi
}
sign_host_cert() {
local if="eth0"
local IP_ADDRESS=$(ip -4 addr show dev $if | awk '/inet /{print $2}' | cut -d/ -f1) && \
local hostname=$(hostname -s) && \
step ssh certificate --host --sign \
--principal "$hostname" \
--principal "$hostname.john-stream.com" \
--principal "$IP_ADDRESS" \
--provisioner admin \
"$hostname" "$SSH_HOST_PUBLIC_KEY"
}
check_ssh_config_files() {
row_success() {
local key="$1"
local path="$2"
local perms=$(stat -c '%a' "$path")
printf "%-17b %-20s %-6s %s\n" " $GREEN_CHECK" "$key" "$perms" "$path"
}
row_missing() {
local key="$1"
local path="$2"
printf "%-15b %-20s %-6s %s\n" " $YELLOW_BANG" "$key" "-" "$path (missing)"
}
row_unconfigured() {
local key="$1"
printf "%-17b %-20s %-6s %s\n" " $RED_X" "$key" "-" "(not configured)"
}
get_key_status() {
local path="$1"
if [[ -z "$path" ]]; then
echo "unconfigured"
elif [[ ! -e "$path" ]]; then
echo "missing"
else
echo "success"
fi
}
row_process() {
local key="$1"
path=$(ssh_config_val "$key")
status=$(get_key_status "$path")
case "$status" in
success) row_success "$key" "$path" ;;
missing) row_missing "$key" "$path" ;;
unconfigured) row_unconfigured "$key" ;;
esac
}
printf "%-6s %-20s %-6s %s\n" "STATUS" "KEY" "PERMS" "PATH"
row_process "hostkey"
row_process "hostcertificate"
row_process "trustedusercakeys"
case "$status" in
success) return ;;
missing)
# Do something if trustedusercakeys is missing
prompt_user "User CA" "Created the trusted keys file?"
if [[ $REPLY =~ ^[Yy]$ ]]; then
(step ssh config --roots > "$path")
update_prompt $GREEN_CHECK "Created public key file for SSH user CA"
else
update_prompt $RED_X
fi
;;
unconfigured) return;;
esac
}
ssh_fingerprint() {
local field="$1"
if [[ -z "$field" ]]; then
echo "usage: ssh_fingerprint <field>" >&2
return 2
fi
local cfg_path=$(ssh_config_val $field)
if [[ -z "$cfg_path" ]]; then
echo "error: sshd field '$field' not found or empty" >&2
return 1
fi
if [[ ! -r "$cfg_path" ]]; then
echo "error: file not readable: $cfg_path" >&2
return 1
fi
ssh-keygen -lf "$cfg_path" | awk '{ print $2 }'
}
check_cert_config() {
local base_dir="/etc/ssh/sshd_config.d"
local cfg_path="$base_dir/${1:-certs.conf}"
install_cert_config() {
mkdir -p $(dirname $cfg_path)
cat <<EOF > $cfg_path
TrustedUserCAKeys $SSH_USER_CA
HostKey $SSH_HOST_KEY
HostCertificate $SSH_HOST_CERT
EOF
}
if [[ ! -e $cfg_path ]]; then
prompt_user "sshd config" "Do you want to configure sshd?"
if [[ $REPLY =~ ^[Yy]$ ]]; then
install_cert_config
update_prompt $GREEN_CHECK "Configured sshd"
fi
fi
restart_sshd
}
restart_sshd() {
if ! systemctl is-active --quiet sshd; then
prompt_user "sshd.service" "sshd.service is not active. Restart?"
if [[ $REPLY =~ ^[Yy]$ ]]; then
systemctl restart sshd
local sshd_pid=$(systemctl show --property MainPID --value sshd)
update_prompt $GREEN_CHECK "Restarted sshd.service on PID: $sshd_pid"
fi
else
local sshd_pid=$(systemctl show --property MainPID --value sshd)
echo -e "$GREEN_CHECK sshd.service is active on PID: $sshd_pid"
fi
}
# Run Process
check_cert_config "certs.conf"
echo
check_ssh_config_files
echo
echo "Host key fingerprint"
ssh_fingerprint hostkey
# prompt_user
# auto_update_prompt