procurement-ingest/scripts/setup_procurement_api_domain.sh
Adam Moussa 5a3729c583
chore(infra): remove cdk tree after hcp cutover (PLAT-89) (#164)
* chore(infra): remove cdk tree after hcp cutover

Delete retired CDK sources, retarget bundle/principal contract tests to
Terraform packaging, disable CDK synth in CI, and scrub deploy-adjacent docs.

* fix(test): restore exact SHOC principal pin in terraform

Pin shoc_consumer_role_arn's Terraform default and example to the trusted
ARN, and require grant sites to consume local.shoc_consumer_role_arn only.
2026-08-07 12:20:29 -04:00

127 lines
5.5 KiB
Bash
Executable file

#!/usr/bin/env bash
###############################################################################
# setup_procurement_api_domain.sh
#
# One-time (idempotent) wiring for the procurement-api custom domain
# (procurement-api.seahaven.com). CROSS-ACCOUNT: the API + ACM cert live in
# seahaven-prod (011934824531), but the seahaven.com public zone lives in the
# mgmt account (328440206208), so the cert's DNS-validation record and the
# final A-alias are added to the mgmt zone.
#
# Order of operations:
# 1. ./setup_procurement_api_domain.sh cert
# - requests (or reuses) the ACM cert in prod, us-east-1
# - adds its DNS-validation CNAME to the mgmt seahaven.com zone
# - waits for ISSUED, then writes the cert ARN to prod SSM
# (/procurement-api/custom-domain/certificate-arn)
# 2. HCP Terraform apply on workspace procurement-ingest-prod -- it reads
# the SSM param and owns the API Gateway DomainName + mapping
# 3. ./setup_procurement_api_domain.sh alias
# - reads the regional alias target from API Gateway get-domain-name
# - adds the A-alias (procurement-api.seahaven.com -> API GW) to the
# mgmt zone
#
# Requires SSO sessions for BOTH profiles (prod for ACM/SSM/API GW, mgmt for Route53).
###############################################################################
set -euo pipefail
DOMAIN="procurement-api.seahaven.com"
REGION="us-east-1"
PROD_PROFILE="${PROD_PROFILE:-seahaven-prod}"
MGMT_PROFILE="${MGMT_PROFILE:-seahaven-mgmt}"
PROD_ACCOUNT="011934824531"
MGMT_ACCOUNT="328440206208"
ZONE_ID="Z06652411XKH89KTZD3XA" # seahaven.com public zone, in the mgmt account
SSM_PARAM="/procurement-api/custom-domain/certificate-arn"
_verify_account() {
local profile="$1" expected="$2"
local got
got="$(aws sts get-caller-identity --profile "${profile}" --query Account --output text)"
if [[ "${got}" != "${expected}" ]]; then
echo "ERROR: profile ${profile} resolves to ${got}, expected ${expected}. Aborting." >&2
exit 1
fi
}
cmd_cert() {
_verify_account "${PROD_PROFILE}" "${PROD_ACCOUNT}"
_verify_account "${MGMT_PROFILE}" "${MGMT_ACCOUNT}"
echo "==> Finding or requesting ACM cert for ${DOMAIN} in ${PROD_ACCOUNT}/${REGION}"
local cert_arn
cert_arn="$(aws acm list-certificates --profile "${PROD_PROFILE}" --region "${REGION}" \
--query "CertificateSummaryList[?DomainName=='${DOMAIN}'].CertificateArn | [0]" --output text)"
if [[ "${cert_arn}" == "None" || -z "${cert_arn}" ]]; then
cert_arn="$(aws acm request-certificate --profile "${PROD_PROFILE}" --region "${REGION}" \
--domain-name "${DOMAIN}" --validation-method DNS \
--query CertificateArn --output text)"
echo " requested ${cert_arn}; waiting for the validation record to populate..."
sleep 8
else
echo " reusing existing ${cert_arn}"
fi
echo "==> Reading the DNS-validation record"
local rec_name rec_value
rec_name="$(aws acm describe-certificate --profile "${PROD_PROFILE}" --region "${REGION}" \
--certificate-arn "${cert_arn}" \
--query "Certificate.DomainValidationOptions[0].ResourceRecord.Name" --output text)"
rec_value="$(aws acm describe-certificate --profile "${PROD_PROFILE}" --region "${REGION}" \
--certificate-arn "${cert_arn}" \
--query "Certificate.DomainValidationOptions[0].ResourceRecord.Value" --output text)"
echo "==> Upserting validation CNAME in the mgmt seahaven.com zone"
aws route53 change-resource-record-sets --profile "${MGMT_PROFILE}" \
--hosted-zone-id "${ZONE_ID}" --change-batch "$(cat <<JSON
{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{
"Name":"${rec_name}","Type":"CNAME","TTL":300,
"ResourceRecords":[{"Value":"${rec_value}"}]}}]}
JSON
)" >/dev/null
echo "==> Waiting for cert to reach ISSUED (can take a few minutes)"
aws acm wait certificate-validated --profile "${PROD_PROFILE}" --region "${REGION}" \
--certificate-arn "${cert_arn}"
echo "==> Writing cert ARN to prod SSM ${SSM_PARAM}"
aws ssm put-parameter --profile "${PROD_PROFILE}" --region "${REGION}" \
--name "${SSM_PARAM}" --type String --overwrite --value "${cert_arn}" >/dev/null
echo "OK: cert ISSUED and SSM param set. Next: HCP apply on procurement-ingest-prod, then '$0 alias'."
}
cmd_alias() {
_verify_account "${PROD_PROFILE}" "${PROD_ACCOUNT}"
_verify_account "${MGMT_PROFILE}" "${MGMT_ACCOUNT}"
echo "==> Reading regional alias target from API Gateway domain ${DOMAIN}"
local target zone
target="$(aws apigateway get-domain-name --profile "${PROD_PROFILE}" --region "${REGION}" \
--domain-name "${DOMAIN}" \
--query "regionalDomainName" --output text)"
zone="$(aws apigateway get-domain-name --profile "${PROD_PROFILE}" --region "${REGION}" \
--domain-name "${DOMAIN}" \
--query "regionalHostedZoneId" --output text)"
if [[ -z "${target}" || "${target}" == "None" ]]; then
echo "ERROR: no regionalDomainName for ${DOMAIN}; HCP-apply the API custom domain first." >&2
exit 1
fi
echo "==> Upserting A-alias ${DOMAIN} -> ${target} in the mgmt zone"
aws route53 change-resource-record-sets --profile "${MGMT_PROFILE}" \
--hosted-zone-id "${ZONE_ID}" --change-batch "$(cat <<JSON
{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{
"Name":"${DOMAIN}","Type":"A",
"AliasTarget":{"DNSName":"${target}","HostedZoneId":"${zone}","EvaluateTargetHealth":false}}}]}
JSON
)" >/dev/null
echo "OK: A-alias set. Verify: curl -sS -o /dev/null -w '%{http_code}\\n' https://${DOMAIN}/docs (expect 401 without a token)."
}
case "${1:-}" in
cert) cmd_cert ;;
alias) cmd_alias ;;
*) echo "usage: $0 {cert|alias}" >&2; exit 2 ;;
esac