~ 16 min read

How to securely configure an AWS EC2 instance

AWS EC2 is one of the most popular and widely used services from AWS. With a variety of options available to tailor the EC2 instances as per one’s requirements, it also poses a risk of introducing security gaps in the form of misconfigurations or insecure defaults. In this article we discuss some of the ways that can help configure our EC2 instances securely.

Table of Contents

Introduction

Secure Configurations for EC2 Instances

     Enable IMDSv2

          Enable IMDSv2 for a new instance via Console

          Enable IMDSv2 for new instance with AWS CLI

          Enable IMDSv2 for existing instances with AWS CLI

     Implement least permissive security group rules

     Regular patching

          Patching multiple machines parallelly with SSM Agent

     Enable regular backups for EBS volumes

          Enable regular backups via AWS Console

          Enable regular backups with AWS CLI

     Encrypt EBS volumes

          Enable encryption via Console

          Enable encryption with AWS CLI

          Additional Notes

     Encrypt EBS snapshots

         Enable encryption for Snapshot via Console

          Enable encryption for Snapshot with AWS CLI

     Use trusted AMIs

     Utilize IAM roles to allow the instance to work with AWS resources

     Use VPCs and Subnets to isolate machines

          Virtual Private Cloud

                Create VPC via Console

                Create VPC with AWS CLI

          Subnet

                Create Subnet via Console

                Create Subnet with AWS CLI

     Enable detailed monitoring for instances

          Enable detailed monitoring via Console

          Enable detailed monitoring with AWS CLI

Conclusion

Introduction

AWS’ Elastic Compute Cloud, more popularly known as EC2, is a service that allows organizations to spin up virtual machines that can be used to host and run applications, databases, and much more. EC2 instances come with a wide variety of options - from selecting the number of CPU cores to disk space, memory, operating system, to name a few. The EC2 service also comes packed with different configuration options and settings for an instance to work with. Uncle Ben said, “With great power comes great responsibility” and in this case with a lot of settings to choose from, comes a lot of misconfigurations. Thus, in this article we will look at how we can securely configure our EC2 instances.

Secure Configurations for EC2 Instances

Although this is not an exhaustive list of actions to take to secure your instances, these configurations are a good starting point as they are easy to understand as well as implement. As one gets familiar with AWS and its various other services, additional (advanced) measures can be taken to further strengthen the security of EC2 instances. For now, we will stick to the list of security settings that are directly applicable to EC2 instances.

Enable IMDSv2

Instance metadata service (IMDS) provides information about the instance and various parameters associated with it such as user data that is specified at launch. IMDSv1 stored credentials in the endpoint which could be retrieved and then used to perform actions with say AWS CLI with those credentials. This could prove devastating in the case of the credentials being exfiltrated and thus IMDSv2 was introduced to stop various attacks against the abuse of metadata endpoints. IMDSv2 uses a session but does not store the session token as information in the endpoint itself, making it impossible to retrieve the token after it is generated in subsequent calls.

Enable IMDSv2 for a new instance via Console

When launching an instance, under “Configure Instance Details” page, navigate to the “Advanced Details” section and:

  • Select “Enabled” for “Metadata accessible” option

  • Select “V2 (token required)” for “Metadata version” option

Metadata version

Enable IMDSv2 for new instance with AWS CLI

To enable IMDSv2 while launching an instance with AWS CLI, use the following flag in the command:

aws ec2 run-instances —image-id <IMAGE_ID> \
\
—metadata-options “HttpEndpoint=enabled,HttpTokens=required”

Enable IMDSv2 for existing instances with AWS CLI

Run the following AWS CLI command to modify the instance and enable IMDSv2:

aws ec2 modify-instance-metadata-options \
—instance-id <INSTANCE_ID> \
—http-tokens required \
—http-endpoint enabled

Implement least permissive security group rules

Security groups are firewalls that define permitted inbound and outbound reachability to and from the instance to various other resources, on public internet as well as within the VPCs. It is important to ensure that we expose only those services running on the instance that are required and limit the access to only those users / groups who require it. For that we need to add security group rules that are as explicit as possible. For example, instead of using 0.0.0.0/0 as the allowed source for SSH protocol, we can specify a common VPN that the team that needs access to the instance uses as the source explicitly.

AWS has extensive documentation for creating and managing Security groups and rules which can be found here.

Regular patching

Patching refers to the activity of applying software updates to the operating system for a performance upgrade, bug fixes, and security fixes released by the vendor that maintains the operating system.

The steps for patching differ from OS to OS but the idea essentially remains the same, use the operating system’s mechanism to check if there is a patch/update available and apply it. Some patches also require reboots for the system although this is not always the case.

For example, the following steps can be performed to patch an EC2 instance running Ubuntu 18.04 as the operating system:

  1. SSH into the EC2 instance
  2. Run sudo apt update
  3. Run sudo apt upgrade
  4. Run sudo reboot

Patching multiple machines parallelly with SSM Agent

Applying a patch manually is fine if the number of instances we are dealing with is small, say 10. But in most real-life cases, the number is usually bigger than that, and thus patching manually becomes a fairly daunting task. Thankfully, AWS has a service called Systems Manager, or SSM for short. SSM can execute commands on multiple machines simultaneously and take away the hassle of manually accessing one machine at a time, making it an amazingly useful tool to utilize.

The following article from Kloudle Academy can be used to understand how to patch multiple EC2 servers using AWS SSM under the section “Patching multiple machines on AWS and GCP > AWS with SSM”

Enable regular backups for EBS volumes

Data stored on EC2 instances should be regularly backed up to avoid issues of data loss due to disk failures, data corruption, etc. AWS; Data Lifecycle Manager is a service that can be utilized to create a backup schedule to take automated backups of our EBS volumes.

Enable regular backups via AWS Console

To enable regular backup with Amazon Data Lifecycle Manager from the console, follow the below mentioned steps:

  1. Navigate to the EC2 details page and then select the “Lifecycle Manager” link under the “Elastic Block Storage” sub-menu
  2. Select the “EBS snapshot policy” and click on the “Next step” button

EBS snapshot policy

  1. Select the target resource type - Volume or Instance and specify the tag to identify the selected resource type and click on the “Add” button

‍Select the target resource type - Volume or Instance and specify the tag to identify the selected resource type and click on the “Add” button

  1. Add a description for the backup policy

Add a description for the backup policy

  1. Add necessary tags for the policy

Add necessary tags for the policy

  1. Ensure “Enabled” option is selected in the “Policy status” section and click on the “Next” button

Ensure “Enabled” option is selected in the “Policy status” section and click on the “Next” button

  1. Add details for the backup schedule as per requirement, ideally, a daily backup is recommended

Add details for the backup schedule as per requirement, ideally, a daily backup is recommended

  1. Scroll down and click on the “Review policy” button

Scroll down and click on the “Review policy” button

  1. Lastly, click on the “Create policy” button to create the backup policy and schedule

Lastly, click on the “Create policy” button to create the backup policy and schedule

Enable regular backups with AWS CLI

To enable regular backup with Amazon Data Lifecycle Manager with AWS CLI, follow the below-mentioned steps:

  1. Create a file called policy.json and add the following contents in the file replacing the configuration as required

  1. Obtain the ARN of the IAM role that would be used to create the backup for EBS volumes
  2. Lastly, run the following AWS CLI command

aws dlm create-lifecycle-policy \
—description “My first policy” \
—state ENABLED \
—execution-role-arn <ARN_OF_IAM_ROLE> \
—policy-details file:///path/to/policy.json

Encrypt EBS volumes

EBS volumes should be encrypted to ensure that the data they hold cannot be read or misused by unauthorized entities who may have gained access to the volume. We can enable a configuration to enforce encryption on all EBS volumes by default when they are created.

Enable encryption via Console

To enable encryption by default for the AWS account with AWS CLI, the following steps can be used:

  1. Navigate to the EC2 dashboard page and click on the “EBS encryption” link

Navigate to the EC2 dashboard page and click on the “EBS encryption” link

  1. Click on the “Manage” button

Click on the “Manage” button

  1. Select the checkbox “Enable” for “Always encrypt new EBS volumes” setting and click on “Update EBS encryption” button

Select the checkbox “Enable” for “Always encrypt new EBS volumes” setting and click on “Update EBS encryption” button

Enable encryption with AWS CLI

To enable encryption by default for the AWS account with AWS CLI, the following command can be used:

aws ec2 enable-ebs-encryption-by-default

Additional Notes

The above configuration encrypts new EBS volumes that are created in the account. To encrypt existing volumes this documentation by AWS can be used as a reference.

Encrypt EBS snapshots

EBS snapshots are used as backups for EBS volumes which can be used to recover instance states, launch new instances from the backup, etc. Since EBS snapshots are essentially equivalent to the EBS volumes themselves, ensuring that the snapshots are encrypted as well as their counterpart EBS volumes is necessary.

A good feature in EC2 snapshots is that when a snapshot is created for a volume that is encrypted, the snapshot too is encrypted by default thus eliminating the need for ever having to encrypt snapshots that were created after enabling EBS encryption setting we configured in the previous section on encrypting EBS volumes. That being said, there might be old snapshots that are unencrypted that we need to encrypt which can be done by creating a copy of the unencrypted snapshot, and for the new, copied snapshot we will enable encryption.

Enable encryption for Snapshot via Console

To enable encryption for an existing unencrypted snapshot via Console, the following steps can be performed:

  1. Navigate to the EC2 dashboard
  2. Click on the “Snapshots” link under the “Elastic Block Storage” sub-menu
  3. Select the snapshot to make an encrypted copy for, click on the Actions drop-down, and click on the “Copy snapshot” option

Copy snapshot

  1. In the “Copy snapshot” page, ensure that the “Encrypt this snapshot” checkbox is selected under the “Encryption” section and click on the “Copy snapshot” button

Encrypt this snapshot

  1. Optionally, a different KMS key can be chosen instead of the default one

Enable encryption for Snapshot with AWS CLI

To enable encryption for an existing snapshot with AWS CLI, the following command can be run:

aws ec2 copy-snapshot \
—source-region <SOURCE_SNAPSHOT_REGION> \
—source-snapshot-id <SOURCE_SNAPSHOT_ID> \
—encrypted \
—kms-key-id <KMS_KEY_ALIAS>

Use trusted AMIs

Amazon Machine Images or AMIs are launch configuration packages for EC2 instances that need to be specified when launching an instance. These AMIs can be created by anyone and shared with specific AWS accounts or with everyone by making them public. This may lead to a possibility where a malicious AMI may be shared. Thus as a security measure, we should either create and use AMIs ourselves for our instances or use public AMIs that are published by trusted vendors only. One such trusted AMI is the Amazon Linux Image that is created and maintained by Amazon itself. Other images can also be trusted although based on the vendor, not the name, as one can create an image and call it Ubuntu, for example, but the publisher may not actually be associated with the Canonical Group that maintains and releases Ubuntu Operating Systems.

AMIs selected at the time of launching an image are not exactly a configuration associated with the instance, so there are no specific steps to take in the case of this security measure. The AMI being used needs to be vetted for trust before usage, and at the time of launching an instance:

  1. With the console, the AMI needs to be selected from the available list present

  2. With the AWS CLI, the appropriate AMI ID needs to be supplied to launch the instance

Utilize IAM roles to allow the instance to work with AWS resources

IAM roles are used to delegate permissions to perform actions on AWS resources and perform their required roles. When an IAM role is attached to an EC2 instance, it is called an instance role, and this instance role can be used by the server to perform permitted actions, for example, uploading a local backup to an S3 bucket.

Least-privilege access is a security best practice where we add the exact permission(s) that a role (or in other cases, an IAM user) requires to perform its job. Applying this principle to IAM roles that are attached to instances, only the permissions that are required by the instance to perform its job should be added to the instance role and nothing else. This ensures that in the case of the credentials getting leaked, the damage is minimized.

Configuring the least-privilege permission for an IAM role is very contextual i.e. it cannot be generalized thus, it goes beyond the scope of this article to provide an exhaustive list of combinations of different possible permissions that can be utilized by an instance and the various use-cases.

Use VPCs and Subnets to isolate machines

Virtual Private Cloud

Virtual Private Cloud or VPC is an AWS service that allows users to create virtual networks that are isolated logically from one another. Talking specifically about EC2 instances, as an example, we can think of a case where some EC2 instances need to access only internal resources and do not require access to the internet. For such instances, we can create a VPC that does not allow inbound and outbound connections from the internet so the communication can only happen between resources in the same VPC. The following documentation from AWS can be used to understand how to create new VPCs.

Create VPC via Console

Perform the following steps to create a new VPC:

  1. Navigate to the VPC management page
  2. Click on the “Launch VPC Wizard” button

Click on the “Launch VPC Wizard” button

  1. Choose the “VPC with a Single Public Subnet” option and click on the “Select” button, we can add more subnets later if we want to

Choose the “VPC with a Single Public Subnet” option and click on the “Select” button, we can add more subnets later if we want to

  1. Provide the IPv4 CIDR block for the VPC and click on the “Create VPC” button

Provide the IPv4 CIDR block for the VPC and click on the “Create VPC” button

Create VPC with AWS CLI

Run the following command to create a new VPC with the specified CIDR being 192.168.0.0/16:

aws ec2 create-vpc —cidr-block 192.168.0.0/16

Subnet

Subnets are sub-components within a VPC that can further segregate resources within smaller virtual networks. For example, a VPC created with CIDR block 192.168.0.0/16,can have subnets 192.168.1.0/24 and 192.168.2.0/24 , where both subnets are within the same VPC but isolated from each other.

Create Subnet via Console

Perform the following steps to create a new VPC:

  1. Navigate to the VPC management page
  2. Click on the “Subnets” link for the “Virtual Private Cloud” menu

Click on the “Subnets” link for the “Virtual Private Cloud” menu

  1. Click on the “Create subnet” button

Click on the “Create subnet” button

  1. Select the VPC to create the Subnet inside

Select the VPC to create the Subnet inside

  1. Add the CIDR block for the subnet and optionally a name and tags

Add the CIDR block for the subnet and optionally a name and tags

  1. Lastly, click on the “Create subnet” button

Lastly, click on the “Create subnet” button

Create Subnet with AWS CLI

Run the following command to create a new Subnet within CIDR block  192.168.1.0/24:

aws ec2 create-subnet —vpc-id <VPC_ID> —cidr-block 192.168.1.0/24

Enable detailed monitoring for instances

EC2 instances have basic monitoring in place by default from the time of launch. The basic monitoring is good-to-have, but more often than not, it falls inadequate, and here comes detailed monitoring for EC2 instances such as CPU credit metrics, instance metrics, and so forth.

Enable detailed monitoring via Console

Perform the following steps to enable detailed monitoring for EC2 instances via console:

  1. Navigate to the EC2 Dashboard
  2. Select the instance that detailed monitoring needs to be enabled for, click on the “Actions” drop-down menu, choose the “Manage detailed monitoring option” under the “Monitor and troubleshoot” sub-menu

Select the instance that detailed monitoring needs to be enabled for, click on the “Actions” drop-down menu, choose the “Manage detailed monitoring option” under the “Monitor and troubleshoot” sub-menu3. Ensure that the “Enable” checkbox is selected and click on the “Save” button

Ensure that the “Enable” checkbox is selected and click on the “Save” button

Enable detailed monitoring with AWS CLI

Run the following AWS CLI command to enable detailed monitoring for existing instances:

aws ec2 monitor-instances —instance-ids <INSTANCE_IDS>

Run the following AWS CLI command to enable detailed monitoring when launching a new instance:

aws ec2 run-instances —image-id <AMI_ID> —monitoring Enabled=true #Amongst other options/flags

Conclusion

EC2 is an extensively utilized service offered by AWS, to run our applications and so much more. With its list of extensive usability, comes a longer list of options to apply to these instances which can lead to misconfigurations or use of insecure default configurations.

In this article we took a look at the various security measures we can take to secure our EC2 instances, some by applying settings directly on the EC2 instances like using trusted AMIs or enabling IMDSv2, and some that align with the instance tangentially such as using VPCs to isolate various instances from each other or encrypting the EBS volumes and snapshots. In all these cases we saw why these configurations are highly recommended to use if not outright mandatory to apply.

***

This article is brought to you by Kloudle Academy, a free e-resource compilation, created and curated by Kloudle. Kloudle is a cloud security management platform that uses the power of automation and simplifies human requirements in cloud security. If you wish to give your feedback on this article, you can write to us here.

;