VPC ENDPOINTS AND AWS PRIVATELINK
Tags: aws, network, loadbalance, privatelink
Published: 2022-04-03 02:48:28

## VPC ENDPOINTS AND AWS PRIVATELINK
 
A VPC endpoint allows you to connect your VPC to AWS services and VPC endpoint services privately. Resources within a VPC do not require public IP addresses to communicate with resources outside the VPC when using VPC endpoints. Traffic between an Amazon Virtual Private Cloud (Amazon VPC) and a service is not routed outside of the Amazon network.
 
VPC endpoints are first and foremost a security product, then a connectivity product. VPC endpoints prevent traffic between your VPC and other services from leaving the Amazon network.
 
You may have stringent compliance requirements that prevent connectivity between a VPC and a service endpoint that is accessible to the public. VPC endpoints, in this case, provide a way to access AWS services from your VPCs that would otherwise be unavailable.
 
An internet gateway, virtual private gateway, network address translation (NAT) device, virtual private network (VPN) connection, or Direct Connect connection are not required for a VPC endpoint. To connect to services presented through a VPC endpoint, instances in your VPC do not need a public IP address.
 
 
The following are the different types of VPC endpoints. 
 
**Gateway vpc endpoints** 
 
A gateway VPC endpoint uses a prefix list to target specific IP routes in a VPC route table. This is used for Amazon DynamoDB or Amazon Simple Storage Service  (S3) traffic. 
 
To communicate with VPC endpoints, instances in a VPC do not need public IP addresses. This is because interface endpoints within the consumer VPC use local IP addresses. Gateway endpoints are destinations accessible from within a VPC via prefix-lists in the VPC's route table.
 
 
**Interface endpoints** 

An interface endpoint, powered by AWS PrivateLink, is an elastic network interface with a private IP address from your subnet's IP address range. It acts as a gateway for traffic headed to a supported AWS service or a VPC endpoint service.
 
**Gateway loadbalancer endpoint** 
 
A Gateway Load Balancer endpoint is an elastic network interface with a private IP address from your subnet's IP address range. This type of endpoint acts as an entry point for traffic to be intercepted and routed to a service that you've configured using Gateway Load Balancers.
 
**AWS PrivateLink** establishes a secure connection between your VPCs and AWS services. This AWS service ensures secure usage within the AWS network while avoiding traffic exposure to the public internet.
 
Prior to AWS PrivateLink, services within a single VPC were linked to other VPCs in two ways:
 
 1) Public IP addresses using the internet gateway of the VPC
 2) Private IP addresses using VPC peering
 
With AWS PrivateLink, services establish a Transmission Control Protocol (TCP) connection between the service provider’s VPC and the service consumer’s VPC. This provides a secure and scalable solution.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wwgahythumujs6gyekb7.png)

Following example shows how to create VPC Endpoint Service using Gateway Load Balancer ARN using AWS CloudFormation. It also creates custom resource to output the service name.

```
AWSTemplateFormatVersion: "2010-09-09"

Description: This template creates Amazon VPC Endpoint Service.

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Endpoint Service Configuration
        Parameters:
          - ElbArn
          - ConnectionAcceptance
      - Label:
          default: Endpoint Service Permissions
        Parameters:
          - AwsAccountToWhitelist
    ParameterLabels:
      ElbArn:
        default: >-
          ELB Amazon Resource Names (ARNs)for your service.
      ConnectionAcceptance:
        default: >-
          Indicate whether requests from service consumers to create an
          endpoint to your service must be accepted.
      AwsAccountToWhitelist:
        default: >-
          The Amazon Resource Names (ARN) of one or more principals (IAM users,
          IAM roles, and AWS accounts). Permissions are granted to the
          principals in this list.
Parameters:
  ElbArn:
    Description: >-
      Enter Elastic load balancer ARN for your service. Network and Gateway
      Load Balancer are the two supported types.
    Type: String
    ConstraintDescription: Must be a valid ELB ARN
  ConnectionAcceptance:
    Description: >-
      Acceptance required for endpoint connection or not. Select true or
      false to either acceptance required or acceptance not required
      default is set to false: acceptance not required
    Default: "false"
    AllowedValues: ["true", "false"]
    Type: String
    ConstraintDescription: Must be true or false
  AwsAccountToWhitelist:
    Description: >-
      Enter ARN of one or more prinicapls: IAM user, IAM roles and AWS accounts.
      To grant permissions to all principals, specify an asterisk (*).
    Type: String
    ConstraintDescription: Must be a valid AWS ARN of one or more principals

Resources:
  VpcEndpointService:
    Type: AWS::EC2::VPCEndpointService
    Properties:
      GatewayLoadBalancerArns:
        - !Ref ElbArn
      AcceptanceRequired: !Ref ConnectionAcceptance

  VpcEndpointServicePermissions:
    Type: AWS::EC2::VPCEndpointServicePermissions
    Properties:
      AllowedPrincipals:
        - !Ref AwsAccountToWhitelist
      ServiceId: !Ref VpcEndpointService

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - ec2:DescribeVpcEndpointServiceConfigurations
                  - ec2:DescribeVpcEndpointServicePermissions
                  - ec2:DescribeVpcEndpointServices
                Resource: "*"

  DescribeVpceService:
    Type: AWS::Lambda::Function
    Properties:
      Handler: "index.handler"
      Role: !GetAtt
        - LambdaExecutionRole
        - Arn
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          def handler(event, context):
              logger = logging.getLogger()
              logger.setLevel(logging.INFO)
              responseData = {}
              responseStatus = cfnresponse.FAILED
              logger.info('Received event: {}'.format(json.dumps(event)))
              if event["RequestType"] == "Delete":
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
              if event["RequestType"] == "Create":
                  try:
                      VpceServiceId = event["ResourceProperties"]["Input"]
                  except Exception as e:
                      logger.info('VPC Endpoint Service Id retrival failure: {}'.format(e))
                  try:
                      ec2 = boto3.client('ec2')
                  except Exception as e:
                      logger.info('boto3.client failure: {}'.format(e))
                  try:
                      response = ec2.describe_vpc_endpoint_service_configurations(
                          Filters=[
                              {
                                  'Name': 'service-id',
                                  'Values': [VpceServiceId]
                              }
                          ]
                      )
                  except Exception as e:
                      logger.info('ec2.describe_vpc_endpoint_service_configurations failure: {}'.format(e))
                  ServiceName = response['ServiceConfigurations'][0]['ServiceName']
                  responseData['Data'] = ServiceName
                  responseStatus = cfnresponse.SUCCESS
                  cfnresponse.send(event, context, responseStatus, responseData)
      Runtime: python3.7
      Timeout: 30

  VpceServiceName:
    DependsOn: VpcEndpointService
    Type: Custom::DescribeVpcEndpointServiceConfigurations
    Properties:
      ServiceToken: !GetAtt DescribeVpceService.Arn
      Input: !Ref VpcEndpointService

Outputs:
  SecurityVpcEndpointServiceId:
    Description: Security VPC Endpoint Service ID
    Value: !Ref VpcEndpointService
  SecurityVpcEndpointServiceName:
    Description: Security VPC Endpoint Service Name. Required to create VPC endpoint
    Value: !GetAtt VpceServiceName.Data
```