DEV Community

Cover image for AWS Automatically Accept Transit Gateway Attachments for allowed CIDR and Account pairs
Jana Hockenberger
Jana Hockenberger

Posted on

AWS Automatically Accept Transit Gateway Attachments for allowed CIDR and Account pairs

This solution will provide an approach to automatically accept Transit Gateway attachments by checking a centrally managed list of allowed CIDR and AccountId value pairs when using a centralized Transit Gateway.

Prerequisite for this solution is the existence of a centralized Transit Gateway which is shared with all accounts via Resource Access Manager.

Problems when creating a Transit Gateway

When creating a Transit Gateway you are offered the option to AutoAcceptSharedAttachments which means that if any account that uses the centralized Transit Gateway creates an attachment, it is automatically accepted.
Which in turn means that if we do not activate this feature we would have to manually accept all created Transit Gateway attachments. Depending on the size of your environment this could lead to a great overhead wasting valuable time resources.

Also probably not all created Transit Gateway Attachments are wanted but just a defined list of CIDR Blocks and Account IDs should be allowed to communicate with all VPCs and with the On-Premise datacenter.

So what if we just want an AutoAccept for specific CIDR blocks we defined prior? Then this solution will help you!

Overview over the Solution

Image description

This solution uses a DynamoDB table to manage the list of allowed CIDR Blocks and Account Ids pairs. Using cidr_block as the primary key makes sure to not include the same CIDR Block multiple times in the Transit Gateway Attachments. As one account can include multiple VPCs with Transit Gateway attachments, setting it as the primary key wouldn't be suitable here.

The values of the DynamoDB Table are set in the code in a Custom Resource which is used to initialize the DynamoDB Table. The Custom Resource executes a Lambda function during deployment or when the stack changes and creates the values for the DynamoDB Table which are documented in the code.

Also in every account an EventBridge Rule gets created which sends an event to the default base as soon as it captures the CloudTrail event CreateTransitGatewayVpcAttachment. The default bus of the corresponding account sends the event to the account where the Transit Gateway is created and triggers an Eventbridge Rule there which executes a Lambda Function.
As well a cross-account Lambda Role gets created in every account to read-out the CIDR Block of the VPC mentioned in the event.

The Lambda function then checks if an entry for the provided CIDR Block and Account Id exists in the DynamoDB table and accepts the Attachment when a match is found.

Deployment Steps

The solutions consists of two stacks.

The tgw-attach-auto-accept-core.yaml file needs to be created in the Account where the Transit Gateway is located.
The following resources will be created in the first stack:

A DynamoDB Table for the entries of allowed CIDR Blocks and Account Ids. The CIDR Block functions as the primary key.

TGWAttachmentDynamoDB:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: 'TGWAttachmentAcceptedCIDR'
      AttributeDefinitions:
        - AttributeName: 'cidr_block'
          AttributeType: 'S'
        - AttributeName: 'account_id'
          AttributeType: 'S'
      KeySchema:
        - AttributeName: 'cidr_block'
          KeyType: 'HASH'  
        - AttributeName: 'account_id'
          KeyType: 'RANGE' 
      BillingMode: PAY_PER_REQUEST
Enter fullscreen mode Exit fullscreen mode

A Custom Resources to initialize the DynamoDB Table entries and set the values. Every time the list of values in the Custom Resource gets updated, the Lambda Function will be executed again to update the DynamoDB Table.

DynamoDBTableInitializer:
    Type: Custom::DynamoDBTableInitializer
    Properties: 
      ServiceToken: !GetAtt TableInitializerFunction.Arn
      TableName: !Ref TGWAttachmentDynamoDB
      TableItems:
        - cidr_block: "1.2.3.4/5"
          account_id: "123456789012"
        - cidr_block: "6.7.8.9/12"
          account_id: "234567890123"
        ### more entries can be added here

  TableInitializerFunction:
    Type: AWS::Lambda::Function
    Properties: 
      Code:
        ZipFile: |
          import json
          import boto3
          import cfnresponse

          def lambda_handler(event, context):
              try:
                  table_name = event['ResourceProperties']['TableName']
                  items = event['ResourceProperties']['TableItems']

                  dynamodb = boto3.resource('dynamodb')
                  table = dynamodb.Table(table_name)

                  for item in items:
                      table.put_item(Item=item)

                  response_data = {'Status': 'Success'}
                  cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
              except Exception as e:
                  response_data = {'Status': str(e)}
                  cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
      Handler: 'index.lambda_handler'
      Runtime: python3.11
      Role: !GetAtt TableInitializerFunctionRole.Arn
Enter fullscreen mode Exit fullscreen mode

An Eventbridge Rule which receives the "CreateTransitGatewayVpcAttachment" event from the default bus and triggers the Lambda function to check and accept the attachment.

CloudWatchRule:
    Type: "AWS::Events::Rule"
    Properties:
      Description: "Accepts the TGW Attachment and sets a Route in the Route Table to OnP-remise"
      State: ENABLED
      EventPattern: {
        "source": [
          "aws.ec2"
        ],
        "detail-type": [
          "AWS API Call via CloudTrail"
        ],
        "detail": {
          "eventSource": [
            "ec2.amazonaws.com"
          ],
          "eventName": [
            "CreateTransitGatewayVpcAttachment"
          ]
        }
      }
      Name: TGWAcceptAutoAttach
      Targets:
      - Arn: !GetAtt LambdaFunction.Arn
        Id: LambdaFunction
Enter fullscreen mode Exit fullscreen mode

A Lambda Function to check the source account which created the attachment, read out the DynamoDB table and if required accept the Transit Gateway Attachment (code in Github).

After that the tgw-attach-auto-accept-global.yaml needs to be executed in all accounts, deploying it as a Stackset is recommended. This will create the following resources:

An Eventbridge Rule to capture CreateTransitGatewayVpcAttachment CloudTrail events from the specific accounts.

TGWAttachAutoAcceptRule:
    Type: "AWS::Events::Rule"
    Condition: IsNotTGWAccount
    Properties: 
      Description: CloudWatch Event Rule for automatically accepting TGW Attachments
      EventPattern: {
        "source": [ 
          "aws.ec2"
        ], 
        "detail-type": [ 
          "AWS API Call via CloudTrail" 
        ], 
        "detail": { 
          "eventSource": [ 
            "ec2.amazonaws.com" 
          ], 
          "eventName": [
            "CreateTransitGatewayVpcAttachment"
          ] 
        } 
      } 
      Name: "RuleForTGWAttachAutoAccept"
      Targets: 
        - Arn: !Sub "arn:aws:events:${AWS::Region}:${TgwAccount}:event-bus/default"
          Id: "TGWAttachAutoAcceptRule"
          RoleArn: !GetAtt TGWAttachAutoAcceptRole.Arn
Enter fullscreen mode Exit fullscreen mode

A Cross-Account IAM Role to read-out the CIDR Block from the corresponding VPC which is given in the event

CrossAccountLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: CrossAccountLambdaRole
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Sub 'arn:aws:iam::${TgwAccount}:root'
            Action:
              - sts:AssumeRole
      MaxSessionDuration: 3600
      Path: /
      Policies:
        - PolicyName: CrossAccountLambdaRolePolicy
          PolicyDocument: 
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ec2:DescribeVpcs
                Resource: "*"
              - Effect: Allow
                Action:
                  - iam:PassRole
                Resource: 'arn:aws:iam::*:role/*'
Enter fullscreen mode Exit fullscreen mode

After the successful deployment and adding the relevant CIDR Block and Account Id pairs, you should be able to see the Transitgateway Attachment gets enabled automatically!

The complete solution is accessible in Github.

About PCG

Public Cloud Group supports companies in their digital transformation through the use of public cloud solutions.

With a product portfolio designed to accompany organisations of all sizes in their cloud journey and competence that is a synonym for highly qualified staff that clients and partners like to work with, PCG is positioned as a reliable and trustworthy partner for the hyperscalers, relevant and with repeatedly validated competence and credibility.

We have the highest partnership status with the three relevant hyperscalers: Amazon Web Services (AWS), Google, and Microsoft. As experienced providers, we advise our customers independently with cloud implementation, application development, and managed services.

Top comments (0)