cdk-vpc-module


Namecdk-vpc-module JSON
Version 0.0.17 PyPI version JSON
download
home_pagehttps://github.com/smallcase/cdk-vpc-module.git
Summary@smallcase/cdk-vpc-module
upload_time2025-07-25 11:52:53
maintainerNone
docs_urlNone
authorBharat Parmar<bharat.parmar@smallcase.com>
requires_python~=3.8
licenseApache-2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # cdk-vpc-module

cdk-vpc-module construct library is an open-source extension of the AWS Cloud Development Kit (AWS CDK) to deploy configurable aws vpc  and its individual components in less than 50 lines of code and human readable configuration which can be managed by pull requests!

## :sparkles: Features

* :white_check_mark: Option to configure custom IPv4 CIDR(10.10.0.0/24)
* :white_check_mark: VPC Peering with  route table entry
* :white_check_mark: Configurable NACL as per subnet group
* :white_check_mark: NATGateway as per availabilityZones

Using cdk a vpc can be deployed using the following sample code snippet:

```python
import { Network } from "@smallcase/cdk-vpc-module/lib/constructs/network";
import { aws_ec2 as ec2, App, Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";

export class VPCStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps = {}) {
    const s3EndpointIamPermission = new iam.PolicyStatement({
      actions: ["s3:*"],
      resources: ['arn:aws:s3:::*'],
      principals: [new iam.AnyPrincipal()],
    })
    const monitoringEndpointIamPermission = new iam.PolicyStatement({
      actions: ["*"],
      resources: ['*'],
      principals: [new iam.AnyPrincipal()],
    })
    super(scope, id, props);
    new Network(this, 'NETWORK', {
      vpc: {
        cidr: '10.10.0.0/16',
        subnetConfiguration: [],
      },
      peeringConfigs: {
        "TEST-PEERING": { // this key will be used as your peering id, which you will have to mention below when you configure a route table for your subnets
          peeringVpcId: "vpc-0000",
          tags: {
            "Name": "TEST-PEERING to CREATED-VPC",
            "Description": "Connect"
          }
        }
      },
      subnets: [
        {
          subnetGroupName: 'NATGateway',
          subnetType: ec2.SubnetType.PUBLIC,
          cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],
          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
          ingressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          routes: [
          ],
          egressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
        },
        {
          subnetGroupName: 'Public',
          subnetType: ec2.SubnetType.PUBLIC,
          cidrBlock: ['10.10.2.0/24', '10.10.3.0/24', '10.10.4.0/24'],
          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
          ingressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          egressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          routes: [
          ],
          tags: {
            // if you use this vpc for your eks cluster, you have to tag your subnets [read more](https://aws.amazon.com/premiumsupport/knowledge-center/eks-vpc-subnet-discovery/)
            'kubernetes.io/role/elb': '1',
            'kubernetes.io/cluster/TEST-CLUSTER': 'owned',
          },
        },
        {
          subnetGroupName: 'Private',
          subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
          cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],
          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
          ingressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          egressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },

          ],
          routes: [
            {
            // if you use this vpc for your eks cluster, you have to tag your subnets [read more](https://aws.amazon.com/premiumsupport/knowledge-center/eks-vpc-subnet-discovery/)
              routerType: ec2.RouterType.VPC_PEERING_CONNECTION,
              destinationCidrBlock: "<destinationCidrBlock>",
              //<Your VPC PeeringConfig KEY, in this example TEST-PEERING will be your ID>
              existingVpcPeeringRouteKey: "TEST-PEERING"
            }
          ],
          tags: {
            'kubernetes.io/role/internal-elb': '1',
            'kubernetes.io/cluster/TEST-CLUSTER': 'owned',
          },
        },
        {
          subnetGroupName: 'Database',
          subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
          cidrBlock: ['10.10.14.0/27', '10.10.14.32/27', '10.10.14.64/27'],
          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
          ingressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          egressNetworkACL: [
            {
              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),
              traffic: ec2.AclTraffic.allTraffic(),
            },
          ],
          routes: [
          ],
          tags: {
          },
        },
      ],
      vpcEndpoints: [
        {
          name: "s3-gw",
          service: ec2.GatewayVpcEndpointAwsService.S3,
          subnetGroupNames: ["Private","Database"],
          externalSubnets: [
            {
              id: "subnet-<id>",
              availabilityZone: "ap-south-1a",
              routeTableId: "rtb-<id>"
            },
            {
              id: "subnet-<id>",
              availabilityZone: "ap-south-1b",
              routeTableId: "rtb-<id>"
            }
          ],
          iamPolicyStatements: [s3EndpointIamPermission]
        },
        {
          name: "da-stag-monitoring-vpe",
          service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_MONITORING,
          subnetGroupNames: ["ManageServicePrivate"],
          iamPolicyStatements: [monitoringEndpointIamPermission],
          securityGroupRules: [
            {
              peer: ec2.Peer.ipv4("10.10.0.0/16"),
              port:  ec2.Port.tcp(443),
              description: "From Test VPC"
            }
          ],
        },
      ]
    });
  }
}
const envDef = {
  account: '<AWS-ID>',
  region: '<AWS-REGION>',
};

const app = new App();

new VPCStack(app, 'TEST', {
  env: envDef,
  terminationProtection: true,
  tags: {
});
app.synth();
```

Please refer [here](/API.md) to check how to use individual resource constructs.

## :clapper: Quick Start

The quick start shows you how to create an **AWS-VPC** using this module.

### Prerequisites

* A working [`aws`](https://aws.amazon.com/cli/) CLI installation with access to an account and administrator privileges
* You'll need a recent [NodeJS](https://nodejs.org) installation

To get going you'll need a CDK project. For details please refer to the [detailed guide for CDK](https://docs.aws.amazon.com/cdk/latest/guide/hello_world.html).

Create an empty directory on your system.

```bash
mkdir aws-quick-start-vpc && cd aws-quick-start-vpc
```

Bootstrap your CDK project, we will use TypeScript, but you can switch to any other supported language.

```bash
npx cdk init sample-vpc  --language typescript
npx cdk bootstrap
```

Install using NPM:

```
npm install @smallcase/cdk-vpc-module
```

Using yarn

```
yarn add @smallcase/cdk-vpc-module
```

Check the changed which are to be deployed

```bash
~ -> npx cdk diff
```

Deploy using

```bash
~ -> npx cdk deploy
```

Features
Multiple VPC Endpoints: Define and manage multiple VPC Endpoints in one configuration.
Flexible Subnet Selection: Attach VPC Endpoints to multiple subnet groups or external subnets.
Custom Security Groups: Configure security groups for Interface VPC Endpoints.
IAM Policies: Attach custom IAM policies to control access to the VPC Endpoints.
Tagging: Apply custom tags to each VPC Endpoint.

Defining VPC Endpoints Configuration
You can define multiple VPC Endpoints in the vpcEndpoints: [] configuration array. Each VPC Endpoint can be customized with different subnet groups, IAM policies, security group rules, and tags.

```
vpcEndpoints: [
  {
    name: "test-s3-gw",
    service: ec2.GatewayVpcEndpointAwsService.S3,
    subnetGroupNames: ["ManageServicePrivate", "ToolPrivate", "Database"],  // Subnet groups for the endpoint
    externalSubnets: [
      {
        id: "subnet-<id>",
        availabilityZone: "ap-south-1a",
        routeTableId: "rtb-<id>",
      },
      {
        id: "subnet-<id>",
        availabilityZone: "ap-south-1b",
        routeTableId: "rtb-<id>",
      }
    ],
    iamPolicyStatements: [s3EndpointIamPermission],  // Custom IAM policy for the endpoint
  },
  {
    name: "DynamoDbGatewayEndpoint",
    service: ec2.GatewayVpcEndpointAwsService.DYNAMODB,
    subnetGroupNames: ["private-subnet"],
    additionalTags: {
      Environment: "Staging",
    },
  },
],
```

In this example:

The S3 Gateway Endpoint is created in three subnet groups: ManageServicePrivate, ToolPrivate, and Database.
External subnets are specified with their IDs, availability zones, and route table IDs for the S3 endpoint.
A custom IAM policy (s3EndpointIamPermission) is attached to control access to the S3 endpoint.
A DynamoDB Gateway Endpoint is created in the private-subnet with additional tags specifying the environment and ownership.

Configuration Options
Here’s a breakdown of the configuration options available:

1. name: A unique name for the VPC Endpoint.
2. service: The AWS service the VPC Endpoint connects to (e.g., S3, DynamoDB, Secrets Manager)
3. subnetGroupNames: The subnet group names where the VPC Endpoint will be deployed.
4. externalSubnets: Specify external subnets if you need to define subnets manually (each with an id, availabilityZone, and routeTableId).
5. iamPolicyStatements: (Optional) Attach IAM policy statements to control access to the endpoint.
6. additionalTags: (Optional) Add custom tags to the VPC Endpoint for easier identification and tracking.

## Dynamic Routing Strategy

The module automatically chooses the optimal routing strategy based on the number of NAT Gateways to prevent duplicate `0.0.0.0/0` route entries:

### **Single NAT Gateway (≤1 NAT Gateway)**

* **Strategy**: One route table per subnet group
* **Benefits**:

  * **Cost Optimized**: Fewer route tables = lower costs
  * **Simpler Management**: One route table per subnet group
  * **No Duplicate Routes**: Single NAT Gateway means no duplicate `0.0.0.0/0` entries
  * **Suitable for**: Development, testing, small workloads
* **Configuration**: All subnets in a group share the same route table with one NAT route

### **Multiple NAT Gateways (>1 NAT Gateway)**

* **Strategy**: One route table per subnet
* **Benefits**:

  * **Prevents Duplicate Routes**: Each subnet gets its own route table, avoiding duplicate `0.0.0.0/0` entries
  * **AZ-Aware Routing**: Each subnet uses NAT Gateway in the same AZ when possible
  * **High Availability**: Better fault tolerance and load distribution
  * **Cross-AZ Cost Reduction**: Reduced data transfer costs
  * **Suitable for**: Production workloads, high availability requirements
* **Configuration**: Each subnet gets its own route table with one NAT route

### **Why This Strategy?**

AWS route tables don't support duplicate entries for the same destination CIDR (like `0.0.0.0/0`). When you have multiple NAT Gateways:

* **❌ Wrong Approach**: Multiple NAT routes in same route table → `AlreadyExists` error
* **✅ Correct Approach**: One route table per subnet → Each gets one NAT route

### **Automatic Strategy Selection**

```python
// Single NAT Gateway - Cost Optimized
new Network(this, 'NETWORK', {
  vpc: {
    cidr: '10.10.0.0/16',
    subnetConfiguration: [],
  },
  subnets: [
    {
      subnetGroupName: 'NATGateway',
      subnetType: ec2.SubnetType.PUBLIC,
      cidrBlock: ['10.10.0.0/28'], // Only one subnet
      availabilityZones: ['ap-south-1a'], // Only one AZ
      useSubnetForNAT: true,
    },
    {
      subnetGroupName: 'Private',
      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],
      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
    },
  ],
});

// Multiple NAT Gateways - Performance Optimized
new Network(this, 'NETWORK', {
  vpc: {
    cidr: '10.10.0.0/16',
    subnetConfiguration: [],
  },
  natEipAllocationIds: [
    'eipalloc-1234567890abcdef',
    'eipalloc-0987654321fedcba',
    'eipalloc-abcdef1234567890',
  ],
  subnets: [
    {
      subnetGroupName: 'NATGateway',
      subnetType: ec2.SubnetType.PUBLIC,
      cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],
      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
      useSubnetForNAT: true,
    },
    {
      subnetGroupName: 'Private',
      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],
      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
    },
  ],
});
```

### **CloudFormation Outputs**

The module provides outputs to show which strategy is being used:

* **RoutingStrategy**: Shows "Route Table per Subnet Group" or "Route Table per Subnet"
* **NATGatewayCount**: Shows the number of NAT Gateways configured

### **Route Table Distribution**

| Scenario | Route Tables | NAT Routes per Table | Strategy |
|----------|-------------|---------------------|----------|
| Single NAT | 1 per subnet group | 1 | Cost optimized |
| Multiple NAT | 1 per subnet | 1 | Performance optimized |

### **Migration Strategy**

You can easily migrate between strategies by changing your configuration:

1. **Development → Production**: Add more NAT Gateway subnets
2. **Production → Development**: Reduce to single NAT Gateway subnet
3. **Cost Optimization**: Monitor usage and adjust NAT Gateway count

The module handles the migration automatically without manual route table changes.

## NAT Gateway EIP Allocation

You can specify existing Elastic IP (EIP) allocation IDs to use with your NAT Gateways. This is useful when you want to:

* Use pre-existing EIPs
* Maintain consistent IP addresses across deployments
* Control EIP costs and management

### **Using EIP Allocation IDs**

```python
new Network(this, 'NETWORK', {
  vpc: {
    cidr: '10.10.0.0/16',
    subnetConfiguration: [],
  },
  // Specify existing EIP allocation IDs
  natEipAllocationIds: [
    'eipalloc-1234567890abcdef', // EIP for NAT Gateway 1
    'eipalloc-0987654321fedcba', // EIP for NAT Gateway 2
    'eipalloc-abcdef1234567890', // EIP for NAT Gateway 3
  ],
  subnets: [
    {
      subnetGroupName: 'NATGateway',
      subnetType: ec2.SubnetType.PUBLIC,
      cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],
      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
      useSubnetForNAT: true,
    },
    {
      subnetGroupName: 'Private',
      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,
      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],
      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],
    },
  ],
});
```

### **EIP Allocation ID Requirements**

* **Count**: Should match the number of NAT Gateway subnets (optional)
* **Format**: Must be valid EIP allocation IDs (e.g., `eipalloc-xxxxxxxxx`)
* **Region**: Must be in the same region as your VPC
* **Account**: Must be owned by the same AWS account

### **Benefits of Using EIP Allocation IDs**

1. **Cost Control**: Reuse existing EIPs instead of creating new ones
2. **IP Consistency**: Maintain the same public IP addresses across deployments
3. **Compliance**: Meet requirements for static IP addresses
4. **DNS**: Use existing DNS records that point to specific EIPs

### **CloudFormation Outputs**

When EIP allocation IDs are provided, the module outputs:

* **NATEipAllocationIds**: Comma-separated list of EIP allocation IDs used
* **RoutingStrategy**: Shows the routing strategy being used
* **NATGatewayCount**: Number of NAT Gateways configured

### **Example Output**

```json
{
  "NATEipAllocationIds": "eipalloc-1234567890abcdef,eipalloc-0987654321fedcba,eipalloc-abcdef1234567890",
  "RoutingStrategy": "Route Table per Subnet",
  "NATGatewayCount": "3"
}
```

### **Creating EIPs for NAT Gateways**

If you need to create EIPs first, you can do so using CDK:

```python
import * as ec2 from 'aws-cdk-lib/aws-ec2';

// Create EIPs
const eip1 = new ec2.CfnEIP(this, 'NATEip1', {
  domain: 'vpc',
});

const eip2 = new ec2.CfnEIP(this, 'NATEip2', {
  domain: 'vpc',
});

const eip3 = new ec2.CfnEIP(this, 'NATEip3', {
  domain: 'vpc',
});

// Use them in your Network construct
new Network(this, 'NETWORK', {
  vpc: {
    cidr: '10.10.0.0/16',
    subnetConfiguration: [],
  },
  natEipAllocationIds: [
    eip1.attrAllocationId,
    eip2.attrAllocationId,
    eip3.attrAllocationId,
  ],
  // ... rest of configuration
});
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/smallcase/cdk-vpc-module.git",
    "name": "cdk-vpc-module",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "~=3.8",
    "maintainer_email": null,
    "keywords": null,
    "author": "Bharat Parmar<bharat.parmar@smallcase.com>",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/b7/84/c716c36f7e5e658eff132bf3150fc03a79fd4a20a7d25fef599bec4abf38/cdk_vpc_module-0.0.17.tar.gz",
    "platform": null,
    "description": "# cdk-vpc-module\n\ncdk-vpc-module construct library is an open-source extension of the AWS Cloud Development Kit (AWS CDK) to deploy configurable aws vpc  and its individual components in less than 50 lines of code and human readable configuration which can be managed by pull requests!\n\n## :sparkles: Features\n\n* :white_check_mark: Option to configure custom IPv4 CIDR(10.10.0.0/24)\n* :white_check_mark: VPC Peering with  route table entry\n* :white_check_mark: Configurable NACL as per subnet group\n* :white_check_mark: NATGateway as per availabilityZones\n\nUsing cdk a vpc can be deployed using the following sample code snippet:\n\n```python\nimport { Network } from \"@smallcase/cdk-vpc-module/lib/constructs/network\";\nimport { aws_ec2 as ec2, App, Stack, StackProps } from \"aws-cdk-lib\";\nimport { Construct } from \"constructs\";\n\nexport class VPCStack extends Stack {\n  constructor(scope: Construct, id: string, props: StackProps = {}) {\n    const s3EndpointIamPermission = new iam.PolicyStatement({\n      actions: [\"s3:*\"],\n      resources: ['arn:aws:s3:::*'],\n      principals: [new iam.AnyPrincipal()],\n    })\n    const monitoringEndpointIamPermission = new iam.PolicyStatement({\n      actions: [\"*\"],\n      resources: ['*'],\n      principals: [new iam.AnyPrincipal()],\n    })\n    super(scope, id, props);\n    new Network(this, 'NETWORK', {\n      vpc: {\n        cidr: '10.10.0.0/16',\n        subnetConfiguration: [],\n      },\n      peeringConfigs: {\n        \"TEST-PEERING\": { // this key will be used as your peering id, which you will have to mention below when you configure a route table for your subnets\n          peeringVpcId: \"vpc-0000\",\n          tags: {\n            \"Name\": \"TEST-PEERING to CREATED-VPC\",\n            \"Description\": \"Connect\"\n          }\n        }\n      },\n      subnets: [\n        {\n          subnetGroupName: 'NATGateway',\n          subnetType: ec2.SubnetType.PUBLIC,\n          cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],\n          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n          ingressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          routes: [\n          ],\n          egressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n        },\n        {\n          subnetGroupName: 'Public',\n          subnetType: ec2.SubnetType.PUBLIC,\n          cidrBlock: ['10.10.2.0/24', '10.10.3.0/24', '10.10.4.0/24'],\n          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n          ingressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          egressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          routes: [\n          ],\n          tags: {\n            // if you use this vpc for your eks cluster, you have to tag your subnets [read more](https://aws.amazon.com/premiumsupport/knowledge-center/eks-vpc-subnet-discovery/)\n            'kubernetes.io/role/elb': '1',\n            'kubernetes.io/cluster/TEST-CLUSTER': 'owned',\n          },\n        },\n        {\n          subnetGroupName: 'Private',\n          subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n          cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],\n          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n          ingressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          egressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n\n          ],\n          routes: [\n            {\n            // if you use this vpc for your eks cluster, you have to tag your subnets [read more](https://aws.amazon.com/premiumsupport/knowledge-center/eks-vpc-subnet-discovery/)\n              routerType: ec2.RouterType.VPC_PEERING_CONNECTION,\n              destinationCidrBlock: \"<destinationCidrBlock>\",\n              //<Your VPC PeeringConfig KEY, in this example TEST-PEERING will be your ID>\n              existingVpcPeeringRouteKey: \"TEST-PEERING\"\n            }\n          ],\n          tags: {\n            'kubernetes.io/role/internal-elb': '1',\n            'kubernetes.io/cluster/TEST-CLUSTER': 'owned',\n          },\n        },\n        {\n          subnetGroupName: 'Database',\n          subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n          cidrBlock: ['10.10.14.0/27', '10.10.14.32/27', '10.10.14.64/27'],\n          availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n          ingressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          egressNetworkACL: [\n            {\n              cidr: ec2.AclCidr.ipv4('0.0.0.0/0'),\n              traffic: ec2.AclTraffic.allTraffic(),\n            },\n          ],\n          routes: [\n          ],\n          tags: {\n          },\n        },\n      ],\n      vpcEndpoints: [\n        {\n          name: \"s3-gw\",\n          service: ec2.GatewayVpcEndpointAwsService.S3,\n          subnetGroupNames: [\"Private\",\"Database\"],\n          externalSubnets: [\n            {\n              id: \"subnet-<id>\",\n              availabilityZone: \"ap-south-1a\",\n              routeTableId: \"rtb-<id>\"\n            },\n            {\n              id: \"subnet-<id>\",\n              availabilityZone: \"ap-south-1b\",\n              routeTableId: \"rtb-<id>\"\n            }\n          ],\n          iamPolicyStatements: [s3EndpointIamPermission]\n        },\n        {\n          name: \"da-stag-monitoring-vpe\",\n          service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_MONITORING,\n          subnetGroupNames: [\"ManageServicePrivate\"],\n          iamPolicyStatements: [monitoringEndpointIamPermission],\n          securityGroupRules: [\n            {\n              peer: ec2.Peer.ipv4(\"10.10.0.0/16\"),\n              port:  ec2.Port.tcp(443),\n              description: \"From Test VPC\"\n            }\n          ],\n        },\n      ]\n    });\n  }\n}\nconst envDef = {\n  account: '<AWS-ID>',\n  region: '<AWS-REGION>',\n};\n\nconst app = new App();\n\nnew VPCStack(app, 'TEST', {\n  env: envDef,\n  terminationProtection: true,\n  tags: {\n});\napp.synth();\n```\n\nPlease refer [here](/API.md) to check how to use individual resource constructs.\n\n## :clapper: Quick Start\n\nThe quick start shows you how to create an **AWS-VPC** using this module.\n\n### Prerequisites\n\n* A working [`aws`](https://aws.amazon.com/cli/) CLI installation with access to an account and administrator privileges\n* You'll need a recent [NodeJS](https://nodejs.org) installation\n\nTo get going you'll need a CDK project. For details please refer to the [detailed guide for CDK](https://docs.aws.amazon.com/cdk/latest/guide/hello_world.html).\n\nCreate an empty directory on your system.\n\n```bash\nmkdir aws-quick-start-vpc && cd aws-quick-start-vpc\n```\n\nBootstrap your CDK project, we will use TypeScript, but you can switch to any other supported language.\n\n```bash\nnpx cdk init sample-vpc  --language typescript\nnpx cdk bootstrap\n```\n\nInstall using NPM:\n\n```\nnpm install @smallcase/cdk-vpc-module\n```\n\nUsing yarn\n\n```\nyarn add @smallcase/cdk-vpc-module\n```\n\nCheck the changed which are to be deployed\n\n```bash\n~ -> npx cdk diff\n```\n\nDeploy using\n\n```bash\n~ -> npx cdk deploy\n```\n\nFeatures\nMultiple VPC Endpoints: Define and manage multiple VPC Endpoints in one configuration.\nFlexible Subnet Selection: Attach VPC Endpoints to multiple subnet groups or external subnets.\nCustom Security Groups: Configure security groups for Interface VPC Endpoints.\nIAM Policies: Attach custom IAM policies to control access to the VPC Endpoints.\nTagging: Apply custom tags to each VPC Endpoint.\n\nDefining VPC Endpoints Configuration\nYou can define multiple VPC Endpoints in the vpcEndpoints: [] configuration array. Each VPC Endpoint can be customized with different subnet groups, IAM policies, security group rules, and tags.\n\n```\nvpcEndpoints: [\n  {\n    name: \"test-s3-gw\",\n    service: ec2.GatewayVpcEndpointAwsService.S3,\n    subnetGroupNames: [\"ManageServicePrivate\", \"ToolPrivate\", \"Database\"],  // Subnet groups for the endpoint\n    externalSubnets: [\n      {\n        id: \"subnet-<id>\",\n        availabilityZone: \"ap-south-1a\",\n        routeTableId: \"rtb-<id>\",\n      },\n      {\n        id: \"subnet-<id>\",\n        availabilityZone: \"ap-south-1b\",\n        routeTableId: \"rtb-<id>\",\n      }\n    ],\n    iamPolicyStatements: [s3EndpointIamPermission],  // Custom IAM policy for the endpoint\n  },\n  {\n    name: \"DynamoDbGatewayEndpoint\",\n    service: ec2.GatewayVpcEndpointAwsService.DYNAMODB,\n    subnetGroupNames: [\"private-subnet\"],\n    additionalTags: {\n      Environment: \"Staging\",\n    },\n  },\n],\n```\n\nIn this example:\n\nThe S3 Gateway Endpoint is created in three subnet groups: ManageServicePrivate, ToolPrivate, and Database.\nExternal subnets are specified with their IDs, availability zones, and route table IDs for the S3 endpoint.\nA custom IAM policy (s3EndpointIamPermission) is attached to control access to the S3 endpoint.\nA DynamoDB Gateway Endpoint is created in the private-subnet with additional tags specifying the environment and ownership.\n\nConfiguration Options\nHere\u2019s a breakdown of the configuration options available:\n\n1. name: A unique name for the VPC Endpoint.\n2. service: The AWS service the VPC Endpoint connects to (e.g., S3, DynamoDB, Secrets Manager)\n3. subnetGroupNames: The subnet group names where the VPC Endpoint will be deployed.\n4. externalSubnets: Specify external subnets if you need to define subnets manually (each with an id, availabilityZone, and routeTableId).\n5. iamPolicyStatements: (Optional) Attach IAM policy statements to control access to the endpoint.\n6. additionalTags: (Optional) Add custom tags to the VPC Endpoint for easier identification and tracking.\n\n## Dynamic Routing Strategy\n\nThe module automatically chooses the optimal routing strategy based on the number of NAT Gateways to prevent duplicate `0.0.0.0/0` route entries:\n\n### **Single NAT Gateway (\u22641 NAT Gateway)**\n\n* **Strategy**: One route table per subnet group\n* **Benefits**:\n\n  * **Cost Optimized**: Fewer route tables = lower costs\n  * **Simpler Management**: One route table per subnet group\n  * **No Duplicate Routes**: Single NAT Gateway means no duplicate `0.0.0.0/0` entries\n  * **Suitable for**: Development, testing, small workloads\n* **Configuration**: All subnets in a group share the same route table with one NAT route\n\n### **Multiple NAT Gateways (>1 NAT Gateway)**\n\n* **Strategy**: One route table per subnet\n* **Benefits**:\n\n  * **Prevents Duplicate Routes**: Each subnet gets its own route table, avoiding duplicate `0.0.0.0/0` entries\n  * **AZ-Aware Routing**: Each subnet uses NAT Gateway in the same AZ when possible\n  * **High Availability**: Better fault tolerance and load distribution\n  * **Cross-AZ Cost Reduction**: Reduced data transfer costs\n  * **Suitable for**: Production workloads, high availability requirements\n* **Configuration**: Each subnet gets its own route table with one NAT route\n\n### **Why This Strategy?**\n\nAWS route tables don't support duplicate entries for the same destination CIDR (like `0.0.0.0/0`). When you have multiple NAT Gateways:\n\n* **\u274c Wrong Approach**: Multiple NAT routes in same route table \u2192 `AlreadyExists` error\n* **\u2705 Correct Approach**: One route table per subnet \u2192 Each gets one NAT route\n\n### **Automatic Strategy Selection**\n\n```python\n// Single NAT Gateway - Cost Optimized\nnew Network(this, 'NETWORK', {\n  vpc: {\n    cidr: '10.10.0.0/16',\n    subnetConfiguration: [],\n  },\n  subnets: [\n    {\n      subnetGroupName: 'NATGateway',\n      subnetType: ec2.SubnetType.PUBLIC,\n      cidrBlock: ['10.10.0.0/28'], // Only one subnet\n      availabilityZones: ['ap-south-1a'], // Only one AZ\n      useSubnetForNAT: true,\n    },\n    {\n      subnetGroupName: 'Private',\n      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],\n      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n    },\n  ],\n});\n\n// Multiple NAT Gateways - Performance Optimized\nnew Network(this, 'NETWORK', {\n  vpc: {\n    cidr: '10.10.0.0/16',\n    subnetConfiguration: [],\n  },\n  natEipAllocationIds: [\n    'eipalloc-1234567890abcdef',\n    'eipalloc-0987654321fedcba',\n    'eipalloc-abcdef1234567890',\n  ],\n  subnets: [\n    {\n      subnetGroupName: 'NATGateway',\n      subnetType: ec2.SubnetType.PUBLIC,\n      cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],\n      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n      useSubnetForNAT: true,\n    },\n    {\n      subnetGroupName: 'Private',\n      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],\n      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n    },\n  ],\n});\n```\n\n### **CloudFormation Outputs**\n\nThe module provides outputs to show which strategy is being used:\n\n* **RoutingStrategy**: Shows \"Route Table per Subnet Group\" or \"Route Table per Subnet\"\n* **NATGatewayCount**: Shows the number of NAT Gateways configured\n\n### **Route Table Distribution**\n\n| Scenario | Route Tables | NAT Routes per Table | Strategy |\n|----------|-------------|---------------------|----------|\n| Single NAT | 1 per subnet group | 1 | Cost optimized |\n| Multiple NAT | 1 per subnet | 1 | Performance optimized |\n\n### **Migration Strategy**\n\nYou can easily migrate between strategies by changing your configuration:\n\n1. **Development \u2192 Production**: Add more NAT Gateway subnets\n2. **Production \u2192 Development**: Reduce to single NAT Gateway subnet\n3. **Cost Optimization**: Monitor usage and adjust NAT Gateway count\n\nThe module handles the migration automatically without manual route table changes.\n\n## NAT Gateway EIP Allocation\n\nYou can specify existing Elastic IP (EIP) allocation IDs to use with your NAT Gateways. This is useful when you want to:\n\n* Use pre-existing EIPs\n* Maintain consistent IP addresses across deployments\n* Control EIP costs and management\n\n### **Using EIP Allocation IDs**\n\n```python\nnew Network(this, 'NETWORK', {\n  vpc: {\n    cidr: '10.10.0.0/16',\n    subnetConfiguration: [],\n  },\n  // Specify existing EIP allocation IDs\n  natEipAllocationIds: [\n    'eipalloc-1234567890abcdef', // EIP for NAT Gateway 1\n    'eipalloc-0987654321fedcba', // EIP for NAT Gateway 2\n    'eipalloc-abcdef1234567890', // EIP for NAT Gateway 3\n  ],\n  subnets: [\n    {\n      subnetGroupName: 'NATGateway',\n      subnetType: ec2.SubnetType.PUBLIC,\n      cidrBlock: ['10.10.0.0/28', '10.10.0.16/28', '10.10.0.32/28'],\n      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n      useSubnetForNAT: true,\n    },\n    {\n      subnetGroupName: 'Private',\n      subnetType: ec2.SubnetType.PRIVATE_WITH_NAT,\n      cidrBlock: ['10.10.5.0/24', '10.10.6.0/24', '10.10.7.0/24'],\n      availabilityZones: ['ap-south-1a', 'ap-south-1b', 'ap-south-1c'],\n    },\n  ],\n});\n```\n\n### **EIP Allocation ID Requirements**\n\n* **Count**: Should match the number of NAT Gateway subnets (optional)\n* **Format**: Must be valid EIP allocation IDs (e.g., `eipalloc-xxxxxxxxx`)\n* **Region**: Must be in the same region as your VPC\n* **Account**: Must be owned by the same AWS account\n\n### **Benefits of Using EIP Allocation IDs**\n\n1. **Cost Control**: Reuse existing EIPs instead of creating new ones\n2. **IP Consistency**: Maintain the same public IP addresses across deployments\n3. **Compliance**: Meet requirements for static IP addresses\n4. **DNS**: Use existing DNS records that point to specific EIPs\n\n### **CloudFormation Outputs**\n\nWhen EIP allocation IDs are provided, the module outputs:\n\n* **NATEipAllocationIds**: Comma-separated list of EIP allocation IDs used\n* **RoutingStrategy**: Shows the routing strategy being used\n* **NATGatewayCount**: Number of NAT Gateways configured\n\n### **Example Output**\n\n```json\n{\n  \"NATEipAllocationIds\": \"eipalloc-1234567890abcdef,eipalloc-0987654321fedcba,eipalloc-abcdef1234567890\",\n  \"RoutingStrategy\": \"Route Table per Subnet\",\n  \"NATGatewayCount\": \"3\"\n}\n```\n\n### **Creating EIPs for NAT Gateways**\n\nIf you need to create EIPs first, you can do so using CDK:\n\n```python\nimport * as ec2 from 'aws-cdk-lib/aws-ec2';\n\n// Create EIPs\nconst eip1 = new ec2.CfnEIP(this, 'NATEip1', {\n  domain: 'vpc',\n});\n\nconst eip2 = new ec2.CfnEIP(this, 'NATEip2', {\n  domain: 'vpc',\n});\n\nconst eip3 = new ec2.CfnEIP(this, 'NATEip3', {\n  domain: 'vpc',\n});\n\n// Use them in your Network construct\nnew Network(this, 'NETWORK', {\n  vpc: {\n    cidr: '10.10.0.0/16',\n    subnetConfiguration: [],\n  },\n  natEipAllocationIds: [\n    eip1.attrAllocationId,\n    eip2.attrAllocationId,\n    eip3.attrAllocationId,\n  ],\n  // ... rest of configuration\n});\n```\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "@smallcase/cdk-vpc-module",
    "version": "0.0.17",
    "project_urls": {
        "Homepage": "https://github.com/smallcase/cdk-vpc-module.git",
        "Source": "https://github.com/smallcase/cdk-vpc-module.git"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "087f5ed2933f83e36b7a68ff8609c89f76ba29a843b96cb96f760a7bef08d604",
                "md5": "83a99cc446afddbea447873232f14b00",
                "sha256": "ac8fcc89d397469c08e1d0efdc11194e5c3f9853e12c93e5140121eed04bf0c5"
            },
            "downloads": -1,
            "filename": "cdk_vpc_module-0.0.17-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "83a99cc446afddbea447873232f14b00",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "~=3.8",
            "size": 86488,
            "upload_time": "2025-07-25T11:52:51",
            "upload_time_iso_8601": "2025-07-25T11:52:51.900854Z",
            "url": "https://files.pythonhosted.org/packages/08/7f/5ed2933f83e36b7a68ff8609c89f76ba29a843b96cb96f760a7bef08d604/cdk_vpc_module-0.0.17-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b784c716c36f7e5e658eff132bf3150fc03a79fd4a20a7d25fef599bec4abf38",
                "md5": "72a60ba6c9d13321b15e67f4dae84d31",
                "sha256": "22fc9b3ab55c41a7666c80404f3c9fbe80b19c07a752c0b1c06dcaf2e7b38c59"
            },
            "downloads": -1,
            "filename": "cdk_vpc_module-0.0.17.tar.gz",
            "has_sig": false,
            "md5_digest": "72a60ba6c9d13321b15e67f4dae84d31",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "~=3.8",
            "size": 89205,
            "upload_time": "2025-07-25T11:52:53",
            "upload_time_iso_8601": "2025-07-25T11:52:53.165742Z",
            "url": "https://files.pythonhosted.org/packages/b7/84/c716c36f7e5e658eff132bf3150fc03a79fd4a20a7d25fef599bec4abf38/cdk_vpc_module-0.0.17.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-25 11:52:53",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "smallcase",
    "github_project": "cdk-vpc-module",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "cdk-vpc-module"
}
        
Elapsed time: 1.98234s