Browse Source

new: [rsync-backup-target] add ``ssh-key {enable|disable} IDENT`` admin command

pull/43/head
Valentin Lab 7 months ago
parent
commit
15f93f6565
  1. 3
      rsync-backup-target/build/Dockerfile
  2. 9
      rsync-backup-target/build/src/usr/local/sbin/ssh-admin-cmd-validate
  3. 147
      rsync-backup-target/build/src/usr/local/sbin/ssh-key

3
rsync-backup-target/build/Dockerfile

@ -4,7 +4,8 @@ MAINTAINER Valentin Lab <valentin.lab@kalysto.org>
## coreutils is for ``date`` support of ``--rfc-3339=seconds`` argument.
## findutils is for ``find`` support of ``--newermt`` argument.
RUN apk add rsync sudo bash openssh-server coreutils findutils
## gawk is for ``awk`` support of unicode strings.
RUN apk add rsync sudo bash openssh-server coreutils findutils gawk
RUN ssh-keygen -A
## New user/group rsync/rsync with home dir in /var/lib/rsync

9
rsync-backup-target/build/src/usr/local/sbin/ssh-admin-cmd-validate

@ -80,6 +80,15 @@ elif [[ "$SSH_ORIGINAL_COMMAND" =~ ^"ssh-key get-type "[a-zA-Z0-9._-]+$ ]]; then
# echo "Would accept: $SSH_ORIGINAL_COMMAND" >&2
exec sudo /usr/local/sbin/ssh-key get-type "$label" "${ssh_args[@]:2}"
elif [[ "$SSH_ORIGINAL_COMMAND" =~ ^"ssh-key "(enable|disable)" "[a-zA-Z0-9._-]+$ ]]; then
log "ACCEPTED: $SSH_ORIGINAL_COMMAND"
## Interpret \ to allow passing spaces (want to avoid possible issue with \n)
#read -a ssh_args <<< "${SSH_ORIGINAL_COMMAND}"
ssh_args=(${SSH_ORIGINAL_COMMAND})
# echo "Would accept: $SSH_ORIGINAL_COMMAND" >&2
exec sudo /usr/local/sbin/ssh-key "${ssh_args[1]}" "$label" "${ssh_args[@]:2}"
elif [[ "$SSH_ORIGINAL_COMMAND" =~ ^"request-recovery-key "[a-zA-Z0-9._-]+$ ]]; then
log "ACCEPTED: $SSH_ORIGINAL_COMMAND"

147
rsync-backup-target/build/src/usr/local/sbin/ssh-key

@ -25,18 +25,115 @@ DARKPINK="${ANSI_ESC}0;35m"
DARKCYAN="${ANSI_ESC}0;36m"
DARKWHITE="${ANSI_ESC}0;37m"
read-0() {
local eof= IFS=''
while [ "$1" ]; do
read -r -d '' -- "$1" || eof=1
shift
done
[ -z "$eof" ]
}
col:normalize:size() {
local alignment="$1" colors="$2"
# Encode the associative array into a string for awk
local col_colors_string=""
for key in "${!col_colors[@]}"; do
col_colors_string+="${key}=${col_colors[$key]} "
done
# Pass the string to awk
awk -v alignment="$alignment" -v colors="$colors" -v colorStr="$col_colors_string" -v normal="$NORMAL" '
BEGIN {
# Split the color string into key-value pairs
n = split(colorStr, pairs);
for (i = 1; i <= n; i++) {
split(pairs[i], kv, "=");
col_colors[kv[1]] = kv[2];
}
}
{
# Store the entire line in the lines array
lines[NR] = $0;
# Split the line into fields and update max lengths
split($0, fields);
for (i = 1; i <= length(fields); i++) {
if (length(fields[i]) > max[i]) {
max[i] = length(fields[i]);
}
}
}
END {
# Print lines with fields padded to max, apply color
for (i = 1; i <= NR; i++) {
split(lines[i], fields);
line = "";
for (j = 1; j <= length(fields); j++) {
# Determine alignment
align = substr(alignment, j, 1) == "+" ? "+" : "-";
color_code = substr(colors, j, 1);
color_prefix = (color_code != "-" && color_code in col_colors) ? col_colors[color_code] : "";
color_suffix = (color_prefix != "") ? normal : "";
# Construct line with alignment and color
line = line color_prefix sprintf("%" align max[j] "s ", fields[j]) color_suffix;
}
print line;
}
}'
}
declare -A col_colors=(
[s]=${DARKGRAY} ## s for 'slate' (actually gray)
[r]=${DARKRED}
[g]=${DARKGREEN}
[y]=${DARKYELLOW}
[b]=${DARKBLUE}
[p]=${DARKPINK}
[c]=${DARKCYAN}
[w]=${DARKWHITE}
[S]=${GRAY}
[R]=${RED}
[G]=${GREEN}
[Y]=${YELLOW}
[B]=${BLUE}
[P]=${PINK}
[C]=${CYAN}
[W]=${WHITE}
)
ssh-key-ls() {
local label="$1" f content
for f in "${RSYNC_KEY_PATH}"/backup/"$label"/*.pub; do
shift
while read-0 f; do
[ -e "$f" ] || continue
ident=${f##*/}
if [ "$f" != "${f%.disabled}" ]; then
enabled="${RED}x"
ident=${ident%.disabled}
else
enabled="${GREEN}✓"
fi
ident=${ident%.pub}
content=$(cat "$f")
content=$(cat "$f") || return 1
key=${content#* }
key=${key% *}
printf "${DARKGRAY}..${NORMAL}%24s ${DARKCYAN}%s${NORMAL}\n" "${key: -24}" "$ident"
done
commentary=${content##* }
type=${commentary%%@*}
# printf "${DARKGRAY}..${NORMAL}%12s ${DARKPINK}%-7s${NORMAL} ${DARKCYAN}%s${NORMAL}\n" \
# "${key: -12}" "${type}" "$ident"
printf "%s %s %s %s\n" "…${key: -12}" "$type" "$enabled" "$ident"
done < <(find "${RSYNC_KEY_PATH}"/backup/"$label" \
-maxdepth 1 -mindepth 1 \
\( -name \*.pub -or -name \*.pub.disabled \) -print0 | sort -z
) | col:normalize:size "----" "ysGc"
}
@ -45,10 +142,47 @@ ssh-key-rm() {
delete="${RSYNC_KEY_PATH}/backup/$label/$ident.pub"
if ! [ -e "$delete" ]; then
if ! [ -e "${delete}.disabled" ]; then
echo "Error: key '$ident' not found." >&2
return 1
fi
rm "${delete}.disabled"
return 0
fi
rm "$delete"
/usr/local/sbin/ssh-update-keys
}
ssh-key-disable() {
local label="$1" ident="$2" disable
disable="${RSYNC_KEY_PATH}/backup/$label/$ident.pub"
if ! [ -e "$disable" ]; then
if ! [ -e "${disable}.disabled" ]; then
echo "Error: key '$ident' not found." >&2
return 1
fi
echo "Already disabled." >&2
return 0
fi
mv "${disable}" "${disable}.disabled"
/usr/local/sbin/ssh-update-keys
}
ssh-key-enable() {
local label="$1" ident="$2" enable
enable="${RSYNC_KEY_PATH}/backup/$label/$ident.pub.disabled"
if ! [ -e "$enable" ]; then
if ! [ -e "${enable%.disabled}" ]; then
echo "Error: key '$ident' not found." >&2
return 1
fi
echo "Already enabled." >&2
return 0
fi
mv "${enable}" "${enable%.disabled}"
/usr/local/sbin/ssh-update-keys
}
@ -141,6 +275,11 @@ case "$1" in
shift
ssh-key-ls "$@"
;;
"disable"|"enable")
arg="$1"
shift
ssh-key-"$arg" "$@"
;;
"get-type")
shift
ssh-key-get-type "$@"

Loading…
Cancel
Save