private apigw integration with external clients

0

Hi everyone,

The AWS console offers the choice to create a REST API GW or REST API GW PRIVATE,

If I choose to create REST API GW PRIVATE, how can my API GW be reachable from outside (by Salesforce SaaS client for example)?

is it by giving to the client consumer the DNS name of my VPC interface endpoint?

or by giving them the DNS name of my API GW in this format : https://[API-ID]-[VPC-ENDPOINT-ID].execute.api.region.amazon.com/stage

if I choose to create REST API GW PRIVATE instead of REST API GW from the console UI, how can I make the client consumer consume the rest API exposed by my REST API GW PRIVATE?

my VPC is a private-only VPC

Thank you for your guidance!

3 Answers
0

Hi,

you can use VPC endpoints to do that, i.e., make http(s) endpoints private to an account accessible from another

This is the server side (extract from 1 of my own CFN templates used in various projects)

You create a VPCEndpoint service pointing to load balancers finally pointing to the gtw api

AllowedPrincipals: !Split [ ",", !Ref AllowedVpcEndpointPrincipals ] points to a CFN parameter defining target account(s)

VpcEndpointService:
    Type: AWS::EC2::VPCEndpointService
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      AcceptanceRequired: false
      NetworkLoadBalancerArns:
        - !Ref ElasticLoadBalancerNetwork

  VpcEndpointServicePermissions:
    Type: AWS::EC2::VPCEndpointServicePermissions
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      AllowedPrincipals: !Split [ ",", !Ref AllowedVpcEndpointPrincipals ]
      ServiceId: !GetAtt VpcEndpointService.ServiceId

  ElasticLoadBalancerNetwork:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      Name: !Join
        - '-'
        - - !GetAtt Name.Value
          - 'network'
      Type: 'network'
      Scheme: 'internal'
      Subnets:
        - !Ref VpcSubnet1
        - !Ref VpcSubnet2
      LoadBalancerAttributes:
        - Key: 'load_balancing.cross_zone.enabled'
          Value: true

  ElasticListenerSsh:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      DefaultActions:
        - Type: 'forward'
          TargetGroupArn: !Ref ElasticTargetGroupSsh
      LoadBalancerArn: !Ref ElasticLoadBalancerNetwork
      Port: !Ref SshPort
      Protocol: 'TCP'

  ElasticListenerBaaRestPort1:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      DefaultActions:
        - Type: 'forward'
          TargetGroupArn: !Ref ElasticTargetGroupBaaRestPort1
      LoadBalancerArn: !Ref ElasticLoadBalancerNetwork
      Port: !Ref BaaRestPort1
      Protocol: 'TCP'

  ElasticListenerBaaRestPort2:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      DefaultActions:
        - Type: 'forward'
          TargetGroupArn: !Ref ElasticTargetGroupBaaRestPort2
      LoadBalancerArn: !Ref ElasticLoadBalancerNetwork
      Port: !Ref BaaRestPort2
      Protocol: 'TCP'

  ElasticTargetGroupSsh:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      TargetType: 'instance'
      Name: !Join
        - '-'
        - - !GetAtt Name.Value
          - 'ssh'
      Port: !Ref SshPort
      Protocol: 'TCP'
      TargetGroupAttributes:
        - Key: 'deregistration_delay.timeout_seconds'
          Value: '20'
      Targets:
        - Id: !Ref BaaInstance1
          Port: !Ref SshPort
        - Id: !Ref BaaInstance2
          Port: !Ref SshPort
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 2
      HealthCheckProtocol: 'HTTP'
      HealthCheckPort: !Ref BaaRestPort1
      HealthCheckPath: '/bac/api/services/rest/bluesamserver/serverIsUp'
      VpcId: !Ref Vpc

  ElasticTargetGroupBaaRestPort1:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      TargetType: 'instance'
      Name: !Join
        - '-'
        - - !GetAtt Name.Value
          - 'baa-rest1'
      Port: !Ref BaaRestPort1
      Protocol: 'TCP'
      TargetGroupAttributes:
        - Key: 'deregistration_delay.timeout_seconds'
          Value: '20'
      Targets:
        - Id: !Ref BaaInstance1
          Port: !Ref BaaRestPort1
        - Id: !Ref BaaInstance2
          Port: !Ref BaaRestPort1
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 2
      HealthCheckProtocol: 'HTTP'
      HealthCheckPort: !Ref BaaRestPort1
      HealthCheckPath: '/bac/api/services/rest/serverIsUp'
      VpcId: !Ref Vpc

  ElasticTargetGroupBaaRestPort2:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Condition: WithVpcEndpointCondition
    DeletionPolicy: Delete
    Properties:
      TargetType: 'instance'
      Name: !Join
        - '-'
        - - !GetAtt Name.Value
          - 'baa-rest2'
      Port: !Ref BaaRestPort2
      Protocol: 'TCP'
      TargetGroupAttributes:
        - Key: 'deregistration_delay.timeout_seconds'
          Value: '20'
      Targets:
        - Id: !Ref BaaInstance1
          Port: !Ref BaaRestPort2
        - Id: !Ref BaaInstance2
          Port: !Ref BaaRestPort2
      HealthCheckEnabled: true
      HealthCheckIntervalSeconds: 30
      HealthCheckTimeoutSeconds: 10
      HealthyThresholdCount: 2
      HealthCheckProtocol: 'HTTP'
      HealthCheckPort: !Ref BaaRestPort1
      HealthCheckPath: '/bac/api/services/rest/serverIsUp'
      VpcId: !Ref Vpc

Definitions of principals:

 AllowedVpcEndpointPrincipals:
    Description: 'comma-separated list of IAM users, IAM roles, or AWS accounts'
    Default: 'arn:aws:iam::account1-id:root',arn:aws:iam::account2-id:root'
    Type: String

This is the client side:

VpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      SecurityGroupIds:
        - !GetAtt VpcEndpointSecGroup.GroupId
      ServiceName: !Ref VpcEndpointServiceName
      SubnetIds:
        - !Ref VpcSubnet1
        - !Ref VpcSubnet2
      VpcEndpointType: 'Interface'
      VpcId: !Ref Vpc
  
  # (can be tightened if needed)

  VpcEndpointSecGroup:
    Type: AWS::EC2::SecurityGroup
    DeletionPolicy: Delete
    Properties:
      VpcId: !Ref Vpc
      GroupDescription: 'security group for vpc endpoint'
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: '0.0.0.0/0'
          FromPort: 0
          ToPort: 65535
          Description: 'Allow any outbound access'
      SecurityGroupIngress:
        - IpProtocol: -1
          CidrIp: '0.0.0.0/0'
          FromPort: 0
          ToPort: 65535
          Description: 'Allow any inbound access'

Hope that you can convert that to your own params

Best

Didier

profile pictureAWS
EXPERT
answered 8 months ago
profile pictureAWS
EXPERT
reviewed 8 months ago
0

Hi,

As described on the AWS documentation, you must use an interface VPC endpoint to access the API.

Using Amazon API Gateway, you can create private REST APIs that can only be accessed from your virtual private cloud in Amazon VPC by using an interface VPC endpoint. This is an endpoint network interface that you create in your VPC.

On the other hand, how to access depend upon whether or not you have enabled private DNS on the VPC endpoint, take a look at the next AWS documentation page.

For example, if you've enabled private DNS, you can access your private API using the private DNS names as follows:

  • curl -X GET https://{restapi-id}.execute-api.{region}.amazonaws.com/{stage}

If not, you could use de VPC endpoint specific DNS hostnames.

  • curl -v https://{public-dns-hostname}.execute-api.{region}.vpce.amazonaws.com/test -H'x-apigw-api-id:{api-id}'
profile picture
EXPERT
answered 8 months ago
0

When you create a Private REST API, it can only be consumed from within a VPC. So, either you create some proxy in the VPC that can be reached from the internet, or, you create a Public API (Regional or Edge optimized).

If you want your API to be accessed by external users, it should not be private.

profile pictureAWS
EXPERT
Uri
answered 8 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions