diff --git a/README.md b/README.md index 66e749a..173d7ad 100644 --- a/README.md +++ b/README.md @@ -5,33 +5,94 @@ Purpose: Manage gpg keys for: # Key Management -## howto create and add a gpg key -- please follow instruction on following link: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key -- add ONLY the _PUBLIC_ part of your gpg key!!! -- checkin via MergeRequest/PullRequest +Roles: -### import gpg keys -```shell -gpg --import /path/to/keys/*.gpg.pub +* New User: new key to be added; can be a new employee being added for first time, existing employee getting access to a new repo, key rotation, etc +* Existing User: user who already has access to the appropriate project + * E.g. look up in the [groups](/groups/) dir + * E.g. look up in in [verify/.sops.yaml](verify/.sops.yaml) + +## 1a. Onboarding: [New User]: create and add a gpg key +- create a branch titled `add_pubkey_-` + - e.g. `git branch add_pubkey_test-user` + - Note: no strict naming convention for the branch, it's strictly a Human-in-the-Loop process +- please follow steps 1-13 at the following link: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key + - CAVEAT: step 14 is not necessary, as it is specific to a GitHub account +- add ONLY the _PUBLIC_ part of your gpg key!!! to this repo + - file format: `@netgo.de.gpg.pub` +- git: commit the new file, push +- open a MergeRequest/PullRequest +- hand-off to an Existing User of the repo. + +## 1b. Onboarding: [Existing User|New User]: Add new user to groups + +Access for each repo is tracked using the `./groups/` directory; each sub-directory represents a "group" (Note: some "groups" are also "roles", e.g. `admin`) + +Most of the groups correspond directly to git repository names, aka "project name" + +```bash +cd groups/ +ln -s ../../ ``` -### list imported gpg keys +Note: this step can be performed by anyone (either new user or existing user), but it makes the most sense for an existing user to configure the groups since this is domain-specific knowledge (i.e. new users won't typically know the grups) + +## 3. Onboarding: [Existing User]: Configure sops config + +Context: This repo stores the keys used to encrypt secrets in other repos; these "consumer" repos each contain a sops config `.sops.yaml` which manages access to the encrypted files (e.g. `secrets.yaml`) + +For verification purposes, this repo also contains a _sample_ `.sops.yaml` to which every key in the repo is added. This allows both Existing Users to instantly verify the new key, and New Users to verify that their sops installation works correctly. + +### Update Verification SOPS Config + +Follow the interactive prompts: ```shell -gpg --list-keys --keyid-format=long +./verify/usr_confirm_keycfg.sh ``` -# EOL: Archive Expired Keys +### Update Project SOPS Config -To mark a key as expired, move it to the `archive/` dir as follows: +The following commands explain how to update the `.sops.yaml` for a repository: -```bash -mv ${keyname} "archive/${keyname}_$(date '+%Y-%m-%d').archive" +#### Prerequisite +```shell +# E.g. update sops config for DevNSO +% git clone git@git.dev-at.de:cloud-solutions/nso/devnso-adp-argocd.git +% cd devnso-adp-argocd/ +``` + +#### Commands + +```shell +# List available groups +% ${PATH_TO_THIS_REPO}/bin/update_sops.sh --list_groups +# INFO: listing groups +admin +automation +devnso-adp-argocd + +# For a given group, update sops config +% ${PATH_TO_THIS_REPO}/bin/update_sops.sh -g devnso-adp-argocd +# RUN: generate SOPS config +# WARN: no secrets file passed in, make sure to call 'sops updatekeys' on secrets files + +# [OPTIONAL] For a given group, update sops config AND specified secrets file +% ${PATH_TO_THIS_REPO}/bin/update_sops.sh -g devnso-adp-argocd -s ./adp-api-devs/adp-api-devs/secrets.yaml + +# commit the changes to any .sops.yaml or secrets files, e.g. with +## OPINIONATED GIT - use preferred method +% git add -p +% git commit -m "adds . to sops config" +% git push ``` -# Configure SOPS +At this point, the New User has been configured and can grant themselves access to any of the secrets files in this project. + +## 4. Onboarding: [New User] Configure SOPS SOPS is used for encrypting secrets, e.g. credentials for various systems + ## Install https://github.com/getsops/sops @@ -51,14 +112,63 @@ Note: The `GPG_TTY` is necessary to have the password prompt appear. src: https: Note: `secrets.yaml` is just an example; the file can have any name -## Example +## 5. Offboarding: [Existing User]: Archive Expired Keys (EOL) + +To mark a key as expired: +1. move it to the `archive/` dir +2. for each group, update the project repo +3. remove the key from the group + +### 1. This repo: archive +```shell +# archive key - DO NOT delete - need this for auditing +git mv ${keyname} "archive/${keyname}_$(date '+%Y-%m-%d').archive" +# remove from verification sops +./verify/usr_confirm_keycfg.sh +``` + +### 2. For each group / repo: + +**Prerequisite**: Local copy of each repo corresponding to a group + +```shell +# list all groups to which the key is registered +find groups/ -name ${keyname} + +# For each group, update sops config in that repo +# Example: +% cd devnso-adp-argocd +% ${PATH_TO_THIS_REPO}/bin/update_sops.sh -g devnso-adp-argocd +# now git commit, push, etc +``` + +### 3. This repo: update groups +```shell +# remove from groups +find groups -name ${keyname} | xargs git rm +``` + +# Advanced + +# Reference: Commands for gpg keys +## import gpg keys +```shell +gpg --import /path/to/keys/*.gpg.pub +``` + +## list imported gpg keys +```shell +gpg --list-keys --keyid-format=long +``` + +## SOPS Example - Manual The steps in the following example can be run locally in order to: * create a sample secrets file * encrypt the file * decrypt the file -If these steps work, sops is configured correctly - on your machine ;-) +If these steps work, sops is configured correctly - on your machine ;-) ```bash #!/usr/bin/env bash @@ -73,3 +183,9 @@ sops -e -i secrets.yaml # decript, print to console sops -d secrets.yaml ``` + +# Contributing + +Tests: `./verify/test.sh` + +Caveat: requires working SOPS config,pgp key, etc diff --git a/bin/update_sops.sh b/bin/update_sops.sh new file mode 100755 index 0000000..f7535f2 --- /dev/null +++ b/bin/update_sops.sh @@ -0,0 +1,235 @@ +#/usr/bin/env bash +# Purpose: manage .sops.yaml based on gpg keys in the same dir _and_ verify correct configuration +set -euo pipefail + +function fn_gpg_extract_fpr(){ + # PURPOSE: get fingerprint from gpg keyfile + gpgkeyfile=$1;shift; + # fingerprint + # caveat: restrict to netgo.de email, use-case: + # uid ... <...@mehrwerk.net> + # uid ... <...@netgo.de> + # fancy gpg src: https://unix.stackexchange.com/a/731872 + fpr="$(gpg --show-keys --list-options show-only-fpr-mbox "${gpgkeyfile}" | grep '@netgo.de' | awk "{print \$1}")" + echo "${fpr}" +} + +function fn_gpg_extract_uid(){ + # PURPOSE: get user-id from gpg keyfile + gpgkeyfile=$1;shift; + # user id + # caveat: restrict to netgo.de email, use-case: + # uid ... <...@mehrwerk.net> + # uid ... <...@netgo.de> + # fancy gpg src: https://unix.stackexchange.com/a/731872 + uid="$(gpg --show-keys --with-colons "${gpgkeyfile}" | awk -F':' '$1=="uid" {print $10}' | grep '@netgo.de')" + echo "${uid}" +} + +function fn_sops_locate_config_in_git_repo(){ + # PURPOSE: locate sops config + # Returns path sops config to be updated; defaults to returning "$(git rev-parse --show-toplevel)/.sops.yaml" + # sops locates config by recursively walking _up_ the tree from the execeution dir context, + # + _but_ does not have a mechanism to update the sops config + # This function does the same in order to locate the correct sops config to update + + # starting dir, default: PWD. Note: 'realpath' to normalise the dir + start_dir="$(realpath "${1:-"${PWD}"}")"; + stop_dir="$(git rev-parse --show-toplevel)" + >&2 echo "# ---" + >&2 echo "# start_dir: "${start_dir}"" + >&2 echo "# stop_dir: "${stop_dir}"" + + # BEGIN + search_dir="${start_dir}" + contender="${search_dir}/.sops.yaml" + # base case - located the file OR stopping condition - at top of repo + if [[ -e "${contender}" ]]; then + >&2 echo "# BASE CASE: found ${contender}" + echo "${contender}" + elif [[ "${search_dir}" == "${stop_dir}" ]]; then + >&2 echo "# STOPPING CONDITION: no sops config found, suggesting: ${contender}" + echo "${contender}" + else + >&2 echo "# walk up one dir..." + fn_sops_locate_config_in_git_repo "$(dirname "${search_dir}")" + fi +} + +function fn_sops_generate_config(){ + # PURPOSE: generate sops config based on keyfiles + # sops.yaml doc: https://github.com/getsops/sops?tab=readme-ov-file#using-sops-yaml-conf-to-select-kms-pgp-and-age-for-new-files + # CAVEAT: dirty hacks, as DRY as feasible within bash + + >&2 echo "# RUN: generate SOPS config" + # hack: 2D list workaround, i.e. difficult to have list-of-lists + fpr_list=() + uid_list=() + type_list=() + for gpgkeyfile in *automation*gpg.pub; do + type_list+=( "autom" ) + fpr_list+=( "$(fn_gpg_extract_fpr "${gpgkeyfile}")" ) + uid_list+=( "$(fn_gpg_extract_uid "${gpgkeyfile}")" ) + done + for gpgkeyfile in $(ls *gpg.pub | grep -v automation); do + type_list+=( "human" ) + fpr_list+=( "$(fn_gpg_extract_fpr "${gpgkeyfile}")" ) + uid_list+=( "$(fn_gpg_extract_uid "${gpgkeyfile}")" ) + done + + + # header + echo "# Fingerprint | User Type | User ID" + # entries/rows + for ind in "${!fpr_list[@]}"; do + printf "# %s | %s | %s\n" \ + "${fpr_list[${ind}]}" \ + "${type_list[${ind}]}" \ + "${uid_list[${ind}]}" + done + echo "# keys in https://git.dev-at.de/smardigo-hetzner/communication-keys" + + cat <- +EOM + + # all but last line get comma + ind_2nd_last=$((${#fpr_list[@]} - 1)) + for fpr in ${fpr_list[@]:0:${ind_2nd_last}}; do + echo " ${fpr}," + done + # last line no comma + # echo " ${fpr_list[-1]}," # requires bash v4.1 + echo " ${fpr_list[${ind_2nd_last}]}" +} + +fn_sops_updatekeys_and_verify(){ + # PURPOSE: call 'sops updatekeys' and dump contents of file so end user can visually verify functionality + sops_enc_file="${1}";shift; + # update keys in secrets file + test -e "${sops_enc_file}" || exit 1 + + # "update the keys of SOPS files using the config file" + >&2 echo "# RUN: sops updatekeys ${sops_enc_file}" + sops updatekeys "${sops_enc_file}" + + # verify: dump secrets, GPG_TTY src: https://www.varokas.com/secrets-in-code-with-mozilla-sops/ + GPG_TTY=$(tty) sops -d "${sops_enc_file}" +} + +function main(){ + if [[ ! -n "${@}" ]]; then + # if empty args, remove + shift + fi + # "anchor" for actions relevant to this script + repo_root="$(realpath $(dirname "${BASH_SOURCE[0]}")/..)" + # OPTIONS: ARGPARSING and VALIDATION + # assume location of script as running directly from repo with keys (instead of as a standalone packaged tool) + keyfiles_dir="${repo_root}" + # assume location of secrets config file in pwd + sops_config_dir="" + # path to group definitions + groups_def_dir="${repo_root}/groups" + # optional: + opt_list_groups=0 + # optional: specify "groups" + groups_list=() + # optional: secrets files to be updated + secrets_file_list=() + + while (( $# >= 1 ));do + cur="${1}"; + case $cur in + # ARGS: print this help + -h|--help) echo "# ARGUMENTS:"; grep -A 1 '# ARGS:' "${BASH_SOURCE[0]}"; exit 0 ;; + # ARGS: [optional] dir containing gpg keyfiles. defaults to git repo root, var: ${repo_root} + -k|--key|--keyfiles) keyfiles_dir="${2}"; shift ;; + # ARGS: [optional] defines dir for sops config file (.sops.yaml), create if needed. defaults to git repo root, var: ${repo_root} + -c|--config_dir) sops_config_dir="${2}"; shift ;; + # ARGS: [optional] show list of groups and exit + -lg|--list_groups) opt_list_groups=1 ;; + # ARGS: [optional] [list] specify "groups" which correspond to e.g. job groups, projects, etc + -g|--group) groups_list+=( "${2}" ); shift ;; + # ARGS: [optional] [list] specify files containing sops-encrypted secrets + -s|--secrets_file|-f|--file) secrets_file_list+=( "${2}" ); shift ;; + # ARGS: [optional] [list] specify files containing sops-encrypted secrets + *) secrets_file_list+=( "${cur}" ) + esac + shift; + done + + # Resolve Parameters + # ... i.e. combine,override,etc options which interact + if [[ "${#groups_list[@]}" -eq 1 ]]; then + # simply change keyfiles_dir to the "groups" dir + keyfiles_dir="${groups_def_dir}/${groups_list[0]}" + elif [[ "${#groups_list[@]}" -gt 1 ]]; then + >&2 echo "# ERROR: only specify one group" + exit 1 + fi + + # VALIDATE INPUTS + keyfiles_dir="$(realpath "${keyfiles_dir}")" + test -d "${keyfiles_dir}" || (echo "E: specify dir containing keyfiles; invalid dir: '${keyfiles_dir}'" && exit 1) + # define sops config location + sops_config="" + if [[ -n "${sops_config_dir:-}" ]]; then + # user-specified + sops_config_dir="$(realpath "${sops_config_dir}")" + # vvv possibly redundant, since the 'realpath' will fail if dir not valid + test -d "${sops_config_dir}" || (echo "E: specify dir containing .sops.yaml, invalid dir: '${sops_config_dir}'" && exit 1) + sops_config="${sops_config_dir}/.sops.yaml" + else + # locate appropriate sops config if default assumption not found + # dev note: '2> /dev/null' to disable debug output + sops_config="$(fn_sops_locate_config_in_git_repo 2> /dev/null)" + fi + if [[ "${#secrets_file_list[@]}" != "0" ]]; then + for secrets_file in "${secrets_file_list[@]}"; do + test -e "${secrets_file}" || (echo "E: could not locate file with secrets, tried: ${secrets_file}" && exit 1) + done + fi + # /VALIDATE INPUTS + # /OPTIONS: ARGPARSING and VALIDATION + + # BEGIN + if [[ "${opt_list_groups}" -eq 1 ]]; then + # list available groups and exit + pushd "${groups_def_dir}" > /dev/null 2>&1 + >&2 echo "# INFO: listing groups" + ls -1d * + exit 0 + popd > /dev/null 2>&1 + fi + + # UPDATE SOPS CONFIG + + # update sops config + # TODO: remove the 'pushd;popd' workaround and make the functions aware of the dir being read + pushd "${keyfiles_dir}" > /dev/null 2>&1 + (fn_sops_generate_config) > "${sops_config}" + popd > /dev/null 2>&1 + + # VERIFY + if [[ "${#secrets_file_list[@]}" != "0" ]]; then + # import keys + pushd "${keyfiles_dir}" > /dev/null 2>&1 + >&2 echo "# RUN: gpg --import *.gpg.pub" + gpg_out="$(gpg --import *.gpg.pub 2>&1)" + popd > /dev/null 2>&1 + # update + for secrets_file in "${secrets_file_list[@]}"; do + fn_sops_updatekeys_and_verify "${secrets_file}" + done + echo "# SUCCESS: all users with keys in this dir should have functional keys" + else + echo "# WARN: no secrets file passed in, make sure to call 'sops updatekeys' on secrets files" + fi +} + +# pass-through, set default value +main "${@-}" +exit diff --git a/groups/.gitignore b/groups/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/groups/admin/.gitignore b/groups/admin/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/groups/admin/claus.paetow@netgo.de.gpg.pub b/groups/admin/claus.paetow@netgo.de.gpg.pub new file mode 120000 index 0000000..2dfa1ff --- /dev/null +++ b/groups/admin/claus.paetow@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../claus.paetow@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/admin/hoan.to@netgo.de.gpg.pub b/groups/admin/hoan.to@netgo.de.gpg.pub new file mode 120000 index 0000000..61b1995 --- /dev/null +++ b/groups/admin/hoan.to@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../hoan.to@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/admin/lee.watson@netgo.de.gpg.pub b/groups/admin/lee.watson@netgo.de.gpg.pub new file mode 120000 index 0000000..e9b0fff --- /dev/null +++ b/groups/admin/lee.watson@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../lee.watson@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/admin/michael.haehnel@netgo.de.gpg.pub b/groups/admin/michael.haehnel@netgo.de.gpg.pub new file mode 120000 index 0000000..bd57eea --- /dev/null +++ b/groups/admin/michael.haehnel@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../michael.haehnel@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/automation/.gitignore b/groups/automation/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/groups/automation/smardigo_automation_buildinfra.gpg.pub b/groups/automation/smardigo_automation_buildinfra.gpg.pub new file mode 120000 index 0000000..521d4a1 --- /dev/null +++ b/groups/automation/smardigo_automation_buildinfra.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_buildinfra.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_demompmx.gpg.pub b/groups/automation/smardigo_automation_demompmx.gpg.pub new file mode 120000 index 0000000..46a8934 --- /dev/null +++ b/groups/automation/smardigo_automation_demompmx.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_demompmx.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_dev.gpg.pub b/groups/automation/smardigo_automation_dev.gpg.pub new file mode 120000 index 0000000..7c47a1b --- /dev/null +++ b/groups/automation/smardigo_automation_dev.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_dev.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_devnso-adp.gpg.pub b/groups/automation/smardigo_automation_devnso-adp.gpg.pub new file mode 120000 index 0000000..8e0e935 --- /dev/null +++ b/groups/automation/smardigo_automation_devnso-adp.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_devnso-adp.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_devnso.gpg.pub b/groups/automation/smardigo_automation_devnso.gpg.pub new file mode 120000 index 0000000..d5bb67b --- /dev/null +++ b/groups/automation/smardigo_automation_devnso.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_devnso.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_poc_workload01.gpg.pub b/groups/automation/smardigo_automation_poc_workload01.gpg.pub new file mode 120000 index 0000000..ae2c3c5 --- /dev/null +++ b/groups/automation/smardigo_automation_poc_workload01.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_poc_workload01.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_prodnso.gpg.pub b/groups/automation/smardigo_automation_prodnso.gpg.pub new file mode 120000 index 0000000..6cfda70 --- /dev/null +++ b/groups/automation/smardigo_automation_prodnso.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_prodnso.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_qa.gpg.pub b/groups/automation/smardigo_automation_qa.gpg.pub new file mode 120000 index 0000000..0efe2f0 --- /dev/null +++ b/groups/automation/smardigo_automation_qa.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_qa.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_qanso.gpg.pub b/groups/automation/smardigo_automation_qanso.gpg.pub new file mode 120000 index 0000000..fddec7b --- /dev/null +++ b/groups/automation/smardigo_automation_qanso.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_qanso.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_rancher_poc.gpg.pub b/groups/automation/smardigo_automation_rancher_poc.gpg.pub new file mode 120000 index 0000000..6b4ee8a --- /dev/null +++ b/groups/automation/smardigo_automation_rancher_poc.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_rancher_poc.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_sot.gpg.pub b/groups/automation/smardigo_automation_sot.gpg.pub new file mode 120000 index 0000000..81c8367 --- /dev/null +++ b/groups/automation/smardigo_automation_sot.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_sot.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_sot_test.gpg.pub b/groups/automation/smardigo_automation_sot_test.gpg.pub new file mode 120000 index 0000000..fe2cceb --- /dev/null +++ b/groups/automation/smardigo_automation_sot_test.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_sot_test.gpg.pub \ No newline at end of file diff --git a/groups/automation/smardigo_automation_sspdev.gpg.pub b/groups/automation/smardigo_automation_sspdev.gpg.pub new file mode 120000 index 0000000..1c05a5d --- /dev/null +++ b/groups/automation/smardigo_automation_sspdev.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_sspdev.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/.gitignore b/groups/devnso-adp-argocd/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/groups/devnso-adp-argocd/frederik.marticke@netgo.de.gpg.pub b/groups/devnso-adp-argocd/frederik.marticke@netgo.de.gpg.pub new file mode 120000 index 0000000..4ff054a --- /dev/null +++ b/groups/devnso-adp-argocd/frederik.marticke@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../frederik.marticke@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/hoan.to@netgo.de.gpg.pub b/groups/devnso-adp-argocd/hoan.to@netgo.de.gpg.pub new file mode 120000 index 0000000..61b1995 --- /dev/null +++ b/groups/devnso-adp-argocd/hoan.to@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../hoan.to@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/kevin.bauske@netgo.de.gpg.pub b/groups/devnso-adp-argocd/kevin.bauske@netgo.de.gpg.pub new file mode 120000 index 0000000..1f6c1dc --- /dev/null +++ b/groups/devnso-adp-argocd/kevin.bauske@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../kevin.bauske@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/kleanthis.damianidis@netgo.de.gpg.pub b/groups/devnso-adp-argocd/kleanthis.damianidis@netgo.de.gpg.pub new file mode 120000 index 0000000..8ae9e4d --- /dev/null +++ b/groups/devnso-adp-argocd/kleanthis.damianidis@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../kleanthis.damianidis@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/lee.watson@netgo.de.gpg.pub b/groups/devnso-adp-argocd/lee.watson@netgo.de.gpg.pub new file mode 120000 index 0000000..e9b0fff --- /dev/null +++ b/groups/devnso-adp-argocd/lee.watson@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../lee.watson@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/michael.haehnel@netgo.de.gpg.pub b/groups/devnso-adp-argocd/michael.haehnel@netgo.de.gpg.pub new file mode 120000 index 0000000..bd57eea --- /dev/null +++ b/groups/devnso-adp-argocd/michael.haehnel@netgo.de.gpg.pub @@ -0,0 +1 @@ +../../michael.haehnel@netgo.de.gpg.pub \ No newline at end of file diff --git a/groups/devnso-adp-argocd/smardigo_automation_devnso-adp.gpg.pub b/groups/devnso-adp-argocd/smardigo_automation_devnso-adp.gpg.pub new file mode 120000 index 0000000..8e0e935 --- /dev/null +++ b/groups/devnso-adp-argocd/smardigo_automation_devnso-adp.gpg.pub @@ -0,0 +1 @@ +../../smardigo_automation_devnso-adp.gpg.pub \ No newline at end of file diff --git a/verify/.sops.yaml b/verify/.sops.yaml new file mode 100644 index 0000000..e894ccb --- /dev/null +++ b/verify/.sops.yaml @@ -0,0 +1,67 @@ +# PURPOSE: BLUEPRINT for .sops.yaml config +# CAVEAT: DO NOT USE THIS FILE AS-IS in another project; copy it and remove the unauthorised users +# Fingerprint | User Type | User ID +# 533A89DD49FBCDA2BF014A936C962DD77704154A | autom | build-infra +# EFBBBB131CF1D863005C18868C8C09CA950B1DFF | autom | smardigo automation DEMOMPMX (smardigo automation DEMOMPMX) +# A7A1D860AA45B6B5B29BC192C55BD9B4CD8DE439 | autom | smardigo automation DEV (smardigo automation DEV) +# C674EFA56D3EDFDA404B1684090D46D8F1D0C0F8 | autom | devnso adp (devnso-adp gpg key) +# 0E8955A79FF4687A3ACF78E50B5E444C75867E58 | autom | smardigo automation DEVNSO (smardigo automation DEVNSO) +# 98235A419EA3586BFF4E3FC692D4A5202A0D9519 | autom | poc-workload01 (poc-workload01 gpg key for sops) +# E5B4FE1E0209DFFE320D2A2E47087747D89B72EC | autom | smardigo automation PRODNSO (smardigo automation PRODNSO) +# 890B2EB48F343D4C6DB9DA0916826F30002D3C1D | autom | smardigo automation QA (smardigo automation QA) +# 4069413B74A3AB13E10DF5FD3EA8F0D0FB1CAF36 | autom | smardigo automation QANSO (smardigo automation QANSO) +# 42AA7F6BF795490C1A522C730ED842BE1216E0C1 | autom | rancher-poc +# B4BAA59056DC362809388F3F2119881095EA7DED | autom | sot production (sot production gpg key) +# DF977A1F65999F4CDD721A27516F64D5932B8AD9 | autom | sot integration (sot integration) +# AC9B0DB590F4AE2017C2AD836113AEB66C510C3F | autom | ssp-prod +# 5623CCAD4242CC3E0225A62986AF09C173781578 | autom | smardigo automation SSPDEV +# 1EBAE111F6EAE0CF136358E8625C5A3B8DA21485 | human | Annika Biermann +# 17B8FDF68AC123EB666934B17D0DF6EC048A5D77 | human | Claus Paetow (Firmenadresse) +# 03ADBCD31737EB474A4BD235CE615FAF927A2054 | human | Esther Fuhrmann (GPG Key for SOPS) +# 04ECA5DBF73E98EBCC1FF0B018F2D15CC56BE487 | human | Hans-Peter Wissenbach +# 9E561083EACDE14694C73A323A2F6C1D153D753F | human | Frederik Marticke +# 9F08DA9D42379AFE6610E9E615CCEC6801DBA02E | human | Hoan To (Hoan To GPG Key) +# BA6328948D50175F196AAB5111F324603D12DD56 | human | Jan Jantzen +# B643A5D780A01F24E95AA100DE6F8E2C149C3748 | human | johannes.wicovsky +# C19A7D807525CE24443CA9A49372E896B41FE700 | human | Kevin Bauske +# 0DB51A7E90AC6418B7DB83724D38970874850C33 | human | Kleanthis Damianidis +# BF3D5CEA36DB58AAE1063D0BB341078652D87924 | human | Lee Watson (dies ist mein schluessel, es gibt viele ähnliche, aber diese ist meins) +# 73C2C9954D1BC94DC6682525D2FA233B52AEC75C | human | Michael Haehnel (NSO DevOps) +# 13E169CF5C35EF164628764AAA2EECBDE0B38CF7 | human | Philipp Eichhorn +# 13D7771BDE5241293F3EDA442AB3335ECC93DDDC | human | Sebastian Schröder +# 0C136F7514100470AD3EC8D37BF1FAEDB2ACCA9A | human | Thomas Steube +# 57F93F2A6585CF2DF9A3B31F13B9F45E122698D5 | human | Tobias Stroehl +# keys in https://git.dev-at.de/smardigo-hetzner/communication-keys +creation_rules: + # list of keys for encryption in stage + - pgp: >- + 533A89DD49FBCDA2BF014A936C962DD77704154A, + EFBBBB131CF1D863005C18868C8C09CA950B1DFF, + A7A1D860AA45B6B5B29BC192C55BD9B4CD8DE439, + C674EFA56D3EDFDA404B1684090D46D8F1D0C0F8, + 0E8955A79FF4687A3ACF78E50B5E444C75867E58, + 98235A419EA3586BFF4E3FC692D4A5202A0D9519, + E5B4FE1E0209DFFE320D2A2E47087747D89B72EC, + 890B2EB48F343D4C6DB9DA0916826F30002D3C1D, + 4069413B74A3AB13E10DF5FD3EA8F0D0FB1CAF36, + 42AA7F6BF795490C1A522C730ED842BE1216E0C1, + B4BAA59056DC362809388F3F2119881095EA7DED, + DF977A1F65999F4CDD721A27516F64D5932B8AD9, + AC9B0DB590F4AE2017C2AD836113AEB66C510C3F, + 5623CCAD4242CC3E0225A62986AF09C173781578, + 1EBAE111F6EAE0CF136358E8625C5A3B8DA21485, + 17B8FDF68AC123EB666934B17D0DF6EC048A5D77, + 03ADBCD31737EB474A4BD235CE615FAF927A2054, + 04ECA5DBF73E98EBCC1FF0B018F2D15CC56BE487, + 9E561083EACDE14694C73A323A2F6C1D153D753F, + 9F08DA9D42379AFE6610E9E615CCEC6801DBA02E, + BA6328948D50175F196AAB5111F324603D12DD56, + B643A5D780A01F24E95AA100DE6F8E2C149C3748, + C19A7D807525CE24443CA9A49372E896B41FE700, + 0DB51A7E90AC6418B7DB83724D38970874850C33, + BF3D5CEA36DB58AAE1063D0BB341078652D87924, + 73C2C9954D1BC94DC6682525D2FA233B52AEC75C, + 13E169CF5C35EF164628764AAA2EECBDE0B38CF7, + 13D7771BDE5241293F3EDA442AB3335ECC93DDDC, + 0C136F7514100470AD3EC8D37BF1FAEDB2ACCA9A, + 57F93F2A6585CF2DF9A3B31F13B9F45E122698D5 diff --git a/verify/mock_secrets.yaml b/verify/mock_secrets.yaml new file mode 100644 index 0000000..4f3fa26 --- /dev/null +++ b/verify/mock_secrets.yaml @@ -0,0 +1,512 @@ +demo: + credentials: + secret: ENC[AES256_GCM,data:m3uKjs2CMg==,iv:REr+W6QAcMXjC6kt4+U9W680N7NmOaPCbf5ZsL5v+GU=,tag:JTcpjBULW1tb6wYyQO1cWw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2025-01-30T16:32:18Z" + mac: ENC[AES256_GCM,data:DNsgx0KhSbgbCqqME9MUJxHQSt4vVc/C2xfkckwjhK5nb4dW1Bz3Y5wAzPlOkPPKp9YB70/q2spw8MKSiJgeujfqnogPtZ409lbi3/RyF/7WxnJM0KFxdrsQwxfOJdYjfXnXicW9CD6xYPn1+LUVVqnRDBXt4MIzc5AMqaXy8pQ=,iv:dhVa4Dig7E3fld2Y3upjw3/P87bV6/C2oGDBgqQYRVY=,tag:RA9qsnRNMnznkNBDkjssIw==,type:str] + pgp: + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA49EwzBHBfyRAQv8CT3tlOGMwEy01F0kZ8tcrYofenVzeKRrUA46FBgOEm/f + 3L+1/C6+BLvDGacMF7e0V0BTJ7f/fzYYAcmSF0WQrICnDwRrrjNgN7qEjtYyhr8c + NqpCSEgeR5juiG/DBNEERDrAxG/nljx0Q5S5ILN3kOk1Bm6biK2f+QX4xf2UX6A+ + vg52KGbpBpZaZLW7S0DxHlkEZAzRNbgKN7oxlPHDQwiQXA8DKw6pPSt26vuEFawN + WDalia6zU5bjQy5xqgtgf3QZJlSCK1HFVc4XCQT7kjdjlpCjEfLJl056dgUG/DZP + IE4oITG/9xQDreyUtOfOFkRugOySpFa0LPHOGFYnW52DTlTv8f1VaPBzHZcRf21b + R3nATTNgkU/XTdZWTb2gfj2AfbLv1xJzDRs38TAGHYpolsFN/+ehgFoFRO4+K0WW + GgMfkZ03Y5mbGXaGFhGcJEQMAzNbtS2RbuOhwkW/C0qm7qDW98KZXSLkeL1pjayo + 07KGaAJFZd2S9Qsb3+3g0lEBmzLIOzqY/n6HCOHIS48/6etFY7jQ42JfN9/yhdRS + coNPK1gQBytmiZLhpVdQ/Nj+1LXzeRZehBPxT0eelH7ILcFTvZhIHPAxplUG33TD + rAg= + =XH0R + -----END PGP MESSAGE----- + fp: 533A89DD49FBCDA2BF014A936C962DD77704154A + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DK0+AyNumsXsSAQdAmnV3rkI32tVB1ne2EE0ZCZoQzd6CDUrPNijrPaXtJk4w + KDShbO0ota2Jj6F5mx+bscpZkY7LhgcyUkg1GcoOconEizgxmcH9cLaX5m7Wfp5B + 0lEBM1wVjbgWVER1GBBay0moPjZLkyucbUmz26QMYBZxTNK9u5c7cxdlvOR3soev + tHhATcB6piyFVIcAHc0Zl+nKfEih2TrH+4E3GPv62shGhrU= + =SC1t + -----END PGP MESSAGE----- + fp: EFBBBB131CF1D863005C18868C8C09CA950B1DFF + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA/3nDyRfgQqhAQ//VluVKHQNlwVoIN5NT3nQa77qYpSEg+Qe/kj9oUJxKhlL + PS9PLfr6jqMmxCpABOEAJU8c4BNNoqqJThrgu6TWQ8iL2nyS9/BspIFrkVSsuCFU + /fpWwkGhzl1bwEebqD0ZBJsYBFVfW/pxVgsreudbkVNMhtCgp1Bphj35+gbimdle + Tw0bOPqkYsPymea4oYAI3TNeqpwxWejuI0trseLQmPUSbseRwAxvX9mB8Id56VmR + GYWP7D5Ujg4RWrl4RRlR+a959ONpnWlkNSPanFgvmLvgEqGxU6ZfgSGjLZtUNC2c + ZPrnXnQc0+H2jg0MSkbSwbUADJ/WtukQEn4scDDWCucXZg8MLbGr4JM1MaSumgJg + QlW6hO0gJ8SgMvpBTUqIOW2+ajaXe/zP979SWotCcZgRLvigfLBRr0L2rITWcP5w + 5a+1DPeZi/mTyDpkt5LmQ+Tb/6aDMD/aHyEqUskB/6dXh24VHQuJLUUrTPdURLe8 + bWFGoGl9GztXJm88d4gOPcvos7mVpRGLRogo1UPe3nwnWnlvWfmV8ONXuAsL+k5d + mxWw99i+fIY/cARftdUmYs+BlUJ3pt8Skzw+Z5T6E7wYWiQnO+LyKp7glk7qnGo7 + 1XKrFfEG4R1luJzwBa5Yt/xBaJ7UYzzLhXvu6rsFHjtHEWhANlAoZifDh5UivsrS + UQEXD61DJ3GdTJf8CcBWBLt5doxTephRyBSszLEHE6cxnBOLqfwVhjzZNd4TBYNu + zr6v8vaR2/G9AJDoAGS38u2AVHPApgTwgQTdnSCsplIp7Q== + =jS8g + -----END PGP MESSAGE----- + fp: A7A1D860AA45B6B5B29BC192C55BD9B4CD8DE439 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DuAaR73LFvScSAQdA3wlRX7/i3qiwCBfTpBaEImSab/kR44A06iwhJfepUjYw + 5y+icqAGk8trnFXpdiQ+QokQAidnHjm5KfU2cGP/Wvx8IQ3WIBjRyhv9wft8VA3V + 0lEBE1yVtElPn6jMr8pRlq/zpMfIhoJbQvBq1xnD9A3MlbK6GRTGXWOwsqcYc1DX + CReclVkSItk2+mn7DqJi4DwTkE6Lpr8X/aNS9OxyrhS4ZD4= + =pQIq + -----END PGP MESSAGE----- + fp: C674EFA56D3EDFDA404B1684090D46D8F1D0C0F8 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA3LBDEB9lMmaAQ/8Du5NDJm2S600M7ODYuB6wDeKFkuaEz42B9mpqyK/lxPG + Lp2jSTZk4qi93+6uBgAeGryJe5qOuUwRdgnnIe//IdiCppuI9iv8W2UAHx32PVEc + vNpipdz1pIhXEmBJuOfyv7C8TT/+nrqdM1NXy3hZeH/JhD/TgKP0VH3XoGFef545 + +tEz9Cfjg6pvy3BumY2N89Ijv/GAuRkgS7BAdcdoFrc4PylXleYN1SS/Fwb0WyGl + uRF20gZgohdllBHFqApdgVTR/jMl5v1CvA9kMMYRcExHNcpsOZ0rFHyXjZoPA52L + VHLeeIovohDJ9nnETX6KHMIe/Z4MpdoYK/PdSXpBT0fw/WM1wC3b8px7stvsIekR + 8ZEh14fTzgo6J4mqLYllfWxEOx3XrJ9D441IcSbV51pswjlg+vaaAjB8GKco/h6F + 95TAiJnwqM6c51XVPfJ4CQWJMnpqdfhXZOeCWIju6EizXu0OCko6h0Dq3gfP2SHP + 7y1KD2G0XbRHtd7u1gd/iMDRiDaO5UahZDgfRNWVqjMtMwkbXkVTz+auIy687VI0 + usW1o6BjMw7v84UmCgcDwo8W/W0w0PmZ3t6WJRXB/EJfirfGR+qerM91KwBT7Mtf + qEG2P/43AYbzFKHndXuJYP8OlCHuWIuCDzb8w+beDqEf8Vh2BQX3tNEmDx+i+a7S + UQHgTUb0hqhOoL572k8SPlf4pW2gw930+Tm24w4VFPhSNp7vL1gDwuFuWfzQ5LcB + A1p6Xx4vBrdG8x0GvFRaiXV3KRhm2TU3XvgxunLtxebwTQ== + =I6Ll + -----END PGP MESSAGE----- + fp: 0E8955A79FF4687A3ACF78E50B5E444C75867E58 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DpyXAcYv7T/8SAQdA5OoUcMnNDngzRgWJZ7Tx4VEGxhxq0XBxaKeSCwQjCGQw + fQpjfG7teEeJsoE1w9PduB7MBdx5s/a1U+6vORYng6oH6hyQsuMVS8Zi9j0eekYR + 0lEB71yT9bwiOPPddxxL8gU0dzG/ntvRVTbDrt4bkNTb+RhBaM2IA1fNt6vAnMYG + cPLk3Z2wFIslMsjAfeXnQqu2IIhtZW7ytKReN8ShYq5vAhw= + =ElKW + -----END PGP MESSAGE----- + fp: 98235A419EA3586BFF4E3FC692D4A5202A0D9519 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA911WKxzIy2nAQ/+OGYey7y+fe2C0NpXJS3mKOpJP0ki8bXD/B5TjGPmEaqk + E3GGNZlBaTkhjEl8GWsN9z6otYIMKIWNYShjBWWADzCFjLFRoTADxxkdrB1npDBf + dgZNPEirxDo8zjuXWo8YX578Pj4MmTyfe6O7Ty56FbDe33sQ6Gl9uH1tp+nAhRag + MLYWSnrH5kTVNv1sqCe9d11YniQUgHaXfyLMCsPyvYlUJCGtBp2Z4ihv2ZbV0/xk + WkJIR7hOLPWKM5CQjQOAH6Ei2zkj7WMW1b0e2EM6d+O2nCjeQq33Y7KzsKzr3L3C + kwJYmZH0fPgibXzV0oyADvgoCdnNiaK3fdWA+5falvSG/Y+SSca3il7/jYEK7RPt + eRzJIeaFSzfJT2wbJX09jFKkgRxN0XTsBXFhasnplxhakEzNQYfJfezDur/BMK7m + Ned90hoRVc0zUKZc4/YOK0bOOGvKnen7VxxL+y4TfReFqkMoeUMMRPSykpKJKMml + 6CuM9nFxEg65/TE1YB1TgI/DJyRYaVxXI+Fadb41yI8ccmtUu8vTOSqpsJiSBX3k + ITY3NQJjXx373Rt50MSbw5ELOybWrXrzqAyBOXLucc9dPz+55XsgBuSoRlzW8iIb + DJZtz3GZDNh7iLTxv6skCTtIuMWv9YY5KwKzvPt/CKus4EP/RtS28b1xb4yaOJPS + UQGh/k8RppgvTLsrgl+okzWlf6JQTXS4e6+WOYiqU0D5oi9VcIYi4hYRJKtGELoY + Xm34iNKYRyuSsUEbmr8ECo5HUsWQVWNSGgfOX2aIy/3pdA== + =JH8i + -----END PGP MESSAGE----- + fp: E5B4FE1E0209DFFE320D2A2E47087747D89B72EC + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA2Cr/drkb+8JAQ/+LxSEQ3e0lxIPVedBh+ANzGhsjA0BoHTl7sjVJGchkKlB + P5E2QQTm9bhRK+iP87h/5yy3JlSj+KS/GehNaqmczORUsrzOWbM13VeB7ESssHYo + Cky0QYNkzYOHxJc963haa4chmtqQbgn8yRmr1Ur1YObPCEdBvi2IaEFe4oojpntB + ym2I3uoOBgvM/xFifEXlCVK31c/mHVXuSVUVu+CYIWWIOcl6mdPLpagNBDxeiGe/ + yY33+VKbF/k+9AtNsow5G623UE42M5ztAkvpLj3GKKwxkV11kdnfv8OCEyFLCu4u + SXRcKocNBLTEqfwKPeVQHsPCYdPG1SYrj1cqSWzEs8fL0/mH/2t1p+d2Jt30qSG4 + GIIS0+wjwg4WTIwAbFk6p7jsSzI/InjB3Zg041Dz5ESQyussyfZZrEtvxHJA0aq6 + ABAdZhA4WUbdzz3jElPmDGpVK2CZ/NavRap+Jwzm8DiaYTRE1C/59345KDkY1qBr + 4WQFUXxbwlhlWCX7rzPastbF1BFfj6v+ay09udaCHJYvg+7URBQldy98RsCpSNUv + p87a8vruFdGoeQ4TXnhHf5m8qgtaGsoBWpTKnkmJ5y4aOJgiZ3HtMzSX+vL5J5MJ + UTK4WH2jQp3d5RtNrb6DgBO2AivADTmlMA2S2fLCnxQzHzUirvlcQTtQvXJrgeTS + UQFdm01Xnc/vdFhbW49YDnw6cfg8B23bgK8KQGuNYV09zrxIgnTUYRXP3hWgTtiv + cTvCMlbV1UY0KXC5cCqTTo66RmS8itbMTs97K3GT/yWNWg== + =eYl+ + -----END PGP MESSAGE----- + fp: 890B2EB48F343D4C6DB9DA0916826F30002D3C1D + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA3Zl11RyMNviAQ/8C5itsVwJLo9SOkYS7/87z1zaESeMlQuf6+OB73GVNAn1 + Li7EbBaxvp+vM73cCHO7XL7umkFCeZG6e9qRGX1XVTNnTZDzeHdHtVc5qkqYxfIi + MMMLK3TUSS5KSxhVFh19UmR+oh8j0uyuu869Bb/pTtiiJB205a0vCY8CAK/2vC7r + /2d+bM/01/5xjgGRLlp7hupe6ahJqg87UAiJe1ieWahsUQO0HWg68UbpxmKvADoF + 345XL+azA13wgrKvSTaYfTjgU6jbqCwReE8YOtS3/mvo+S4U+HiVbcfhWlIzjktu + otjXokBdU+hew+ICaK1imuZhR0R79mEsHI7mLJChyV23lVdl+3K1ct3B0dITj3Un + T6lwMeOMNUz7BrhY8PK7Yf3xgR9gIzdstj99L2ViymIi9YibxBOhdQTGp94fVyOT + d83CQz1YgvfP+sMbfr0kI/ytmZHTl5ydh8nAYTULeGTEAX0T6dylwKhZsBB8652I + Vivwq4OVfVvjLRsDIN+Ph4kA1+mpyF9GTFVLax7Fjry3hgDHSFthiYADoe3ifNdo + DeN8BjmC4ofPjB1n9RTrwh4YRwwbTjcUgHG0KpYuDy2KWAnzg1GYOxIK7sIdOPbI + 93k5BRiIF76pHF9q7220EfpfllLFzcGC9XCGcAucrVTO9FN5W9IRn3iESce8MrDS + UQETS9yF3qmHF7Fo4BD8b8pYIH5N1WjYxEYYUdd80rxfPn9xlCRz3EZ12o22UOF3 + 3N7sfLFCXT99mF/NWkfNDgxHt2+UuyIWMttffnaVSSpWFw== + =R5Jt + -----END PGP MESSAGE----- + fp: 4069413B74A3AB13E10DF5FD3EA8F0D0FB1CAF36 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4D0Z3mmZqL/KkSAQdAWib8+GRxR4uu43HT9lWpkizPQIB4RfmZS4k1opXHqnIw + F8fuwxqA8jSQ4jU0XvI/UCKXD1nm4hMdE7bb3f2tCQbFW+YDFL8OrnWw/lnEYWhH + 0lEBATRPWV4BrFs4LqlsVOx3XUljHqs9XQ0lczS4eQsEmOBKvR5p1xOp5qwm3VpC + JQzkbVRHDtf1o/y6T+AWFgiSXbJjzbYOmiXnMcNJqNFT9N4= + =5cs2 + -----END PGP MESSAGE----- + fp: 42AA7F6BF795490C1A522C730ED842BE1216E0C1 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA5pTFdxsndstAQv/UBdK0phdO3wdODohmgA6iiEH77FRCQR7ejamKiux4sip + 6h2evC6yIrupB7KbdjiIjFqBE3luoF0+4gFbzv7oCl6t5U6K/mAV/i/3ChXHrUIL + BYGLs7Nbaakw+Xpj8QWa9waSPnzf5etF3l8Dw+uQZT5dgFmOL0YvqBcBr4gRzNz6 + M0ln6e0/ghCQ9NylPSdsfnLU9CHjChQLU0VYAOzF3GIxkDV7M0PlH6/z+OVHEYGA + A89xm7zSieXU0GAQdrqfks6iC2QOdh5wkXysfgvlSaRGJg4bb2M3+LwvAX8WTxur + 0H5Ob+xizTEbDo1RsuihVgW0Qjj/sAe/qB3aDNXmMUma31czckK2ZqjI0ma//+BV + wel83HSILZKkSzl36+fgFWqhmeSXIKq9PQ68TRi6//YtZ+/1/qGEdNx75bxrplsK + LZtJ3JAGVCysarbmqbPWPepxZKXQUuRYrnjQuND8AT2dTWaHyGwhZ+PZkX2yIYhC + 8xPOGIDnGUNuM3n8GTou0lEBRrorCd/HjOYyy3U6v4Q1RUqsQA7bisycArqEpXmd + hfE2tKDFs/qM3VXJ5Wi5BzOZsQqC5m+S/az+XqmS25J5Ho+0VFDcZ9dJD98ImUfp + rgc= + =Wa4b + -----END PGP MESSAGE----- + fp: B4BAA59056DC362809388F3F2119881095EA7DED + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DwvSwby3S138SAQdAOKuVWPXdHIVVb4Zp5TcobpWmXIv8OL34RlLDJwKQkgow + f4JLS6CS7MwIjQE6H9CGv144tyHed0v2CH8LPG2flUq6em+Z97hR9yg5QoD+UMKM + 0lEBPhHLRZaz+qEmSIkUHrzSTNHMcaB9SxYJ7Y1fRaiznFuNf3+tCCK8LxHsSp85 + UyGaxDu9Vt0yI6A/zCtTCCvAg5tTz2mDvuoW92YU8yh7oHA= + =hvTl + -----END PGP MESSAGE----- + fp: DF977A1F65999F4CDD721A27516F64D5932B8AD9 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4D3RW6IFeToCoSAQdAmI9V3uW4skY/V5u/CDXuj4+7ua+W0DnDouvwWfPUOC0w + +a5o0/2As2OiIY4m9q9yBiMWzad8bd1c7kWOSP3hCgZ6v19Zbj/Ddw89ApObrFBX + 0l4BQDaZcmRQPP1wiCMUZkSFN5eDNr7YVHqyRCO2y77fotG8pPIs6OwF4zyIk2TP + xRSyqyg4HrNbrNlw8Qk3bO5Jt3kZHCHz1PIcbjrI+YShHLhbgSsdJ+EWcNuy3Zhc + =PAI5 + -----END PGP MESSAGE----- + fp: AC9B0DB590F4AE2017C2AD836113AEB66C510C3F + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA1j++ZN0cDPgAQv/bT4ensVZeqgxctDgRtF3QbsWz7Yl0iFT362uHbv4auAQ + zEK1uP1KY8E9qKaE0ALOIudT+kcOh7apQrfa5C33Kp4cRnzHvv5xQfAzxNbFMHuh + TfjrFP9HLdcYvPJ8NyH8ZSxxpblk2y5x8TVB6Efl+hPk4lW3jHYA2dkCae/9eQG9 + 1A5pLzrz+q4J2jfHCW7XBbRDqevIIRz3AgEU/S3zrWyaGFLUkArTNTVBVHB99Ntb + DwqNJwQFOMJRHxQMHhB+Jsu79p7PhCFdYi7Oq886AJug0V9BW6qKF4Dsab60fcMP + RkELN7OIQhAFYIODHX9aN4cW93dTEdjaW5bnwbagO+gGlqjGfarCctSNOWDPNCWp + y5fZr/7JA1g0VMY/XEmrYjTVKZ+ZN2z+04j38LOvJ43oE69gbBfQV9Xl3jt1iIuf + lKF6zmZSo9bPrFFcAaWbR94pxpQxR/Tnj4G+g4H1l6gNStyrlXmGO8omFgf5gsFp + EumSxyD/MVdpDMdYEUsP0lEB3CHznlT+gsJ1UP/MFcHgH2N0QJJnZDR9YmR4Mp2d + 1SGFI5nD/YaA8C5TnJOA980Db4IpuvzakmLOMlIXUFWfoC46DswxXNUVsWbdXK7F + An0= + =TgU7 + -----END PGP MESSAGE----- + fp: 5623CCAD4242CC3E0225A62986AF09C173781578 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMAx5drVN5V7yDAQv/SdfbVExUoA38vmJaYrHqPgtmqHhZAXZ71OhhZJxF30v8 + wsyyaHHCgv/hPncBvZnCXiCUSO1T+Ci7uGHVK4M9+1ma5v02KjIe6ObcW848pfEc + HyN/nGmusPSCKZi0ty/tm7V96qzjJim/6ahfvQdxAGcsB/4MrG0fDB4OxRZ3nQKD + 0ixMBaxGPjzWE9FOXb/TzbcuKFRZCMw3heLgm2NiFiCU/W1CyLeyFyVbsUyWFoTT + nLTZF3SuDkewXlKtZrObXRRXBIRkNIQ4iMGewRHhrp8LJgQ4D4x3Bw4OMUXV/x9S + oPleprSEkx9heWYHSb6vC1D/TvsMfU7+sE2cojYJI6imIhTLEW9rAZedNw/ZQw/j + 1tWpHSCt4NBRMFB4wKLrrSZy4iQZd6+bYDrxcWYZBN65TvVVBO6OSnAEH5cC/7/s + lEMHYqWzkwsAD3d+BaewQIrGv9Dp5IKRGRrQYkel8/+d5qqE5vzwW1rktObdVhxy + Y9y+xXGKstpLSUUTieok0lEB+y2zGDLSUBsWlQIhN1Srf6rFmqRjZfe3WGj6DzoY + gmuEIzQemTcn1i0Z9sUYi6aM9vz0SAXvxdPsjzZmQgAz2TdANjjqjIBtbG9qcNO0 + bDA= + =LuZC + -----END PGP MESSAGE----- + fp: 1EBAE111F6EAE0CF136358E8625C5A3B8DA21485 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA1kDHheI9SLWAQ//ZXmA/CzEJ9cfr5cLf3ofKaQaS7uLze02R/qOyWFYSVb+ + vhF2x2OGoA0A7u3BnmihcmD/pjd2iVcf7Rr9DUGl2Kyzj7SIX3JbTjwIZt1SmNfE + e8nhuFQzFKXrsgLSXgiH23S6sh7tE5Tk2DQZ/OexLL3Z3OrHxmhRiFVx2Nwx1LU8 + mkZKup1zkZL8XaOcArRwx/DAOoFSBKyqQ4PlIz17ipcuocZj6VxT94rnjEE9i0oL + JPjAU299RUS8nC19+o6XSu9DYOxQlEJ4ccvCksO7fRZBAnVmPC5gjOCu8h5oHooN + /k/VmLbtojaqVouzh5lxuXm+orexY0tE7APIEBbpS1jCTbo8ZNYnhmRVH0b2OxuF + bAA5P15e8MJr3BJRb8YwkDze7K0AKtvHW56L7uGqSetS7IAu7eyhG3w9Id8RylPr + 5SAuhD3yZpPIp4aI/NhxbDruT5Acanvkfx9XbLgtnr+JaCL37N290yCwvlAnEKhw + jerrOEZuQ0CVoc15WTvxsj30NpH/50HeMNuLco5Mdqm9mvRAEgGYugTedn9rzcAS + qDUarFOaCnI6OOA+AsutIdH43OT1t4oOKlInfzx1zHbSF++hS7xKZi7fgM6mgE7c + BPXIAPFy/s0TaF5PQmrZIPRkSkH9bCL21Rb34Lb6M0jF4xuXzR4MRCJtjYfz0rbS + UQEDXQ4COYhunZVWcKG/g6TcezUnpK7jfdeO0+yQOXEDBIDBNA0fZyRhcAUbT1Bh + weRFN7s1qA0/0y3CD8Cn9Dmww3y665UFV4Hh/A0evhIMrA== + =dgwl + -----END PGP MESSAGE----- + fp: 17B8FDF68AC123EB666934B17D0DF6EC048A5D77 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA195cwtvYnl1AQv9Hr0Fpe5haXmpcy2kaoy5beaJP1AXqcEY5huomy3RpGex + 7/J0LB5nvjx1Y5SFu94l8bD7AAwgTnY7jEQKVDPtqzKuHRFItuHcYEYyYukZk/OT + tRs5QSiOB4zfboGB8uFwI0YO5QWfUaBcK5O+v4KgaywecxDlEed7FaV66CuEfNIo + GFC342+dh+TX9cwKxj76tUFtaoQLfB/ThCejxcOu8Z20tkagGd4hV54p1Hvo1RXr + 5sNop4ppbq0yDmuyjYADTOnv/eQKBBXTXDhR/ZxzRRc5+lHvx5oOxQplqDAsd09k + YjjichphXK090iJTrHVB5EAQb8ePA05JBysA2nE8rMTFcZ2bkCek27nWN/SoIVEi + 0faFpiMM4Mfy2cSAlyod+xrWVCOX7XvvoO7a9mEKl21wEO8q3FAVjl07DdDPM0sN + wMplp8fLaz5P7KDMf92m6MclbqsyFXqFfsHI9gNSajZi8ylzaB9HLTTC2d+4YVjO + QUIuH8MXBa+fs9RIcV5Q0lEBjojsANreO8pPwoAmmP/ExVZo0nXJ3Ovdqd8oKkbc + 6OYvaZJnVUfaUf7AAeBrhjudGymJaEIIQnEN4juF/89dg7mqrn0VLmRsuHAc5BBB + TQw= + =mDJM + -----END PGP MESSAGE----- + fp: 03ADBCD31737EB474A4BD235CE615FAF927A2054 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA/IHQvF5YsEcAQv+N5Gij2qXj4gjhGxSjpORDuuS9HMyAWKfpshnvYWjr3QT + Wdu2FdaYv1XHWbTMcVH0+B3Pe4INQboGiB2wY/DCzA0vuverBR5DciZ8vN78k05W + +IqDYLfljeclaoJlXnlaPOtWKI2OWm2fsg8/4lBqGnsJ92Y9Bc9qXbmaBgPvgtkU + B3dYDNZ1W6Mo/wm6Pk7QMVdZoJDGvs7PpOhJ3D83koSx4BmZvrDrPpwRtWwkbEl/ + zSvpL4qXv4NWQjc71Djj9/uAtlXIt2QPWeCCqsoyIMHd7Vr7qrCAcZpQH2GYnn0v + 5Tb3ZcCH6CNRrKQMS5Fn7OH6aeLuKHja012jJxnplYHzpp8hdL/ysqLlgw/wKxS4 + rOThNHDAPtCoS2jDRmaNJgiSvOwtwPq1E2JkaInjaB4xciuaK/r5R1CwE7J/uKRp + j86JEC4hLgBwZX4llzMgk575O4CN+5HX/ywHMH3JXozkBPh3EBun79Il7AogUVRa + 2uoMm5cHhHZ9M077YLOd0lEB4+qgj4o/p60cx/oiaGEQcQzjcYn8aoFyT023xuta + qrk4sKQDKQo58tQ2FzbKxQeKE7Ehadv05dRevc9j3+MwcbyEDCzbZ1k/zb+41mCj + agA= + =2PBo + -----END PGP MESSAGE----- + fp: 04ECA5DBF73E98EBCC1FF0B018F2D15CC56BE487 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA/fyan/DNa3uAQ/+NqLkSl9GWeDK81+MPPeU0bkbOSw5Awv2xn3eWjFKIjEJ + V5H1Hr0a3b/Vx0WdVM5eat0LpH5/OFWljx0QNJfqFBz25TFgBqHT4Ew3eCtZFxJC + ElwDpI6eCCkZ3w4Zk3BsBwCwcRt0kCHXJb7STFJ8OGg6qb0mB9Weg5Rauh8jArao + VhxrE//oqzLjdDCNE7jXb68/6Rw75TsKZ+nAAtecK4qtliU+gP3o78utoWb4+8hJ + 0hhbLjQpKcwPEZWi8/O2gzePHNudHHPwVHOKcIs5kuXF5TPd9skiqZoNTtuiVtGA + LjM04k73fUm4JlqvtlSLXN+epm6ekTQWabslDK6yxXIovu8ycBS1EVudRjMdpBX0 + 5bi7nKKOsELiZ2k/bULmbLoKmiKSO9F9ulmQGTeH+dOZHPcPxDkRa8waBw6vpM47 + 4UDEbOcadc8+mAsMVoEiyGl7HNFWyVp6W0V4wWTtICZdty0AK6nyOp5VF9loUewE + jDbk/swUsILWdgDNbquwGkgVbbGWTuGt8wsc9i5erX5dkgeM2ghKpW6PgtDveDkD + uSINtgk6n8izcBOmiw7igD8+5e/bYpiwrHHvgX2d2FqnlK6zoTI8wjsekp+Cy2ps + VO4blkqYmdkbK3DCEQoVrShrRezlSU43wq4dZ6qi97Nk70qjbDoVuXpzNWhP3cvS + UQGmUKqjHRzV9c8lBKZEWdeJlyiWoaFrSoQvdE4an7QptYUjaN62HhG7Fwr3mzxJ + Hbewf3rU3gHC539+2W8wZ3teF0eik0gDU/ug36xun3uZ8Q== + =eVAS + -----END PGP MESSAGE----- + fp: 9E561083EACDE14694C73A323A2F6C1D153D753F + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA+cOSmNXMUmKAQv/YwIURSy3K/pt9nr7Et4FJmjQVh5M95bMlve/7w1W1C89 + bFVodCQJuKKH99o4pC/FlIb0DWmHY3AsHnTyC61QJ0Mlca0W5eosye4vzeI02KE8 + 9FvYZRLGJ5f1XwIQTh25K3dGMS2J0CMVZDYXBm1EyqqdxoPuHZZOvas29j1CL5Of + Y6KRbgV323N8xXkuP6THBjVnDwyQUjnrLLlMAJX8bxBgKMtGcON5xqRji4SaWHeN + 6ZbZMVjk6o3i00XOQe5xqDcEnBNtpzPXPbIf6enyEKfbzZBMoS28M/4gMkFtmaaF + gMqdH0qwfu4ZsrMCNUf3bQZawPm7JUxOVhzHpz/J22AxODF3CpH2romgJX2igtZ0 + XX6nU2iFJDPCfpIIqJAq3D1+DajXDSOlkSmRU9yWUPI4PS2kj03xgR11YDE38m6a + 1uvjDJ3p6CfFpBOs+gL5DrAspW6kbOyi309OmfQ+WWUDvSBloCePTbzdbFDPR7Qe + j8lu3vwkT/lOmR/haIN60lEBtig7+AKnJ5218r9So/4WOyl33hYikRj2G/sjrbPs + IktUHFgWuALcNgSCYPkx48WjHUcpjTDjAxkmgup4t5t9wupl+Hf82CkcBrffbnza + 8sI= + =vFuE + -----END PGP MESSAGE----- + fp: 9F08DA9D42379AFE6610E9E615CCEC6801DBA02E + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA5bUWViEqX+EAQv+P4bjeVEVjMrI6tv/HaJd7PI0jDjaHLIKvH+EzamJWM+d + +bf5dh/ChV11bqNn+ziqTQKROOnjaWb4dKmZWU+12/kWUOVrpB2KcOj9QPOAZra0 + z13iQzZy/aMSMHLZbOMzEpNaqvNSEuqnl3UgeEnjTav7JuMzw9Y13lWw68i0Bfog + QHQQ5HecuP1vnBfnY7j5rSx+ivKQZ368idArmcVuivbE3yTnigx9EJgw74TOlmOz + p9KuUQzAoTMQ9xle7Af41Q7vgI3sZndWvi/8dtcfPGe9BJocxK536ZumwXmwMZh9 + htPA3s2JhnCUwwU+vnFRZsqBkbYRxgTlpE3FLWsfFXlRoqaWs9tz88mtS6ColxqF + 035i3L68U6gZpXCNJEtUhjx4WHHDnjKi6bvQGx5jCLmhnHsUU0dTuSa9fr7SY1Jl + 2G3nwfpCLaJE9IH6t00GRqgVWtniQLZ9b2UJ+uFbqgRRuZ9EWOCZWQvk1oq1M1te + QCg3Cbu7b7jZjTkk1GKf0lEBZUWHLxamR+THxo4I3nZq5J52P+7UB1V1sylO7vYk + 1MFrHazA+51LZrhn57FIkMUCQ/Y4f/jOSFVtFVCIHD0j5+SfNnWFC2AQYoKH42Rl + Tcs= + =7YdW + -----END PGP MESSAGE----- + fp: BA6328948D50175F196AAB5111F324603D12DD56 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA8YZutSkx0fiAQ//XrSOZC3C1b53P7Nxq4lpJvkjFX07YwoQ2uKXFFQLcSC7 + PufLzJvRxceytIUhEhCUbx5hASxLfCrupKSQ33FCTEg90eMRpAX3G0eHC+0bj0Ma + qAwAZJnG+vnLHc6W1no1NsijmGXvRzBRUdUk3yWt/pa+9qW09opJPsyrRwye3ZIL + IJk3rmm6d13TA7RVRHmy94TCIGSGHqfDUXLM405oxHQoMpOvXg+hl/YXqBNU8Lrv + 610dKzKElS7cksyVdZ2LNL1Th9IvwxnN+l8+UKkq+aj0x5CtuYNjdQnucEthgZ4z + pwayS74uW0vmpCP3RgOhQ4hTdr4ZKxuQbaPeE3/V2dbTwT5XxUSTSOJxf8/Qu6kS + 3T6hgIufirl3sIRGVsLn/dB0GRvgdrmBwuxyR1pvJocRdpnlYHciszZFnFrhGihH + qPF+p+UweYQi4CtIDOC2/eswhA1snA0oEvvMShCWrACGVLiGgDc2c8dI97zwfHvu + UQ9RGk0deal1egcQ5FshMVJU9b/onW8dw8q3nqTkaThTZgUJChQ/1pglmjb4Umk3 + mwXuK7lX2hIguVDrgPu9EMN9ujiV1uE6ozLRjKDPYlirVx+6t8IKS7gEMv0K2gPM + yn6BUUID/13Gr8jcGQW/0snIpG50J9xRSLP2XtR5kPhrv0uBH8ACvX3dRUAPdorS + UQE6Q4EsrEFWxB8HMb6bQ9DsgkFJyDC044nd9HKpFI9IZUlhP/nAuTmqSxCMErVd + dPG0PyY0nUUA8kqnWtHpFhm4CCgl00uGr0rMwqM/ienspg== + =YQEC + -----END PGP MESSAGE----- + fp: B643A5D780A01F24E95AA100DE6F8E2C149C3748 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA9vEXLVODHp3AQv9FIxXFwDFg9EQ0bwdrxPWzrZnVIXKOpQeHtv+aA+iT8Hi + pMz8kimNlgHjWUthJsmAujMcoyvH04PTDlJUd6UTzVbqSRaSh4+8DrSsINyofjgn + 0l/Wy1w1Bv3zmcAZwHD4/sITjgCZ8ETYOFSsZ67JoDz5MZ5jqCSSrvtFOrDIwlvl + sZTSY0gU/J27GJ7Oc2FJ8mxKeWN+ZO5HEpRZgoyo3rj6SKIgqw1mYAVPwl/e9eVv + hzhNe2A9bpSWFjLUKSrAW0VAai23HrdSHup45rKOEv28iAOSOTXon3jZNSH1au7K + KbBKahvvdJ679F0/9zH/iZAsnrY5oW+shgIjpi0moWnih0YPwZNu1mzDkcfLDQDH + F60eoZrg3iieS9DWcxOksbprqWdyF+B1d0AxrxR57Ru2nFdR+ST/8oIcGue6I+uK + kVSJFeArdbAjEI8ldB9WCqkLeKXVTPGLcOOQxSWLNFsHuuOpZWnWpOAMF06HtBcY + eSZHsqGHgyvndIgQ8FLv0lEBXgxpZl826/2gkLVSdNveCLF90yxaagrtdbTEfm3T + 7LIUdeZlRhYe+eg0diWcAyDG1XWgXiCUfocFR0yfQRPHWEVXGh98zZ3MFndPYrfB + Rf8= + =J4gG + -----END PGP MESSAGE----- + fp: C19A7D807525CE24443CA9A49372E896B41FE700 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMAztV5cc72nziARAAieRTsV9FNm/utlda05oE5ALMM+clIAtxw5grfaNBWeUo + Xy4fgkzBQx6UhKDwsIsAi9wUBS1Dzd9HG4tUmmAf85TEbX0llKdc8KD9gdzt22C3 + Roq2oCQKHdomA41qVpnwudPQXDakc6pltLZy+TAuziypgzLHc+7nY5Kd9wFhzeGf + f4sIQj+ctHSd3ghGu7UQpJW6W6zfmkBjSHMnbZj/pQndg9i0+2YtxUJ9yqij5q0P + zIWVZgNt4dLoik3Q/CDDtw7u4IWPHN0vSNJRgeylUTMuF8Q5oVQgGcq6TTUYtrxp + 76h/e8kFdxfif4fQkHVUB+kDvrGO7CUUjtgk+tMop5165BlkdZx3NpcPaAuk0ZP1 + 9CtCDRnGBRCz5sjjailmjEGXagUci/nWD7qT02I+ZWzqwnHPYA75FBmIrb6qeUNm + KsrAVsTNqb3o/iuLHaBAdEvncOQnV9ne9QAyp/i0KbLyTQ/zJaZEAIANY2GspRb3 + gsCnL0vr2knofMVQD618WByyiTt2fqTnbfb47Jadp9otsim6OVNCzxYxFKX3VpYr + ncZxuxn+FxIFMn2tyFC6Og+xYPe4eBtbb5rqaEZdmzwYW2FMP6U2b4YyLqpQE3hw + miwo9ODNgtUpbVBrb5pRM9DVvsEVmibAEPV7uWzpPXFBCaLIlWSuHGtvWttEcQzS + UQFATosYmOKZjPcjPAFfr4avz2co17LZ38N98JQ5posfLFMlLMxqGfFcDZmQdxep + EGSR4dkO4xzzZ7ORcCdxhZaOtcB092kIJKtM9RCFegXo8g== + =LPni + -----END PGP MESSAGE----- + fp: 0DB51A7E90AC6418B7DB83724D38970874850C33 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4DxQtfVaqAjfQSAQdAL9rn+f5L3cPwmS+NM7vM5tR0VCDD/p+b43nFFhAnVQow + XcSpJNehn1E4JmgY5ixYk5hysPoDTanHvytXKSSOJF8XpybUz1K1BF06iiCnq6X9 + 1GgBCQIQfTwPQePieWp4usWB7gkimOQ5KeSmMRQ8vqRTa9i5AXzWlGruP/i5OSHq + FAKhcdcihAt9jFwxsAymbmrpqWOTA/H7uu5385cRiCRvJUydmz1AjD+e9U96dYT2 + Z9OHZM/x7057bQ== + =dZEu + -----END PGP MESSAGE----- + fp: BF3D5CEA36DB58AAE1063D0BB341078652D87924 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DZmNQj/lmIGsSAQdAMt1u6obZgLUjVDQFJ4cXDfUwzy+n9p+rZa/5DtAC+R8w + ChbOqargvUW+TPuA2KAOrH0m7QrzpUAXvk0grF5qewdTwvp9zRArCobkz/xwF6jS + 0lEB/rra99F+Wp4c7IBque3HnyWbcNhw06BfK8jhmwjLcy/pNZkj93WYcvannZLJ + Lc93MffCPEK6eMXW4cFHT9BacyGTHKtvagwLPOo7yryKwTs= + =nYcx + -----END PGP MESSAGE----- + fp: 73C2C9954D1BC94DC6682525D2FA233B52AEC75C + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMAxSu/PO9GEkJAQv+KGOnoZBVSEuWqR+m1npSR59qdPU/XQpkfRKTKK1XQOo5 + 0IU+uAnqweIXaScnI5+Mf+k9QbVPUw00w5ot5JlXfupBL2dS/0ZE9a8iESEu/hIR + d9FWSMGs2BwUlCVIlZPSz/p/+5NaxsckWKORDP8QBABHQ1c8bzq4yUWCt74gkjgc + oK2idCXqkvRaPe9ihiyq8fSWtKUPq84aSlQ2cVJMQ1C36xdbQi8Q4gQnTGr9Ncup + qUbryHejG7Zd1lUtgUZDPVdHnuDck2OUjD6R6DOe4U8dH+5/aH8mk1u7iBoxjAw+ + InWUubfQJzEwpBZ3bojfz8oWKoEpToln3sJGfnlb/ssPFhh+AiH0sBfRgqbSf5Jh + pCMDKN3X8sy53pJdcaENwSRbZ4LcgsgyR9XihG9ZxGgPhXpDzMxZ65pTrvDjz3Kp + UloSzEjSSrQNE+z5sYbbjRTNk8YOkVW6FpzU5gmKrnsOFLARd96fdAvgyI/9Etuu + g45uD4GnNrq/wd6DLN4y0lEBUGFCPdh/eLsgsss830UVtCs2lQPfj5C1Q3yxhxjP + Hae+f/+bTfpOepMrd8huxQ0tB8qKDW94mdsikowJewX+5wV5EdErQ/4G2YtJZTOA + oTE= + =3jwE + -----END PGP MESSAGE----- + fp: 13E169CF5C35EF164628764AAA2EECBDE0B38CF7 + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcDMA8b/EJ6Mi55zAQv9GnVQNxIAnrBOPolTnJ46tHKs/Ny5QCn8i0pJ0cmj8LR3 + l6eCrrvb5aEZRYV1DIMzP9BR9D6G0ShZBsqcBgpm3DgNjQDD1eWAAZxMuWMLMFlQ + 0KDG1myVgRNzGXP2cpiJHPJPcdXTd9aNntMDzc/xpHlfW2UXCmdNwl9Q0NrMHR1w + xjcf2UIg6BN3yjxUOxxUbDPw5cRWlIUiIPC52R6V8hHBzh1UUhdj06Hln4e1aVp7 + Wpa4K9KJd2n6q9XkF9aRuYyGybOvnPJlL6OHaR9PgIfGCZ+pufI5AneQeahrc+EU + /DkQZNILkBEW8hnwkrXGk53CnS7GQPg8s1kiab7nIuQNF21dpSA4RATMlESC3i0t + BmTfI0HuIaZMxbnRvPSfQwGiMhf6ea+02QwTIjuN59lDuFyQBa3CwJXpiAAtFyyz + 9Lu+HAsnRmheK48PXtLkZ8ldNH2r/IYFjtjbANKKzn5HelmPWwLmHo3N4YIerKrj + znhdrY/9imhtA7CiC89Y0lEB6Y/cfSWKtoOLkx4RKknkQURvyJfAMjRhVVFxGZCc + LerDo0Ofmm0z7ZgibYiL1W7Rv4TsnZXr1KDbSrJzD9PcSZt0rTQ9Rw7MpqBeHH/f + /CI= + =L8LE + -----END PGP MESSAGE----- + fp: 13D7771BDE5241293F3EDA442AB3335ECC93DDDC + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wV4DAQRCY74qADkSAQdAERj1PfuanNLwdZgD+mojcIflbrh8NbXqU0kBicBH6SYw + 3ZBhzUo72iPSpfHOzk3uZhLw1gIxyEwIAfg35k+2GQUlIO2yFjNGMrNXEXnd2QKz + 0lEBhmYkMPlKeRXHAbaq2jF72GoHss5LxBVi88L68QkXeUSlITa4dN/YLcpn1rIA + 1DvGGEEyrRt5zbYkOZsMxXgbAtarBf/HxDB2nHKmKUo38GE= + =xzey + -----END PGP MESSAGE----- + fp: 0C136F7514100470AD3EC8D37BF1FAEDB2ACCA9A + - created_at: "2025-02-26T16:39:44Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + wcFMA5KoiSc3R+FfAQ//WNYLuMOvDNX4ieMs8YwYFnti9ZBjuopwrPSMvNY+k+yt + AhAFN4DX2m5s76U2ILjyJbd2c2ZRUxa2Pmv2BjVhxjHt+Jkh1AznWCqX9BxcBlxd + q8kQAp2ciznmYePrPnZAOQkyu8Ik1A5/W0W9shL2LAfjRuwcqeOGEhoVSsXRQdi3 + knGTqbCF52MX1yN/Z/AU6jJwFUPz7aUzpkJwW2Y8vWV+ndiyjZjyu8jT3qJtlH2z + JlaTBBTH0GWtXtlY2v+W9szfL70IzJVaKciqY7y6G767i+jPYLFXVOgudsAAfnPe + JMp0uvm6Hw1po9qgpoWGmiG8NPp8Sl4BCRQsk4oiddm/+34yfBDq+ra9hmeqiVan + 9z0oFnpBY18L8MVimwoeAJOoihuq2/8k3OlpJoqRkLV+ez6o65qoPd8rS17+iOqb + ZDQwmqUf8lgYI1Sfq9qwWk88UYgBnwhRmyw7eZuqeCoaKv4x605cIydgKfd25xr8 + SeeuLzrWeXGQF3friqj2LujtTOAH34O5XkQVp0TKHXoVyL0wqgVPPIGBs14HOh3M + FQQH2knRmoQDARIzlN8+UCf29VVG73BxRG71XbZnVTL54mwDjBYYOW7T9A9DpBGK + wo+8zzptoXc4bhIYCYz06mvuEyH3IMe2o4/MQ38fboU7Qsi3no9jqxRb/H6ye0PS + UQGRIaDP3cKXh34JQLT6XTpuVDpDpVw/F5xy92VDDafvD1PiSiFhQzWD15zEw1tw + 2QcLcJZI3pUGf5aV9HK+thjzZKMTOtDog02GkIblov1EWA== + =sR1k + -----END PGP MESSAGE----- + fp: 57F93F2A6585CF2DF9A3B31F13B9F45E122698D5 + unencrypted_suffix: _unencrypted + version: 3.9.3 diff --git a/verify/test.sh b/verify/test.sh new file mode 100755 index 0000000..fdb721d --- /dev/null +++ b/verify/test.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# PURPOSE: Test to verify update_sops.sh script +set -ueo pipefail +test_dir="$(realpath $(dirname "${BASH_SOURCE[0]}"))" +cd "${test_dir}" + +# opinionated: keys located in current repo, one level up +keys_dir="$(dirname "${test_dir}")" +# deliberate: just "dot" for current dir +sops_cfg_dir=. +secrets_file="mock_secrets.yaml" + +# prerequisite: for verification of sops config, idempotent create file with a mock secret, src: https://bash-org-archive.com/?244321 +test -e "${secrets_file}" || (yq -n '.demo.credentials.secret = "hunter2"' > "${secrets_file}" && sops -e -i "${secrets_file}" ) + +# Special Case: Add caveat header +cat < .sops.yaml.tmp +# PURPOSE: BLUEPRINT for .sops.yaml config +# CAVEAT: DO NOT USE THIS FILE AS-IS in another project; copy it and remove the unauthorised users +$( cat .sops.yaml ) +EOM +mv .sops.yaml.tmp .sops.yaml + +# TESTCASES +# define "fixture" +repo_root="$(git rev-parse --show-toplevel)" +# --- +if [[ 1 -eq 1 ]]; then + >&2 echo -e "# ---\n# TEST: create sops cfg in default dir: ${repo_root}" + set -x + rm "${PWD}/.sops.yaml" || : + # note: fail if for any reason sops config defined at top level; this repo should not have this! + test ! -e "${repo_root}/.sops.yaml" + ../bin/update_sops.sh -s "${secrets_file}" > /dev/null 2>&1 + test ! -e "${PWD}/.sops.yaml" + test -e "${repo_root}/.sops.yaml" + set +x + # teardown + # enmesh: restore, since this particular one is checked in + git checkout "${PWD}/.sops.yaml" > /dev/null 2>&1 + rm "${repo_root}/.sops.yaml" +else + >&2 echo "# INFO: skipping ...." +fi + +# --- +if [[ 1 -eq 1 ]]; then + >&2 echo -e "# ---\n# TEST: create sops cfg in curdir: ${PWD}" + set -x + # note: fail if for any reason sops config defined at top level; this repo should not have this! + test ! -e "${repo_root}/.sops.yaml" + rm "${PWD}/.sops.yaml" || : + # minimal operation: update .sops.yaml, update keys in encrypted file + ../bin/update_sops.sh -c "${PWD}" "${secrets_file}" > /dev/null 2>&1 + test -e "${PWD}/.sops.yaml" + test ! -e "${repo_root}/.sops.yaml" + set +x + # teardown + # not necessary, all tracked in git + # enmesh: restore, since this particular one is checked in + git checkout "${PWD}/.sops.yaml" > /dev/null 2>&1 +else + >&2 echo "# INFO: skipping ...." +fi + +# --- +if [[ 1 -eq 1 ]]; then + >&2 echo -e "# ---\n# TEST: Full Args: specify path to each, also for secrets, mix specified and positional params" + set -x + ../bin/update_sops.sh -k "${keys_dir}" -c "${sops_cfg_dir}" -s "${secrets_file}" "${secrets_file}" > /dev/null 2>&1 + set +x + # teardown + # not necessary, all tracked in git + # enmesh: restore, since this particular one is checked in + git checkout "${PWD}/.sops.yaml" > /dev/null 2>&1 +else + >&2 echo "# INFO: skipping ...." +fi + +# --- +if [[ 1 -eq 1 ]]; then + >&2 echo -e "# ---\n# TEST: induce error: invalid file" + # dev note: ':' is a noop operator; could also just temporarily disable strict errors + set -x + ../bin/update_sops.sh "${secrets_file}" -s non_existing_secrets.yaml > /dev/null 2>&1 || : + set +x + # teardown + # not necessary, all tracked in git + # enmesh: restore, since this particular one is checked in + git checkout "${PWD}/.sops.yaml" > /dev/null 2>&1 +else + >&2 echo "# INFO: skipping ...." +fi + + +# --- +echo "TESTCASES PASSED" +exit 0 diff --git a/verify/usr_confirm_keycfg.sh b/verify/usr_confirm_keycfg.sh new file mode 100755 index 0000000..51170c6 --- /dev/null +++ b/verify/usr_confirm_keycfg.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +set -ueo pipefail +# PURPOSE: Allows User to verify their local SOPS configuration using a sample SOPS config and SOPS-encrypted file +# Usage: 1. Existing User: upon adding key, run this script to update the SOPS Config and encrypted file +# 2. New User: 'Existing User' has added key, run this script to confirm correct local configuration +cd "$(dirname "${BASH_SOURCE[0]}")" + +secrets_file="mock_secrets.yaml" + +# prerequisite: for verification of sops config, idempotent create file with a mock secret, src: https://bash-org-archive.com/?244321 +test -e "${secrets_file}" || (yq -n '.demo.credentials.secret = "hunter2"' > "${secrets_file}" && sops -e -i "${secrets_file}" ) + +set -x +# within current dir: update .sops.yaml, update keys in encrypted file +../bin/update_sops.sh -c "${PWD}" "${secrets_file}" + +# Special Case: Add caveat header +cat < .sops.yaml.tmp +# PURPOSE: BLUEPRINT for .sops.yaml config +# CAVEAT: DO NOT USE THIS FILE AS-IS in another project; copy it and remove the unauthorised users +$( cat .sops.yaml ) +EOM +mv .sops.yaml.tmp .sops.yaml +# if reached this far, is success, due to bash strict mode. I.e. script would have failed by now. +echo "SUCESS"