#!/bin/bash if [ ! "$BASH_VERSION" ] ; then bash $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 exit 1 fi wxRed=$(tput setaf 196) wxGreen=$(tput setaf 46) wxYellow=$(tput setaf 226) wxBlue=$(tput setaf 21) wxPurple=$(tput setaf 165) wxTurquoise=$(tput setaf 14) wxPink=$(tput setaf 198) wxOrange=$(tput setaf 202) wxUnderline=$(tput smul) wxBold=$(tput bold) wxNormal=$(tput sgr0) declare -Ax config wx-header(){ if [[ $2 == "h1" ]] then echo "" echo "" echo "" echo "==============================" wx-repeat " " $((30/2-${#1}/2)) echo -n "$wxBold" echo -n "$1" echo -n "$wxNormal" echo "" echo "==============================" fi if [[ $2 == "h2" || -z $2 ]] then wx-start wx-repeat " " $((30/2-6/2-${#1}/2)) echo -n ">> $1 <<" echo "" echo "------------------------------" fi } wx-repeat() { local str=$1 n=$2 spaces printf -v spaces "%*s" $n " " printf "%s" "${spaces// /$str}" } wx-restricted(){ if [[ $USER == "root" || $USER == "local" ]] then echo "Status: Command Restricted" echo " " echo " " echo " " exit 1 fi } wx-start(){ wx-header "Warén CLI" h1 if [[ $USER != "root" && $USER != "local" ]] then mkdir -p $HOME/.warengroup &> /dev/null touch $HOME/.warengroup/config.json &> /dev/null if [[ ! -f "$HOME/.warengroup/config.json" || $(cat $HOME/.warengroup/config.json | jq -e . >/dev/null 2>&1 | echo ${PIPESTATUS[1]}) -gt 0 ]] then echo '{}' | jq > $HOME/.warengroup/config.json fi mkdir -p $HOME/.ssh/keys chmod 700 -R $HOME/.ssh/keys mkdir -p $HOME/.ssh/multiplex chmod 700 -R $HOME/.ssh/multiplex fi } wx-stop (){ echo " " echo " " echo " " wx-install --auto exit 1 } wx-help(){ wx-header "Help" echo -n " Usage: $0 COMMAND [OPTIONS] Common Commands: init Init help Help ssh SSH config Config edit Edit save Save sync Sync clean Clean keys Keys generate Generate sign Sign retrieve Retrieve save Save sync Sync delete Delete clean Clean Authentication Commands: login Login logout Logout Management Commands: auto Auto clean Clean settings Settings Maintenance Commands: install Install update Update "; } wx-infra(){ wx-login wx-auto &> /dev/null wx-header "Infra" wx-restricted case $USERNAME in cwchristerw) if [[ -d "$HOME/Desktop/Work in Progress/Programming/warengroup/infra" ]] then INFRA_PATH="$HOME/Desktop/Work in Progress/Programming/warengroup/infra" else if [[ -d "$HOME/.warengroup/infra" ]] then INFRA_PATH="$HOME/.warengroup/infra" else INFRA_PATH="$HOME/.warengroup/infra" mkdir -p "$INFRA_PATH" &> /dev/null git clone ssh://git@git.waren.io:2222/warengroup-private/infra.git --config core.sshCommand="ssh -i $HOME/.ssh/keys/warengroup-legacy -o ProxyJump=none" "$INFRA_PATH" &> /dev/null fi fi if [[ ! -f "$INFRA_PATH/vault/cwchristerw" || ! -f "$INFRA_PATH/vault/warengroup" ]] then mkdir -p "$INFRA_PATH/vault" &> /dev/null curl \ -H "X-Vault-Token: ${config["login",$ORG]}" \ -X GET \ https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.cwchristerw' > "$INFRA_PATH/vault/cwchristerw" curl \ -H "X-Vault-Token: ${config["login",$ORG]}" \ -X GET \ https://$VAULT_DOMAIN/v1/cli/data/cwchristerw/settings/infra -s | jq -r '.data.data.warengroup' > "$INFRA_PATH/vault/warengroup" fi if [[ -z $1 ]] then echo "Tag Required" else if [[ $1 == "init" ]] then if [[ -z $2 ]] then 2=init fi cd "$INFRA_PATH" git pull &> /dev/null ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null ansible-playbook --vault-id warengroup@vault/warengroup --vault-id cwchristerw@vault/cwchristerw playbooks/init.yml -t $2 $3 $4 $5 $6 $7 $8 $9 cd "$OLDPWD" elif [[ $1 == "manager" ]] then cd "$INFRA_PATH" git pull &> /dev/null ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null ansible-playbook --vault-id warengroup@vault/warengroup --vault-id cwchristerw@vault/cwchristerw manager.yml $2 $3 $4 $5 $6 $7 $8 $9 cd "$OLDPWD" else cd "$INFRA_PATH" git pull &> /dev/null ansible-galaxy collection install -r requirements.yml --upgrade &> /dev/null ansible-playbook --vault-id warengroup@vault/warengroup --vault-id cwchristerw@vault/cwchristerw playbooks.yml -t $1 $2 $3 $4 $5 $6 $7 $8 $9 cd "$OLDPWD" fi fi ;; *) echo "User Unsupported" ;; esac } wx-ssh(){ wx-login case $1 in keys) wx-ssh-keys $2 $3 ;; config) wx-ssh-config $2 ;; *) wx-header "SSH" wx-stop ;; esac } wx-welcome(){ wx-header "Welcome" } wx-login(){ if [[ ! -z $1 ]] then ORG=$1 jq '.org = "'$ORG'"' $HOME/.warengroup/config.json 1> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null elif [[ $(hostname -d) = *"devices.waren.io" ]] then ORG=warengroup elif [[ $(hostname -d) = *"devices.cwinfo.net" ]] then ORG=cwinfo elif [[ $(hostname -d) = *"devices.christerwaren.fi" ]] then ORG=cwchristerw elif [[ $USER != "root" && $USER != "local" && -f "$HOME/.warengroup/config.json" && $(cat $HOME/.warengroup/config.json | jq -r .org) ]] then ORG=$(cat $HOME/.warengroup/config.json | jq -r .org) else wx-header "Login" echo "Status: Organization Required" wx-stop fi if [[ $ORG == "warengroup" ]] then DOMAIN=waren.io elif [[ $ORG == "cwinfo" ]] then DOMAIN=cwinfo.net elif [[ $ORG == "cwchristerw" ]] then DOMAIN=christerwaren.fi else wx-header "Login" echo "Status: Organization Unsupported" wx-stop fi FOLDER=$ORG DEVICE_DOMAIN="devices.$DOMAIN" IDM_DOMAIN="idm.waren.io" VAULT_DOMAIN="vault.cwinfo.net" if [[ -z $USER || $USER == "root" || $USER == "local" ]] then if [[ -z $SUDO_USER ]] then if [[ -z LOGNAME ]] then wx-header "Login" echo "Status: Username Required" wx-stop else USERNAME=$LOGNAME fi else USERNAME=$SUDO_USER fi else USERNAME=$USER fi VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/sys/health) if [[ $VAULT_STATUS -eq 200 ]] then if [[ $USER != "root" && $USER != "local" && -f "$HOME/.warengroup/config.json" ]] then if [[ $(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.username) != "null" ]] then USERNAME="$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.username)" fi TOKEN="$(cat $HOME/.warengroup/config.json | jq -r .login.$ORG.token)" fi VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/token/renew -X POST --header "X-Vault-Token: $TOKEN" -d '{ "token": "'$TOKEN'" }' -s | jq -r '.auth.client_token') if [[ ! -z $VAULT_LOGIN && ${#VAULT_LOGIN} == 95 ]] then config["login",${ORG}]=$VAULT_LOGIN if [[ $USER != "root" && $USER != "local" ]] then jq '.login.'$ORG'.token = "'$VAULT_LOGIN'"' $HOME/.warengroup/config.json 1> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null fi else IDM_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$IDM_DOMAIN) if [[ $IDM_STATUS -eq 301 ]] then wx-header "Login" echo $wxBold$ORG$wxNormal if [[ -z $USERNAME || $USERNAME == "root" || $USERNAME == "local" || $USERNAME == "nobody" ]] then echo -n "Username: " read USERNAME else echo "Username: $USERNAME" fi jq '.login.'$ORG'.username = "'$USERNAME'"' $HOME/.warengroup/config.json 1> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null echo -n "Password: " read -s PASSWORD echo "****************" if [[ -z $USERNAME || -z $PASSWORD ]] then echo "Status: Username & Password Required" wx-stop else VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/ldap/login/$USERNAME -X POST -d '{ "password": "'$PASSWORD'" }' -s | jq -r '.auth.client_token') if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]] then echo "Status: Login Failed" wx-stop fi config["login",${ORG}]=$VAULT_LOGIN if [[ $USER != "root" && $USER != "local" ]] then jq '.login.'$ORG'.token = "'$VAULT_LOGIN'"' $HOME/.warengroup/config.json &> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null fi fi else wx-header "Login" echo $wxBold$ORG$wxNormal echo -n "Token: " read -s TOKEN echo "****************" if [[ -z $TOKEN || ${#TOKEN} -lt 95 || ${#TOKEN} -gt 95 ]] then echo "Status: Vault Token Required" wx-stop fi VAULT_LOGIN=$(curl https://$VAULT_DOMAIN/v1/auth/token/renew -X POST --header "X-Vault-Token: $TOKEN" -d '{ "token": "'$TOKEN'" }' -s | jq -r '.auth.client_token') if [[ -z $VAULT_LOGIN || ${#VAULT_LOGIN} -lt 95 || ${#VAULT_LOGIN} -gt 95 ]] then echo "Status: Login Failed" wx-stop fi config["login",${ORG}]=$VAULT_LOGIN if [[ $USER != "root" && $USER != "local" ]] then jq '.login.'$ORG'.token = "'$VAULT_LOGIN'"' $HOME/.warengroup/config.json &> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null fi fi fi else wx-header "Login" echo $wxBold$ORG$wxNormal echo "Status: Vault Offline" wx-stop fi } wx-logout(){ wx-header "Logout" if [[ $USER != "root" && $USER != "local" && -f "$HOME/.warengroup/config.json" ]] then VAULT_LOGIN=$(cat $HOME/.warengroup/config.json | jq -r .login) if [[ $VAULT_LOGIN != null && $VAULT_LOGIN != "{}" ]] then wx-clean &> /dev/null jq '.login = {}' $HOME/.warengroup/config.json &> $HOME/.warengroup/config.json.tmp mv $HOME/.warengroup/config.json.tmp $HOME/.warengroup/config.json &> /dev/null fi fi } wx-install(){ if [[ -z $1 ]] then wx-header "Install" fi wx-restricted if [[ -f "./wx" ]] && [[ -d "./src" ]] then podman run -it --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp docker.io/library/php:8-cli php generator.php &> /dev/null mv wx.tmp wx &> /dev/null chmod +x wx &> /dev/null fi mkdir $HOME/bin &> /dev/null curl https://git.waren.io/warengroup/wx/raw/branch/master/wx -o $HOME/bin/wx &> /dev/null chmod +x $HOME/bin/wx &> /dev/null } wx-uninstall(){ wx-header "Uninstall" wx-logout if [[ ! -d "$HOME/.warengroup" ]] then rm "$HOME/.warengroup" -rf fi } wx-update(){ wx-header "Update" wx-install --update } wx-auto(){ wx-login wx-header "Auto" wx-ssh-config-sync wx-ssh-keys-sync wx-ssh-keys-sign } wx-clean(){ wx-login wx-header "Clean" wx-ssh-config-clean wx-ssh-keys-clean } wx-settings(){ wx-login wx-header "Settings" } wx-ssh-config(){ wx-restricted case $1 in edit) wx-ssh-config-sync wx-ssh-config-edit wx-ssh-config-save ;; save) wx-ssh-config-save ;; sync) wx-ssh-config-sync ;; clean) wx-ssh-config-clean ;; *) wx-ssh-config-sync wx-stop ;; esac } wx-ssh-config-edit(){ wx-header "SSH / Config / Edit" wx-restricted nano ~/.ssh/config } wx-ssh-config-save(){ wx-header "SSH / Config / Save" wx-restricted curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X POST --header "X-Vault-Token: ${config["login",$ORG]}" -d "{ \"data\": { \"data\": \"$(cat ~/.ssh/config | base64 -w 0)\" } }" -s &> /dev/null } wx-ssh-config-sync(){ wx-header "SSH / Config / Sync" wx-restricted VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: ${config["login",$ORG]}") if [[ $VAULT_STATUS -eq 200 ]] then touch ~/.ssh/config SSH1_CONFIG_MD5=$(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: ${config["login",$ORG]}" -s | jq -r '.data.data.data' | base64 -d | md5sum | base64) SSH2_CONFIG_MD5=$(cat ~/.ssh/config | md5sum | base64) if [[ $SSH1_CONFIG_MD5 != $SSH2_CONFIG_MD5 ]] then echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: ${config["login",$ORG]}" -s | jq -r '.data.data.data') | base64 -d > ~/.ssh/config 2>&1 chmod 700 ~/.ssh/config fi fi } wx-ssh-config-clean(){ wx-header "SSH / Config / Clean" wx-restricted VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/config -X GET --header "X-Vault-Token: ${config["login",$ORG]}") if [[ -f "$HOME/.ssh/config" && $VAULT_STATUS -eq 200 ]] then rm "$HOME/.ssh/config" fi } wx-ssh-keys(){ wx-restricted case $1 in generate) wx-ssh-keys-retrieve $2 wx-ssh-keys-generate $2 wx-ssh-keys-save $2 ;; sign) wx-ssh-keys-sign ;; retrieve) wx-ssh-keys-retrieve $2 ;; save) wx-ssh-keys-save $2 ;; sync) wx-ssh-keys-sync $2 ;; delete) wx-ssh-keys-delete $2 ;; clean) wx-ssh-keys-clean $2 ;; *) wx-stop ;; esac } wx-ssh-keys-generate(){ wx-header "SSH / Keys / Generate" wx-restricted if [[ ! -z $1 ]] then if [[ ! -f "$HOME/.ssh/keys/$1" ]] then ssh-keygen -t ed25519 -f $HOME/.ssh/keys/$1 -q -N "" -C "$USERNAME" &> /dev/null fi fi } wx-ssh-keys-sign(){ wx-header "SSH / Keys / Sign" wx-restricted if [[ $ORG == "warengroup" && $USERNAME != "cwchristerw" ]] then wx-ssh-keys-sign-create warengroup sysadmin 3600 elif [[ $ORG == "cwinfo" && $USERNAME != "cwchristerw" ]] then wx-ssh-keys-sign-create cwinfo sysadmin 3600 elif [[ $ORG == "cwchristerw" || $USERNAME == "cwchristerw" ]] then wx-ssh-keys-sign-create warengroup sysadmin 3600 wx-ssh-keys-sign-create cwinfo sysadmin 3600 wx-ssh-keys-sign-create cwchristerw sysadmin 3600 fi } wx-ssh-keys-sign-create(){ wx-restricted NAME=$1 ROLE=$2 PRINCIPALS=$2 TTL=$3 if [[ ! -f "$HOME/.ssh/keys/$NAME" ]] then ssh-keygen -t ed25519 -f $HOME/.ssh/keys/$NAME -q -N "" -C "$USERNAME" &> /dev/null fi if [[ -f "$HOME/.ssh/keys/$NAME" ]] then echo "$NAME/$ROLE" echo $(curl https://$VAULT_DOMAIN/v1/ssh/sign/$ROLE -X POST --header "X-Vault-Token: ${config["login",$ORG]}" -d "{ \"public_key\": \"$(cat $HOME/.ssh/keys/$NAME.pub)\", \"valid_principals\": \"$PRINCIPALS,$USERNAME\", \"ttl\": \"$TTL\" }" -s | jq -r '.data.signed_key') > ~/.ssh/keys/$NAME.sig 2>&1 fi } wx-ssh-keys-retrieve(){ if [[ -z $2 ]] then wx-header "SSH / Keys / Retrieve" fi wx-restricted if [[ ! -z $1 ]] then VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: ${config["login",$ORG]}") if [[ $VAULT_STATUS -eq 200 ]] then echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: ${config["login",$ORG]}" -s | jq -r '.data.data.private') | base64 -d > ~/.ssh/keys/$1 2>&1 chmod 700 ~/.ssh/keys/$1 echo $(curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X GET --header "X-Vault-Token: ${config["login",$ORG]}" -s | jq -r '.data.data.public') | base64 -d > ~/.ssh/keys/$1.pub 2>&1 chmod 700 ~/.ssh/keys/$1.pub fi fi } wx-ssh-keys-save(){ wx-header "SSH / Keys / Save" wx-restricted if [[ ! -z $1 ]] then if [[ -f "$HOME/.ssh/keys/$1" ]] then curl https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$1 -X POST --header "X-Vault-Token: ${config["login",$ORG]}" -d "{ \"data\": { \"private\": \"$(cat ~/.ssh/keys/$1 | base64 -w 0)\", \"public\": \"$(cat ~/.ssh/keys/$1.pub | base64 -w 0)\" } }" -s &> /dev/null fi fi } wx-ssh-keys-sync(){ wx-header "SSH / Keys / Sync" wx-restricted VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: ${config["login",$ORG]}") if [[ $VAULT_STATUS -eq 200 ]] then for name in $(curl https://$VAULT_DOMAIN/v1/cli/metadata/$USERNAME/settings/ssh/keys -X LIST --header "X-Vault-Token: ${config["login",$ORG]}" -s | jq -r '.data.keys | @sh' | tr -d \') do echo $name wx-ssh-keys-retrieve $name --multiple done fi } wx-ssh-keys-clean(){ if [[ -z $1 ]] then wx-header "SSH / Keys / Clean" fi wx-restricted if [[ ! -z $1 ]] then if [[ -f "$HOME/.ssh/keys/$1" && $(basename "$HOME/.ssh/keys/$1") != "legacy" ]] then rm "$HOME/.ssh/keys/$1" &> /dev/null rm "$HOME/.ssh/keys/$1.pub" &> /dev/null rm "$HOME/.ssh/keys/$1.sig" &> /dev/null fi else if [[ $ORG == "warengroup" && $USERNAME != "cwchristerw" ]] then wx-ssh-keys-clean warengroup elif [[ $ORG == "cwinfo" && $USERNAME != "cwchristerw" ]] then wx-ssh-keys-clean cwinfo elif [[ $ORG == "cwchristerw" || $USERNAME == "cwchristerw" ]] then wx-ssh-keys-clean warengroup wx-ssh-keys-clean cwinfo wx-ssh-keys-clean cwchristerw fi for file in ~/.ssh/keys/* do VAULT_STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://$VAULT_DOMAIN/v1/cli/data/$USERNAME/settings/ssh/keys/$(basename "$file" .pub) -X GET --header "X-Vault-Token: ${config["login",$ORG]}") if [[ $(basename "$file") != "legacy" && $VAULT_STATUS -eq 200 ]] then rm "$file" &> /dev/null fi done fi } if [[ ! -z $1 ]] && [[ $(type -t wx-$1) == function ]] then wx-$1 $2 $3 $4 $5 $6 $7 $8 $9 else wx-welcome fi wx-stop