From 585270ebd6ee233aaeeb479b5686b30e4618c6d8 Mon Sep 17 00:00:00 2001 From: Joey Hafner Date: Fri, 23 Aug 2024 00:12:20 -0700 Subject: [PATCH] #3 Set up sops at repo root --- .gitattributes | 1 + .sops.yaml | 11 +++++++++++ .sops/age-author-pubkeys | 1 + .sops/decrypt-filter.sh | 34 ++++++++++++++++++++++++++++++++++ .sops/encrypt-filter.sh | 39 +++++++++++++++++++++++++++++++++++++++ .sops/sops-setup.sh | 24 ++++++++++++++++++++++++ 6 files changed, 110 insertions(+) create mode 100644 .gitattributes create mode 100644 .sops.yaml create mode 100644 .sops/age-author-pubkeys create mode 100644 .sops/decrypt-filter.sh create mode 100644 .sops/encrypt-filter.sh create mode 100644 .sops/sops-setup.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..250b3dc3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +secrets.env filter=sops diff=sops \ No newline at end of file diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 00000000..0b512eac --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,11 @@ +creation_rules: + - path_regex: secrets.env + shamir_threshold: 2 + key_groups: + - age: # Author keys + - 'age1zswcq6t5wl8spr3g2wpxhxukjklngcav0vw8py0jnfkqd2jm2ypq53ga00' # joey@dungeon-master + - age: # CICD runner keys + - 'age12xgfd2w8acy5c2mrg3xv7ndzx3zw2j4kxv2a6ull385vxe8lcq2qpkhnv5' + - age: # Deploy host key + - 'age13prhyye2jy3ysa6ltnjgkrqtxrxgs0035d86jyn4ltgk3wxtqgrqgav855' # fighter + - 'age1n20krynrj75jqfy2muvhrygvzd4ee8ngamljqavsrk033zwx0ses2tdtfe' # druid diff --git a/.sops/age-author-pubkeys b/.sops/age-author-pubkeys new file mode 100644 index 00000000..7137f672 --- /dev/null +++ b/.sops/age-author-pubkeys @@ -0,0 +1 @@ +age1zswcq6t5wl8spr3g2wpxhxukjklngcav0vw8py0jnfkqd2jm2ypq53ga00 \ No newline at end of file diff --git a/.sops/decrypt-filter.sh b/.sops/decrypt-filter.sh new file mode 100644 index 00000000..11c20245 --- /dev/null +++ b/.sops/decrypt-filter.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Takes file path as first positional argument +# Takes encrypted file contents from /dev/stdin +# Outputs to stdout + +SOPS_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +REPO_ROOT=$(realpath "$SOPS_DIR/../../") + +if [[ -f $HOME/.age/key ]]; then + export SOPS_AGE_KEY_FILE=$HOME/.age/key +else + echo "SOPS_AGE_KEY_FILE not found at $HOME/.age/key" + echo "Cannot decrypt secrets." +fi + +# Set input/output type +FILE_EXT="${1##*.}" + +case $FILE_EXT in + "env") + FILE_TYPE=dotenv ;; + "json") + FILE_TYPE=json ;; + "yaml") + FILE_TYPE=yaml ;; + "ini") + FILE_TYPE=ini ;; +esac + +if [[ -z ${FILE_TYPE+x} ]]; then + sops --decrypt /dev/stdin +else + sops --decrypt --input-type $FILE_TYPE --output-type $FILE_TYPE /dev/stdin +fi \ No newline at end of file diff --git a/.sops/encrypt-filter.sh b/.sops/encrypt-filter.sh new file mode 100644 index 00000000..87effb5d --- /dev/null +++ b/.sops/encrypt-filter.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# Takes file path as $1 +# Takes file contents from stdin +# Outputs to stdout + +# Set up directory variables and default age recipients +SOPS_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +SOPS_AGE_RECIPIENTS="$(<$SOPS_DIR/age-author-pubkeys)" +HOST_AGE_PUBKEY_PATH="$(echo $1 | cut -d'/' -f -2)/.age-pubkey" +if [[ -f "$HOST_AGE_PUBKEY_PATH" ]]; then + SOPS_AGE_RECIPIENTS="$SOPS_AGE_RECIPIENTS,$(<$HOST_AGE_PUBKEY_PATH)" +fi + +if [[ -f $HOME/.age/key ]]; then + export SOPS_AGE_KEY_FILE=$HOME/.age/key +else + echo "SOPS_AGE_KEY_FILE not found at $HOME/.age/key" + echo "Cannot encrypt secrets." +fi + +# Set input/output type +FILE_EXT="${1##*.}" + +case $FILE_EXT in + "env") + FILE_TYPE=dotenv ;; + "json") + FILE_TYPE=json ;; + "yaml") + FILE_TYPE=yaml ;; + "ini") + FILE_TYPE=ini ;; +esac + +if [[ -z ${FILE_TYPE+x} ]]; then + sops --encrypt --age ${SOPS_AGE_RECIPIENTS} /dev/stdin +else + sops --encrypt --input-type $FILE_TYPE --output-type $FILE_TYPE --age ${SOPS_AGE_RECIPIENTS} /dev/stdin +fi \ No newline at end of file diff --git a/.sops/sops-setup.sh b/.sops/sops-setup.sh new file mode 100644 index 00000000..f722e4a1 --- /dev/null +++ b/.sops/sops-setup.sh @@ -0,0 +1,24 @@ +SOPS_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) + +# Set up age keypair +if [[ -f $HOME/.age/key ]]; then + if ! cat ~/.bashrc | grep -q "export SOPS_AGE_KEY_FILE"; then + echo "Add this line to your shell profile (e.g. ~/.bashrc or ~/.zshrc):" + echo "export SOPS_AGE_KEY_FILE=$HOME/.age/key" + else + echo "SOPS_AGE_KEY_FILE: $SOPS_AGE_KEY_FILE" + fi +else + mkdir -p $HOME/.age + HOST_CONFIG_DIR=$SOPS_DIR/../$HOSTNAME/ + mkdir -p $HOST_CONFIG_DIR + age-keygen -o $HOME/.age/key > $HOST_CONFIG_DIR/.age-pubkey + echo "Pubkey added to $HOST_CONFIG_DIR/.age-pubkey" + echo "If any secrets have already been committed for this host, re-encrypt them with the new pubkey as a recipient." +fi + +# Configure the git filters +git config --local filter.sops.smudge $SOPS_DIR/decrypt-filter.sh %f +git config --local filter.sops.clean $SOPS_DIR/encrypt-filter.sh %f +git config --local filter.sops.required true +git config --local diff.sops.textconv "sops decrypt" \ No newline at end of file