Template of AWS Cross Region VPC-endpoint

Background

This terraform project illustrates the AWS Cross Region VPC Interface endpoint (PrivateLink) implementation with VPC peering.

It referenced guideline from AWS: https://docs.aws.amazon.com/vpc/latest/userguide/vpc-inter-region-peering-consumer-side.html

Main region = region of market data service hosted Satellite region = region of data consumer located

Architecture diagram

architecture

MockProvider

A dummy HTTP SSE service streaming data at port 8194.
This service is running on ECS fargate.
It serves as a "MOCK" to check the vpc peering and vpc endpoint setup.

Configuration

It is maintained in "profilefargate.auto.tfvars".

Fargate Task docker image
docker image name of the dummy HTTP SSE service
Example
task_docker_image="192592784707.dkr.ecr.us-west-2.amazonaws.com/marketservice-sse:rc.java"

White list principal White list principal to establish endpoint for data consumption It is a list of ARN id of IAM principal.
Example
vpc_endpointsvc_allowed_principals=["arn:aws:iam::119217677828:user/TerraformDeploy"]

Run Command

cd MockProvider
terraform apply

Expected output Outputs:

nlb_address = <load balancer dns name e.g. load-balancer-dd9cbd4dd36c99b8.elb.us-west-2.amazonaws.com>
VPC_PRIMARY_SERVICE_NAME = <primary vpc endpoint service name e.g. com.amazonaws.vpce.us-east-1.vpce-svc-02c793cdda772424f>
VPC_SECONDARY_SERVICE_NAME = <secondary vpc endpoint service name e.g. com.amazonaws.vpce.us-east-1.vpce-svc-077e904bd2a82dae4>

ClientConsumer

Implement the AWS setup of AWS PrivateLink

Configuration

VPC Endpoint Service (PrivateLink) dns name DNS name of the VPC endpoint service (PrivateLink) for connection in main region app_primary_endpoint_svc_name="com.amazonaws.vpce.us-west-2.vpce-svc-09c04c40432fd9b4c"

S3 vpc endpoint log bucket ARN of S3 bucket as log data sink of vpc endpoint traffic in remote region s3_vpc_endpoint_log_arn = "arn:aws:s3:::boargcp-vpcendpointlog"

Run Command

cd ClientConsumer
export VPC_PRIMARY_SERVICE_NAME=<vpc endpoint primary service name e.g. com.amazonaws.vpce.us-east-1.vpce-svc-0c078abf59c16d2a0>
export VPC_SECONDARY_SERVICE_NAME=<vpc endpoint secondary service name e.g. com.amazonaws.vpce.us-east-1.vpce-svc-0b2948573a91a6ddf>

#Setup the vpc endpoint for both region and network for both region first
terraform apply -target module.origin -target module.remote \
-var "app_primary_endpoint_svc_name=${VPC_PRIMARY_SERVICE_NAME}" \
-var "app_secondary_endpoint_svc_name=${VPC_SECONDARY_SERVICE_NAME}"

#setup vpc peering
terraform apply -var "app_primary_endpoint_svc_name=${VPC_PRIMARY_SERVICE_NAME}" \
-var "app_secondary_endpoint_svc_name=${VPC_SECONDARY_SERVICE_NAME}"

Expected output DNS names of vpc endpoint for connections.

mkt_service_vpc_endpoint_dns_address = [
  {
    "dns_name" = "vpce-0d6b99e2c3337cc85-6snpjv75.vpce-svc-013983b5873316d7c.us-west-2.vpce.amazonaws.com"
    "hosted_zone_id" = "Z1YSA3EXCYUU9Z"
  },
  {
    "dns_name" = "vpce-0d6b99e2c3337cc85-6snpjv75-us-west-2b.vpce-svc-013983b5873316d7c.us-west-2.vpce.amazonaws.com"
    "hosted_zone_id" = "Z1YSA3EXCYUU9Z"
  },
  {
    "dns_name" = "vpce-0d6b99e2c3337cc85-6snpjv75-us-west-2a.vpce-svc-013983b5873316d7c.us-west-2.vpce.amazonaws.com"
    "hosted_zone_id" = "Z1YSA3EXCYUU9Z"
  },
]

Approve the VPC Endpoint connection in Mock application account ###

You will find state "Pending Acceptance" in the EndPoint service from AWS console Seek Approval After approval, you find the state changing to "Pending" Approved Wait until the state turning to "Available"

Testing

We would use curl to test the connection: Notes: You may receive following DNS error:
curl: (6) Could not resolve host:
AWS may take minutes to update DNS records to all AWS running instances
If you don't want to wait, you can use ip address of VPC endpoint instead

curl -X GET '<vpc end point dns name>:8194/blp/mktdata?token=JWT1&sessionId=sessionid1&mktdatacode=XAUUSD+Curncy&fields=BID&fields=ASK'

export BPIPEHOSTNAME= export BBG_CLIENTCERT_PWD=

Expected result Streaming market data with HTTP Server Side Emit (SSE)

id:XAUUSD Curncy-1602139886640
event:XAUUSD Curncy-1602139886640-BID,
data:{"timestamp_ms":1602139886640,"mktdatacode":"XAUUSD Curncy","responseStatus":"OK","message":null,"valuesMap":{"BID":1893.44}}

id:XAUUSD Curncy-1602139886669
event:XAUUSD Curncy-1602139886669-ASK,
data:{"timestamp_ms":1602139886669,"mktdatacode":"XAUUSD Curncy","responseStatus":"OK","message":null,"valuesMap":{"ASK":1894.2}}

id:null-1602139886715
event:null-1602139886715-
data:{"timestamp_ms":1602139886715,"mktdatacode":null,"responseStatus":"EXPIRED","message":"sessionid1 session is not valid now","valuesMap":{}}

Monitor VPC endpoint traffic with cloud watch

Monitor the VPC endpoint traffic. First, we get the eni id get eni of VPC endpoint Then, we go to cloud watch query the eni id cloudwatch - query eni id

Clean up

Clean ClientConsumer

cd ClientConsumer
terraform destroy
<note type any value four times to skip the vpc endpoint names>

cd MockProvider
terraform destroy

Reference

https://binx.io/blog/2020/06/17/creating-multiple-resources-at-once-with-terraform-for-each/