#!/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 " >&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 msg="${1:-$full_prompt_msg}" echo -en "\e[1A\r\e[K" echo -e "$1 $msg $REPLY" } 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_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 " >&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 < $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 restart_sshd fi fi } restart_sshd() { if systemctl is-active --quiet sshd; then local sshd_pid=$(systemctl show --property MainPID --value sshd) echo "Restarting sshd service..." systemctl restart sshd echo -e "$GREEN_CHECK Restarted sshd service on PID: $sshd_pid" else echo -e "$YELLOW_BANG Not running sshd service" read -p "Do you want to start sshd? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then systemctl start sshd echo -e "$GREEN_CHECK Started sshd" fi fi } # # Run Process # # check_cert_config "certs.conf" # check_ssh_files # echo "" # echo "Host key fingerprint" # ssh_fingerprint hostkey prompt_user