who_need_help/scripts/sync-kind-runtime-secret.sh

163 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
umask 077
ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
env_file=${1:-"$ROOT/.env"}
mode=${2:-}
render_target=${3:-}
if [[ "$env_file" != /* ]]; then
env_file="$ROOT/$env_file"
fi
if [[ -n "$mode" && "$mode" != "--render-only" ]]; then
echo "Usage: $0 [ENV_FILE] [--render-only OUTPUT_FILE]" >&2
exit 2
fi
if [[ "$mode" == "--render-only" && -z "$render_target" ]]; then
echo "Usage: $0 [ENV_FILE] [--render-only OUTPUT_FILE]" >&2
exit 2
fi
[[ -f "$env_file" ]] || {
echo "Development environment does not exist: $env_file" >&2
exit 2
}
[[ "$(stat -c '%a' "$env_file")" == 600 ]] || {
echo "Development environment must have mode 0600: $env_file" >&2
exit 2
}
[[ "$(stat -c '%u' "$env_file")" == "$(id -u)" ]] || {
echo "Development environment must be owned by the current user: $env_file" >&2
exit 2
}
managed_keys=(
ANDROID_APP_LINKS_PACKAGE_NAME
ANDROID_APP_LINKS_SHA256_CERT_FINGERPRINTS
EMAIL_FROM_ADDRESS
EMAIL_FROM_NAME
FCM_PROJECT_ID
FCM_SERVICE_ACCOUNT_JSON_BASE64
GITHUB_OAUTH_CLIENT_ID
GITHUB_OAUTH_CLIENT_SECRET
GOOGLE_OAUTH_AUTHORIZED_PARTY_IDS
GOOGLE_OAUTH_CLIENT_ID
GOOGLE_OAUTH_CLIENT_SECRET
SUPPORT_INBOX_ADDRESS
SUPPORT_INBOUND_RECIPIENT
SUPPORT_INBOUND_WEBHOOK_TOKEN
SUPPORT_OPERATOR_EMAIL_MODE
WEB_PUSH_VAPID_PRIVATE_KEY
WEB_PUSH_VAPID_PUBLIC_KEY
WEB_PUSH_VAPID_SUBJECT
)
runtime_dir=$(mktemp -d "${TMPDIR:-/tmp}/wnh-kind-runtime-secret.XXXXXX")
cleanup() {
status=$?
trap - EXIT HUP INT TERM
find "$runtime_dir" -xdev -depth -delete 2>/dev/null || true
exit "$status"
}
trap cleanup EXIT HUP INT TERM
keys_file="$runtime_dir/managed-keys"
printf '%s\n' "${managed_keys[@]}" >"$keys_file"
filtered_env="$runtime_dir/runtime.env"
awk -F= '
NR == FNR {
managed[$1] = 1
next
}
{
key = $1
if (!(key in managed)) next
seen[key]++
if (seen[key] > 1) {
printf "Managed development key occurs more than once: %s\n", key > "/dev/stderr"
invalid = 1
next
}
value = substr($0, length(key) + 2)
if ((value ~ /^".*"$/) || (value ~ /^\047.*\047$/)) {
value = substr(value, 2, length(value) - 2)
}
if (length(value) > 0) print key "=" value
}
END { if (invalid) exit 1 }
' "$keys_file" "$env_file" >"$filtered_env"
chmod 600 "$filtered_env"
if [[ "$mode" == "--render-only" ]]; then
case "$render_target" in
/*) ;;
*) render_target="$ROOT/$render_target" ;;
esac
install -m 600 "$filtered_env" "$render_target"
echo "Rendered managed development runtime keys without printing their values."
exit 0
fi
KUBECTL_BIN=${KUBECTL_BIN:-kubectl}
KUBE_CONTEXT=${KUBE_CONTEXT:-kind-who-need-help}
KUBE_NAMESPACE=${KUBE_NAMESPACE:-who-need-help}
KUBE_SECRET_NAME=${KUBE_SECRET_NAME:-who-need-help-local}
existing_json="$runtime_dir/existing.json"
extra_json="$runtime_dir/extra.json"
desired_json="$runtime_dir/desired.json"
observed_json="$runtime_dir/observed.json"
"$KUBECTL_BIN" --context "$KUBE_CONTEXT" --namespace "$KUBE_NAMESPACE" \
get secret "$KUBE_SECRET_NAME" --output json >"$existing_json"
if [[ -s "$filtered_env" ]]; then
"$KUBECTL_BIN" create secret generic "$KUBE_SECRET_NAME" \
--namespace "$KUBE_NAMESPACE" \
--from-env-file="$filtered_env" \
--dry-run=client \
--output json >"$extra_json"
else
printf '%s\n' '{"data":{}}' >"$extra_json"
fi
jq --slurpfile extra "$extra_json" --rawfile managed "$keys_file" '
($managed | split("\n") | map(select(length > 0))) as $managed_keys
| .data = (
((.data // {})
| with_entries(select(.key as $key | ($managed_keys | index($key) | not))))
+ ($extra[0].data // {})
)
| {
apiVersion: "v1",
kind: "Secret",
metadata: {
name: .metadata.name,
namespace: .metadata.namespace,
resourceVersion: .metadata.resourceVersion
},
type: (.type // "Opaque"),
data: .data
}
' "$existing_json" >"$desired_json"
"$KUBECTL_BIN" --context "$KUBE_CONTEXT" --namespace "$KUBE_NAMESPACE" \
replace --filename "$desired_json" >/dev/null
"$KUBECTL_BIN" --context "$KUBE_CONTEXT" --namespace "$KUBE_NAMESPACE" \
get secret "$KUBE_SECRET_NAME" --output json >"$observed_json"
jq --exit-status --slurpfile desired "$desired_json" \
'.data == $desired[0].data' "$observed_json" >/dev/null || {
echo "Kubernetes Secret verification did not match the desired key set." >&2
exit 1
}
synced_count=$(wc -l <"$filtered_env" | tr -d '[:space:]')
echo "Synchronized $synced_count managed development runtime keys without printing their values."