Table of contents
No headings in the article.
In this article, ec2 (Amazon Linux) will be configured with Cloud Watch to send its logs.
All the resources will be created with Terraform.
Let's start with VPC, subnet, route tables & etc..
resource "aws_vpc" "vpc" {
cidr_block = var.vpc_cidr
instance_tenancy = "default"
tags = {
Name = "${var.environment}-vpc"
}
}
resource "aws_internet_gateway" "igw" {
vpc_id = aws_vpc.vpc.id
depends_on = [
aws_vpc.vpc
]
tags = {
"Name" = "${var.environment}-igw"
}
}
resource "aws_subnet" "subnet" {
vpc_id = aws_vpc.vpc.id
cidr_block = var.subnet_cidr
tags = {
Name = "${var.environment}-subnet"
}
}
resource "aws_route_table" "public-rt" {
vpc_id = aws_vpc.vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.igw.id
}
tags = {
"Name" = "${var.environment}-public-route-table"
}
}
resource "aws_route_table_association" "rta-sub" {
subnet_id = aws_subnet.subnet.id
route_table_id = aws_route_table.public-rt.id
}
resource "aws_security_group" "sg" {
name = "${var.environment}-demo-sg"
vpc_id = aws_vpc.vpc.id
ingress {
from_port = var.security_group_open_port[0]
to_port = var.security_group_open_port[1]
protocol = "tcp"
cidr_blocks = [local.workstation_external_ip]
}
egress {
from_port = 0
to_port = 0
protocol = -1
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_security_group_rule" "access_for_ip" {
for_each = toset(var.security_group_allow_ip)
type = "ingress"
from_port = var.security_group_open_port[0]
to_port = var.security_group_open_port[1]
protocol = "tcp"
cidr_blocks = [each.value]
security_group_id = aws_security_group.sg.id
}
In security group block, ingress cidr_block is configured to local.workstation_external_ip. This will be your local-machine public IP, which you can see at whatismyipaddress.com
Now, we have to get the IP through terraform.
get_external_ip.tf
data "http" "workstation-external-ip" {
url = "http://ipv4.icanhazip.com"
}
locals {
workstation_external_ip = "${chomp(data.http.workstation-external-ip.body)}/32"
}
resource "tls_private_key" "ssh" {
algorithm = "RSA"
rsa_bits = "4096"
}
resource "local_file" "ssh_private_key" {
content = tls_private_key.ssh.private_key_pem
filename = "./tls/private.pem"
file_permission = "0600"
}
resource "aws_key_pair" "tf-ssh-key" {
key_name = "${var.environment}-ssh-key"
public_key = tls_private_key.ssh.public_key_openssh
}
resource "aws_instance" "ec2" {
count = var.instance_count
ami = var.instance_ami
instance_type = var.instance_type
key_name = aws_key_pair.tf-ssh-key.key_name
vpc_security_group_ids = [aws_security_group.sg.id]
tags = {
Name = "${var.environment}-vm"
}
associate_public_ip_address = true
subnet_id = aws_subnet.subnet.id
iam_instance_profile = aws_iam_instance_profile.profile.id
user_data = <<-EOF
#!/bin/bash
yum update -y
yum install -y awslogs
systemctl start awslogsd
EOF
}
resource "aws_iam_policy" "logs-push-policy" {
name = "cw-policy-to-push-logs-to-ec2"
path = "/"
description = "cw-policy-to-push-logs-to-ec2"
policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
})
}
resource "aws_iam_role" "ec2-cw-role" {
name = "cw-ec2-logs-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "attach-cw-role" {
role = aws_iam_role.ec2-cw-role.id
policy_arn = aws_iam_policy.logs-push-policy.id
}
resource "aws_iam_instance_profile" "profile" {
name = "ec2-cw-profile"
role = aws_iam_role.ec2-cw-role.id
}
variable "region" {
default = "us-east-1"
}
variable "environment" {
default = "dev"
}
variable "vpc_cidr" {
default = "18.0.0.0/16"
}
variable "subnet_cidr" {
default = "18.0.0.0/24"
}
variable "security_group_open_port" {
default = [22, 22]
}
variable "security_group_allow_ip" {
default = ["180.0.0.0/32"]
}
variable "instance_count" {
default = 1
}
variable "instance_type" {
default = "t2.micro"
}
variable "instance_ami" {
default = "ami-026b57f3c383c2eec" ## amazon linux
}
output "local_workstation_ip" {
value = local.workstation_external_ip
}
output "ec2_public_ip" {
# value = aws_instance.ec2[0].public_ip
value = aws_instance.ec2[*].public_ip
}
Run terraform commands to create resourcs
$ terraform init
$ terraform plan
-> Plan: 15 to add, 0 to change, 0 to destroy.
$ terraform apply --auto-approve
->
Apply complete! Resources: 15 added, 0 changed, 0 destroyed.
Outputs:
ec2_public_ip = [
"52.87.50.72",
]
local_workstation_ip = "***.49.55.31/32"
Once resources are created, check In-bound Rule in Security Groups
go to AWS Dashboard > VPC management > Security Groups
Now, try ssh log-in with private key generated in tls folder. Get public IP from outputs.
$ ssh -i ./tls/private.pem ec2-user@52.87.50.72
Check Cloudwatch logs go to AWS Dashboard > CloudWatch > Log groups > /var/log/messages
Destroy the resources once done
$ terraform destroy
-> Destroy complete! Resources: 15 destroyed.
Terraform code will be available at Github.
Thanks for reading.... :)