DEV Community

Nuwan Arambage
Nuwan Arambage

Posted on • Edited on

Terraform in AWS | Provision EC2 with AWS Systems Manager SSM access

You all come across this task which I'm going to discuss today. It is a trivial and most common one if you start to work on DevOps stuff. This is all about provisioning EC2 instance using terraform. It is somewhat extenstive version of EC2 instance provisioning because of below reasons.

  1. All TF configurations which are environment specific inside the infra-configs.tfvars file.

  2. All configurations are in human readable format which means no subnet_id, no vpc_id. It has only vpc_name, security_group_names etc. How we do it is , id are retrived via terraform data blocks where ever possible.

  3. It uses the tagging which is most important in Enterprise cloud application environment

  4. Multiple ingress rules can be configured via infra-configs.tfvars config file rather .tf file itself.

  5. It supports configuring multuple subnets and it chooses one subnet randomly to spin up EC2 instance.

  6. TF code written in a modularized approach where iam role, security group, ec2 provisioned via seperate modules.

Code is published into github public repository. Git repo URL is mentioned here.
https://github.com/arambage0/cloud-infra-wyoc/tree/main/terraform/provision_ec2_ssm

Well, there are prerequisites in order to setup SSM access to EC2. There is a nice blog https://dev.to/aws-builders/securely-access-your-ec2-instances-with-aws-systems-manager-ssm-and-vpc-endpoints-1bli#how-to-use-ssm-for-ssh-less-login written by https://dev.to/sunnynazar so I would like to extact details from his blog because it is nicely written and I do not want to repeat myself here. I would extact few details from his blog to show up prerequisites.

Prerequisites for SSM to work with EC2

Security Group for EC2 Instance: The minimum traffic you need to allow for SSM access to work is to add an Outbound HTTPS (port 443) in the security group for EC2 instance.

Create an IAM Role: To use SSM to log in to EC2 instances, you must first create an IAM role with the required permissions. The role must have the AmazonSSMManagedInstanceCore policy attached to it, which allows SSM to access the EC2 instances.

Install SSM Agent: After creating the IAM role, you need to install the SSM agent on each EC2 instance you want to access using SSM. The SSM agent is pre-installed on Amazon Linux 2 and Amazon Linux AMIs, but you must install it manually on other instances.

Configure EC2 Instances: Once the SSM agent is installed, you need to configure your EC2 instances to allow SSM access. You can do this by creating a VPC endpoint for SSM. VPC endpoints which are required when using Private Subnets are below:

com.amazonaws.region.ec2messages
com.amazonaws.region.ssmmessages
com.amazonaws.region.ssm
com.amazonaws.region.kms (This is needed if you want to use AWS KMS encryption for Session Manager.)

Note:The security group for VPC Endpoints must allow inbound HTTPS (port 443) traffic from the resources in your VPC that communicate with the service.

In the terraform code published into the repo works in a already provisioned cloud infrastructure where subnets, vpc endpoints are available and ssm agent is baked into ami that we used to spin up the EC2 instance.

As part of the terraform code, it provisions IAM role, EC2 isntance profile, security group and EC2 with best practices which are used in the Industry.

If you are eager to execute the code. Following steps are for you.

Step 1: Clone the git repository https://github.com/arambage0/cloud-infra-wyoc.git

  `git clone https://github.com/arambage0/cloud-infra-wyoc.git`
Enter fullscreen mode Exit fullscreen mode

Step 2: Configure the tfvar file infra-configs.tfvars. The most mandatory ones are region, vpc_name, instance_type, key_name, private_subnets, pre_existing_sg_names depends on your environment.

cd terraform/provision_ec2_ssm/configs/nonprod/
vim infra-configs.tfvars

region          = "eu-west-1"
vpc_name        = "LSA-NONPROD-LTSQA-vpc"
instance_type   = "t2.large"
key_name        = "lsa-nonprod-ire-private-key"
private_subnets = ["LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1a", "LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1b", "LSA-NONPROD-LTSQA-app_internal_subnets-eu-west-1c"]
instance_name   = "app-node01"

sg_name        = "AppNodeSecurityGroup"
sg_description = "Allow multiple ports"

# Existing Security Groups
pre_existing_sg_names = ["App-Tier-LTSQA-SG", "App2Endpoint-Tier-LTSQA-SG"]


sg_ingress_rules = [
  {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  },
  {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  },
  {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["20.101.58.0/23"]
  }
]

role_name                       = "AppNodeSSMEC2Role"
ssm_policy_name                 = "AmazonSSMManagedInstanceCore"
permission_boundary_policy_name = "ServiceRoleBoundary"
instance_profile_name           = "AppNodeSSMInstanceProfile"


environment       = "non-prod"
environment_level = "nonprod-e2e"
project_prefix    = "saga-lts"


mandatory_tags = {
  ApplicationName    = "SAGASurveillanceAnalytics"
  ApplicationID      = "APP-80897"
  CostCentre         = "L96532-IMO"
  ProjectCode        = "P007723"
  Environment        = "LTS-NONPROD"
  DataClassification = "Restricted"
  ManagedBy          = "XYO"
  Automation         = "YES"
}



recommended_tags = {
  BusinessUnit        = "LSEGSurveillance"
  Owner               = "AWS-SAGA-LTS-NONPROD@SAGA.COM"
  BusinessCriticality = "1"
  AssignmentGroup     = "CMUKAppSupportSurv"
}


optional_tags = {
  Account  = "AWS-SAGA-LTS-NONPROD"
  Workload = "NONPROD"
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Configure the configs.tf file as well for mentioning terraform s3 configuration. For instance bucket, key, region, dynamodb_table

vim configs.tf

terraform {
  backend "s3" {
    bucket         = "my-wyoc-s3-bucket"
    key            = "terraform/state/my-project.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "my-wyoc-state-lock" 
    encrypt        = true
  }
}

provider "aws" {
  region = var.region
}
Enter fullscreen mode Exit fullscreen mode

Step 4: After that, we are good to execute terraform commands.

cd /<YOUR_OWN_DIRECTORY_PATH>/cloud-infra-wyoc/terraform/provision_ec2_ssm
terraform init
terraform plan -var-file="./configs/nonprod/infra-configs.tfvars"
terraform apply -var-file="./configs/nonprod/infra-configs.tfvars"

Ok cool. If you come to this stage successfully, we are really good to login to EC2 machine via SSM.

First of all check the EC2 status. You should see EC2 status is running and both ec2 status should be completed OK. Once it is okay, you try login via SSM.

Happy learning for all of you and thanks for reading. I would like to add a nice quote. It grabs my attention.

"We learn by doing things. We learn by experimenting thigs. We learn by breaking and fixing things."

Top comments (0)