Setting up a development environment in a private subnet for controlled access
TypeScriptTo set up a development environment in a private subnet on AWS with controlled access, we'll create a Virtual Private Cloud (VPC), a private subnet, an AWS Cloud9 environment for the development workspace, a NAT Gateway to allow the Cloud9 environment to access the internet for updates, and a security group to control inbound and outbound traffic.
Firstly, a VPC is a logical data center in AWS that allows you to launch AWS resources in a virtual network that you've defined. After setting up the VPC, we'll create a subnet. A subnet is a range of IP addresses in your VPC. In this case, we create a private subnet, meaning that instances launched into it don't have public IP addresses and can't be directly accessed from the internet.
Next, we'll configure an AWS Cloud9 environment, which is a cloud-based integrated development environment (IDE) that lets you write, run, and debug your code with just a browser. The
aws.cloud9.EnvironmentEC2
resource is used to set up this environment.To allow our Cloud9 environment in a private subnet to access the internet for package updates and other needs without exposing it to incoming internet traffic, we have to set up a NAT Gateway.
Finally, we'll create a security group, which acts as a virtual firewall for your instance to control inbound and outbound traffic.
Below is a TypeScript program using Pulumi to set up the above resources:
import * as aws from "@pulumi/aws"; // Create a new VPC. const vpc = new aws.ec2.Vpc("devVpc", { cidrBlock: "10.0.0.0/16", enableDnsSupport: true, enableDnsHostnames: true, tags: { Name: "dev-vpc", }, }); // Create an Internet Gateway for our VPC const igw = new aws.ec2.InternetGateway("devIgw", { vpcId: vpc.id, tags: { Name: "dev-internet-gateway", }, }); // Create a new private subnet in the VPC. const privateSubnet = new aws.ec2.Subnet("devSubnet", { vpcId: vpc.id, cidrBlock: "10.0.1.0/24", availabilityZone: "us-west-2a", // Change this to your preferred AZ tags: { Name: "dev-private-subnet", }, }); // Create an Elastic IP for our NAT gateway. const eip = new aws.ec2.Eip("natEip", { vpc: true, }); // Create a NAT Gateway for the private subnet. const natGw = new aws.ec2.NatGateway("devNatGw", { subnetId: privateSubnet.id, allocationId: eip.id, tags: { Name: "dev-nat-gateway", }, }); // Creating a route table for the private subnet to use the NAT Gateway. const privateRouteTable = new aws.ec2.RouteTable("privateRouteTable", { vpcId: vpc.id, routes: [{ cidrBlock: "0.0.0.0/0", natGatewayId: natGw.id, }] }); // Associate the private subnet with the route table. const privateRouteTableAssoc = new aws.ec2.RouteTableAssociation("privateRouteTableAssoc", { subnetId: privateSubnet.id, routeTableId: privateRouteTable.id, }); // Create the AWS Cloud9 EC2 development environment in the private subnet. const cloud9Env = new aws.cloud9.EnvironmentEC2("devCloud9Env", { instanceType: "t2.micro", // Choose the instance type for the environment subnetId: privateSubnet.id, automaticStopTimeMinutes: 30, ownerArn: aws.getCallerIdentity().then(id => id.arn), description: "Development environment", }); // Create a security group for the Cloud9 environment. const cloud9SecurityGroup = new aws.ec2.SecurityGroup("cloud9SecurityGroup", { description: "Allow SSH and Cloud9", vpcId: vpc.id, ingress: [{ protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"], // For the example, we allow SSH access from any IP. Replace with your IP range in production! }], egress: [{ protocol: "-1", fromPort: 0, toPort: 0, cidrBlocks: ["0.0.0.0/0"], }], }); // Export the VPC and subnet IDs export const vpcId = vpc.id; export const subnetId = privateSubnet.id; // Export the Cloud9 IDE URL export const cloud9EnvUrl = cloud9Env.ideUrl;
Here's what each section of the code does:
- VPC and Internet Gateway: The VPC is set up with a CIDR block and DNS settings. An Internet Gateway is attached to the VPC to allow the traffic from the NAT Gateway.
- Subnet: A private subnet is created within the VPC.
- Elastic IP (EIP) and NAT Gateway: An EIP is allocated and associated with a NAT Gateway deployed in the private subnet. It allows the EC2 instance within the private subnet to initiate outbound internet traffic without allowing inbound traffic.
- Route Table: We set up a route table with routes to allow the instances in the private subnet (the Cloud9 environment) to go out to the internet via the NAT Gateway.
- Cloud9 Environment: We provision a new Cloud9 EC2 environment in the private subnet, configuring it to stop automatically after 30 minutes of inactivity. It assumes the role of the current account.
- Security Group: We create a security group that acts as a virtual firewall, controlling the traffic to the Cloud9 instance. In the code, the SSH port is opened to all IPs for demonstration purposes; however, in a production environment, you should limit the IP range to known IPs for security.
To use this Pulumi program, you should replace placeholders and adjust values to fit your requirements, such as the
availabilityZone
, instance type, or IP ranges. After setting up the resources, we export the VPC and subnet IDs, as well as the Cloud9 environment URL, to be used elsewhere if needed.