Validate FCM service account credentials
This commit is contained in:
parent
a7f076514c
commit
6582b61dc4
|
|
@ -332,8 +332,12 @@ fcm_credentials =
|
||||||
raise "Set only one of FCM_SERVICE_ACCOUNT_FILE or FCM_SERVICE_ACCOUNT_JSON_BASE64."
|
raise "Set only one of FCM_SERVICE_ACCOUNT_FILE or FCM_SERVICE_ACCOUNT_JSON_BASE64."
|
||||||
end
|
end
|
||||||
|
|
||||||
if fcm_credentials && fcm_credentials["type"] != "service_account" do
|
if fcm_credentials &&
|
||||||
raise "The configured FCM credentials must be a Google service-account document."
|
(fcm_credentials["type"] != "service_account" ||
|
||||||
|
Enum.any?(["project_id", "client_email", "private_key"], fn field ->
|
||||||
|
not is_binary(fcm_credentials[field]) or fcm_credentials[field] == ""
|
||||||
|
end)) do
|
||||||
|
raise "The configured FCM credentials must be a complete Google service-account document."
|
||||||
end
|
end
|
||||||
|
|
||||||
fcm_configuration =
|
fcm_configuration =
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,15 @@ contains_template_marker() {
|
||||||
"$observed" == *example.com* || "$observed" == *example.invalid* ]]
|
"$observed" == *example.com* || "$observed" == *example.invalid* ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valid_fcm_service_account_json() {
|
||||||
|
jq -e '
|
||||||
|
.type == "service_account" and
|
||||||
|
(.project_id | type == "string" and length > 0) and
|
||||||
|
(.client_email | type == "string" and length > 0) and
|
||||||
|
(.private_key | type == "string" and length > 0)
|
||||||
|
' >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
failures=0
|
failures=0
|
||||||
warnings=0
|
warnings=0
|
||||||
|
|
||||||
|
|
@ -178,16 +187,19 @@ elif [[ -z "$(value FCM_PROJECT_ID)" || (-n "$fcm_file" && -n "$fcm_base64") ||
|
||||||
(-z "$fcm_file" && -z "$fcm_base64") ]]; then
|
(-z "$fcm_file" && -z "$fcm_base64") ]]; then
|
||||||
partial "Android FCM delivery" "project ID and exactly one credential source are required"
|
partial "Android FCM delivery" "project ID and exactly one credential source are required"
|
||||||
elif [[ -n "$fcm_file" ]]; then
|
elif [[ -n "$fcm_file" ]]; then
|
||||||
if [[ "$fcm_file" == /* && -r "$fcm_file" ]]; then
|
if [[ "$fcm_file" == /* && -r "$fcm_file" ]] &&
|
||||||
ready "Android FCM delivery" "readable service-account file is configured"
|
valid_fcm_service_account_json <"$fcm_file"; then
|
||||||
|
ready "Android FCM delivery" "complete service-account file is configured"
|
||||||
else
|
else
|
||||||
invalid "Android FCM delivery" "FCM_SERVICE_ACCOUNT_FILE must be an absolute readable file"
|
invalid "Android FCM delivery" \
|
||||||
|
"FCM_SERVICE_ACCOUNT_FILE must be an absolute readable complete service-account JSON file"
|
||||||
fi
|
fi
|
||||||
elif printf '%s' "$fcm_base64" | base64 --decode 2>/dev/null |
|
elif printf '%s' "$fcm_base64" | base64 --decode 2>/dev/null |
|
||||||
jq -e '.type == "service_account" and (.project_id | type == "string")' >/dev/null 2>&1; then
|
valid_fcm_service_account_json; then
|
||||||
ready "Android FCM delivery" "valid Base64 service-account document is configured"
|
ready "Android FCM delivery" "complete Base64 service-account document is configured"
|
||||||
else
|
else
|
||||||
invalid "Android FCM delivery" "Base64 credential is not a service-account JSON document"
|
invalid "Android FCM delivery" \
|
||||||
|
"Base64 credential is not a complete service-account JSON document"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if all_empty ANDROID_APP_LINKS_PACKAGE_NAME ANDROID_APP_LINKS_SHA256_CERT_FINGERPRINTS; then
|
if all_empty ANDROID_APP_LINKS_PACKAGE_NAME ANDROID_APP_LINKS_SHA256_CERT_FINGERPRINTS; then
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,26 @@ if { [ -n "$fcm_project_id" ] || [ -n "$fcm_service_account_json_base64" ]; } &&
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$fcm_service_account_json_base64" ]; then
|
||||||
|
for command in base64 jq; do
|
||||||
|
command -v "$command" >/dev/null 2>&1 || {
|
||||||
|
echo "Required command is unavailable for FCM validation: $command" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
if ! printf '%s' "$fcm_service_account_json_base64" |
|
||||||
|
base64 --decode 2>/dev/null |
|
||||||
|
jq -e '
|
||||||
|
.type == "service_account" and
|
||||||
|
(.project_id | type == "string" and length > 0) and
|
||||||
|
(.client_email | type == "string" and length > 0) and
|
||||||
|
(.private_key | type == "string" and length > 0)
|
||||||
|
' >/dev/null 2>&1; then
|
||||||
|
echo "Production FCM credential is not a complete service-account JSON document." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
case "$compose_project_name" in
|
case "$compose_project_name" in
|
||||||
*[!a-zA-Z0-9_-]* | '')
|
*[!a-zA-Z0-9_-]* | '')
|
||||||
echo "PRODUCTION_COMPOSE_PROJECT_NAME must contain only letters, numbers, underscores, or hyphens." >&2
|
echo "PRODUCTION_COMPOSE_PROJECT_NAME must contain only letters, numbers, underscores, or hyphens." >&2
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,26 @@ if [[ (-n "$fcm_project_id" || -n "$fcm_service_account_json_base64") &&
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$fcm_service_account_json_base64" ]]; then
|
||||||
|
for command in base64 jq; do
|
||||||
|
command -v "$command" >/dev/null 2>&1 || {
|
||||||
|
echo "Required command is unavailable for FCM validation: $command" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
if ! printf '%s' "$fcm_service_account_json_base64" |
|
||||||
|
base64 --decode 2>/dev/null |
|
||||||
|
jq -e '
|
||||||
|
.type == "service_account" and
|
||||||
|
(.project_id | type == "string" and length > 0) and
|
||||||
|
(.client_email | type == "string" and length > 0) and
|
||||||
|
(.private_key | type == "string" and length > 0)
|
||||||
|
' >/dev/null 2>&1; then
|
||||||
|
echo "Test FCM credential is not a complete service-account JSON document." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
for pair in "HTTP:$http_port" "MAILPIT:$mailpit_port"; do
|
for pair in "HTTP:$http_port" "MAILPIT:$mailpit_port"; do
|
||||||
value=${pair#*:}
|
value=${pair#*:}
|
||||||
if [[ ! "$value" =~ ^[0-9]+$ ]] || ((value < 1 || value > 65535)); then
|
if [[ ! "$value" =~ ^[0-9]+$ ]] || ((value < 1 || value > 65535)); then
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,8 @@ test "$(sha256sum "$legacy_load_env" | awk '{print $1}')" = "$legacy_load_hash"
|
||||||
|
|
||||||
echo "Checking independent test and production environment initialization"
|
echo "Checking independent test and production environment initialization"
|
||||||
quality_fcm_base64=$(
|
quality_fcm_base64=$(
|
||||||
printf '%s' '{"type":"service_account","project_id":"quality-production"}' |
|
printf '%s' \
|
||||||
|
'{"type":"service_account","project_id":"quality-production","client_email":"quality-fcm@quality-production.iam.gserviceaccount.com","private_key":"quality-private-key"}' |
|
||||||
base64 -w 0
|
base64 -w 0
|
||||||
)
|
)
|
||||||
test_env="$scan_dir/test.env"
|
test_env="$scan_dir/test.env"
|
||||||
|
|
@ -206,6 +207,25 @@ PRODUCTION_SUPPORT_INBOX_ADDRESS=support@help.test \
|
||||||
test "$(stat -c '%a' "$production_env")" = 600
|
test "$(stat -c '%a' "$production_env")" = 600
|
||||||
./scripts/validate-production-env.sh "$production_env" help.test >/dev/null
|
./scripts/validate-production-env.sh "$production_env" help.test >/dev/null
|
||||||
./scripts/check-environment-readiness.sh "$production_env" --require-release >/dev/null
|
./scripts/check-environment-readiness.sh "$production_env" --require-release >/dev/null
|
||||||
|
invalid_fcm_env="$scan_dir/production.invalid-fcm.env"
|
||||||
|
invalid_fcm_base64=$(
|
||||||
|
printf '%s' '{"type":"service_account","project_id":"quality-production"}' |
|
||||||
|
base64 -w 0
|
||||||
|
)
|
||||||
|
cp "$production_env" "$invalid_fcm_env"
|
||||||
|
sed -i \
|
||||||
|
"s|^FCM_SERVICE_ACCOUNT_JSON_BASE64=.*|FCM_SERVICE_ACCOUNT_JSON_BASE64=$invalid_fcm_base64|" \
|
||||||
|
"$invalid_fcm_env"
|
||||||
|
if ./scripts/validate-production-env.sh \
|
||||||
|
"$invalid_fcm_env" help.test >/dev/null 2>&1; then
|
||||||
|
echo "Production validation accepted an incomplete FCM service account." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ./scripts/check-environment-readiness.sh \
|
||||||
|
"$invalid_fcm_env" --require-release >/dev/null 2>&1; then
|
||||||
|
echo "Environment readiness accepted an incomplete FCM service account." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
grep -Fx 'COMPOSE_PROJECT_NAME=who_need_help_production' "$production_env" >/dev/null
|
grep -Fx 'COMPOSE_PROJECT_NAME=who_need_help_production' "$production_env" >/dev/null
|
||||||
grep -E '^APP_IMAGE=who-need-help:production-[0-9a-f]{12}$' "$production_env" >/dev/null
|
grep -E '^APP_IMAGE=who-need-help:production-[0-9a-f]{12}$' "$production_env" >/dev/null
|
||||||
grep -Fx 'EDGE_COMPOSE_PROJECT_NAME=who_need_help_edge' "$production_env" >/dev/null
|
grep -Fx 'EDGE_COMPOSE_PROJECT_NAME=who_need_help_edge' "$production_env" >/dev/null
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,15 @@ require_value() {
|
||||||
printf '%s' "$value"
|
printf '%s' "$value"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valid_fcm_service_account_json() {
|
||||||
|
jq -e '
|
||||||
|
.type == "service_account" and
|
||||||
|
(.project_id | type == "string" and length > 0) and
|
||||||
|
(.client_email | type == "string" and length > 0) and
|
||||||
|
(.private_key | type == "string" and length > 0)
|
||||||
|
' >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
reject_marker() {
|
reject_marker() {
|
||||||
local key=$1
|
local key=$1
|
||||||
local value=$2
|
local value=$2
|
||||||
|
|
@ -378,10 +387,18 @@ if [[ -n "$fcm_project_id" || -n "$fcm_service_account_file" ||
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -n "$fcm_service_account_file" ]]; then
|
if [[ -n "$fcm_service_account_file" ]]; then
|
||||||
|
command -v jq >/dev/null 2>&1 || {
|
||||||
|
echo "Required command is unavailable for FCM validation: jq" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
[[ "$fcm_service_account_file" == /* && -r "$fcm_service_account_file" ]] || {
|
[[ "$fcm_service_account_file" == /* && -r "$fcm_service_account_file" ]] || {
|
||||||
echo "FCM_SERVICE_ACCOUNT_FILE must be an absolute readable file." >&2
|
echo "FCM_SERVICE_ACCOUNT_FILE must be an absolute readable file." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
valid_fcm_service_account_json <"$fcm_service_account_file" || {
|
||||||
|
echo "FCM_SERVICE_ACCOUNT_FILE is not a complete service-account JSON document." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
else
|
else
|
||||||
for command in base64 jq; do
|
for command in base64 jq; do
|
||||||
command -v "$command" >/dev/null 2>&1 || {
|
command -v "$command" >/dev/null 2>&1 || {
|
||||||
|
|
@ -391,9 +408,8 @@ if [[ -n "$fcm_project_id" || -n "$fcm_service_account_file" ||
|
||||||
done
|
done
|
||||||
printf '%s' "$fcm_service_account_json_base64" |
|
printf '%s' "$fcm_service_account_json_base64" |
|
||||||
base64 --decode 2>/dev/null |
|
base64 --decode 2>/dev/null |
|
||||||
jq -e '.type == "service_account" and (.project_id | type == "string")' \
|
valid_fcm_service_account_json || {
|
||||||
>/dev/null 2>&1 || {
|
echo "FCM_SERVICE_ACCOUNT_JSON_BASE64 is not a complete service-account JSON document." >&2
|
||||||
echo "FCM_SERVICE_ACCOUNT_JSON_BASE64 is not a service-account JSON document." >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,15 @@ require_value() {
|
||||||
printf '%s' "$value"
|
printf '%s' "$value"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valid_fcm_service_account_json() {
|
||||||
|
jq -e '
|
||||||
|
.type == "service_account" and
|
||||||
|
(.project_id | type == "string" and length > 0) and
|
||||||
|
(.client_email | type == "string" and length > 0) and
|
||||||
|
(.private_key | type == "string" and length > 0)
|
||||||
|
' >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
[[ "$(require_value DEPLOYMENT_ENV)" == test ]] || {
|
[[ "$(require_value DEPLOYMENT_ENV)" == test ]] || {
|
||||||
echo "Test validation requires DEPLOYMENT_ENV=test." >&2
|
echo "Test validation requires DEPLOYMENT_ENV=test." >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -174,6 +183,34 @@ if [[ -n "$fcm_project_id" || -n "$fcm_service_account_file" ||
|
||||||
echo "Test FCM project ID and exactly one credential source are required together." >&2
|
echo "Test FCM project ID and exactly one credential source are required together." >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [[ -n "$fcm_service_account_file" ]]; then
|
||||||
|
command -v jq >/dev/null 2>&1 || {
|
||||||
|
echo "Required command is unavailable for FCM validation: jq" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
[[ "$fcm_service_account_file" == /* && -r "$fcm_service_account_file" ]] || {
|
||||||
|
echo "Test FCM_SERVICE_ACCOUNT_FILE must be an absolute readable file." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
valid_fcm_service_account_json <"$fcm_service_account_file" || {
|
||||||
|
echo "Test FCM_SERVICE_ACCOUNT_FILE is not a complete service-account JSON document." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
for command in base64 jq; do
|
||||||
|
command -v "$command" >/dev/null 2>&1 || {
|
||||||
|
echo "Required command is unavailable for FCM validation: $command" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
done
|
||||||
|
printf '%s' "$fcm_service_account_json_base64" |
|
||||||
|
base64 --decode 2>/dev/null |
|
||||||
|
valid_fcm_service_account_json || {
|
||||||
|
echo "Test FCM_SERVICE_ACCOUNT_JSON_BASE64 is not a complete service-account JSON document." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
android_package=$(read_value ANDROID_APP_LINKS_PACKAGE_NAME 2>/dev/null || true)
|
android_package=$(read_value ANDROID_APP_LINKS_PACKAGE_NAME 2>/dev/null || true)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user