diff options
| author | Patrick Spek <p.spek@tyil.nl> | 2024-10-06 13:31:21 +0200 |
|---|---|---|
| committer | Patrick Spek <p.spek@tyil.nl> | 2024-10-06 13:31:21 +0200 |
| commit | 71d1f7f2ff3caa4f910cb7a24475863fa5668587 (patch) | |
| tree | 783eac6a298bf203a200798cd9d9a7ed5fc69a09 | |
| parent | 14875f61c46f73616468c05778d9f4e163d8cd09 (diff) | |
| download | bashtard-71d1f7f2ff3caa4f910cb7a24475863fa5668587.tar.gz bashtard-71d1f7f2ff3caa4f910cb7a24475863fa5668587.tar.bz2 | |
Introduce PGP-encrypted variable files
| -rw-r--r-- | CHANGELOG.md | 13 | ||||
| -rw-r--r-- | lib/subcommands/var.bash | 27 | ||||
| -rw-r--r-- | lib/util/config.bash | 38 |
3 files changed, 58 insertions, 20 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 4003ffb..88bbfa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 with Systemd. They can be installed separetely with the `make` target `install-svc-systemd`. +### Changed + +- The mechanic for secret variables has been changed. The `secrets` is + deprecated, and instead a new system based on OpenPGP is added. Variable files + in the `$BASHTARD_ETCDIR` (`defaults`, `hosts.d/$host`, `os.d/$os`) can now + have a `.pgp` extension. If they have, the file will be decrypted using `sq`, + the CLI utility from SequoiaPGP. This will be available _alongside_ the + regular plaintext files, so you can mix publicly available variables and + encrypted variables. Using the `var` subcommand with the `-s` option will + write the variable to the PGP encrypted host variable file + (`hosts.d/$host.pgp`), again using `sq`. The key to use for encryption can be + configured with `bashtard.secrets.key.id`. + ### Fixed - `config_subkeys` and `config_subkeys_for` should now leave off the `&` at the diff --git a/lib/subcommands/var.bash b/lib/subcommands/var.bash index 4eaf14d..b492a51 100644 --- a/lib/subcommands/var.bash +++ b/lib/subcommands/var.bash @@ -39,19 +39,28 @@ subcommand() fi # Set the var for this specific host - local kvfile - local buffer - if [[ $secret ]] then - kvfile="$BASHTARD_ETCDIR/secrets" + # Check if Key ID is configured, or bail out immediately + if [[ "$(config "bashtard.secrets.key.id")" == "" ]] + then + emerg "$BASHTARD_NAME/var" "No Key ID specified in bashtard.secrets.key.id" + return 4 + fi + + data="$(sq decrypt "$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}.pgp" 2>/dev/null)" else - kvfile="$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}" + data="$(<"$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}")" fi - buffer="$(tmpfile)" + data="$(printf "%s\n%s=%s\n" "$(grep -v "^$key=" <<< "$data")" "$key" "$value" | sort)" - grep -v "^$key=" < "$kvfile" > "$buffer" - printf "%s=%s\n" "$key" "$value" >> "$buffer" - sort "$buffer" > "$kvfile" + if [[ $secret ]] + then + sq encrypt --recipient-cert "$(config "bashtard.secrets.key.id")" - <<< "$data" >/dev/null \ + > "$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}.pgp" + else + cat <<< "$data" \ + > "$BASHTARD_ETCDIR/hosts.d/${BASHTARD_PLATFORM[fqdn]}" + fi } diff --git a/lib/util/config.bash b/lib/util/config.bash index ff20bd0..fddc82c 100644 --- a/lib/util/config.bash +++ b/lib/util/config.bash @@ -23,15 +23,16 @@ config_for() { # defined even if an empty string was passed. test -v 1 && { local default=$1 ; shift ; } + local data local default local file local files files=( - "$BASHTARD_ETCDIR/secrets" - "$BASHTARD_ETCDIR/hosts.d/$host" - "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}" - "$BASHTARD_ETCDIR/defaults" + "$BASHTARD_ETCDIR/secrets" # Deprecated + "$BASHTARD_ETCDIR/hosts.d/$host"* + "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}"* + "$BASHTARD_ETCDIR/defaults"* ) if [[ -n "$BASHTARD_PLAYBOOK" ]] @@ -55,11 +56,18 @@ config_for() { [[ ! -f $file ]] && continue + # Decrypt the file if needed, otherwise just get the file + # contents as-is. + case "$file" in + *.pgp) data="$(sq decrypt - < "$file" 2>/dev/null)" ;; + *) data="$(<"$file")" + esac + # Check if the lookup is a reference variable, defined by using # &= instead of just a single = as seperator. If this exists, # do a new config_for lookup, this time using the value as the # key for the new lookup. - value="$(awk -F= '$1 == "'"$key"'&" { print $0 }' "$file" | cut -d'=' -f 2-)" + value="$(awk -F= '$1 == "'"$key"'&" { print $0 }' <<< "$data" | cut -d'=' -f 2-)" if [[ -n $value ]] then @@ -74,7 +82,7 @@ config_for() { # comes with whitespace issues or having to deal with values # containing the seperator (=), so using cut is much simpler # and easier to understand. - value="$(awk -F= '$1 == "'"$key"'" { print $0 }' "$file" | cut -d'=' -f 2-)" + value="$(awk -F= '$1 == "'"$key"'" { print $0 }' <<< "$data" | cut -d'=' -f 2-)" if [[ -n $value ]] then @@ -100,15 +108,16 @@ config_subkeys_for() { local host=$1 ; shift local key=$1 ; shift + local data local file local files local results files=( - "$BASHTARD_ETCDIR/secrets" - "$BASHTARD_ETCDIR/hosts.d/$host" - "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}" - "$BASHTARD_ETCDIR/defaults" + "$BASHTARD_ETCDIR/secrets" # Deprecated + "$BASHTARD_ETCDIR/hosts.d/$host"* + "$BASHTARD_ETCDIR/os.d/${BASHTARD_PLATFORM[key]}"* + "$BASHTARD_ETCDIR/defaults"* ) if [[ -n "$BASHTARD_PLAYBOOK" ]] @@ -132,6 +141,13 @@ config_subkeys_for() { [[ ! -f $file ]] && continue + # Decrypt the file if needed, otherwise just get the file + # contents as-is. + case "$file" in + *.pgp) data="$(sq decrypt - < "$file" 2>/dev/null)" ;; + *) data="$(<"$file")" + esac + while read -r result do local subkey @@ -143,7 +159,7 @@ config_subkeys_for() { debug "bashtard/config_subkeys" "Found '$subkey' as subkey of '$key' through '$result'" results+=("$subkey") - done < <(grep "^$key\." "$file" | awk -F= '{ print $1 }') + done < <(grep "^$key\." <<< "$data" | awk -F= '{ print $1 }') done # Return unique results |
