Remove internal notification caller tokens
This commit is contained in:
1 parent
1fe173397f
commit
caad7a3d5b
27 files changed
+112
-165
No files matched your search
@@ -38,5 +38,4 @@ api:
|
||||
min_length: 12
|
||||
notifications:
|
||||
address: notifications:8083
|
||||
token_env: SXCHNGE_NOTIFICATIONS_TOKEN
|
||||
activation_url: https://localhost:5126/verify-email
|
||||
@@ -17,8 +17,6 @@ messaging:
|
||||
max_reconnects: -1
|
||||
reconnect_wait: 2
|
||||
templates: "/etc/sxchnge/templates.json"
|
||||
callers:
|
||||
product: "SXCHNGE_NOTIFICATIONS_PRODUCT_TOKEN"
|
||||
email:
|
||||
driver: resend
|
||||
settings:
|
||||
|
||||
@@ -58,8 +58,8 @@ provision_agents() {
|
||||
directory="$STATE/agents/$service"
|
||||
mkdir -p "$directory"; chmod 755 "$directory"
|
||||
case "$service" in
|
||||
bff) paths='services/bff/jwt services/notifications/callers/bff';;
|
||||
notifications) paths='services/notifications/callers/bff infrastructure/nats/auth services/notifications/email/resend';;
|
||||
bff) paths='services/bff/jwt';;
|
||||
notifications) paths='infrastructure/nats/auth services/notifications/email/resend';;
|
||||
nats) paths=infrastructure/nats/auth;;
|
||||
esac
|
||||
: > "$WORK/policy"
|
||||
@@ -92,7 +92,7 @@ up() {
|
||||
initialize
|
||||
mounts
|
||||
migrate_secrets
|
||||
for path in infrastructure/nats/auth services/notifications/callers/bff services/bff/jwt; do
|
||||
for path in infrastructure/nats/auth services/bff/jwt; do
|
||||
if [ "$(kv "$path")" = null ]; then
|
||||
field=token; [ "$path" != services/bff/jwt ] || field=jwt
|
||||
random | jq -Rs --arg field "$field" '{($field):rtrimstr("\n")}' | put "$path"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# Canonical paths follow ownership. Shared callers live under the receiving service.
|
||||
# Canonical paths follow ownership.
|
||||
secret_moves() {
|
||||
cat <<'PATHS'
|
||||
bff services/bff/jwt
|
||||
caller services/notifications/callers/bff
|
||||
email services/notifications/email/resend
|
||||
nats infrastructure/nats/auth
|
||||
bootstrap/mongo infrastructure/mongo/bootstrap
|
||||
@@ -47,7 +46,7 @@ retire_secrets() (
|
||||
archive_secret "$old"
|
||||
printf '{}' | vault "kv/metadata/$old" DELETE >/dev/null
|
||||
done < "$WORK/moves"
|
||||
for old in tls frontend-tls notifications-tls; do
|
||||
for old in caller services/notifications/callers/bff tls frontend-tls notifications-tls; do
|
||||
archive_secret "$old"
|
||||
if [ "$(vault "kv/metadata/$old" GET yes)" != null ]; then printf '{}' | vault "kv/metadata/$old" DELETE >/dev/null; fi
|
||||
done
|
||||
|
||||
@@ -74,3 +74,22 @@ printf '{"data":{"metadata":{"version":43},"data":{"api_key":"preserved-fixture-
|
||||
if (normalize_email_secret) >/dev/null 2>&1; then fail 'Unknown secret field was silently dropped'; fi
|
||||
if grep -q EMAIL_CONFIG infra/local/vault/notifications.hcl infra/local/scripts/start-service.sh; then fail 'Email configuration is still rendered from Vault'; fi
|
||||
echo 'PASS: email migration preserves API key, removes configuration fields and rejects unknown fields'
|
||||
# Caller retirement is repeatable and must not remove NATS authentication.
|
||||
secret_moves() { :; }
|
||||
printf '{"caller":true,"services/notifications/callers/bff":true,"infrastructure/nats/auth":true}' > "$WORK/retirement"
|
||||
vault() {
|
||||
path=${1#kv/metadata/}
|
||||
case "${2:-GET}" in
|
||||
GET) jq -c --arg path "$path" '.[$path] // null' "$WORK/retirement";;
|
||||
DELETE)
|
||||
case "$path" in caller|services/notifications/callers/bff) ;; *) fail 'Unexpected secret retirement';; esac
|
||||
jq --arg path "$path" 'del(.[$path])' "$WORK/retirement" > "$WORK/retirement-next"
|
||||
mv "$WORK/retirement-next" "$WORK/retirement"
|
||||
;;
|
||||
*) fail 'Unexpected retirement method';;
|
||||
esac
|
||||
}
|
||||
retire_secrets
|
||||
retire_secrets
|
||||
jq -e '.=={"infrastructure/nats/auth":true}' "$WORK/retirement" >/dev/null
|
||||
echo 'PASS: obsolete caller secrets retired idempotently; NATS authentication preserved'
|
||||
@@ -6,7 +6,7 @@ policies() (
|
||||
directory="$STATE/agents/$service"
|
||||
login=$(jq -n --rawfile role "$directory/role-id" --rawfile secret "$directory/secret-id" '{role_id:($role|rtrimstr("\n")),secret_id:($secret|rtrimstr("\n"))}' | vault auth/approle/login POST)
|
||||
identity=$(printf '%s' "$login" | jq -er '.auth.client_token')
|
||||
printf '%s' "$login" | jq '{token:.auth.client_token,paths:["kv/data/bootstrap/mongo","kv/data/infrastructure/mongo/bootstrap","sys/init","kv/data/bff","kv/data/caller","kv/data/email","kv/data/nats","kv/data/tls"]}' | vault sys/capabilities POST | jq -e '.data | all(.[]; .==["deny"])' >/dev/null || fail 'Service can access bootstrap credentials'
|
||||
printf '%s' "$login" | jq '{token:.auth.client_token,paths:["kv/data/bootstrap/mongo","kv/data/infrastructure/mongo/bootstrap","sys/init","kv/data/bff","kv/data/caller","kv/data/services/notifications/callers/bff","kv/data/email","kv/data/nats","kv/data/tls"]}' | vault sys/capabilities POST | jq -e '.data | all(.[]; .==["deny"])' >/dev/null || fail 'Service can access bootstrap credentials'
|
||||
VAULT_TOKEN=$(printf '%s' "$login" | jq -er '.auth.client_token')
|
||||
printf '{}' | vault auth/token/revoke-self POST >/dev/null
|
||||
VAULT_TOKEN=$root_token
|
||||
@@ -51,10 +51,10 @@ product() {
|
||||
}
|
||||
layout() {
|
||||
kv services/notifications/email/resend | jq -e 'keys==["api_key"]' >/dev/null || fail 'Non-secret email configuration remains in Vault'
|
||||
for old in bootstrap/mongo bff caller email nats tls frontend-tls notifications-tls; do
|
||||
for old in bootstrap/mongo bff caller services/notifications/callers/bff email nats tls frontend-tls notifications-tls; do
|
||||
[ "$(vault "kv/metadata/$old" GET yes)" = null ] || fail "Obsolete KV entry remains: $old"
|
||||
done
|
||||
for path in services/bff/jwt services/notifications/callers/bff services/notifications/email/resend infrastructure/nats/auth infrastructure/mongo/bootstrap; do
|
||||
for path in services/bff/jwt services/notifications/email/resend infrastructure/nats/auth infrastructure/mongo/bootstrap; do
|
||||
vault "kv/metadata/$path" | jq -e '.data.current_version>0' >/dev/null || fail "Missing canonical KV entry: $path"
|
||||
done
|
||||
echo 'PASS: canonical Vault hierarchy present; obsolete flat and TLS entries absent'
|
||||
|
||||
@@ -19,10 +19,6 @@ env_template "SXCHNGE_JWT_SECRET" {
|
||||
error_on_missing_key = true
|
||||
}
|
||||
|
||||
env_template "SXCHNGE_NOTIFICATIONS_TOKEN" {
|
||||
contents = "{{ with secret \"kv/data/services/notifications/callers/bff\" }}{{ .Data.data.token }}{{ end }}"
|
||||
error_on_missing_key = true
|
||||
}
|
||||
|
||||
exec {
|
||||
command = ["/usr/local/bin/start-service"]
|
||||
|
||||
@@ -14,10 +14,6 @@ template_config {
|
||||
}
|
||||
|
||||
|
||||
env_template "SXCHNGE_NOTIFICATIONS_PRODUCT_TOKEN" {
|
||||
contents = "{{ with secret \"kv/data/services/notifications/callers/bff\" }}{{ .Data.data.token }}{{ end }}"
|
||||
error_on_missing_key = true
|
||||
}
|
||||
|
||||
env_template "SXCHNGE_NATS_URL" {
|
||||
contents = "{{ with secret \"kv/data/infrastructure/nats/auth\" }}nats://{{ .Data.data.token }}@nats:4222{{ end }}"
|
||||
|
||||
Reference in new issue
Block a user