DEV Community

bikash119
bikash119

Posted on

Foundation – Networking & IAM

This is Part 1 of a 3-part series on Deploy Docling to AWS ECS infrastructure.

AWS VPC Infrastructure Setup Guide

Overview

This guide provides step-by-step instructions for creating a secure Virtual Private Cloud (VPC) infrastructure on AWS using the AWS CLI. A VPC enables you to provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define.

Prerequisites

  • AWS CLI installed and configured with appropriate credentials
  • Basic understanding of networking concepts (CIDR blocks, subnets)
  • Appropriate IAM permissions for VPC and EC2 operations

Resource Tagging Strategy

Throughout this tutorial, we implement a consistent tagging strategy for all resources. This approach ensures:

  • Easy resource identification and tracking
  • Simplified cost allocation
  • Better resource organization and management

Standard tags used:

  • Name: Descriptive identifier for the resource
  • Environment: Development stage (e.g., Dev, Staging, Production)
  • Purpose: Project or application identifier

1. Virtual Private Cloud (VPC) Setup

Create the VPC

Create a VPC with a /16 CIDR block, providing approximately 65,536 IP addresses:

aws ec2 create-vpc \
    --cidr-block 10.0.0.0/16 \
    --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=DoclingVPC},{Key=Environment,Value=Dev}]'
Enter fullscreen mode Exit fullscreen mode

Note: The CIDR block 10.0.0.0/16 means all resources within this VPC will have IP addresses starting with 10.0.x.x, where the first two octets remain constant.

Store VPC ID for Future Reference

VPC_ID=$(aws ec2 describe-vpcs \
    --filters Name=tag-key,Values=Name \
    --query "Vpcs[?Tags[?Key=='Name' && Value=='DoclingVPC']].VpcId" \
    --output text)
Enter fullscreen mode Exit fullscreen mode

Apply Additional Tags

Create a tags.json file:

{
    "Tags": [
        {
            "Key": "Purpose",
            "Value": "DoclingSetup"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Apply the tags to the VPC:

aws ec2 create-tags --resources $VPC_ID --cli-input-json file://tags.json
Enter fullscreen mode Exit fullscreen mode

Verify VPC Creation

aws ec2 describe-vpcs \
    --filters Name=tag-key,Values=Purpose \
    --query "Vpcs[].[VpcId,CidrBlock,State]" \
    --output table
Enter fullscreen mode Exit fullscreen mode

2. Subnet Configuration

Subnets segment your VPC into smaller networks. We'll create both public and private subnets following AWS best practices.

Create Private Subnet

Deploy a private subnet in availability zone us-east-1b:

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.4.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PrivateSubnet-1b}]'
Enter fullscreen mode Exit fullscreen mode

Create Public Subnet

Deploy a public subnet in availability zone us-east-1a:

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.3.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=PublicSubnet-1a}]'
Enter fullscreen mode Exit fullscreen mode

Note: Each /24 subnet provides 256 IP addresses (though AWS reserves 5 IPs per subnet for internal use).

Retrieve Subnet IDs

# Get Private Subnet ID
PRIVATE_SUBNET=$(aws ec2 describe-subnets \
    --filters Name=tag-value,Values=PrivateSubnet-1b \
    --query "Subnets[0].SubnetId" \
    --output text)

# Get Public Subnet ID
PUBLIC_SUBNET=$(aws ec2 describe-subnets \
    --filters Name=tag-value,Values=PublicSubnet-1a \
    --query "Subnets[0].SubnetId" \
    --output text)
Enter fullscreen mode Exit fullscreen mode

Apply Tags to Subnets

aws ec2 create-tags --resources $PUBLIC_SUBNET --cli-input-json file://tags.json
aws ec2 create-tags --resources $PRIVATE_SUBNET --cli-input-json file://tags.json
Enter fullscreen mode Exit fullscreen mode

Verify Subnet Configuration

aws ec2 describe-subnets \
    --filters Name=tag-key,Values=Purpose \
    --query "Subnets[].[SubnetId,CidrBlock,AvailabilityZone]" \
    --output table
Enter fullscreen mode Exit fullscreen mode

3. Internet Gateway Configuration

An Internet Gateway (IGW) enables communication between your VPC and the internet.

Create Internet Gateway

IGW_ID=$(aws ec2 create-internet-gateway \
    --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=DoclingIGW}]' \
    --query "InternetGateway.InternetGatewayId" \
    --output text)
Enter fullscreen mode Exit fullscreen mode

Apply Tags

aws ec2 create-tags --resources $IGW_ID --cli-input-json file://tags.json
Enter fullscreen mode Exit fullscreen mode

Attach Internet Gateway to VPC

aws ec2 attach-internet-gateway \
    --internet-gateway-id $IGW_ID \
    --vpc-id $VPC_ID
Enter fullscreen mode Exit fullscreen mode

Verify Internet Gateway

aws ec2 describe-internet-gateways \
    --filters Name=tag-key,Values=Purpose \
    --query "InternetGateways[].[InternetGatewayId,Attachments[0].VpcId,Attachments[0].State]" \
    --output table
Enter fullscreen mode Exit fullscreen mode

4. Route Table Configuration

Route tables determine where network traffic is directed. AWS creates a main route table automatically with each VPC, but best practice dictates creating custom route tables for better security control.

Create Public Route Table

PUBLIC_ROUTE_TABLE_ID=$(aws ec2 create-route-table \
    --vpc-id $VPC_ID \
    --query "RouteTable.RouteTableId" \
    --output text)
Enter fullscreen mode Exit fullscreen mode

Add Internet Route

Configure the route table to direct internet-bound traffic through the Internet Gateway:

aws ec2 create-route \
    --route-table-id $PUBLIC_ROUTE_TABLE_ID \
    --destination-cidr-block 0.0.0.0/0 \
    --gateway-id $IGW_ID
Enter fullscreen mode Exit fullscreen mode

Associate Public Subnet with Route Table

PUBLIC_SUBNET_ASSOCIATION_ID=$(aws ec2 associate-route-table \
    --route-table-id $PUBLIC_ROUTE_TABLE_ID \
    --subnet-id $PUBLIC_SUBNET \
    --query "AssociationId" \
    --output text)
Enter fullscreen mode Exit fullscreen mode

Verify Route Table Configuration

aws ec2 describe-route-tables \
    --route-table-ids $PUBLIC_ROUTE_TABLE_ID \
    --query "RouteTables[].[RouteTableId,Routes[].DestinationCidrBlock,Associations[].SubnetId]" \
    --output table
Enter fullscreen mode Exit fullscreen mode

Security Best Practices

  1. Main Route Table: Never add internet routes to the main route table. This ensures new subnets don't accidentally become public.

  2. Subnet Isolation: Keep private subnets truly private by not associating them with route tables containing internet gateway routes.

  3. Multi-AZ Deployment: For production environments, deploy subnets across multiple availability zones for high availability.

  4. Network ACLs: Consider implementing Network Access Control Lists for additional subnet-level security.

AWS IAM Roles and Instance Profiles

AWS IAM operates on three fundamental components:

  1. Trust Relationship - Defines which entities can assume a role
  2. Permissions - Specifies what actions the role can perform
  3. Temporary Credentials - Provides time-limited access tokens for role assumption

IAM Implementation Process

  1. Create Trust Policy - Define which AWS services can assume the role
  2. Create Role - Establish the role with the trust policy
  3. Attach Permissions - Grant specific permissions to the role
  4. Create Instance Profile - Package the role for EC2 instances (when needed)
  5. Associate Resources - Link the role or instance profile to AWS resources

You may want to dive into the concepts here.

EC2 IAM Configuration

Trust Policy for EC2

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "ec2.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Create EC2 Instance Role

# Create the role
aws iam create-role \
  --role-name ec2_instance_role \
  --assume-role-policy-document file://ec2-trust-policy.json \
  --tags Key=Name,Value=EC2InstanceRole

# Add additional tags
aws iam tag-role \
  --role-name ec2_instance_role \
  --cli-input-json file://tags.json

# Attach managed policy
aws iam attach-role-policy \
  --role-name ec2_instance_role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role
Enter fullscreen mode Exit fullscreen mode

Create Instance Profile

# Create instance profile
aws iam create-instance-profile \
  --instance-profile-name ec2_instance_role-profile \
  --tags Key=Name,Value=EC2InstanceRoleProfile

# Add tags to instance profile
aws iam tag-instance-profile \
  --instance-profile-name ec2_instance_role-profile \
  --cli-input-json file://tags.json

# Associate role with instance profile
aws iam add-role-to-instance-profile \
  --role-name ec2_instance_role \
  --instance-profile-name ec2_instance_role-profile
Enter fullscreen mode Exit fullscreen mode

ECS IAM Configuration

Trust Policy for ECS Tasks

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "ecs-tasks.amazonaws.com" },
      "Action": "sts:AssumeRole"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

ECS Task Execution Role

The task execution role is required for ECS to pull container images and write logs on your behalf.

# Create ECS task execution role
ECS_TASK_EXEC_ROLE=$(aws iam create-role \
  --role-name ecs_task_exec_role \
  --assume-role-policy-document file://ecs-trust-policy.json \
  --tags Key=Name,Value=ECSTaskExecutionRole \
  --query "Role.RoleName" \
  --output text)

# Add tags
aws iam tag-role \
  --role-name $ECS_TASK_EXEC_ROLE \
  --cli-input-json file://tags.json

# Attach AWS managed policy for task execution
aws iam attach-role-policy \
  --role-name $ECS_TASK_EXEC_ROLE \
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
Enter fullscreen mode Exit fullscreen mode

ECS Task Role (Optional)

The task role provides permissions for your application code running inside the container.

Note: This role can be omitted if your application doesn't need AWS API access. Test without it first to determine if it's necessary.

# Create ECS task role (if needed)
ECS_ROLE=$(aws iam create-role \
  --role-name ecs_task_role \
  --assume-role-policy-document file://ecs-trust-policy.json \
  --tags Key=Name,Value=ECSTaskRole \
  --query "Role.RoleName" \
  --output text)

# Add tags
aws iam tag-role \
  --role-name $ECS_ROLE \
  --cli-input-json file://tags.json

# Attach application-specific policies as needed
# aws iam attach-role-policy --role-name $ECS_ROLE --policy-arn <policy-arn>
Enter fullscreen mode Exit fullscreen mode

Summary

You now have the essential IAM & networking foundation for our AWS ECS deployment.

Next Steps: In the next part of this series, we'll configure the EC2 infrastructure that will use these roles to run your containerized applications.

Top comments (0)