npm package: @infraless-cdk-constructs/aws-vpc
Description: AWS CDK L3 construct for VPC with production-ready networking defaults
Latest version: 1.0.2

# AWS VPC L3 Construct

A production-ready AWS CDK L3 construct for creating Virtual Private Clouds (VPCs) with best-practice networking configurations.

## Features

- **Multi-Tier Subnet Architecture**: Automatic creation of Public, Private, Secure, and Database subnet tiers across multiple Availability Zones
- **Managed NAT Gateways**: Highly available managed NAT Gateways for private subnet internet access
- **Security by Default**: VPC Flow Logs with KMS encryption, Network ACLs, and security groups
- **AWS Service Integration**: Built-in support for VPC Endpoints (Interface and Gateway)
- **Kubernetes Ready**: Optional EKS cluster tagging for seamless Kubernetes integration
- **SSM Parameter Store Integration**: Automatic export of VPC outputs to SSM Parameter Store for cross-stack references
- **Extensible Design**: Protected hook methods allow customization without forking
- **Type-Safe API**: Full TypeScript support with comprehensive type definitions
- **Production Tested**: Based on battle-tested patterns used in enterprise deployments

## Installation

```bash
npm install @cdk-constructs/aws-vpc
```

### Peer Dependencies

This package requires the following peer dependencies:

```bash
npm install aws-cdk-lib constructs
```

## Quick Start

```typescript
import { AwsVpc } from '@cdk-constructs/aws-vpc';
import * as cdk from 'aws-cdk-lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'MyStack');

const vpc = new AwsVpc(stack, 'MyVpc', {
  vpcName: 'production-vpc',
  vpcCidr: '10.0.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3
});

// Access VPC resources
console.log(`VPC ID: ${vpc.vpcId}`);
console.log(`VPC CIDR: ${vpc.vpcCidrBlock}`);
```

## Usage Examples

### Basic VPC with NAT Gateways

Creates a VPC with public, private, and secure subnets across 3 AZs with managed NAT Gateways.

```typescript
const basicVpc = new AwsVpc(this, 'BasicVpc', {
  vpcName: 'my-vpc',
  vpcCidr: '10.0.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3
});
```

### VPC with Database Tier

Add a fourth isolated subnet tier for database resources.

```typescript
const dbVpc = new AwsVpc(this, 'DbVpc', {
  vpcName: 'database-vpc',
  vpcCidr: '10.2.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  databaseSubnetCidrMask: 24,  // Add database tier
  maxAzs: 3,
  natCount: 3
});

// Access database subnets
console.log(`Database subnets: ${dbVpc.databaseSubnets?.length}`);
```

### VPC with Kubernetes Integration

Tag subnets for EKS cluster integration.

```typescript
const eksVpc = new AwsVpc(this, 'EksVpc', {
  vpcName: 'eks-vpc',
  vpcCidr: '10.3.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  kubernetesClusterName: 'my-eks-cluster'  // Adds K8s tags
});
```

### VPC with Network ACLs

Add Network ACL rules for subnet-level traffic control.

```typescript
const secureVpc = new AwsVpc(this, 'SecureVpc', {
  vpcName: 'secure-vpc',
  vpcCidr: '10.4.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  databaseSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  nacls: {
    public: [80, 443, 22],           // HTTP, HTTPS, SSH
    private: [80, 443, 22],          // HTTP, HTTPS, SSH
    secure: [443, 22],               // HTTPS, SSH only
    database: [5432, 3306]           // PostgreSQL, MySQL
  }
});

// Access security groups created for NACLs
if (secureVpc.publicSecurityGroup) {
  console.log(`Public SG: ${secureVpc.publicSecurityGroup.securityGroupId}`);
}
```

### VPC with Interface Endpoints

Add VPC endpoints for private access to AWS services.

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

const endpointVpc = new AwsVpc(this, 'EndpointVpc', {
  vpcName: 'endpoint-vpc',
  vpcCidr: '10.5.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  nacls: {
    private: [443]  // Required for interface endpoints
  },
  interfaceEndpoints: [
    ec2.InterfaceVpcEndpointAwsService.SSM,
    ec2.InterfaceVpcEndpointAwsService.SSM_MESSAGES,
    ec2.InterfaceVpcEndpointAwsService.ECR,
    ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
    ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
    ec2.InterfaceVpcEndpointAwsService.KMS
  ],
  enableSqsEndpoint: true
});
```

### VPC with Custom Flow Logs Retention

Configure VPC Flow Logs retention period.

```typescript
import * as logs from 'aws-cdk-lib/aws-logs';

const customLogsVpc = new AwsVpc(this, 'CustomLogsVpc', {
  vpcName: 'custom-logs-vpc',
  vpcCidr: '10.6.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  flowLogsRetention: logs.RetentionDays.ONE_MONTH
});
```

### VPC with Custom KMS Key

Provide your own KMS key for Flow Logs encryption.

```typescript
import * as kms from 'aws-cdk-lib/aws-kms';

const existingKey = kms.Key.fromKeyArn(
  this,
  'ExistingKey',
  'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
);

const customKeyVpc = new AwsVpc(this, 'CustomKeyVpc', {
  vpcName: 'custom-key-vpc',
  vpcCidr: '10.7.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  encryptionKey: existingKey
});
```

### VPC with SSM Parameter Store Outputs

Export VPC information to SSM Parameter Store for cross-stack references.

```typescript
const ssmVpc = new AwsVpc(this, 'SsmVpc', {
  vpcName: 'production-vpc',
  vpcCidr: '10.8.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  databaseSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3,
  enableSsmParameters: true,  // Enabled by default
  ssmParameterPrefix: '/myapp/vpc/production'  // Custom prefix
});

// Parameters created:
// - /myapp/vpc/production/vpc-id
// - /myapp/vpc/production/vpc-cidr
// - /myapp/vpc/production/public-subnet-ids
// - /myapp/vpc/production/private-subnet-ids
// - /myapp/vpc/production/secure-subnet-ids
// - /myapp/vpc/production/database-subnet-ids

// Reference in another stack:
import * as ssm from 'aws-cdk-lib/aws-ssm';

const vpcId = ssm.StringParameter.valueFromLookup(
  this,
  '/myapp/vpc/production/vpc-id'
);
```

To disable SSM parameter creation:

```typescript
const devVpc = new AwsVpc(this, 'DevVpc', {
  vpcName: 'dev-vpc',
  vpcCidr: '10.9.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 2,
  natCount: 1,
  enableSsmParameters: false  // Disable SSM parameters
});
```

## Extending the Construct

The `AwsVpc` construct uses the Template Method pattern with protected hooks for customization.

### Custom VPC with Lifecycle Hooks

```typescript
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { AwsVpc } from '@cdk-constructs/aws-vpc';

class CustomAwsVpc extends AwsVpc {
  protected onVpcCreated(vpc: ec2.IVpc): void {
    // Add custom tags
    cdk.Tags.of(vpc).add('CostCenter', '12345');
    cdk.Tags.of(vpc).add('Environment', 'production');

    // Add custom logic
    console.log(`VPC ${vpc.vpcId} created successfully`);
  }

  protected onConstructComplete(): void {
    // Custom logic after all resources are created
    console.log('All VPC resources created');
  }
}

// Use the custom construct
const customVpc = new CustomAwsVpc(this, 'CustomVpc', {
  vpcName: 'custom-vpc',
  vpcCidr: '10.8.0.0/16',
  publicSubnetCidrMask: 24,
  privateSubnetCidrMask: 24,
  secureSubnetCidrMask: 24,
  maxAzs: 3,
  natCount: 3
});
```

### Available Hook Methods

Override these protected methods to customize behavior:

- `createEncryptionKey(props)`: Customize KMS key creation
- `createFlowLogs(props)`: Customize Flow Logs configuration
- `applyKubernetesTags(vpc, clusterName)`: Customize Kubernetes tagging
- `configureNacls(vpc, props)`: Customize Network ACL setup
- `createVpcEndpoints(vpc, securityGroup, endpoints)`: Customize VPC endpoints
- `onVpcCreated(vpc)`: Post-VPC creation hook
- `onConstructComplete()`: Post-construct completion hook

## API Reference

### AwsVpcProps

| Property | Type | Required | Default | Description |
|----------|------|----------|---------|-------------|
| `vpcName` | `string` | Yes | - | Name of the VPC |
| `vpcCidr` | `string` | Yes | - | CIDR block (e.g., '10.0.0.0/16') |
| `publicSubnetCidrMask` | `number` | Yes | - | CIDR mask for public subnets |
| `privateSubnetCidrMask` | `number` | Yes | - | CIDR mask for private subnets |
| `secureSubnetCidrMask` | `number` | Yes | - | CIDR mask for secure subnets |
| `databaseSubnetCidrMask` | `number` | No | - | CIDR mask for database subnets |
| `maxAzs` | `number` | Yes | - | Maximum number of AZs to use |
| `natCount` | `number` | Yes | - | Number of NAT Gateways |
| `kubernetesClusterName` | `string` | No | - | EKS cluster name for subnet tagging |
| `enableSqsEndpoint` | `boolean` | No | `false` | Create SQS VPC endpoint |
| `nacls` | `object` | No | - | Network ACL port configuration |
| `interfaceEndpoints` | `ec2.InterfaceVpcEndpointAwsService[]` | No | - | VPC interface endpoints to create |
| `encryptionKey` | `kms.IKey` | No | - | KMS key for Flow Logs encryption |
| `flowLogsRetention` | `logs.RetentionDays` | No | `INFINITE` | Flow Logs retention period |
| `enableSsmParameters` | `boolean` | No | `true` | Create SSM parameters for VPC outputs |
| `ssmParameterPrefix` | `string` | No | `/cdk/${constructId}` | Custom prefix for SSM parameter paths |

### AwsVpc Properties

| Property | Type | Description |
|----------|------|-------------|
| `vpc` | `ec2.IVpc` | The VPC resource |
| `vpcId` | `string` | VPC ID |
| `vpcCidrBlock` | `string` | VPC CIDR block |
| `publicSubnets` | `ec2.ISubnet[]` | Public subnets |
| `privateSubnets` | `ec2.ISubnet[]` | Private subnets |
| `secureSubnets` | `ec2.ISubnet[]` | Secure subnets |
| `databaseSubnets` | `ec2.ISubnet[]` | Database subnets (if created) |
| `encryptionKey` | `kms.IKey` | KMS encryption key |
| `flowLogGroup` | `logs.ILogGroup` | Flow Logs CloudWatch log group |
| `publicSecurityGroup` | `ec2.ISecurityGroup` | Public subnet security group (if NACLs enabled) |
| `privateSecurityGroup` | `ec2.ISecurityGroup` | Private subnet security group (if NACLs enabled) |
| `secureSecurityGroup` | `ec2.ISecurityGroup` | Secure subnet security group (if NACLs enabled) |
| `databaseSecurityGroup` | `ec2.ISecurityGroup` | Database subnet security group (if NACLs enabled) |

## Subnet Architecture

The construct creates a multi-tier subnet architecture:

### Public Subnets
- Internet-facing resources (ALBs, NAT Gateways)
- Direct internet access via Internet Gateway
- Auto-assigned public IPs: **disabled** by default

### Private Subnets
- Application workloads (ECS, EKS, EC2)
- Outbound internet access via NAT Gateway/Instance
- No inbound internet access

### Secure Subnets
- Completely isolated resources
- No internet access (inbound or outbound)
- Internal communication only

### Database Subnets (Optional)
- Database instances (RDS, Aurora, ElastiCache)
- Completely isolated
- Access only from private/secure subnets

## Security Features

### VPC Flow Logs
- Automatically enabled for all traffic
- Encrypted with KMS
- Logged to CloudWatch Logs
- Configurable retention period

### Network ACLs
- Optional subnet-level traffic control
- Port-based rules for each tier
- Automatic ephemeral port handling
- Security group integration

### Encryption
- KMS encryption for Flow Logs
- Automatic key rotation enabled
- CloudWatch Logs service principal access

## Cost Optimization

### NAT Gateway Recommendations

**NAT Gateway** (managed service):
- Managed service with no maintenance required
- High availability within AZ
- Up to 45 Gbps bandwidth
- ~$32/month per gateway + data transfer

### Cost Optimization Strategies

1. **Development/Testing Environments**: Use fewer NAT Gateways
   ```typescript
   const devVpc = new AwsVpc(this, 'DevVpc', {
     vpcName: 'dev-vpc',
     vpcCidr: '10.0.0.0/16',
     publicSubnetCidrMask: 24,
     privateSubnetCidrMask: 24,
     secureSubnetCidrMask: 24,
     maxAzs: 2,        // Reduce AZs
     natCount: 1       // Single NAT Gateway
   });
   ```

2. **Production Environments**: Use one NAT Gateway per AZ for high availability
   ```typescript
   const prodVpc = new AwsVpc(this, 'ProdVpc', {
     vpcName: 'prod-vpc',
     vpcCidr: '10.0.0.0/16',
     publicSubnetCidrMask: 24,
     privateSubnetCidrMask: 24,
     secureSubnetCidrMask: 24,
     maxAzs: 3,        // Multi-AZ
     natCount: 3       // One NAT per AZ
   });
   ```

3. **VPC Endpoints**: Reduce NAT Gateway data transfer costs by using VPC endpoints for AWS services

## Troubleshooting

### VPC Endpoint Connection Issues

**Problem**: Cannot connect to AWS services via endpoints

**Solution**: Ensure NACLs allow HTTPS (port 443):

```typescript
nacls: {
  private: [443]  // Required for VPC endpoints
}
```

### Insufficient Subnet IP Addresses

**Problem**: Running out of IP addresses in subnets

**Solution**: Adjust CIDR masks for more IPs (smaller mask = more IPs):

```typescript
publicSubnetCidrMask: 20,   // 4096 IPs per subnet
privateSubnetCidrMask: 20,  // 4096 IPs per subnet
```

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

MIT

## Support

For issues, questions, or feature requests, please open a GitHub issue.