Skip to content

Instantly share code, notes, and snippets.

@tionis

tionis/cfg Secret

Created May 7, 2024 13:51
Show Gist options
  • Save tionis/a0f23a7a33b0e289f1b03cc6ff503f86 to your computer and use it in GitHub Desktop.
Save tionis/a0f23a7a33b0e289f1b03cc6ff503f86 to your computer and use it in GitHub Desktop.
#!/bin/env bash
#{"deps": ["jq", "openssh", "bash", "gpg", "git", "tree"]}
#--------------------------------------------
set -Eeuo pipefail
if [[ -n "${DEBUG:-}" ]]; then
set -x
fi
trap stack_trace ERR
function stack_trace() {
echo -e "\nThe command '$BASH_COMMAND' triggered a stacktrace:\nStack Trace:"
for (( i = 1; i < ${#FUNCNAME[@]}; i++ )); do
echo " ($i) ${FUNCNAME[$i]:-(top level)} ${BASH_SOURCE[$i]:-(no file)}:${BASH_LINENO[$(( i - 1 ))]}"
done
}
error(){ printf "\e[1;31m[ERROR]\e[0m %s\n" "${1:-error message missing}" && trap true ERR && exit 1; }
warning(){ printf "\e[1;33m[WARNING]\e[0m %s\n" "$1" >&2; }
success(){ printf "\e[1;32m[SUCCESS]\e[0m %s\n" "$1" >&2; }
info(){ printf "\e[1;34m[INFO]\e[0m %s\n" "$1" >&2; }
log(){ if [[ -n "${VERBOSE:-}" ]]; then printf "\e[1;34m[INFO]\e[0m %s\n" "$1" >&2; fi }
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
export SCRIPT_DIR
#--------------------------------------------
# deps:
##################### General Helper Funcs ############################
join_elements() {
local index="$1"
shift
local array=("$@")
# Check if index is within array bounds
if (( index < 0 || index >= ${#array[@]} )); then
echo "Index out of bounds"
return 1
fi
local result=""
for ((i = 0; i <= index; i++)); do
if [ -n "$result" ]; then
result="${result}.${array[$i]}"
else
result="${array[$i]}"
fi
done
echo "$result"
}
git_cfg(){
git "--git-dir=$HOME/.cfg" "--work-tree=$HOME" "$@"
}
get_worktree_dir(){ # gets worktree of branch, creating it if needed
worktree_info="$(git_cfg worktree list | grep "\[$1\]\$")" 2>/dev/null || worktree_info=""
if [ -n "$worktree_info" ]; then
worktree_path=$(echo "$worktree_info" | awk '{print $1}')
echo "$worktree_path"
else
worktree_path="$HOME/.cfg/non-main-worktrees/$1"
cfg worktree add "$worktree_path" "$1" >&2
echo "$worktree_path"
fi
}
sha256(){
sha256sum <(printf "%s" "$1") | grep -o '^[a-z0-9]*'
}
sha256:file(){
sha256sum "$1" | grep -o '^[a-z0-9]*'
}
tree(){
if command -v tree >/dev/null; then
command tree "$@"
else
old_pwd="$PWD"
cd "$1"
find . -type f -printf "%P\n"
cd "$old_pwd"
fi
}
trim_prefix_from_list() {
local prefix=$1
shift
local list=("$@")
for i in "${!list[@]}"; do
list[i]="${list[$i]#"$prefix"}"
done
if [[ "${#list[@]}" -gt 0 ]]; then
printf "%s\n" "${list[@]}"
fi
}
run(){
executable="$1"
shift
if test -x "$executable"; then
"$executable" "$@"
else
IFS=' ' read -r -a interpreter <<< "$(head -n 1 "$executable" | sed -n 's|^#! *\(.*\)|\1|p')"
if [[ -z "${interpreter[*]}" ]]; then
interpreter=(bash)
fi
"${interpreter[@]}" "$executable" "$@"
fi
}
##################################### Constants ######################################
CACHE_ROOT_DIR="$HOME/.cache/cfg/cache"
test -d "$CACHE_ROOT_DIR" || mkdir -p "$CACHE_ROOT_DIR"
STORE_ROOT_DIR="$HOME/.config/store"
MAIN_GPG_KEY=995DFE267EA741AD6429131E2A3880E05C5DC4B8
##################################### Cache Management ################################
cache_key_exists(){ # check ttl signature?
if test -f "$CACHE_ROOT_DIR/${1:?}"; then
if [[ -f "$CACHE_ROOT_DIR.ttl/${1:?}" ]] && [[ "$(date +%s)" -gt "$(cat "$CACHE_ROOT_DIR.ttl/${1:?}")" ]]; then
echo "Key expired, deleting it"
rm "$CACHE_ROOT_DIR/${1:?}"
log "Key expired: ${1:?}"
return 1
else
log "Key exists: ${1:?}"
return 0
fi
else
log "Key not found: ${1:?}"
return 1
fi
}
cache_key_set(){ # TODO encrypt as needed
while [[ "$#" -gt 0 ]]; do
case "$1" in
--ttl)
ttl="$2"
shift 2;;
-h|--help)
echo "Usage: set [--ttl <seconds>] <path> <value>"
return 0;;
*)
key="$1"
value="$2"
shift 2;;
esac
done
if [[ -z "${key:-}" ]] || [[ -z "${value:-}" ]]; then
error "No key or value provided"
fi
mkdir -p "$CACHE_ROOT_DIR/$(dirname "$key")"
echo "$value" > "$CACHE_ROOT_DIR/$key"
if [[ -n "${ttl:-}" ]]; then
mkdir -p "$CACHE_ROOT_DIR.ttl/$(dirname "${1:?}")"
echo "$(($(date +%s) + "$ttl"))" > "$CACHE_ROOT_DIR.ttl/$key"
fi
}
cache_key_get(){ # TODO decrypt as needed
if cache_key_exists "${1:?}"; then
cat "$CACHE_ROOT_DIR/${1:?}"
else
error "Key not found or expired: '${1:?}'"
fi
}
cache_key_rm(){
if [[ -e "$CACHE_ROOT_DIR.ttl/${1:?}" ]]; then
rm -r "$CACHE_ROOT_DIR.ttl/${1:?}"
fi
rm -r "$CACHE_ROOT_DIR/${1:?}"
}
cache_check_expiry(){
prev_dir="$PWD"
cd "$CACHE_ROOT_DIR"
pattern="${1:-.*}"
while read -r file; do
if [[ -f "$CACHE_ROOT_DIR.ttl/$file" ]] && [[ "$(date +%s)" -gt "$(cat "$CACHE_ROOT_DIR.ttl/$file")" ]]; then
echo "Key expired, deleting it"
rm "$CACHE_ROOT_DIR/$file"
fi
done < <(find . -regextype posix-extended -regex "$pattern")
cd "$prev_dir"
}
cache_exec(){ # TODO use unified hash cache?
while [[ "$#" -gt 0 ]]; do
case "$1" in
--ttl)
ttl="$2"
shift 2;;
-h|--help)
echo "Usage: exec [--ttl <seconds>] <command>"
return 0;;
*)
command="$1"
shift;;
esac
done
if [[ -z "${command:-}" ]]; then
error "No command provided"
fi
hash="$(sha256 "$command")"
log "Hash: $hash"
result_file="$CACHE_ROOT_DIR/hash-cache/$hash"
if ! cache_key_exists "hash-cache/$hash"; then
mkdir -p "$CACHE_ROOT_DIR/hash-cache/"
bash -c "$command" > "$result_file"
if [[ -n "${ttl:-}" ]]; then
mkdir -p "$CACHE_ROOT_DIR.ttl/hash-cache/"
echo "$(($(date +%s) + "$ttl"))" > "$CACHE_ROOT_DIR.ttl/hash-cache/$hash"
fi
fi
cat "$result_file"
}
cache_exec_file(){
file="$1"
shift || true
args=("$@")
file_hash="$(sha256:file "$file")"
args_hash="$(sha256 "$(printf "%s\n" "${args[@]}")")"
hash="$(sha256 "$file_hash$args_hash")"
if ! cache_key_exists "hash-cache/$hash"; then
cache_key_set "hash-cache/$hash" "$("$file" "${args[@]}")"
fi
cache_key_get "hash-cache/$hash"
}
cache_ls(){
prev_dir="$PWD"
cd "$CACHE_ROOT_DIR"
dir="."
while [[ "$#" -gt 0 ]]; do
case "$1" in
-h|--help)
echo "Usage: find [options] <dir>"
echo " -n <glob>, --name <glob> - list only files matching the glob"
echo " -r <regex>, --regex <regex> - list only files matching the regex (applies to full path)"
echo " -t, --trim - trim the dir prefix from the output"
cd "$prev_dir"
return 0;;
-n|--name)
name="$2"
shift 2;;
-r|--regex)
regex="$2"
shift 2;;
-t|--trim)
trim=1
shift;;
*)
dir="$1"
shift;;
esac
done
if [[ ! -d "$dir" ]]; then
return 0
fi
find_args=()
if [[ -n "${name:-}" ]]; then
find_args+=("-name" "$name")
fi
if [[ -n "${regex:-}" ]]; then
find_args+=("-regex" "$regex")
fi
key_list=()
while IFS=$'\n' read -r -d '' file; do
key_list+=("$file")
done < <(find "$dir" -type f -regextype posix-extended "${find_args[@]}" -print0)
if [[ "${trim:-0}" -gt 0 ]]; then
trim_prefix_from_list "$dir/" "${key_list[@]}"
elif [[ "$dir" = "." ]]; then
trim_prefix_from_list "./" "${key_list[@]}"
else
printf '%s\n' "${key_list[@]}"
fi
cd "$prev_dir"
}
cfg_cache(){
case ${1:-help} in
get)
shift || true
cache_key_get "$@";;
exec)
shift || true
cache_exec "$@";;
exec_file)
shift || true
cache_exec_file "$@";;
exists)
shift || true
cache_key_exists "$@";;
set)
shift || true
cache_key_set "$@";;
rm)
shift || true
cache_key_rm "$@";;
ls)
shift || true
cache_check_expiry ".*"
cache_ls "$@";;
tree)
cache_check_expiry ".*"
tree "$CACHE_ROOT_DIR/${2:-""}";;
help)
echo "Available commands:"
echo " get \$path"
echo " exec \$command - exec a command and cache the result"
echo " exec_file \$script_path - exec a script and cache it's result based on file content"
echo " set \$path \$value"
echo " rm \$path"
echo " ls \$opt_dir"
;;
*)
echo "Unknown subcommand: '${1:-}'"
exit 1;;
esac
}
##################################### Store Handling ###################################
cfg_store_set(){
recipients=("$MAIN_GPG_KEY")
while [[ "$#" -gt 0 ]]; do
case "$1" in
--recipient|-r)
recipients+=("$2")
encrypt=1
shift 2
;;
--encrypt|-e)
encrypt=1
shift
;;
--commit|-c)
commit=1
shift
;;
-h|--help)
echo "Usage: store set [-r|--recipient <gpg-recipient>] [-c|--commit] [-e|--encrypt] <key> <value>"
echo "main gpg key is always in the recipient list per default"
echo "if any recipients are added encryption is enabled by default"
return 0
;;
*)
key="$1"
value="$2"
shift 2
;;
esac
done
mkdir -p "$(dirname "$STORE_ROOT_DIR/$key")"
if [[ "${encrypt:-0}" -eq 1 ]]; then
gpg_cmd="gpg --encrypt --armor"
for recipient in "${recipients[@]}"; do
gpg_cmd+=" --recipient $recipient"
done
gpg_cmd+=" --output -"
printf "%s" "$value" | $gpg_cmd > "$STORE_ROOT_DIR/$key"
else
printf "%s" "$value" > "$STORE_ROOT_DIR/$key"
fi
if [[ "${commit:-0}" -eq 1 ]]; then
git_cfg add "$STORE_ROOT_DIR/$key"
case "$(git_cfg status --short "$STORE_ROOT_DIR/$key" | awk '{ print $1 }')" in
A)
git_cfg commit -m "added $key to store";;
*)
git_cfg commit -m "modified $key in store";;
esac
fi
}
cfg_store_get(){
if [[ "$(head -n 1 "$STORE_ROOT_DIR/$1")" = "-----BEGIN PGP MESSAGE-----" ]]; then
hash="$(sha256:file "$STORE_ROOT_DIR/$1")"
if cache_key_exists "hash-cache/$hash"; then
cache_key_get "hash-cache/$hash"
else
# TODO if gpg key is not available either tell user or request the secret via some other channel
result="$(gpg --default-key "$NODE_NAME@tionis.dev" -d < "$STORE_ROOT_DIR/$1" 2>/dev/null)"
cache_key_set "hash-cache/$hash" "$result"
echo "$result"
fi
else
cat "$STORE_ROOT_DIR/$1"
fi
}
cfg_store(){
case "${1:-help}" in
get)
shift
cfg_store_get "$@"
;;
set)
shift
cfg_store_set "$@"
;;
rm)
shift
rm -r "${STORE_ROOT_DIR:?}/${1:?}"
;;
ls)
if [[ -n "${2:-}" ]]; then
ls "$STORE_ROOT_DIR/$2"
else
tree "$STORE_ROOT_DIR"
fi;;
exists)
shift
test -f "$STORE_ROOT_DIR/$1";;
help)
echo "Available commands:"
echo " get \$path"
echo " set \$path"
echo " rm \$path"
echo " ls \$path"
;;
*)
echo "Unknown subcommand"
exit 1;;
esac
}
##################################### Sync and Git funcs ###############################
apply-commit(){
commit=${1:-$(git_cfg rev-parse --abbrev-ref HEAD)}
parents="$(cfg cat-file -p "$commit" | head -n 3 | grep -cE '^parent [a-z0-9]{40}$')"
if [[ $parents -gt 1 ]]; then
echo "Detected merge commit, defaulting to merging using first parent (-m 1)"
fi
target=${2:-""}
IFS='.' read -ra branch_path <<< "$(git_cfg rev-parse --abbrev-ref HEAD)"
branch_count=${#branch_path[@]}
max="$((branch_count - 2))"
# Iterate over the branch array in reverse, starting from the one before the last
for ((i = max; i >= 0; i--)); do
branch=$(join_elements "$i" "${branch_path[@]}")
if test "$i" = "$max"; then
child="$commit"
else
child=$(join_elements "$((i+1))" "${branch_path[@]}")
fi
cd "$(get_worktree_dir "$branch")"
if [[ $parents -gt 1 ]]; then
echo "cherry-picking merge in $branch"
git cherry-pick -m 1 "$child"
else
echo "cherry-picking in $branch"
git cherry-pick "$child"
fi || (echo "Cherry picking encountered a problem, exit shell when it is fixed" && "${SHELL:-bash}")
if test "$branch" = "$target"; then
break
fi
done
cd
git_cfg push --all || error "Error during pushing, commits where applied though"
}
cfg_sync(){
# Environment should already be loaded here
#head_before_sync="$(cfg_git rev-parse HEAD)"
echo "===> Starting cfg Sync @[$(date --iso-8601=seconds)]"
if type -v systemctl >/dev/null 2>&1; then
( (systemctl --user --failed | grep -oP '(?<=^● ).*') || true) > ~/.cache/systemd-failed-user-services 2>&1
fi
cfg fetch || error "Fetch failed (No internet connection?)"
IFS='.' read -ra branch_path <<< "$(cfg rev-parse --abbrev-ref HEAD)"
branch_count=${#branch_path[@]}
sources=("${branch_path[@]:0:$((branch_count-1))}") # Use array slicing to get all but the last element
echo "Processing parent branches:"
for index in "${!sources[@]}"; do
branch=$(join_elements "$index" "${branch_path[@]}")
echo "[$index] Merging $branch..."
cd "$(get_worktree_dir "$branch")"
git merge "origin/$branch" --no-edit --autostash
if test "$index" -gt 0; then
previous_branch="${branch_path[$((index-1))]}"
git merge "$previous_branch" --no-edit --autostash
fi
done
echo "Processing active branch:"
main_branch="$(cfg rev-parse --abbrev-ref HEAD)"
echo "Merging origin/$main_branch into $main_branch"
cfg merge "origin/$main_branch" --no-edit --autostash
if test "$branch_count" -gt 1; then
branch=$(join_elements "$((branch_count-2))" "${branch_path[@]}")
echo "Merging $branch into $main_branch"
cfg merge "$branch" --no-edit --autostash
fi
echo "Finished merging, starting pushing..."
cfg push --all
if test -f ~/.glyph/.main; then
echo "===> Starting Glyph Sync @[$(date --iso-8601=seconds)]"
~/.glyph/.main sync
fi
echo "===> Generating ssh authorized_keys file from allowed_signers @[$(date --iso-8601=seconds)]"
# TODO replace this with a call to ssh-sigchain once its ready
ssh:authorized_keys:generate
}
##################################### Vars ###################################
vars_print_var(){
case "${VAR_EXPORT_MODE:-posix}" in
posix)
echo "export $1=\"$2\";";;
fish)
echo "set -x $1 \"$2\";";;
*)
error "Unknown VAR_EXPORT_MODE: ${VAR_EXPORT_MODE:-posix}";;
esac
declare "$1"="$2"
}
handle_ssh_agent_startup(){
# Look into overrides
if cache_key_exists "cfg/use-gpg-agent" && [[ "$(cache_key_get "cfg/use-gpg-agent")" -gt 0 ]]; then
log "Using gpg-agent"
if command -v okc-ssh-agent >/dev/null; then
if [[ -f "$HOME/.cache/okc-ssh-agent.env" ]]; then
source "$HOME/.cache/okc-ssh-agent.env"
else
warning "okc-ssh-agent is available but no env file found"
fi
else
SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
export SSH_AUTH_SOCK
fi
result="$(echo UPDATESTARTUPTTY | gpg-connect-agent 2>/dev/null)"
if [[ "$result" != "OK" ]]; then
warning "Failed to update gpg-agent's TTY:"
fi
fi
# Then try using existing agents
if [[ -n "${SSH_AUTH_SOCK:-}" && -S "$SSH_AUTH_SOCK" ]]; then
log "Using existing ssh-agent"
status=0
timeout 0.3 ssh-add -l > /dev/null 2>&1 || status=$?
if [[ ! "$status" -eq 2 ]]; then
return
fi
log "ssh-agent is dead, starting new one"
fi
if [[ -n "${XDG_RUNTIME_DIR:-}" && -S "$XDG_RUNTIME_DIR/gcr/.ssh" ]]; then
log "Using gnome keyring ssh-agent"
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gcr/.ssh"
return
fi
# Finally try starting own agent
log "Starting new ssh-agent"
eval "$(ssh-agent -s)" >/dev/null # TODO replace this later with static/dynamic approach
}
ssh:cert:time_remaining(){
cert_expiry_secs="$(date --date "$(ssh-keygen -L -f "$cert_path" | grep 'Valid: from' | grep -oP '(?<= to ).*$')" +%s)"
now_secs="$(date +%s)"
remaining_secs="$((cert_expiry_secs - now_secs))"
echo "$remaining_secs"
}
cert_path="$HOME/.ssh/id_ed25519-cert.pub"
ssh:add-keys(){
if ! ssh-add -l >/dev/null; then
echo "Adding on-disk ssh keys..."
ssh-add
fi
if [[ -f "$cert_path" ]]; then
secs_remaining="$(ssh:cert:time_remaining "$cert_path")"
if [[ "$secs_remaining" -lt 0 ]]; then
warning "Certificate expired!"
ssh-add -d "$cert_path"
elif [[ "$secs_remaining" -lt 43200 ]]; then
warning "Certificate about to expire ($(date -d "@$secs_remaining" -u +%H:%M:%S) remaining)"
fi
fi
}
ssh_agent_ensure_keys_loaded(){
ssh:add-keys
}
vars_export(){
VAR_EXPORT_MODE="posix"
while [[ "$#" -gt 0 ]]; do
case "$1" in
-h|--help)
echo "Usage: export [options]"
echo " --shell - set the shell for which to export the vars"
echo " valid values are: posix, fish"
return 0
;;
--shell)
VAR_EXPORT_MODE="$2"
shift 2
;;
*)
echo "Unknown argument: $1"
return 1
;;
esac
done
handle_ssh_agent_startup
vars_print_var SSH_AUTH_SOCK "$SSH_AUTH_SOCK"
if ! test -f "$CACHE_ROOT_DIR.vars/NODE_NAME"; then
mkdir -p "$CACHE_ROOT_DIR.vars"
if command -v hostnamectl >/dev/null 2>&1; then
hostnamectl hostname > "$CACHE_ROOT_DIR.vars/NODE_NAME"
else
hostname > "$CACHE_ROOT_DIR.vars/NODE_NAME"
fi
fi
for file in "$CACHE_ROOT_DIR.vars"/*; do
vars_print_var "$(basename "$file")" "$(cat "$file")"
done
ssh_agent_ensure_keys_loaded >&2
}
cfg_vars(){
case "${1:-help}" in
export)
shift || true
vars_export "$@";;
set)
shift || true
mkdir -p "$CACHE_ROOT_DIR.vars"
echo "$2" > "$CACHE_ROOT_DIR.vars/$1";;
rm)
shift || true
rm -r "$CACHE_ROOT_DIR.vars/$1";;
ls)
ls "$CACHE_ROOT_DIR.vars";;
help)
echo "Available Subcommands:"
echo " set \$key \$value - set a env var to a value"
echo " rm \$key - remove an env var"
echo " export - export static and dynamic vars"
esac
}
##################################### SSH ###################################
ssh:authorized_keys:generate(){ # TODO replace with call to ssh-sigchain like e.g. ssh-sigchain get_authorized_keys tionis.dev
trust_anchor="*tionis.dev,*tasadar.net,*wendland.dev,*construct-rpg.net valid-after=\"20221007\" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDU1dl1LIBDFZ5aKALIUGdUHB70VuBqGH2+BbLvioaUWBnDCSB8mrr75EY1FpyxDIW7q/Gvc43wnc2bLXuGyLEY78gm7chBzVcajJCST7Dq8TNiezp4mnBagRixreMBk8M29ld9p6J6aGejbysc8vLta3xXnYmRKfWeZKayegtIm3/KciLvPuK4+UrMiKO0fC17wukuqUvDZVklDeFBFLSO/lee7oPvTI5f/KBeVF0rs21ZSDKZN+8Q7VPIohI/xVlCvdEyqDTICOUKroaAPGa1/1NkSd4fe5F02C5h7WChHad8btWNSu8nTP86KUAOFOYa8UUpoaHt2GuUCU87pHosQ08tTijAAx8bDyq2KdnJl9kgXh/2LaRnu3/DJDQXBJpV821Gyzt8hlqXA0cdrbyE6x13yIA+Ta1WXlR2Igzai3UOTkLL6POJBCOycO4dxd9fS7l8WNic6TIQmQDl2ecUECgSYWvBH2TJiltCUQEy0V2Rx8I28RvtuyzkmGbR4Tz5mQiwEuk0dyxRCoct6z9CpC9FSZRiXH7+qUHlaleZLEI6EYqMWFMj0VncQ3ddklEEzEOP9weUWvdgIWy8woCQuZ/YuW4lNS2Qt25jqFgv9XVddzsTDdSt1GFsdDnyHyhrnaSf0bayYtCo2849GI/QKR3dvjGogpYz/5jspxZZEQ== pgp.tionis.dev"
if ! ssh-keygen -Y verify -f <(echo "$trust_anchor") -n allowed_signers -s ~/.ssh/allowed_signers.sig -I tionis.dev < "$HOME/.ssh/allowed_signers"; then
error "Failed to verify signature of allowed_signers file using static trust_anchor"
fi
authorized_principals="$(cfg cache get ssh/authorized_principals || (cfg cache set ssh/authorized_principals "tionis.dev,$NODE_NAME.tionis.dev"; printf "tionis.dev,%s.tionis.dev" "$NODE_NAME"))"
ssh:authorized_keys_from_allowed_signers --principals "$authorized_principals" # TODO replace janet?
}
cfg_ssh(){
case "${1:-help}" in
help)
echo "Available commands:"
echo " help - show this help"
echo " authorized_keys:generate - generate the authorized_keys file from allowed_signers"
echo " set_principals \$comma_separated_principals - set the principals that have access to this machine"
echo " get_principals - get the principals that have access to this machine"
return 0
;;
authorized_keys:generate)
ssh:authorized_keys:generate
;;
set_principals)
shift || true
if test -z "$1"; then
error "No principals provided"
fi
cfg cache set ssh/authorized_principals "$1"
;;
get_principals)
cfg cache get ssh/authorized_principals || (cfg cache set ssh/authorized_principals "tionis.dev,$NODE_NAME.tionis.dev"; printf "tionis.dev,%s.tionis.dev" "$NODE_NAME")
;;
*)
echo "Unknown subcommand"
exit 1;;
esac
}
#################################### Util ###################################
cfg_util(){
case "${1:-help}" in
fetch-main-gpg-key)
gpg --recv-keys "$MAIN_GPG_KEY";;
update_embedded)
for file in "$STORE_ROOT_DIR/cfg/embedded_deps/"*; do
run "$file"
done;;
ssh:add-keys)
ssh:add-keys;;
ssh:cert:time_remaining)
shift || true
ssh:cert:time_remaining "$1";;
help)
echo "Available commands:"
echo " fetch-main-gpg-key"
echo " update_embedded - update the embedded dependencies using scripts in store (cfg/embedded_deps/*)"
;;
*)
echo "Unknown subcommand"
exit 1;;
esac
}
#################################### Main ###################################
case "${1:-help}" in
git)
shift || true
git_cfg "$@";;
apply|apply-commit)
shift
apply-commit "$@";;
sync)
cfg_sync "$@";;
cache)
shift || true
cfg_cache "$@";;
vars)
shift || true
cfg_vars "$@";;
store)
shift || true
cfg_store "$@";;
ssh)
shift || true
cfg_ssh "$@";;
help)
echo "Available commands:"
echo " prompt ... - config status prompt for shell"
echo " cache ... - a key value store local to this machine"
echo " store ... - a key value store shared between all nodes"
echo " vars ... - manage universal env vars"
echo " ssh ... - manage ssh auth to this node"
echo " apply \$OPT_COMMIT \$OPT_UPSTREAM_TARGET_BRANCH - apply (cherry-pick) last commit backwards to upstream branches"
echo " todo - list todos"
echo " prompt - get a line for your shell prompt, please note that this is only for demonstation, shell inline code will run faster"
echo " help - show this help"
;;
prompt)
changes="$(git "--git-dir=$HOME/.cfg" "--work-tree=$HOME" status --short | wc -l)"
if test "$changes" -gt 0; then
printf "\x1b[31m%d uncommited changes \x1b[37m" "$changes"
else
printf ""
fi
if test -f "$cert_path"; then
remaining_secs="$(ssh:cert:time_remaining "$cert_path")"
if [[ "$remaining_secs" -lt 0 ]]; then
printf "\x1b[31mCertificate expired! \x1b[37m"
elif [[ "$remaining_secs" -lt 43200 ]]; then
printf "\x1b[31mCertificate expires in %s \x1b[37m" "$(date -d "@$remaining_secs" -u +%H:%M:%S)"
fi
fi
;;
util)
shift || true
cfg_util "$@";;
todo)
cd && git_cfg grep "# TODO";;
*)
git_cfg "$@";;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment