diff --git a/scripts/machines b/scripts/machines index fbc6b51..209f9cb 100755 --- a/scripts/machines +++ b/scripts/machines @@ -7,14 +7,15 @@ MACHINES_HOME=$HOME MACHINES_CONFIG=$HOME/.config/machines MACHINES_API=https://machines.frogeye.fr -mkdir -p $MACHINES_HOME &> /dev/null -mkdir -p $MACHINES_CONFIG &> /dev/null +mkdir -p "$MACHINES_HOME" &> /dev/null +mkdir -p "$MACHINES_CONFIG" &> /dev/null # COMMON function prompt { # text - while true; do - read -p "$1 [yn] " yn + while true + do + read -r -p "$1 [yn] " yn case $yn in [Yy]* ) return 1;; [Nn]* ) return 0;; @@ -32,7 +33,7 @@ urlencode() { # string for (( i = 0; i < length; i++ )); do local c="${1:i:1}" case $c in - [a-zA-Z0-9.~_-]) printf "$c" ;; + [a-zA-Z0-9.~_-]) printf "%s" "$c" ;; *) printf '%%%02X' "'$c" ;; esac done @@ -49,7 +50,7 @@ urldecode() { # string function _machines-api { route=$1 shift - wget $MACHINES_API/$route --content-on-error --quiet --output-document=- "$@" + wget "$MACHINES_API/$route" --content-on-error --quiet --output-document=- "$@" result=$? if [ $result != 0 ]; then echo "[ERROR] wget returned $result for route $route" 1>&2; @@ -58,53 +59,53 @@ function _machines-api { } function _machines-apiToken { - read -p 'TOTP token: ' token + read -r -p 'TOTP token: ' token _machines-api "$@" --header="X-TOTP: $token" } function _machines-apiSigned { _machines-ensureAdmin - _machines-api "$@" --certificate=$MACHINES_CONFIG/machines.crt --private-key=$MACHINES_CONFIG/machines.key + _machines-api "$@" --certificate="$MACHINES_CONFIG/machines.crt" --private-key="$MACHINES_CONFIG/machines.key" } # APPLICATION KEYS & CERTIFICATE function _machines-pubFromCrt { - openssl x509 -in $MACHINES_CONFIG/machines.crt -pubkey -noout > $MACHINES_CONFIG/machines.pub + openssl x509 -in "$MACHINES_CONFIG/machines.crt" -pubkey -noout > "$MACHINES_CONFIG/machines.pub" } function _machines-verifyCertificate { return - if openssl verify $MACHINES_CONFIG/machines.crt | grep -v 'error 18' | grep 'error' --quiet; then + if openssl verify "$MACHINES_CONFIG/machines.crt" | grep -v 'error 18' | grep 'error' --quiet; then echo "[ERROR] Invalid certificate" 1>&2; exit 1 fi } function _machines-ensurePub { - if [ ! -f $MACHINES_CONFIG/machines.crt ]; then + if [ ! -f "$MACHINES_CONFIG/machines.crt" ]; then CERT_FILE=$(mktemp) echo "[INFO] Downloading certificate..." - _machines-api cert > $CERT_FILE - openssl x509 -fingerprint -in $CERT_FILE | grep Fingerprint --color=never + _machines-api cert > "$CERT_FILE" + openssl x509 -fingerprint -in "$CERT_FILE" | grep Fingerprint --color=never prompt "Is this correct ?" if [ $? == 1 ]; then - mv $CERT_FILE $MACHINES_CONFIG/machines.crt &> /dev/null + mv "$CERT_FILE" "$MACHINES_CONFIG/machines.crt" &> /dev/null else echo "[ERROR] Certificate rejected." 1>&2; exit 1 fi fi _machines-verifyCertificate - if [ ! -f $MACHINES_CONFIG/machines.pub ]; then + if [ ! -f "$MACHINES_CONFIG/machines.pub" ]; then _machines-pubFromCrt fi return 0 } function _machines-ensureAdmin { - if [ ! -f $MACHINES_CONFIG/machines.key ]; then + if [ ! -f "$MACHINES_CONFIG/machines.key" ]; then echo "[ERROR] You need have to have the private key to do that" 1>&2; exit 1 fi @@ -115,52 +116,52 @@ function _machines-ensureAdmin { function _machines-signAkey { # network KEY_FILE=$(mktemp) SIGN_FILE=$(mktemp) - _machines-apiSigned akey/$1?unsigned > $KEY_FILE - openssl dgst -sha256 -sign $MACHINES_CONFIG/machines.key -out $SIGN_FILE $KEY_FILE - _machines-apiSigned akey/$1 --method=PUT --body-file=$SIGN_FILE - rm $KEY_FILE $SIGN_FILE &> /dev/null + _machines-apiSigned "akey/$1?unsigned" > "$KEY_FILE" + openssl dgst -sha256 -sign "$MACHINES_CONFIG/machines.key" -out "$SIGN_FILE" "$KEY_FILE" + _machines-apiSigned "akey/$1" --method=PUT --body-file="$SIGN_FILE" + rm "$KEY_FILE" "$SIGN_FILE" &> /dev/null } function _machines-getAkey { # network _machines-ensurePub KEY_FILE=$(mktemp) SIGN_FILE=$(mktemp) - _machines-api akey/$1 > $KEY_FILE - _machines-api akey/$1?signature > $SIGN_FILE - md5sum $KEY_FILE &1>&2; - md5sum $SIGN_FILE &1>&2; - md5sum $MACHINES_CONFIG/machines.pub &1>&2; + _machines-api "akey/$1" > "$KEY_FILE" + _machines-api "akey/$1?signature" > "$SIGN_FILE" + md5sum "$KEY_FILE" 1>&2; + md5sum "$SIGN_FILE" 1>&2; + md5sum "$MACHINES_CONFIG/machines.pub" 1>&2; - openssl dgst -sha256 -verify $MACHINES_CONFIG/machines.pub -signature $SIGN_FILE $KEY_FILE &> /dev/null - if [ $? == 0 ]; then - cat $KEY_FILE - rm $KEY_FILE $SIGN_FILE &> /dev/null + if openssl dgst -sha256 -verify "$MACHINES_CONFIG/machines.pub" -signature "$SIGN_FILE" "$KEY_FILE" &> /dev/null + then + cat "$KEY_FILE" + \rm "$KEY_FILE" "$SIGN_FILE" return 0 else - rm $KEY_FILE $SIGN_FILE &> /dev/null + \rm "$KEY_FILE" "$SIGN_FILE" exit 1 fi } function _machines-updateAkey { MYKEY_FILE=$(mktemp) - network=$(cat $MACHINES_CONFIG/this | grep '^network=' | cut -d '=' -f 2) - _machines-getAkey $network > "$MYKEY_FILE" - if [ $? == 0 ]; then - yes | mv $MYKEY_FILE $MACHINES_HOME/.ssh/authorized_keys &> /dev/null + network=$(grep '^network=' "$MACHINES_CONFIG/this" | cut -d '=' -f 2) + if _machines-getAkey "$network" > "$MYKEY_FILE" + then + \mv -f "$MYKEY_FILE" "$MACHINES_HOME/.ssh/authorized_keys" return 0 else - cat $MYKEY_FILE + cat "$MYKEY_FILE" echo "[ERROR] Authorized keys are not properly signed" 1>&2; - rm $MYKEY_FILE + \rm "$MYKEY_FILE" exit 1 fi } function _machines-postFile { # filename - cat $1 | while read line; do - parameter=$(echo $line | cut -d '=' -f 1) - value="$(echo $line | sed 's/^[a-zA-Z0-9]\+\(\[\]\)\?=//')" + cat $1 | while read -r line; do + parameter=$(echo "$line" | cut -d '=' -f 1) + value="$(echo "$line" | sed 's/^[a-zA-Z0-9]\+\(\[\]\)\?=//')" echo -n "&$parameter=$(urlencode "$value")" done } @@ -168,44 +169,47 @@ function _machines-postFile { # filename function _machines-addElement { # element elementType default FILE=$(mktemp) - echo -e $3 > $FILE - $EDITOR $FILE - data=$(_machines-postFile $FILE) - rm $FILE &> /dev/null - _machines-apiSigned $2 --post-data "name=$1$data" + echo -e "$3" > "$FILE" + $EDITOR "$FILE" + data=$(_machines-postFile "$FILE") + \rm "$FILE" + _machines-apiSigned "$2" --post-data "name=$1$data" +} + +function _machines-viewElement { # element elementType + _machines-apiSigned "$2/$1" } function _machines-editElement { # element elementType FILE=$(mktemp) - _machines-apiSigned $2/$1 > $FILE - $EDITOR $FILE - data=$(_machines-postFile $FILE) - rm $FILE &> /dev/null - err=$(_machines-apiSigned $2/$1 --post-data "$data") + _machines-apiSigned "$2/$1" > "$FILE" + $EDITOR "$FILE" + data=$(_machines-postFile "$FILE") + rm "$FILE" &> /dev/null + err=$(_machines-apiSigned "$2/$1" --post-data "$data") } function _machines-deleteElement { # element elementType - err=$(_machines-apiSigned $2/$1 --method=DELETE) + err=$(_machines-apiSigned "$2/$1" --method=DELETE) } # USER ADMIN FUNCTIONS function machines_history { - if [ -f $MACHINES_CONFIG/lastVerifiedLog ]; then + if [ -f "$MACHINES_CONFIG/lastVerifiedLog" ]; then from=$(<"$MACHINES_CONFIG/lastVerifiedLog") else from=0 fi d=$(date +%s) _machines-apiSigned log?from=$from | less - prompt "Is this OK?" - if [ $? == 1 ]; then - echo $d > $MACHINES_CONFIG/lastVerifiedLog - return 0 - else - echo "Houston, we have a problem..." + if prompt "Is this OK?" + then exit 1 + else + echo "$d" > "$MACHINES_CONFIG/lastVerifiedLog" + return 0 fi } @@ -213,7 +217,7 @@ function machines_sign { machines_history echo "Signing default network authorized_keys..." _machines-signAkey - _machines-apiSigned network | while read network; do + _machines-apiSigned network | while read -r network; do echo "Signing network $network authorized_keys..." _machines-signAkey $network done @@ -235,11 +239,11 @@ function machines_machine_add_help { return 0 } function machines_machine_add { # machine - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_machine_add_help exit 1 fi - _machines-addElement $1 machine "host[]=\nnetwork=\nuserkey=\nhostkey=\nuser=" + _machines-addElement "$1" machine "host[]=\nnetwork=\nuserkey=\nhostkey=\nuser=" } function machines_network_add_help { @@ -249,42 +253,75 @@ function machines_network_add_help { echo " NETWORK Network to add" return 0 } + function machines_network_add { # network - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_network_add_help exit 1 fi - _machines-addElement $1 network "allowed[]=\nsecure=false" + _machines-addElement "$1" network "allowed[]=\nsecure=false" +} + +function machines_machine_view_help { + echo "Usage: $0 machine|mac|m view MACHINE" + echo + echo "Arguments:" + echo " MACHINE machine to view" + return 0 +} + +function machines_machine_view { # machine + if [ -z "$1" ]; then + machines_machine_view_help + exit 1 + fi + _machines-viewElement "$1" machine +} + +function machines_network_view_help { + echo "Usage: $0 network|net|n view NETWORK" + echo + echo "Arguments:" + echo " NETWORK Network to view" + return 0 +} +function machines_network_view { # network + if [ -z "$1" ]; then + machines_network_view_help + exit 1 + fi + _machines-viewElement "$1" network } function machines_machine_edit_help { echo "Usage: $0 machine|mac|m edit MACHINE" echo echo "Arguments:" - echo " MACHINE machine to remove" + echo " MACHINE machine to edit" return 0 } + function machines_machine_edit { # machine - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_machine_edit_help exit 1 fi - _machines-editElement $1 machine + _machines-editElement "$1" machine } function machines_network_edit_help { echo "Usage: $0 network|net|n edit NETWORK" echo echo "Arguments:" - echo " NETWORK Network to remove" + echo " NETWORK Network to edit" return 0 } function machines_network_edit { # network - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_network_edit_help exit 1 fi - _machines-editElement $1 network + _machines-editElement "$1" network } function machines_machine_delete_help { @@ -295,11 +332,11 @@ function machines_machine_delete_help { return 0 } function machines_machine_delete { # machine - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_machine_delete_help exit 1 fi - _machines-deleteElement $1 machine + _machines-deleteElement "$1" machine } function machines_network_delete_help { @@ -310,11 +347,11 @@ function machines_network_delete_help { return 0 } function machines_network_delete { # network - if [ -z $1 ]; then + if [ -z "$1" ]; then machines_network_delete_help exit 1 fi - _machines-deleteElement $1 network + _machines-deleteElement "$1" network } function machines_machine_help { @@ -323,6 +360,7 @@ function machines_machine_help { echo "Commands:" echo " list List all machines" echo " add Interactively add a machine" + echo " view Display a machine" echo " edit Interactively edit a specified machine" echo " delete Remove a specified machine" echo " help Get help with commands" @@ -344,6 +382,7 @@ function machines_network_help { echo "Commands:" echo " list List all networks" echo " add Interactively add a network" + echo " view Display a network" echo " edit Interactively edit a specified network" echo " delete Remove a specified network" echo " help Get help with commands" @@ -369,10 +408,9 @@ machines_net_help() { machines_network_help "$@"; } machines_n_help() { machines_network_help "$@"; } function machines_update-all { - machines_machine_list | while read machine; do + machines_machine_list | while read -r machine; do echo "Updating $machine..." - ssh $machine 'machines update' & - ssh $machine 'cd .dotfiles && git pull' & + ssh "$machine" 'cd .dotfiles && git pull; machines update' & done } @@ -381,10 +419,10 @@ function machines_regen-keys { echo "[ERROR] Please delete the pem files manually to prove you know what you're doing." 1>&2; exit 1 else - openssl genrsa -out $MACHINES_CONFIG/machines.key 4096 - chmod 600 $MACHINES_CONFIG/machines.key - openssl req -key $MACHINES_CONFIG/machines.key -new -out $MACHINES_CONFIG/machines.csr - openssl x509 -req -days 1826 -in $MACHINES_CONFIG/machines.csr -signkey $MACHINES_CONFIG/machines.key -out $MACHINES_CONFIG/machines.crt + openssl genrsa -out "$MACHINES_CONFIG/machines.key" 4096 + chmod 600 "$MACHINES_CONFIG/machines.key" + openssl req -key "$MACHINES_CONFIG/machines.key" -new -out "$MACHINES_CONFIG/machines.csr" + openssl x509 -req -days 1826 -in "$MACHINES_CONFIG/machines.csr" -signkey "$MACHINES_CONFIG/machines.key" -out "$MACHINES_CONFIG/machines.crt" _machines-pubFromCrt fi } @@ -393,7 +431,7 @@ function machines_regen-keys { # USER FUNCTIONS function machines_setup { - if [ -e $MACHINES_CONFIG/this.name ]; then + if [ -e "$MACHINES_CONFIG/this.name" ]; then echo "[ERROR] This machine is already set up" 1>&2; exit 1 fi @@ -401,13 +439,13 @@ function machines_setup { _machines-ensurePub # Variables - read -p 'Machine name? ' name - read -p 'Hosts (separated by spaces)? ' hosts + read -r -p 'Machine name? ' name + read -r -p 'Hosts (separated by spaces)? ' hosts # User key - mkdir -p $MACHINES_HOME/.ssh &> /dev/null + mkdir -p "$MACHINES_HOME/.ssh" &> /dev/null if [[ ! -f $MACHINES_HOME/.ssh/id_rsa || ! -f $MACHINES_HOME/.ssh/id_rsa.pub ]]; then - ssh-keygen -b 4096 -C "$name@machines.frogeye.fr" -f $MACHINES_HOME/.ssh/id_rsa -t rsa + ssh-keygen -b 4096 -C "$name@machines.frogeye.fr" -f "$MACHINES_HOME/.ssh/id_rsa" -t rsa fi userkey=$(<"$MACHINES_HOME/.ssh/id_rsa.pub") @@ -427,12 +465,12 @@ function machines_setup { _machines-apiToken machine --post-data "$data" - echo $name > $MACHINES_CONFIG/this.name + echo "$name" > "$MACHINES_CONFIG/this.name" machines_update } function machines_update { - _machines-api machine/$(cat $MACHINES_CONFIG/this.name) > $MACHINES_CONFIG/this + _machines-api "machine/$(cat "$MACHINES_CONFIG/this.name")" > "$MACHINES_CONFIG/this" _machines-updateAkey } @@ -475,5 +513,5 @@ shift if type "machines_$command" &> /dev/null; then "machines_$command" "$@" else - machines_help + machines_help "$@" fi