AWS

Bad Practice: IAM Access Keys

IAM Access Keys, even when securely stored (such as in environment variables), due to their long-lived nature, remain active and valid until manually rotated or revoked. This poses a security risk as they provide continuous access if compromised.

import boto3
import os

# Long-lived credentials stored in environment variables

aws_access_key_id = os.getenv('AWS_ACCESS_KEY_ID')
aws_secret_access_key = os.getenv('AWS_SECRET_ACCESS_KEY')

# Initialize S3 client with long-lived credentials
client = boto3.client(
  's3',
  aws_access_key_id=aws_access_key_id,
  aws_secret_access_key=aws_secret_access_key
)

# List S3 buckets
response = client.list_buckets()
print("S3 Buckets:", response['Buckets'])

Good Practice: IAM Roles

The more secure approach is to use ephemeral credentials through AWS IAM roles. These credentials are short-lived and dynamically generated, limiting their validity. Even if compromised, they are only valid for a short time, drastically reducing the risk window.

How to Use Ephemeral Credentials with IAM Roles

To convert an IAM access key to a role in AWS, you first create an IAM role with the necessary permissions that match the original access key's usage.

You then update any applications or services to use the STS AssumeRole API, which allows them to assume the role and obtain temporary credentials instead of using long-term access keys.

Once the applications are successfully configured to use the role, you deactivate and delete the old access keys associated with the IAM user, improving security by using short-lived credentials and following best practices for AWS identity and access management.

import boto3

# Assume an IAM role to obtain ephemeral credentials
sts_client = boto3.client('sts')
response = sts_client.assume_role(
  RoleArn='arn:aws:iam::123456789012:role/YourRoleName',
  RoleSessionName='SessionName'
)

# Extract temporary credentials
credentials = response['Credentials']

# Use ephemeral credentials for the S3 client
client = boto3.client(
  's3',
  aws_access_key_id=credentials['AccessKeyId'],
  aws_secret_access_key=credentials['SecretAccessKey'],
  aws_session_token=credentials['SessionToken']
)

# List S3 buckets
response = client.list_buckets()
print("S3 Buckets:", response['Buckets'])

How it Works

Basically when a resource in one AWS account (Like EC2, Lambda Function, ECS Task, etc) wants to have access to a resource on another account it can “Assume” a role instead of using an long lived Access Key.

Source: AWS Security Blog
How Assuming a Role Works:
  1. When an entity (like an IAM user or AWS service) wants to assume a role, it makes a request to AWS STS. This request specifies the role ARN (Amazon Resource Name) of the role to assume.
  2. The request may come from a CLI command, SDK call, or AWS service using STS operations such as AssumeRole.
  3. STS then verifies that the requesting entity is allowed to assume the specified role.
Trust Policy:
  1. For an entity to assume a role, the role must have an associated trust policy. This trust policy is an IAM policy that explicitly defines who (which users, groups, or services) is trusted to assume the role.
  2. The trust policy uses a JSON format and typically looks like this:
{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Effect": "Allow",
   "Principal": {
    "AWS": "arn:aws:iam::123456789012:root"
   },
   "Action": "sts:AssumeRole"
  }
 ]
}

This policy allows the role to be assumed by users or services from the specified account (123456789012 in this case) or specific AWS services.

Temporary Security Credentials:
  • Once the role is successfully assumed, STS returns a set of temporary credentials that are valid only for the role being assumed.
  • The credentials include a session token in addition to the standard access key and secret key. The session token must be included in all API requests that use the temporary credentials, ensuring the credentials are only valid during the session duration.
Permissions Derived from the Role:
  1. The assumed role grants permissions based on its attached IAM policies. These policies define what actions and resources the role can access.
  2. Unlike an IAM user or service with long-term credentials, the permissions and access rights of an assumed role are confined by the role’s policies for the duration of the session.
Session Duration and Termination:
  • The session created by assuming a role lasts for a pre-defined period, after which the temporary credentials expire, and the entity loses access unless it assumes the role again.
  • Once the credentials expire, they can no longer be used to access AWS services, adding a layer of security.

Example in Pictures

You need to basically copy all of the policies attached to the IAM User that generated the IAM access key that you would like to convert and attach them to the new role that you are converting it to