aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Spek <p.spek@tyil.nl>2024-10-06 13:31:21 +0200
committerPatrick Spek <p.spek@tyil.nl>2024-10-06 13:31:21 +0200
commit71d1f7f2ff3caa4f910cb7a24475863fa5668587 (patch)
tree783eac6a298bf203a200798cd9d9a7ed5fc69a09
parent14875f61c46f73616468c05778d9f4e163d8cd09 (diff)
downloadbashtard-71d1f7f2ff3caa4f910cb7a24475863fa5668587.tar.gz
bashtard-71d1f7f2ff3caa4f910cb7a24475863fa5668587.tar.bz2
Introduce PGP-encrypted variable files
-rw-r--r--CHANGELOG.md13
-rw-r--r--lib/subcommands/var.bash27
-rw-r--r--lib/util/config.bash38
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