Skip to content

Commit

Permalink
feat: validate the authorized_keys file when running the list subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
josegonzalez committed Feb 26, 2025
1 parent 388f152 commit 37a997c
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,23 @@ no-agent-forwarding,no-user-rc,no-X11-forwarding,no-port-forwarding

This can be useful for cases where the ssh server does not allow certain options or you
wish to further constrain a user's environment. Please see `man sshd` for more information.

Existing keys can be listed via the `list` subcommand:

```shell
# in text format
sshcommand list cmd

# filter by a particular name
sshcommand list cmd progrium

# in json format
sshcommand list cmd "" json

# with name filtering
sshcommand list cmd progrium json

# ignore validation errors (though they will be printed to stderr)
export SSHCOMMAND_IGNORE_LIST_WARNINGS=true
sshcommand list cmd
```
42 changes: 42 additions & 0 deletions sshcommand
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,49 @@ fn-adduser() {
esac
}

fn-verify-file() {
declare desc="Test that public key is valid"
declare file="$1"
local has_errors=false

local key line=0
local TMP_KEY_FILE
TMP_KEY_FILE=$(mktemp "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
trap "rm -rf '$TMP_KEY_FILE' >/dev/null" RETURN INT TERM EXIT

SSHCOMMAND_IGNORE_LIST_WARNINGS="${SSHCOMMAND_IGNORE_LIST_WARNINGS:-false}"
while read -r key; do
line=$((line + 1))
[[ -z "$key" ]] && continue
[[ "$key" =~ ^#.*$ ]] && continue

echo "$key" >"$TMP_KEY_FILE"
if ! ssh-keygen -lf "$TMP_KEY_FILE" &>/dev/null; then
has_errors=true
if [[ "$SSHCOMMAND_IGNORE_LIST_WARNINGS" == "false" ]]; then
log-warn "${file} line $line failed ssh-keygen check."
else
log-warn "${file} line $line failed ssh-keygen check, ignoring."
fi
fi
done <"${file}"

if [[ "$has_errors" == "true" ]]; then
return 1
fi
}

log-fail() {
declare desc="Log fail formatter"
echo "$@" 1>&2
exit 1
}

log-warn() {
declare desc="Log warn formatter"
echo "$@" 1>&2
}

log-verbose() {
declare desc="Log verbose formatter"
if [[ -n "$SSHCOMMAND_VERBOSE_OUTPUT" ]]; then
Expand Down Expand Up @@ -209,6 +246,11 @@ sshcommand-list() {
[[ -e "$userhome/.ssh/authorized_keys" ]] || log-fail "authorized_keys not found for $USER"
[[ -s "$userhome/.ssh/authorized_keys" ]] || log-fail "authorized_keys is empty for $USER"

SSHCOMMAND_IGNORE_LIST_WARNINGS="${SSHCOMMAND_IGNORE_LIST_WARNINGS:-false}"
if ! fn-verify-file "$userhome/.ssh/authorized_keys" && [[ "$SSHCOMMAND_IGNORE_LIST_WARNINGS" == "false" ]]; then
return 1
fi

if [[ -n "$OUTPUT_TYPE" ]] && [[ "$OUTPUT_TYPE" == "json" ]]; then
data=$(sed --silent --regexp-extended \
's/^command="FINGERPRINT=(\S+) NAME=(\\"|)(.*)\2 `.*",(\S+).*/{ "fingerprint": "\1", "name": "\3", "SSHCOMMAND_ALLOWED_KEYS": "\4" }/p' \
Expand Down

0 comments on commit 37a997c

Please sign in to comment.