

# Managing your own Amazon VPC endpoints on Amazon MWAA
<a name="vpc-endpoint-management"></a>

Amazon MWAA uses Amazon VPC endpoints to integrate with various AWS services necessary to set up an Apache Airflow environment. Managing your own endpoints has two primary use cases:

1. It means you can create Apache Airflow environments in a shared Amazon VPC when you use an [AWS Organizations](https://aws.amazon.com/organizations/) to manage multiple AWS accounts and share resources.

1. It lets you use more restrictive access policies by narrowing down your permissions to the specific resources that use your endpoints.

If you choose to manage your own VPC endpoints, you're responsible for creating your own endpoints for the environment RDS for PostgreSQL database and for the environment webserver.

For more information about how Amazon MWAA deploys Apache Airflow in the cloud, refer to the [Amazon MWAA architecture diagram](what-is-mwaa.md#architecture-mwaa).

**Important**  
Amazon MWAA does not validate the IP address type (`AddressType`) selection for customer-managed endpoints, so make sure you correctly specify `AddressType` (valid options are IPv4 or IPv6).



## Creating an environment in a shared Amazon VPC
<a name="configure-shared-vpc"></a>

If you use [AWS Organizations](https://aws.amazon.com/organizations/) to manage multiple AWS accounts that share resources, you can use customer-managed VPC endpoints with Amazon MWAA to share environment resources with another account in your organization.

When you configure shared VPC access, the account that owns the main Amazon VPC (*owner*) shares the two private subnets required by Amazon MWAA with other accounts (*participants*) that belong to the same organization. Participant accounts that share those subnets can view, create, modify, and delete environments in the shared Amazon VPC.

Assume you have an account, `Owner`, which acts as the `Root` account in the organization and owns the Amazon VPC resources, and a participant account, `Participant`, a member of the same organization. When `Participant` creates a new Amazon MWAA in Amazon VPC it shares with `Owner`, Amazon MWAA will first create the service VPC resources, then enter a [`PENDING`](https://docs.aws.amazon.com/mwaa/latest/API/API_Environment.html#mwaa-Type-Environment-Status) state for up to 72 hours.

After the environment status changes from `CREATING` to `PENDING`, a principal acting on behalf of `Owner` creates the required endpoints. To do this, Amazon MWAA lists the database and webserver endpoint in the Amazon MWAA console. You can also call the [`GetEnvironment`]() API action to get the service endpoints.

**Note**  
If the Amazon VPC you use to share resources is a private Amazon VPC, you must still complete the steps described in [Managing access to service-specific Amazon VPC endpoints on Amazon MWAA](vpc-vpe-access.md). The topic covers setting up a different set of Amazon VPC endpoints related to other AWS services that AWS integrates with, such as Amazon ECR, Amazon ECS, and Amazon SQS. These services are essential in operating, and managing, your Apache Airflow environment in the cloud.

### Prerequisites
<a name="configure-shared-vpc-prerequisites"></a>

Before you create an Amazon MWAA environment in a shared VPC, you need the following resources:
+ An AWS account, `Owner` to be used as the account that owns the Amazon VPC.
+ An [AWS Organizations](https://aws.amazon.com/organizations/) organization unit, `MyOrganization` created as a *root*.
+ A second AWS account, `Participant`, under `MyOrganization` to serve the participant account that creates the new environment.

In addition, we recommend that you familiarize yourself with the [responsibilities and permissions for owners and participants](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-sharing.html#vpc-share-limitations) when sharing resources in Amazon VPC.

### Create the Amazon VPC
<a name="configure-shared-vpc-create-vpc"></a>

First, create a new Amazon VPC that the owner and participant accounts will share:

1. Sign in to the console using `Owner`, then, open the CloudFormation console. Use the following template to create a stack. This stack provisions a number of networking resources including a Amazon VPC, and the subnets that the two accounts will share in this scenario.

   ```
   AWSTemplateFormatVersion: "2010-09-09"
   Description: This template deploys a VPC, with a pair of public and private subnets spread across two Availability Zones. It deploys an internet gateway, with a default route on the public subnets. It deploys a pair of NAT gateways (one in each AZ), and default routes for them in the private subnets.
   Parameters:
       EnvironmentName:
         Description: An environment name that is prefixed to resource names
         Type: String
         Default: mwaa-
       VpcCIDR:
         Description: Please enter the IP range (CIDR notation) for this VPC
         Type: String
         Default: 10.192.0.0/16
       PublicSubnet1CIDR:
         Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
         Type: String
         Default: 10.192.10.0/24
       PublicSubnet2CIDR:
         Description: Please enter the IP range (CIDR notation) for the public subnet in the second Availability Zone
         Type: String
         Default: 10.192.11.0/24
       PrivateSubnet1CIDR:
         Description: Please enter the IP range (CIDR notation) for the private subnet in the first Availability Zone
         Type: String
         Default: 10.192.20.0/24
       PrivateSubnet2CIDR:
         Description: Please enter the IP range (CIDR notation) for the private subnet in the second Availability Zone
         Type: String
         Default: 10.192.21.0/24
   Resources:
       VPC:
         Type: 'AWS::EC2::VPC'
         Properties:
           CidrBlock: !Ref VpcCIDR
           EnableDnsSupport: true
           EnableDnsHostnames: true
           Tags:
             - Key: Name
               Value: !Ref EnvironmentName
     
       InternetGateway:
         Type: 'AWS::EC2::InternetGateway'
         Properties:
           Tags:
             - Key: Name
               Value: !Ref EnvironmentName
     
       InternetGatewayAttachment:
         Type: 'AWS::EC2::VPCGatewayAttachment'
         Properties:
           InternetGatewayId: !Ref InternetGateway
           VpcId: !Ref VPC
     
       PublicSubnet1:
         Type: 'AWS::EC2::Subnet'
         Properties:
           VpcId: !Ref VPC
           AvailabilityZone: !Select
             - 0
             - !GetAZs ''
           CidrBlock: !Ref PublicSubnet1CIDR
           MapPublicIpOnLaunch: true
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Public Subnet (AZ1)'
     
       PublicSubnet2:
         Type: 'AWS::EC2::Subnet'
         Properties:
           VpcId: !Ref VPC
           AvailabilityZone: !Select
             - 1
             - !GetAZs ''
           CidrBlock: !Ref PublicSubnet2CIDR
           MapPublicIpOnLaunch: true
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Public Subnet (AZ2)'
     
       PrivateSubnet1:
         Type: 'AWS::EC2::Subnet'
         Properties:
           VpcId: !Ref VPC
           AvailabilityZone: !Select
             - 0
             - !GetAZs ''
           CidrBlock: !Ref PrivateSubnet1CIDR
           MapPublicIpOnLaunch: false
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Private Subnet (AZ1)'
     
       PrivateSubnet2:
         Type: 'AWS::EC2::Subnet'
         Properties:
           VpcId: !Ref VPC
           AvailabilityZone: !Select
             - 1
             - !GetAZs ''
           CidrBlock: !Ref PrivateSubnet2CIDR
           MapPublicIpOnLaunch: false
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Private Subnet (AZ2)'
     
       NatGateway1EIP:
         Type: 'AWS::EC2::EIP'
         DependsOn: InternetGatewayAttachment
         Properties:
           Domain: vpc
     
       NatGateway2EIP:
         Type: 'AWS::EC2::EIP'
         DependsOn: InternetGatewayAttachment
         Properties:
           Domain: vpc
     
       NatGateway1:
         Type: 'AWS::EC2::NatGateway'
         Properties:
           AllocationId: !GetAtt NatGateway1EIP.AllocationId
           SubnetId: !Ref PublicSubnet1
     
       NatGateway2:
         Type: 'AWS::EC2::NatGateway'
         Properties:
           AllocationId: !GetAtt NatGateway2EIP.AllocationId
           SubnetId: !Ref PublicSubnet2
     
       PublicRouteTable:
         Type: 'AWS::EC2::RouteTable'
         Properties:
           VpcId: !Ref VPC
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Public Routes'
     
       DefaultPublicRoute:
         Type: 'AWS::EC2::Route'
         DependsOn: InternetGatewayAttachment
         Properties:
           RouteTableId: !Ref PublicRouteTable
           DestinationCidrBlock: 0.0.0.0/0
           GatewayId: !Ref InternetGateway
     
       PublicSubnet1RouteTableAssociation:
         Type: 'AWS::EC2::SubnetRouteTableAssociation'
         Properties:
           RouteTableId: !Ref PublicRouteTable
           SubnetId: !Ref PublicSubnet1
     
       PublicSubnet2RouteTableAssociation:
         Type: 'AWS::EC2::SubnetRouteTableAssociation'
         Properties:
           RouteTableId: !Ref PublicRouteTable
           SubnetId: !Ref PublicSubnet2
     
       PrivateRouteTable1:
         Type: 'AWS::EC2::RouteTable'
         Properties:
           VpcId: !Ref VPC
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Private Routes (AZ1)'
     
       DefaultPrivateRoute1:
         Type: 'AWS::EC2::Route'
         Properties:
           RouteTableId: !Ref PrivateRouteTable1
           DestinationCidrBlock: 0.0.0.0/0
           NatGatewayId: !Ref NatGateway1
     
       PrivateSubnet1RouteTableAssociation:
         Type: 'AWS::EC2::SubnetRouteTableAssociation'
         Properties:
           RouteTableId: !Ref PrivateRouteTable1
           SubnetId: !Ref PrivateSubnet1
     
       PrivateRouteTable2:
         Type: 'AWS::EC2::RouteTable'
         Properties:
           VpcId: !Ref VPC
           Tags:
             - Key: Name
               Value: !Sub '${EnvironmentName} Private Routes (AZ2)'
     
       DefaultPrivateRoute2:
         Type: 'AWS::EC2::Route'
         Properties:
           RouteTableId: !Ref PrivateRouteTable2
           DestinationCidrBlock: 0.0.0.0/0
           NatGatewayId: !Ref NatGateway2
     
       PrivateSubnet2RouteTableAssociation:
         Type: 'AWS::EC2::SubnetRouteTableAssociation'
         Properties:
           RouteTableId: !Ref PrivateRouteTable2
           SubnetId: !Ref PrivateSubnet2
     
       SecurityGroup:
         Type: 'AWS::EC2::SecurityGroup'
         Properties:
           GroupName: mwaa-security-group
           GroupDescription: Security group with a self-referencing inbound rule.
           VpcId: !Ref VPC
     
       SecurityGroupIngress:
         Type: 'AWS::EC2::SecurityGroupIngress'
         Properties:
           GroupId: !Ref SecurityGroup
           IpProtocol: '-1'
           SourceSecurityGroupId: !Ref SecurityGroup
   Outputs:
       VPC:
         Description: A reference to the created VPC
         Value: !Ref VPC
       PublicSubnets:
         Description: A list of the public subnets
         Value: !Join
           - ','
           - - !Ref PublicSubnet1
             - !Ref PublicSubnet2
       PrivateSubnets:
         Description: A list of the private subnets
         Value: !Join
           - ','
           - - !Ref PrivateSubnet1
             - !Ref PrivateSubnet2
       PublicSubnet1:
         Description: A reference to the public subnet in the 1st Availability Zone
         Value: !Ref PublicSubnet1
       PublicSubnet2:
         Description: A reference to the public subnet in the 2nd Availability Zone
         Value: !Ref PublicSubnet2
       PrivateSubnet1:
         Description: A reference to the private subnet in the 1st Availability Zone
         Value: !Ref PrivateSubnet1
       PrivateSubnet2:
         Description: A reference to the private subnet in the 2nd Availability Zone
         Value: !Ref PrivateSubnet2
       SecurityGroupIngress:
         Description: Security group with self-referencing inbound rule
         Value: !Ref SecurityGroupIngress
   ```

1. After the new Amazon VPC resources have been provisioned, navigate to the AWS Resource Access Manager console, then choose **Create resource share**.

1. Choose the subnets you created in the first step from the list of available subnets you can share with `Participant`.

### Create the environment
<a name="configure-shared-vpc-create-mwaa"></a>

Complete the following steps to create an Amazon MWAA environment with customer-managed Amazon VPC endpoints.

1. Sign in using `Participant`, and open the Amazon MWAA console. Complete **Step one: Specify details** to specify an Amazon S3 bucket, a DAG folder, and dependencies for your new environment. For more information, refer to [getting started](create-environment.md#create-environment-start-details).

1. On the **Configure advanced settings** page, under **Networking**, choose the subnets from the shared Amazon VPC.

1. Under **Endpoint management** choose **CUSTOMER** from the dropdown list.

1. Keep the default for the remaining options on the page, then, choose **Create environment** on the **Review and create** page.

The environment begins in a `CREATING` state, then changes to `PENDING`. When the environment is `PENDING`, write down the **Database endpoint service name** and **webserver endpoint service name** (if you set up a private webserver) using the console.

When you create a new environment using the Amazon MWAA console. Amazon MWAA creates a new security group with the required inbound and outbound rules. Write down the security group ID.

In the next section, `Owner` will use the service endpoints and the security group ID to create new Amazon VPC endpoints in the shared Amazon VPC.

### Create the Amazon VPC endpoints
<a name="configure-shared-vpc-create-endpoints"></a>

Complete the following steps to create the required Amazon VPC endpoints for your environment.

1. Sign in to the AWS Management Console using `Owner`, the open [https://console.aws.amazon.com/vpc/](https://console.aws.amazon.com/vpc/).

1. Choose **Security groups** from the left navigation panel, then create a new security group in the shared Amazon VPC using the following inbound, and outbound, rules:    
[See the AWS documentation website for more details](http://docs.aws.amazon.com/mwaa/latest/userguide/vpc-endpoint-management.html)
**Warning**  
The `Owner` account must set up a security group in the `Owner` account to allow traffic from the new environment to the shared Amazon VPC. You can do this by creating a new security group in `Owner`, or editing an existing one.

1. Choose **Endpoints**, then choose **Create endpoint**. Under **Endpoint settings**, select **Endpoint services that use NLBs and GWLBs**. In the **Service name** field, enter the database endpoint service name you noted from the Amazon MWAA console, then choose **Verify service**. Choose the shared Amazon VPC, select the subnets you used for the environment, and select the security group you created in the previous step. Choose **Create endpoint**. If your environment uses a private webserver, repeat these steps using the webserver endpoint service name.

**Note**  
If you create VPC endpoints using infrastructure as code, set the endpoint type to `Interface` explicitly. The default endpoint type in both AWS CloudFormation and Terraform is `Gateway`, which is not compatible with Amazon MWAA endpoint services.

If successful, the environment will change from `PENDING` back to `CREATING`, then finally to `AVAILABLE`. When it is `AVAILABLE`, you can sign in to the Apache Airflow console.

### Shared Amazon VPC Troubleshooting
<a name="configure-shared-vpc-troubleshooting"></a>

Use the following reference to resolve issues you encounter when creating environments in a shared Amazon VPC.

**Environment in `CREATE_FAILED` after `PENDING` status**  
+ Verify that `Owner` is sharing the subnets with `Participant` using [AWS Resource Access Manager](https://docs.aws.amazon.com/ram/latest/userguide/what-is.html).
+ Verify that the Amazon VPC endpoints for the database and webserver are created in the same subnets associated with the environment.
+ Verify that the security group used with your endpoints allows traffic from the security groups used for the environment. The `Owner` account creates rules that reference the security group in `Participant` as `{{123456789012}}/{{security-group-id}}`:.    
[See the AWS documentation website for more details](http://docs.aws.amazon.com/mwaa/latest/userguide/vpc-endpoint-management.html)

  For more information, refer to [Responsibilities and permissions for owners and participants](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-sharing.html#vpc-share-limitations)

**Environment stuck in `PENDING` status**  
Verify each VPC endpoint status to ensure it is `Available`. If you configure an environment with a private webserver, you must also create an endpoint for the webserver. If the environment is stuck in `PENDING`, this might indicate that the private webserver endpoint is missing.

**Received `The Vpc Endpoint Service '{{vpce-service-name}}' does not exist` error**  
If you refer to the following error, verify that the account creating the endpoints in the `Owner` account that owns the shared VPC:  

```
ClientError: An error occurred (InvalidServiceName) when calling the CreateVpcEndpoint operation: 
							
The Vpc Endpoint Service '{{vpce-service-name}}' does not exist
```