AWS VPC Automation Setup in Ruby

What is VPC?

A virtual private cloud (VPC) is an on-demand configurable pool of shared computing resources allocated within a public cloud environment, providing a certain level of isolation between the different VPC resources. The isolation between one VPC resource and all other resources of the same cloud is achieved normally through allocation of a private IP subnet and a virtual communication construct per resources.

While Amazon Web Service has provision to setup a VPC manually through it’s console, the process isquite time consuming and might not be conducive at all times. It ususallytakes several hoursand can fail if not done appropriately.

An automated setup in Ruby can resolve this and reduce the time consumption by more than 70%.

Following are the key concepts for Amazon VPC and their definitions: 

  • Subnets
  • Route tables
  • Internet gateway
  • NAT gateway
  • Security groups

nat-gateway-diagram

 

Subnets:

A subnet is a range of IP addresses in your VPC. You can launch AWS resources into a subnet that you select. Use a public subnet for resources that must be connected to the Internet, and a private subnet for resources that won’t be connected to the Internet.

 Route Tables:

A route table contains a set of rules, called routes, that are used to determine where network traffic is directed.

Each subnet in your VPC must be associated with a route table; the table controls the routing for the subnet. A subnet can only be associated with one route table at a time, but you can associate multiple subnets with the same route table

Internet Gateway:

An Internet gateway is a horizontally scaled, redundant, and highly available VPC component that allows communication between instances in your VPC and the Internet.

NAT gateway:

NAT gateway is to enable instances in a private subnet to connect to the Internet (for example, for software updates) or other AWS services

Security Groups:

A security group acts as a virtual firewall for your instance to control inbound and outbound traffic. Security groups act at the instance level, not the subnet level. For each security group, you add rules that control the inbound traffic to instances, and a separate set of rules that control the outbound traffic.

VPC Environment Setup in Ruby

 We will be using the AWS-SDK ruby gem to access AWS API services for the setup.

 Steps to follow: 

  1. AWS Client initialization
  2. Creating VPC
  3. Creating Internet gateway
  4. Creating Route table
  5. Associate Route table and Internet gateway
  6. Creating Subnets
  7. Creating NAT gateway
  8. Creating Security group

Setp 1 : AWS Client initialization

Here, we are using Oregan (us-west-2) region.

# Initialize AWS EC2 client

begin

@ec2client = Aws::EC2::Client.new(region: ”us-west-2”)

rescue

raise "Failed to get EC2 client"

end

Setp 2 : Creating VPC

 To create a VPC, we have to pass CIDR block IP

@vpc = @ec2client.create_vpc({ :cidr_block => "10.0.0.0/16"})[:vpc]

Setp 3 : Creating Internet gateway(IGW)

Creating internet gateway is a two step process. First we have to create an IGW. Second, we have to attach the created IGW to the VPC.

igw = @ec2client.create_internet_gateway()[:internet_gateway]

@ec2client.attach_internet_gateway({

:internet_gateway_id => igw[:internet_gateway_id],

:vpc_id => @vpc[:vpc_id]

})

Setp 4 : Creating Route table

 To create a Route table we have to pass the VPC id as input,

 @routeTable = @ec2client.create_route_table({:vpc_id => @vpc[:vpc_id]})[:route_table]

Step 5 : Associate Route table and Internet gateway

 We have to associate the route table and internet gateway to enable traffic between AWS resources.

@ec2client.create_route({

:route_table_id => @routeTable[:route_table_id],

:destination_cidr_block => "0.0.0.0/0",

:gateway_id => igw[:internet_gateway_id]

})

Step 6 : Creating Subnets

We have to create atleast one public subnet to receive inbound traffic directly from the Internet. If your application is not receiving inbound traffic directly from the Internet then there would be no need to create Public subnets.

  1. a) Creating Public Subnet: 

For better performance we need to create public subnets for each availability zone.

@public_subnet = @ec2client.create_subnet({

:vpc_id => @vpc[:vpc_id],

:cidr_block => "10.0.10.0/24",

:availability_zone => "us-west-2a"

})[:subnet]

After creating the subnet we have to associate the route table to the subnet,

@ec2client.associate_route_table({

:subnet_id => @public_subnet[:subnet_id],

:route_table_id => @routeTable[:route_table_id]

})[:association_id]

  1. b) Creating Private Subnet: 

              

@private_subnet = @ec2client.create_subnet({

:vpc_id => @vpc[:vpc_id],

:cidr_block => "10.0.10.0/24",

:availability_zone => "us-west-2a"

})[:subnet]

After creating the subnet we have to map private access,

@ec2client.create_tags({

:resources => [

@private_subnet[:subnet_id]

],

:tags => [{:key => "access", :value => "private"}]

})

Step 7 : Creating NAT gateway

 To create NAT gateway we have to pass the public subnet Id and the elastic IP,

at_gateway = @ec2client.create_nat_gateway({

subnet_id: @public_subnet, # required

allocation_id: @elastic_ip, # required

})

Step 8 : Creating Security group

 

I suggest that we create atleast two Security groups for better security purposes; one for Public facing resources and another for Private resources.

  1. a) Public Security Group

             While adding ssh access instead of default port (22), configure different ports for public facing security groups. 

  1. b) Private Security Group 

            While adding ssh access restrict for private security groups, allow access only for resources available inside the same VPC environment. 

For all inbound port config allow access for the public security group alone

@ec2client.create_security_group(

group_name: group_name,

description: group_description,

vpc_id: @vpc[:vpc_id]

)

After successful creation of security group we need to configure the ports,

@ec2client.authorize_security_group_ingress(

group_id: sg_id,

ip_permissions: [

{

ip_protocol: "protocol",

to_port: port,

from_port: port,

ip_ranges:[

{

cidr_ip: cidr_ip,

}]

}]

)

This is all that we need as a script to get the VPC environment all set and automated in Ruby. As mentioned in the beginning of this article, this will greatly reduce the time and complexity involved in manually setting up VPC enovironment in AWS. In the next article, we shall see how to deploy a Ruby on Rails application inside this VPC setup.