diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2bd678c..9487c37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,10 @@ --- name: CI on: - - push - - pull_request + pull_request: + push: + branches: + - master jobs: test: @@ -17,6 +19,21 @@ jobs: - name: Run Molecule tests uses: robertdebock/molecule-action@2.1.0 + shellcheck: + name: Shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # XXX: we ignore the bash files that are included during execution from the list + # files passed to shellcheck. See https://unix.stackexchange.com/questions/164025/exclude-one-pattern-from-glob-match + # This still allows shellcheck to analyze them, but we don't pass them to shellcheck + # as individual shell scripts; to avoid it from complaining of undefined variables + - name: shellcheck + run: | + cd shellscripts + GLOBIGNORE="_*.inc.bash" + shellcheck -x * + release: name: Release needs: @@ -28,3 +45,4 @@ jobs: uses: robertdebock/galaxy-action@1.0.3 with: galaxy_api_key: ${{ secrets.ansible_galaxy_api_key }} + diff --git a/README.md b/README.md index 3c42ac2..31ffa9e 100644 --- a/README.md +++ b/README.md @@ -52,12 +52,33 @@ It is suggested that whilst these are limitations, it is not necessarily a bad s For each script, execute without arguments to get usage instructions +### Default and Specified Environment + +For all actions, an environment name is required. This will default to `dev`. + +You can override this on a per script call basis by passing the env name for the `specifiedEnv` parameter, for example: + +```bash +bash shellscripts/vault/generateVaultSecret.bash prod +``` + +Alternatively, you can `export vaultScriptsDefaultEnv='prod'` to define a default environment for your current session, for example +```bash +export vaultScriptsDefaultEnv=prod + +bash shellscripts/vault/generateVaultSecret.bash + +bash shellscripts/vault/createVaultedPassword.bash vault_pass_user_foo ./environment/$vaultScriptsDefaultEnv/group_vars/all/vault_user_passwords.yml + +bash shellscripts/vault/createVaultedSshKeyPair.bash vault_default ops@domain.com ./environment/$vaultScriptsDefaultEnv/group_vars/all/vault_ssh_keys.yml +``` + ### Generate Vault Secret This script will generate a secret file for you with a good long chunk of random text ```bash -bash shellscripts/vault/generateVaultSecret.bash dev +bash shellscripts/vault/generateVaultSecret.bash ``` eg `vault-pass-dev.secret` ``` @@ -81,14 +102,14 @@ For example, in the `dev` environment, generate a password and vault it, then wr ```bash -bash shellscripts/vault/createVaultedPassword.bash dev vault_pass_user_foo ./environment/dev/group_vars/all/vault_user_passwords.yml +bash shellscripts/vault/createVaultedPassword.bash vault_pass_user_foo ./environment/dev/group_vars/all/vault_user_passwords.yml ``` As above, but instead of writing to file, just write to stdout so that you can copy paste it manually where ever you want ```bash -bash shellscripts/vault/createVaultedPassword.bash dev vault_pass_user_foo +bash shellscripts/vault/createVaultedPassword.bash vault_pass_user_foo ``` @@ -99,7 +120,7 @@ If you need to encrypt a password that is predefined or has specific requirement For example, if we need a shorter password than the standard one: ```bash -bash shellscripts/vault/createVaultedString.bash prod vault_pass_user_foo "$(bash shellscripts/vault/generatePassword.bash 20)" +bash shellscripts/vault/createVaultedString.bash vault_pass_user_foo "$(bash shellscripts/vault/generatePassword.bash 20)" ``` ### Create Vaulted SSH Key Pair @@ -111,10 +132,10 @@ For example ```bash # echo to stdout -bash shellscripts/vault/createVaultedSshKeyPair.bash dev vault_default ops@domain.com +bash shellscripts/vault/createVaultedSshKeyPair.bash vault_default ops@domain.com # write directly to file -bash shellscripts/vault/createVaultedSshKeyPair.bash dev vault_default ops@domain.com ./environment/dev/group_vars/all/vault_ssh_keys.yml +bash shellscripts/vault/createVaultedSshKeyPair.bash vault_default ops@domain.com ./environment/dev/group_vars/all/vault_ssh_keys.yml ``` @@ -145,13 +166,13 @@ For this, you can use this script For example, to view all secrets in the dev environment ```bash -bash shellscripts/vault/dumpSecrets.bash dev +bash shellscripts/vault/dumpSecrets.bash ``` Or you can dump a single secret: ```bash -bash shellscripts/vault/dumpSecrets.bash dev vault_root_pass +bash shellscripts/vault/dumpSecrets.bash vault_root_pass ``` Example output: diff --git a/shellscripts/.shellcheckrc b/shellscripts/.shellcheckrc new file mode 100644 index 0000000..b1a5b5a --- /dev/null +++ b/shellscripts/.shellcheckrc @@ -0,0 +1,8 @@ +# Look for 'source'd files relative to the checked script, +source-path=SCRIPTDIR + +# bash only +shell=bash + +# Turn on warnings for unassigned uppercase variables +enable=check-unassigned-uppercase \ No newline at end of file diff --git a/shellscripts/_top.inc.bash b/shellscripts/_top.inc.bash index f6df306..be3b138 100644 --- a/shellscripts/_top.inc.bash +++ b/shellscripts/_top.inc.bash @@ -158,8 +158,6 @@ $(hostname &>/dev/null || echo 'no hostname set') $0 $@ " fi -# assumes scriptDir is shellscripts/vault -#readonly projectDir="$(dirname "$( dirname "$scriptDir")")" readonly projectDir="$(findAnsibleCfgDir)" if [[ ! -f $projectDir/ansible.cfg ]]; then @@ -169,4 +167,6 @@ if [[ ! -f $projectDir/ansible.cfg ]]; then " exit 1 -fi \ No newline at end of file +fi + +readonly defaultEnv="${vaultScriptsDefaultEnv:-dev}" \ No newline at end of file diff --git a/shellscripts/_vault.functions.inc.bash b/shellscripts/_vault.functions.inc.bash index e3bf585..b65b51f 100644 --- a/shellscripts/_vault.functions.inc.bash +++ b/shellscripts/_vault.functions.inc.bash @@ -1,5 +1,3 @@ - - function assertValidEnv(){ local _env="$1" if [[ "${environmentArray[*]}" == *${_env}* ]]; then diff --git a/shellscripts/_vault.inc.bash b/shellscripts/_vault.inc.bash index 5776a1c..e603407 100644 --- a/shellscripts/_vault.inc.bash +++ b/shellscripts/_vault.inc.bash @@ -1,4 +1,8 @@ #Bring in functions + +# shellcheck source=./_top.inc.bash + +# shellcheck source=./_vault.functions.inc.bash source ./_vault.functions.inc.bash # Basic sanity checks diff --git a/shellscripts/createPasswordsFromTemplate.bash b/shellscripts/createPasswordsFromTemplate.bash index eb71860..867f5f4 100755 --- a/shellscripts/createPasswordsFromTemplate.bash +++ b/shellscripts/createPasswordsFromTemplate.bash @@ -1,17 +1,15 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" -# Set up bash -source ./_top.inc.bash +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Usage -if (( $# < 2 )) +if (( $# < 1 )) then echo " This script will allow you to create a vaulted string that is the contents of the specified file, then optionally add it to the file you specify - Usage ./$(basename $0) [specifiedEnv] [pathToFileToParseVarsFrom] (outputToFile) + Usage ./$(basename $0) [pathToFileToParseVarsFrom] (optional: outputToFile) (optional: specifiedEnv - defaults to $defaultEnv) e.g @@ -22,9 +20,9 @@ e.g fi # Set variables -readonly specifiedEnv="$1" -readonly pathToFileToParseVarsFrom="$(getFilePath $2)" -readonly outputToFile="$(getFilePathOrEmptyString "${3:-}")" +readonly pathToFileToParseVarsFrom="$(getFilePath $1)" +readonly outputToFile="$(getFilePathOrEmptyString "${2:-}")" +readonly specifiedEnv="${3:-$defaultEnv}" # Source vault top source ./_vault.inc.bash diff --git a/shellscripts/createVaultedDataFromFile.bash b/shellscripts/createVaultedDataFromFile.bash index 4dcbbcc..a4779d0 100755 --- a/shellscripts/createVaultedDataFromFile.bash +++ b/shellscripts/createVaultedDataFromFile.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash @@ -11,8 +11,7 @@ then This script will allow you to create a vaulted string that is the contents of the specified file, then optionally add it to the file you specify - Usage ./$(basename $0) [specifiedEnv] [varname] [path to file] (output to file, defaults to - dev/null) + Usage ./$(basename $0) [varname] [path to file] (optional: output to file, defaults to dev/null) (optional: specifiedEnv - defaults to $defaultEnv) e.g @@ -25,10 +24,10 @@ Please note, the varname must be prefixed with 'vault_' fi # Set variables -readonly specifiedEnv="$1" -readonly varname="$2" -readonly pathToFileToEncrypt="$3" -readonly outputToFile="$(getFilePathOrEmptyString "${4:-}")" +readonly varname="$1" +readonly pathToFileToEncrypt="$2" +readonly outputToFile="$(getFilePathOrEmptyString "${3:-}")" +readonly specifiedEnv="${4:-$defaultEnv}" # Source vault top source ./_vault.inc.bash diff --git a/shellscripts/createVaultedPassword.bash b/shellscripts/createVaultedPassword.bash index f80c794..2428711 100755 --- a/shellscripts/createVaultedPassword.bash +++ b/shellscripts/createVaultedPassword.bash @@ -1,11 +1,11 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash # Usage -if (($# < 2 || $# > 3)); then +if (($# < 1 || $# > 3)); then echo " Usage: @@ -13,7 +13,7 @@ if (($# < 2 || $# > 3)); then Please note, the varname must be prefixed with 'vault_' - $(basename $0) [specifiedEnv] [varname] (optional: outputToFile) + $(basename $0) [varname] (optional: outputToFile) (optional: specifiedEnv - defaults to $defaultEnv) @@ -22,9 +22,10 @@ if (($# < 2 || $# > 3)); then fi # Set variables -readonly specifiedEnv="$1" -readonly varname="$2" -readonly outputToFile="$(getProjectFilePathCreateIfNotExists "${3:-}")" +readonly varname="$1" +readonly outputToFile="$(getProjectFilePathCreateIfNotExists "${2:-}")" +readonly specifiedEnv="${3:-$defaultEnv}" + readonly password='=+'"$(scriptDir/generatePassword.bash)" # Source vault top diff --git a/shellscripts/createVaultedSshKeyPair.bash b/shellscripts/createVaultedSshKeyPair.bash index cb036d6..4c7e873 100755 --- a/shellscripts/createVaultedSshKeyPair.bash +++ b/shellscripts/createVaultedSshKeyPair.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash @@ -11,7 +11,7 @@ USAGE: This script will generate a random password and then an SSH key pair protected by that password, then optionally add it to the file you specify. Finally it can either leave the generated key files in place or otherwise will delete them -Usage ./$(basename $0) [specifiedEnv] [varname_prefix] [email] (optional: outputToFile) (optional: keepKeys) +Usage ./$(basename $0) [varname_prefix] [email] (optional: outputToFile) (optional: specifiedEnv - defaults to $defaultEnv) (optional: keepKeys) Please note, the varname_prefix must start with 'vault_' @@ -21,24 +21,24 @@ e.g To generate a private and public key with variables -github_id_rsa -github_id_rsa_pub +github +github_pub " } # Usage -if (( $# < 3 )) +if (( $# < 2 )) then usage exit 1 fi # Set variables -readonly specifiedEnv="$1" -readonly varname_prefix="$2" -readonly email="$3" -readonly outputToFile="$(getProjectFilePathCreateIfNotExists "${4:-}")" +readonly varname_prefix="$1" +readonly email="$2" +readonly outputToFile="$(getProjectFilePathCreateIfNotExists "${3:-}")" +readonly specifiedEnv="${4:-$defaultEnv}" readonly keepKeys="${5:-no}" # Source vault top @@ -64,7 +64,7 @@ esac readonly password='=+'"$(openssl rand -base64 32)" #Write out encrypted Password -readonly varname="${varname_prefix}_id_rsa_passphrase" +readonly varname="${varname_prefix}_passphrase" encrypted="$(echo -n "$password" | ansible-vault encrypt_string \ --vault-id="$specifiedEnv@$vaultSecretsPath" \ --stdin-name $varname)" @@ -74,20 +74,20 @@ writeEncrypted "$encrypted" "$varname" "$outputToFile" workDir=/tmp/_keys rm -rf $workDir mkdir $workDir -ssh-keygen -t rsa -b 4096 -C "$email" -N "$password" -f $workDir/${varname_prefix}_id_rsa +ssh-keygen -t ed25519 -C "$email" -N "$password" -f $workDir/${varname_prefix} # Write Variables -encryptedPrivKey="$(cat "$workDir/${varname_prefix}_id_rsa" | ansible-vault encrypt_string \ +encryptedPrivKey="$(cat "$workDir/${varname_prefix}" | ansible-vault encrypt_string \ --vault-id="$specifiedEnv@$vaultSecretsPath" \ ---stdin-name "${varname_prefix}_id_rsa")" +--stdin-name "${varname_prefix}")" -writeEncrypted "$encryptedPrivKey" "${varname_prefix}_id_rsa" "$outputToFile" +writeEncrypted "$encryptedPrivKey" "${varname_prefix}" "$outputToFile" -encryptedPubKey="$(cat "$workDir/${varname_prefix}_id_rsa.pub" | ansible-vault encrypt_string \ +encryptedPubKey="$(cat "$workDir/${varname_prefix}.pub" | ansible-vault encrypt_string \ --vault-id="$specifiedEnv@$vaultSecretsPath" \ ---stdin-name "${varname_prefix}_id_rsa_pub")" +--stdin-name "${varname_prefix}_pub")" -writeEncrypted "$encryptedPubKey" "${varname_prefix}_id_rsa_pub" "$outputToFile" +writeEncrypted "$encryptedPubKey" "${varname_prefix}_pub" "$outputToFile" # Clean up if [[ "yes" == "$keepKeys" ]]; then @@ -96,4 +96,4 @@ if [[ "yes" == "$keepKeys" ]]; then printf "\n\n\n" exit 0 fi -rm -rf $workDir \ No newline at end of file +rm -rf $workDir diff --git a/shellscripts/createVaultedString.bash b/shellscripts/createVaultedString.bash index e270f8e..1209bee 100755 --- a/shellscripts/createVaultedString.bash +++ b/shellscripts/createVaultedString.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash @@ -15,7 +15,7 @@ if (($# < 1 || $# > 3)); then If you are storing a password, consider using ./createVaultedPassword.bash instead which will auto generate a long random password - $(basename $0) [specifiedEnv] [varname] [string] (optional: outputToFile) + $(basename $0) [varname] [string] (optional: outputToFile) (optional: specifiedEnv - defaults to $defaultEnv) Please note, the varname must be prefixed with 'vault_' @@ -27,10 +27,10 @@ if (($# < 1 || $# > 3)); then exit 1 fi -readonly specifiedEnv="$1" -readonly varname="$2" -readonly string="$3" -readonly outputToFile="$(getFilePathOrEmptyString "${4:-}")" +readonly varname="$1" +readonly string="$2" +readonly outputToFile="$(getFilePathOrEmptyString "${3:-}")" +readonly specifiedEnv="${4:-$defaultEnv}" # Source vault top source ./_vault.inc.bash diff --git a/shellscripts/dumpSecrets.bash b/shellscripts/dumpSecrets.bash index 2310631..415d0d7 100755 --- a/shellscripts/dumpSecrets.bash +++ b/shellscripts/dumpSecrets.bash @@ -1,25 +1,26 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" -# Set up bash +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 + +# shellcheck source=./_top.inc.bash source ./_top.inc.bash # Usage -if (($# < 1 )); then +if [[ "$*" == *-h* ]]; then echo " Usage: This script will dump all the secrets in the specifiedEnv - $(basename $0) [specifiedEnv] (optional: singleVariable to dump) + $(basename $0) (optional: singleVariable to dump) (optional: specifiedEnv - defaults to $defaultEnv) " exit 1 fi -readonly specifiedEnv="$1" -readonly singleVariable="${2:-}" +readonly singleVariable="${1:-}" +readonly specifiedEnv="${2:-$defaultEnv}" readonly roleName="$(basename "$(dirname "$scriptDir")")" diff --git a/shellscripts/generatePassword.bash b/shellscripts/generatePassword.bash index 969bdf8..2089a40 100755 --- a/shellscripts/generatePassword.bash +++ b/shellscripts/generatePassword.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash readonly noHeader="no header" source ./_top.inc.bash diff --git a/shellscripts/generateVaultSecret.bash b/shellscripts/generateVaultSecret.bash index ee004f4..f68af6c 100755 --- a/shellscripts/generateVaultSecret.bash +++ b/shellscripts/generateVaultSecret.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash @@ -11,13 +11,13 @@ if (($# < 1 )); then This script will generate a vault secret file for the specifiedEnv - $(basename $0) [specifiedEnv] + $(basename $0) (optional: specifiedEnv - defaults to $defaultEnv) (optional: update pass a second param of 'update' to overwrite an existing vault secret) " exit 1 fi -readonly specifiedEnv="$1" +readonly specifiedEnv="${1:-$defaultEnv}" update=${2:-''} diff --git a/shellscripts/rekeyVaultFile.bash b/shellscripts/rekeyVaultFile.bash index ecf17e6..b8f5b9b 100755 --- a/shellscripts/rekeyVaultFile.bash +++ b/shellscripts/rekeyVaultFile.bash @@ -1,6 +1,6 @@ #!/usr/bin/env bash -readonly scriptDir="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd -P)" -cd "$scriptDir" +readonly scriptDir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +cd "$scriptDir" || exit 1 # Set up bash source ./_top.inc.bash diff --git a/tasks/dump-secrets.yml b/tasks/dump-group-vars-secrets.yml similarity index 100% rename from tasks/dump-secrets.yml rename to tasks/dump-group-vars-secrets.yml diff --git a/tasks/dump-host-vars-secrets.yml b/tasks/dump-host-vars-secrets.yml new file mode 100644 index 0000000..f9ae4ab --- /dev/null +++ b/tasks/dump-host-vars-secrets.yml @@ -0,0 +1,16 @@ +- debug: + msg: | + {% for hostname, values in hostvars.items() %} + + ####################################################################### + {{ hostname }} + ####################################################################### + + {% for key,val in values.items() %} + {% if key.startswith('vault') %} + + {{ hostname }}.{{ key }}: {{ val }} + + {% endif %} + {% endfor %} + {%- endfor %} \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml index 2c912e0..ef1a8c9 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,7 +1,12 @@ --- -- name: Dump Secrets +- name: Dump Group Vars Secrets when: single_variable is undefined - import_tasks: dump-secrets.yml + import_tasks: dump-group-vars-secrets.yml + tags: dump-secrets + +- name: Dump Host Vars Secrets + when: single_variable is undefined + import_tasks: dump-host-vars-secrets.yml tags: dump-secrets - name: Dump single secret