If you have rest api gateway in your application to exposing EKS/ECS services and you still working with http proxy integration you need to change it right now.
here is a tutorial on how to change your http proxy integration to https proxy integration to your VPC services.
all you need is a public domain.
So What Is The Problem?
Now a days when you want to do a proxy integration from your rest api gateway to your VPC ECS\EKS services you have to create network load balancer and work with this Amazon's official tutorial
in this tutorial Amazon recommend to proxy our request to the network load balancer with the load balancer's http DNS, but what if we want to keep our secured tls connection?
So here is a lot of solutions that just don't work:
Solution that didn't work #1
Create self signed / private ca - we can create route 53 private domain and self signed certificate or private ca certificate, but Amazon's rest api gateway proxy integration don't support any private ca or self signed certificate, api gateway expect public certified ca certificate as described in Amazon's official documentation
Solution that didn't work #2
Create private domain and route it to network load balancer DNS - as i mentioned above api gateway expect public certificate but also it cannot get any unknown domain name like: "application.local" etc..
Solution that didn't work #3
Route to your network load balancer https url - this cannot be done because your network load balancer DNS is an Amazon's DNS and network load balancer don't have this domain certificate and therefore api gateway cannot invoke this request to an not secured connection.
Solution that didn't work #4
we have a domain and certificate for our api gateway, why not to use this? - lets assume that we have a domain and certificate, api.example.com, we cannot setup a new private hosted zone with the same name api.example.com because it is already in use for the record to point to the api gateway custom domain name, and we must have a private hosted zone so that the VPC link knows where to route to.
This is how we can solve it?
Let's assume you have rest api gateway and in your VPC you have network load balancer for your application and you're using VPC link to connect to your application.
the api gateway have a domain name for example: api.example.com and certificate for this domain, this is how you solve it:
We are creating new public certificate because api gateway demands only public certificate as i mentioned before, for this we are creating also a new public hosted zone that we can validate the certificate.
We are creating a private hosted zone with the same name as the public hosted zone and now we have a public certificate for our private hosted zone, now we can attach this certificate to our network load balancer and create a record that our api gateway can connect in https to our network load balancer.
Tutorial:
- Create public route 53 with this name for example: app.example.com
- Create NS record in example.com to your new subdomain app.example.com - with NS from app.example.com
- Create certificate in certificate manager for this FQDN app.example.com and *.app.example.com and pass the validation process using route 53 records
- Create private route 53 hosted zone with the same domain app.example.com
- Create a record for you application network load balancer in the private hosted zone for example - application.app.example.com
- Add the public certificate we created in section 3. to your network load balancer.
- Change your api gateway proxy integration url to your newly created a record - https://application.app.example.com/{proxy}, and don't forget to deploy this api.
And now you can remove the http port 80 listener from your application load balancer, and your working with https from your api gateway to your application load balancer.
And here it is in CloudFormation Template:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
all resources for creating your proxy integration using https
Parameters:
SubnetName:
Type: String
Description: subnet name
TargetGroupServiceArn:
Type: String
Description: target group service arn
ServiceName:
Type: String
Description: eks/ecs service name
DomainName:
Type: String
Default: example.com
Description: youre domain name
PrivateSubdomainName:
Type: String
Default: app
Description: subdomain for your vpc resources
PublicSubdomainName:
Type: String
Default: api
Description: subdomain for your api gateway
VPC:
Type: String
Description: vpc id
StageName:
Type: String
Default: v1
Description: api gateway stage name
Resources:
#your public domain
PublicDomainHostedZone:
Type: AWS::Route53::HostedZone
Properties:
HostedZoneConfig:
Comment: 'public hosted zone'
Name: !Ref DomainName
PublicDomainCertificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref DomainName
ValidationMethod: DNS
SubjectAlternativeNames:
- !Join ['.',['*', !Ref DomainName]]
DomainValidationOptions:
- DomainName: !Ref DomainName
HostedZoneId: !Ref PublicDomainHostedZone
#the public domain for creating certificate
PublicApplicationDomainHostedZone:
Type: AWS::Route53::HostedZone
Properties:
HostedZoneConfig:
Comment: 'public application hosted zone'
Name: !Join ['.',[ !Ref PrivateSubdomainName, !Ref DomainName]]
PublicApplicationNSHostedZoneRecordSet:
Type: 'AWS::Route53::RecordSet'
Properties:
HostedZoneId: !Ref PublicDomainHostedZone
Name: !Join ['.',[ !Ref PrivateSubdomainName, !Ref DomainName]]
Type: NS
TTL: '900'
ResourceRecords: !GetAtt PublicApplicationDomainHostedZone.NameServers
PublicApplicationCertificate:
Type: AWS::CertificateManager::Certificate
DependsOn: PublicApplicationNSHostedZoneRecordSet
Properties:
DomainName: !Join ['.',[ !Ref PrivateSubdomainName, !Ref DomainName]]
ValidationMethod: DNS
SubjectAlternativeNames:
- !Join ['.',['*', !Ref PrivateSubdomainName, !Ref DomainName]]
DomainValidationOptions:
- DomainName: !Join ['.',[ !Ref PrivateSubdomainName, !Ref DomainName]]
HostedZoneId: !Ref PublicApplicationDomainHostedZone
# private hosted zone for api gateway --> network load balancer
PrivateApplicationDomainHostedZone:
Type: AWS::Route53::HostedZone
Properties:
HostedZoneConfig:
Comment: 'private application hosted zone'
Name: !Join ['.',[ !Ref PrivateSubdomainName, !Ref DomainName]]
VPCs:
- VPCId: !Ref VPC
VPCRegion : !Ref 'AWS::Region'
# network load balancer for your application
PrivateLoadBalancer:
Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
Properties:
Scheme: internal
Subnets:
- !Ref SubnetName
Type: network
SecuredPrivateLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref TargetGroupServiceArn
LoadBalancerArn: !Ref PrivateLoadBalancer
Port: 443
Protocol: TLS
SslPolicy: 'ELBSecurityPolicy-TLS13-1-2-2021-06'
Certificates:
- CertificateArn: !Ref PublicApplicationCertificate
LoadBalancerDNSRecordSet:
Type: AWS::Route53::RecordSetGroup
Properties:
HostedZoneId: !Ref PrivateApplicationDomainHostedZone
Comment: !Sub DNS record for the ${ServiceName} service
RecordSets:
- Name: !Join ['.',[!Ref ServiceName, !Ref PrivateSubdomainName, !Ref DomainName]]
Type: A
AliasTarget:
EvaluateTargetHealth: false
HostedZoneId: !GetAtt PrivateLoadBalancer.CanonicalHostedZoneID
DNSName: !GetAtt PrivateLoadBalancer.DNSName
#api gateway public domain name and certificate
ApiGatewayDomainName:
Type: AWS::ApiGateway::DomainName
Properties:
RegionalCertificateArn: !Ref PublicDomainCertificate
DomainName: !Join ['.',[!Ref PublicSubdomainName, !Ref DomainName]]
SecurityPolicy: TLS_1_2
EndpointConfiguration:
Types:
- 'REGIONAL'
ApiGatewayDomainRoute53RecordSet:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref PublicDomainHostedZone
Comment: record for api gateway public domain
Name: !Join ['.',[!Ref PublicSubdomainName, !Ref DomainName]]
Type: A
AliasTarget:
DNSName: !GetAtt ApiGatewayDomainName.RegionalDomainName
HostedZoneId: !GetAtt ApiGatewayDomainName.RegionalHostedZoneId
# api gateway for your application
RestApiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub ${ServiceName}-apigw
Description: !Sub Api Gateway for ${ServiceName}
EndpointConfiguration:
Types: [EDGE]
ApiGatewayVpcLink:
Type: AWS::ApiGateway::VpcLink
Properties:
Description: !Sub vpc link for ${ServiceName}
Name: !Sub ${ServiceName}-private-link
TargetArns: [!Ref PrivateLoadBalancer]
ApiGatewayProxyResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref RestApiGateway
ParentId: !GetAtt RestApiGateway.RootResourceId
PathPart: '{proxy+}'
ApiGatewayProxyMethod:
Type: AWS::ApiGateway::Method
DependsOn: LoadBalancerDNSRecordSet
Properties:
RestApiId: !Ref RestApiGateway
ResourceId: !Ref ApiGatewayProxyResource
HttpMethod: ANY
RequestParameters:
method.request.path.proxy: true
Integration:
ConnectionType: VPC_LINK
Type: HTTP_PROXY
IntegrationHttpMethod: ANY
ConnectionId: !Ref ApiGatewayVpcLink
Uri: !Join ['',['https://', !Ref ServiceName, '.', !Ref PrivateSubdomainName, '.', !Ref DomainName , '/{proxy}']]
RequestParameters:
integration.request.path.proxy: 'method.request.path.proxy'
ApiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn: ApiGatewayProxyMethod
Properties:
RestApiId: !Ref RestApiGateway
Description: !Sub deployment for {ServiceName} api gateway
StageName: !Ref StageName
StageDescription:
TracingEnabled: true
LoggingLevel: INFO
MetricsEnabled: true
DataTraceEnabled: true
ApiGatewayPublicDomainMapping:
Type: AWS::ApiGateway::BasePathMapping
DependsOn: ApiGatewayDeployment
Properties:
BasePath: !Ref ServiceName
DomainName: !Ref ApiGatewayDomainName
RestApiId: !Ref RestApiGateway
Stage: !Ref StageName
Top comments (2)
I stumbled upon your blog post and I must say it's been incredibly helpful! Your step-by-step tutorial on transitioning from http proxy integration to https proxy integration for VPC services is a game-changer.
I've been working with a REST API Gateway in my application, exposing EKS/ECS services, and your insights have made the transition seamless. The clarification on the necessity to switch from http to https proxy integration and the detailed guide on implementing it with a public domain have been a lifesaver.
Thanks a ton for sharing your expertise! Your blog has become my go-to resource for AWS and DevOps insights.
Great post, welcome!