Compare commits
12 Commits
7f634bf0ba
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42b7ec401a | ||
|
|
d248af25a0 | ||
|
|
fd8ab31779 | ||
|
|
c020c481cf | ||
|
|
fe0c66d57a | ||
|
|
b08ef16aec | ||
|
|
b6fd58a7ca | ||
|
|
d30123dc4a | ||
|
|
cff9d8d3a9 | ||
|
|
fc7af4a1f1 | ||
|
|
623c8ef437 | ||
|
|
b18c0f3400 |
@@ -18,6 +18,12 @@ step ca init --ssh --acme
|
|||||||
|
|
||||||
## SSH Certificates
|
## SSH Certificates
|
||||||
|
|
||||||
|
Install script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash <(curl -sL https://gitea.john-stream.com/john/janus/raw/branch/main/scripts/ssh-server-check.sh)
|
||||||
|
```
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
|
|
||||||
Use step-ca to sign an existing public key to produce a signed certificate with some principals on it.
|
Use step-ca to sign an existing public key to produce a signed certificate with some principals on it.
|
||||||
|
|||||||
121
scripts/ssh-client.sh
Executable file
121
scripts/ssh-client.sh
Executable file
@@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
#
|
||||||
|
# Env vars
|
||||||
|
#
|
||||||
|
|
||||||
|
SSH_CFG_PATH="$(readlink -f ~/.ssh)"
|
||||||
|
SSH_USER_KEY="$SSH_CFG_PATH/id_ed25519"
|
||||||
|
SSH_USER_PUBLIC_KEY="$SSH_USER_KEY.pub"
|
||||||
|
SSH_USER_CERT="$SSH_USER_KEY-cert.pub"
|
||||||
|
|
||||||
|
GREEN_CHECK="\e[32m✔\e[0m"
|
||||||
|
RED_X="\e[31m✗\e[0m"
|
||||||
|
YELLOW_BANG="\e[33m!\e[0m"
|
||||||
|
MAGENTA_QUESTION="\e[35m?\e[0m"
|
||||||
|
UP_ONE_LINE="\e[1A"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Function Definitions
|
||||||
|
#
|
||||||
|
|
||||||
|
reset_line() {
|
||||||
|
echo -en "\r\e[K"
|
||||||
|
}
|
||||||
|
|
||||||
|
title_msg() {
|
||||||
|
local title="\e[1m${1:-Title}:\e[0m"
|
||||||
|
local prompt="${2:-Prompt for the user}"
|
||||||
|
# printf "%b %b" "$title" "$prompt"
|
||||||
|
echo -e "$title $prompt"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_user() {
|
||||||
|
full_prompt_msg="$(title_msg "${1}" "${2}")"
|
||||||
|
echo -n -e "$MAGENTA_QUESTION $full_prompt_msg"
|
||||||
|
read -p " (y/n) " -r
|
||||||
|
}
|
||||||
|
|
||||||
|
update_prompt() {
|
||||||
|
local icon="$1"
|
||||||
|
case $# in
|
||||||
|
1) msg="$full_prompt_msg $REPLY";;
|
||||||
|
2) msg="$2";;
|
||||||
|
3) msg="$(title_msg "${2}" "${3}")";;
|
||||||
|
*) msg="Too many arguments";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
reset_line
|
||||||
|
echo -e "$icon $msg"
|
||||||
|
}
|
||||||
|
|
||||||
|
reupdate_prompt() {
|
||||||
|
# echo -en "$UP_ONE_LINE"
|
||||||
|
echo -en "$UP_ONE_LINE"
|
||||||
|
update_prompt "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
icon_msg() {
|
||||||
|
local icon="$1"
|
||||||
|
echo -en "$icon "
|
||||||
|
title_msg "${@:2}"
|
||||||
|
}
|
||||||
|
|
||||||
|
success_msg() {
|
||||||
|
icon_msg "${GREEN_CHECK}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn_msg() {
|
||||||
|
icon_msg "${YELLOW_BANG}" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_user_private_key() {
|
||||||
|
if [[ -e "$SSH_USER_KEY" ]]; then
|
||||||
|
success_msg "SSH User" "Private key: $SSH_USER_KEY"
|
||||||
|
else
|
||||||
|
prompt_user "SSH User" "Private key missing: ${SSH_USER_KEY}. Create?"
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
reupdate_prompt $YELLOW_BANG "SSH User" "Creating private key"
|
||||||
|
ERROR_MSG=$(ssh-keygen -t ed25519 -f "$SSH_USER_KEY" -N "" 2>&1)
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
reupdate_prompt $GREEN_CHECK "SSH User" "Created private key: ${SSH_USER_KEY}"
|
||||||
|
else
|
||||||
|
reupdate_prompt $RED_X "SSH User" "Failed to create key: ${SSH_USER_KEY}"
|
||||||
|
echo -e "Error: $ERROR_MSG"
|
||||||
|
fi
|
||||||
|
elif [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
reupdate_prompt $YELLOW_BANG "SSH User" "Continuing without private key"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_user_cert() {
|
||||||
|
if [[ -e "$SSH_USER_CERT" ]]; then
|
||||||
|
success_msg "SSH User" "Certificate: $SSH_USER_CERT"
|
||||||
|
else
|
||||||
|
prompt_user "SSH User" "Cert missing. Renew cert?"
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
if renew_user_cert; then
|
||||||
|
update_prompt $GREEN_CHECK "SSH User" "Renewed cert"
|
||||||
|
else
|
||||||
|
update_prompt $RED_X "SSH User" "Failed to renew cert"
|
||||||
|
fi
|
||||||
|
elif [[ $REPLY =~ ^[Nn]$ ]]; then
|
||||||
|
reupdate_prompt $RED_X "SSH User" "Declined to renew cert"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
renew_user_cert() {
|
||||||
|
step ssh certificate --sign \
|
||||||
|
--principal root --principal john \
|
||||||
|
--provisioner admin \
|
||||||
|
john@john-pc-ubuntu ~/.ssh/id_ed25519.pub < /dev/tty
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run Process
|
||||||
|
#
|
||||||
|
|
||||||
|
check_user_private_key
|
||||||
|
check_user_cert
|
||||||
@@ -15,8 +15,13 @@ GREEN_CHECK="\e[32m✔\e[0m"
|
|||||||
RED_X="\e[31m✗\e[0m"
|
RED_X="\e[31m✗\e[0m"
|
||||||
YELLOW_BANG="\e[33m!\e[0m"
|
YELLOW_BANG="\e[33m!\e[0m"
|
||||||
|
|
||||||
|
CREATE_USER_CA=0
|
||||||
|
CREATE_HOST_CERT=0
|
||||||
|
NEEDS_RESTART=0
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Function Definition
|
# Function Definitions
|
||||||
#
|
#
|
||||||
|
|
||||||
# This test loads the sshd config to see what values actually get parsed.
|
# This test loads the sshd config to see what values actually get parsed.
|
||||||
@@ -32,38 +37,30 @@ ssh_config_val() {
|
|||||||
echo $(sshd -T 2>/dev/null | grep -i "^$field " | head -1 | awk '{print $2}')
|
echo $(sshd -T 2>/dev/null | grep -i "^$field " | head -1 | awk '{print $2}')
|
||||||
}
|
}
|
||||||
|
|
||||||
prompt_user() {
|
title_msg() {
|
||||||
local title="\e[1m${1:-Title}\e[0m"
|
local title="\e[1m${1:-Title}:\e[0m"
|
||||||
local prompt="${2:-Prompt for the user}"
|
local prompt="${2:-Prompt for the user}"
|
||||||
full_prompt_msg="$title: $prompt"
|
# printf "%b %b" "$title" "$prompt"
|
||||||
|
echo -e "$title $prompt"
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_user() {
|
||||||
|
full_prompt_msg="$(title_msg "${1}" "${2}")"
|
||||||
echo -n -e "$YELLOW_BANG $full_prompt_msg"
|
echo -n -e "$YELLOW_BANG $full_prompt_msg"
|
||||||
read -p " (y/n) " -n 1 -r
|
read -p " (y/n) " -n 1 -r
|
||||||
echo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update_prompt() {
|
update_prompt() {
|
||||||
local icon="$1"
|
local icon="$1"
|
||||||
local msg="${2:-$full_prompt_msg}"
|
case $# in
|
||||||
|
1) msg="$full_prompt_msg $REPLY";;
|
||||||
|
2) msg="$2";;
|
||||||
|
3) msg="$(title_msg "${2}" "${3}")";;
|
||||||
|
*) msg="Too many arguments";;
|
||||||
|
esac
|
||||||
|
|
||||||
# \e[1A: Move up one line
|
echo -en "\r\e[K"
|
||||||
# \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"
|
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() {
|
sign_host_cert() {
|
||||||
@@ -124,21 +121,14 @@ check_ssh_config_files() {
|
|||||||
|
|
||||||
row_process "hostkey"
|
row_process "hostkey"
|
||||||
row_process "hostcertificate"
|
row_process "hostcertificate"
|
||||||
|
case "$status" in
|
||||||
|
missing) CREATE_HOST_CERT=1;;
|
||||||
|
esac
|
||||||
row_process "trustedusercakeys"
|
row_process "trustedusercakeys"
|
||||||
case "$status" in
|
case "$status" in
|
||||||
success) return ;;
|
missing) CREATE_USER_CA=1;;
|
||||||
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
|
esac
|
||||||
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_fingerprint() {
|
ssh_fingerprint() {
|
||||||
@@ -178,26 +168,50 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [[ ! -e $cfg_path ]]; then
|
if [[ ! -e $cfg_path ]]; then
|
||||||
prompt_user "sshd config" "Do you want to configure sshd?"
|
prompt_user "sshd" "Currently unconfigured for certs. Do you want to configure?"
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
install_cert_config
|
install_cert_config
|
||||||
update_prompt $GREEN_CHECK "Configured sshd"
|
update_prompt $GREEN_CHECK "sshd" "Configured to use and accept certs"
|
||||||
|
NEEDS_RESTART=1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
restart_sshd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
restart_sshd() {
|
restart_sshd() {
|
||||||
if ! systemctl is-active --quiet sshd; then
|
if [[ $NEEDS_RESTART -eq 0 ]]; then return; fi
|
||||||
prompt_user "sshd.service" "sshd.service is not active. Restart?"
|
echo -en "$YELLOW_BANG Restarting sshd..."
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
systemctl restart sshd
|
systemctl restart sshd
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
local sshd_pid=$(systemctl show --property MainPID --value sshd)
|
local sshd_pid=$(systemctl show --property MainPID --value sshd)
|
||||||
update_prompt $GREEN_CHECK "Restarted sshd.service on PID: $sshd_pid"
|
update_prompt $GREEN_CHECK "sshd" "Restarted sshd.service on PID: $sshd_pid"
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
local sshd_pid=$(systemctl show --property MainPID --value sshd)
|
update_prompt $RED_X "sshd" "Failed to restart sshd.service"
|
||||||
echo -e "$GREEN_CHECK sshd.service is active on PID: $sshd_pid"
|
exit 1
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
create_files() {
|
||||||
|
if [[ $CREATE_HOST_CERT -eq 1 ]]; then
|
||||||
|
prompt_user "SSH Host" "Cert missing. Sign the ssh host cert?"
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
update_prompt $YELLOW_BANG "Signing ssh host cert"
|
||||||
|
sign_host_cert
|
||||||
|
NEEDS_RESTART=1
|
||||||
|
else
|
||||||
|
update_prompt $RED_X
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $CREATE_USER_CA -eq 1 ]]; then
|
||||||
|
prompt_user "SSH Host" "Create the trusted keys file?"
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
(step ssh config --roots > "$path")
|
||||||
|
update_prompt $GREEN_CHECK "SSH Host" "Created the trusted keys file for the SSH host."
|
||||||
|
NEEDS_RESTART=1
|
||||||
|
else
|
||||||
|
update_prompt $RED_X
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,12 +219,12 @@ restart_sshd() {
|
|||||||
# Run Process
|
# Run Process
|
||||||
|
|
||||||
check_cert_config "certs.conf"
|
check_cert_config "certs.conf"
|
||||||
echo
|
|
||||||
check_ssh_config_files
|
check_ssh_config_files
|
||||||
|
create_files
|
||||||
|
restart_sshd
|
||||||
|
|
||||||
echo
|
title_msg "SSH Host Cert" "$SSH_HOST_CERT"
|
||||||
echo "Host key fingerprint"
|
CERT_INFO=$(ssh-keygen -Lf "$SSH_HOST_CERT")
|
||||||
ssh_fingerprint hostkey
|
echo -e "$CERT_INFO" | grep "Public key"
|
||||||
|
echo -e "$CERT_INFO" | grep "Valid"
|
||||||
# prompt_user
|
echo -e "$CERT_INFO" | grep -A3 "Principals"
|
||||||
# auto_update_prompt
|
|
||||||
|
|||||||
Reference in New Issue
Block a user