This Terraform project builds a full private cross-cloud path and then layers mTLS on top:
- Azure Function (Linux, Node) inside an Azure VNet
- Site-to-site VPN: Azure VPN Gateway <-> AWS VPC (VGW)
- Azure DNS Private Resolver forwards
secrets.guruqueries to AWS Route 53 Resolver inbound endpoint - AWS internal ALB (HTTPS) with:
- Server certificate issued by your AWS Private CA
- mTLS verify using an ALB Trust Store
- ECS Fargate service behind ALB returning "hello world" and logging client cert subject
- You already created an AWS ACM Private CA (PCA) and have its ARN.
- You have the CA cert chain (root + any intermediate) exported to a PEM bundle, e.g.
certs/ca-bundle.pem. - You have a client certificate for Azure Function
- AWS credentials, Azure credentials.
Create the CA bundle used by the ALB trust store. This verifies client certs:
mkdir -p certs
cat root-ca.pem intermediate-ca.pem > certs/ca-bundle.pemDo NOT put
client.crt.pemin the trust store. The trust store must contain the issuer CA certificates.
cd azure_function_code
npm install
cd ..
tofu init
tofu applyOnce VPN is up and DNS forwarding works:
- Resolve
api.secrets.guru(should return a private IP / internal ALB routing) - Call the service with your client cert.
The included Function code calls https://${service_fqdn}/ and returns the upstream response.
The service logs client-cert-subject=... (from the x-amzn-tls-client-cert-subject header) and also includes it in the HTTP response body.
Export PFX:
cat client.crt.pem client.chain.pem > client.fullchain.pem
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.fullchain.pem
base64 -i client.pfx -o client.pfx.b64You can set app settings directly, or use Key Vault (recommended):
CLIENT_CERT_PFX_BASE64= contents ofclient.pfx.b64CLIENT_CERT_PFX_PASSWORD= your PFX password
Terraform now creates a Key Vault and grants the Function's managed identity get/list on secrets.
Upload these secrets manually (names are defaults; override via tofu.tfvars):
client-cert-pfx-b64= base64 contents ofclient.pfxclient-cert-pfx-password= your PFX passwordserver-ca-pem= PEM bundle for the ALB server cert
The Function reads them at runtime. Provide these app settings:
KEY_VAULT_URIKV_CLIENT_CERT_PFX_SECRET_NAMEKV_CLIENT_CERT_PASSWORD_SECRET_NAMEKV_SERVER_CA_PEM_SECRET_NAME
Because the ALB server cert is issued by your private CA, you must also provide SERVER_CA_PEM to the Function runtime or install it in the trust store.
- This demo wires only AWS tunnel #1 into Azure's Local Network Gateway for simplicity. For production-grade redundancy, wire both tunnels. AWS will be very persistant with their emails if you don't. Don't be surprised to get messages like this:
Important notice about your AWS Account regarding VPN connections [AWS Account: 123456789012]
View details in service console
Hello AWS VPN Customer,
You're receiving this message because you have at least one VPN Connection in the us-east-1 Region, for which your VPN Customer Gateway is not using both tunnels. This mode of operation is not recommended as you may experience connectivity issues if your active tunnel fails.
The VPN Connection(s) which do not currently have both tunnels established are:
vpn-xxxxxxx
- ALB Trust Stores sometimes take a short time to become ACTIVE. If the first apply fails with a trust store readiness error, re-run
tofu apply.
This can cost you money. To destroy everything:s
tofu destroy