Cybersecurity/AWS Cybersecurity papers/AWS Secrets Example: Difference between revisions

From Cramsession
Jump to navigationJump to search
✍️ Verified Author: Mflavell • Click to view professional profile & credentials
(Created page with "== AWS Secrets Manager Retrieval on EC2 via IAM Instance Profiles == === Overview === This guide details the end-to-end setup for creating a secret in AWS Secrets Manager, granting access to an Amazon EC2 instance using an IAM instance profile (eliminating hardcoded credentials), configuring a Python runtime environment on Amazon Linux, and retrieving the secret payload programmatically using boto3. === Architecture & Security Model === * '''AWS Secrets Manager''': St...")
 
Line 172: Line 172:


AWS Secrets Manager incurs $0.40/secret/month (prorated hourly). To prevent ongoing charges after completing lab tests, force-delete the secret without entering the default recovery retention period:
AWS Secrets Manager incurs $0.40/secret/month (prorated hourly). To prevent ongoing charges after completing lab tests, force-delete the secret without entering the default recovery retention period:
=== Troubleshooting Matrix ===
{| class="wikitable"
|-
! Symptom !! Root Cause !! Remediation
|-
| botocore.exceptions.NoCredentialsError
| No IAM role attached to EC2; IMDS unreachable.
| Verify IAM instance profile association or ensure instance metadata options allow hop limit >= 2 if running in containers. |
| --- |
| TypeError: unsupported operand type(s) for |
| Running Python < 3.10 with PEP 604 type unions. |
| Add from **future** import annotations as line 1 or use typing.Union[dict, str]. |
| - |
| ClientError: AccessDeniedException |
| IAM policy ARN mismatch or missing secretsmanager:GetSecretValue. |
| Ensure the policy Resource ARN matches the full secret ARN wildcard (Secrets Manager appends random suffix characters to names). |
| } |

Revision as of 01:57, 5 October 2026

AWS Secrets Manager Retrieval on EC2 via IAM Instance Profiles

Overview

This guide details the end-to-end setup for creating a secret in AWS Secrets Manager, granting access to an Amazon EC2 instance using an IAM instance profile (eliminating hardcoded credentials), configuring a Python runtime environment on Amazon Linux, and retrieving the secret payload programmatically using boto3.

Architecture & Security Model

  • AWS Secrets Manager: Stores sensitive configuration data encrypted at rest with AWS KMS.
  • IAM Instance Profile: Temporary security credentials rotated automatically via the EC2 Instance Metadata Service (IMDSv2). No static AWS access keys are stored on the instance.
  • Principle of Least Privilege: The IAM role permissions are restricted strictly to the secretsmanager:GetSecretValue action on the target secret resource ARN.

---

Step 1: Create the Secret in AWS Secrets Manager

Execute the following command via AWS CLI (or deploy via the AWS Management Console) to generate the secret with a JSON payload:

Note the generated ARN from the output:

arn:aws:secretsmanager:us-east-1:843771826066:secret:test/secret-cK45Ko


---

Step 2: Configure IAM Permissions and Instance Profile

1. Create the IAM Role Trust Policy

Save the following trust policy document as ec2-trust-policy.json:

Create the role:

aws iam create-role

--role-name EC2-SecretsManager-ReadOnly

--assume-role-policy-document file://ec2-trust-policy.json


2. Create and Attach the Least-Privilege IAM Policy

Save the permissions policy as secrets-policy.json, locking the resource down to the target secret ARN:

Attach the policy:

aws iam put-role-policy

--role-name EC2-SecretsManager-ReadOnly

--policy-name SecretsManagerAccessPolicy

--policy-document file://secrets-policy.json


3. Create the Instance Profile and Attach to EC2

  1. Create instance profile and add the role

aws iam create-instance-profile --instance-profile-name EC2-SecretsManager-Profile aws iam add-role-to-instance-profile

--instance-profile-name EC2-SecretsManager-Profile

--role-name EC2-SecretsManager-ReadOnly

  1. Attach to the running EC2 instance

aws ec2 associate-iam-instance-profile

--instance-id <YOUR_INSTANCE_ID>

--iam-instance-profile Name=EC2-SecretsManager-Profile


Note: In the AWS Console, this can also be applied via: EC2 Console -> Select Instance -> Actions -> Security -> Modify IAM role.

---

Step 3: EC2 System & Python Environment Setup

Log in to the Amazon Linux instance and configure the runtime.

1. Verify IMDSv2 Credential Acquisition

Confirm the instance profile is detected:

TOKEN=$(curl -s -S -X PUT "[1](https://www.google.com/search?q=http://169.254.169.254/latest/api/token)" -H "X-aws-ec2-metadata-token-ttl-seconds: 60") curl -s -H "X-aws-ec2-metadata-token: $TOKEN" [2](https://www.google.com/search?q=http://169.254.169.254/latest/meta-data/iam/security-credentials/)

The command should return: EC2-SecretsManager-ReadOnly.

2. Install Packages & Virtual Environment

  1. Amazon Linux 2023:

sudo dnf update -y sudo dnf install -y python3 python3-pip

  1. Amazon Linux 2:
  1. sudo yum update -y && sudo yum install -y python3 python3-pip
  1. Set up project workspace

mkdir ~/secrets-lab && cd ~/secrets-lab python3 -m venv venv source venv/bin/activate

  1. Install AWS SDK

pip install --upgrade pip pip install boto3


---

Step 4: Python Retrieval Script

Create fetch.py.

Note on Python compatibility: Including from **future** import annotations ensures the union type syntax (dict | str) parses cleanly across Python 3.7+ through 3.9 environments without throwing TypeError: unsupported operand type(s) for |: 'type' and 'type'.

import json import boto3 from botocore.exceptions import ClientError

def get_secret(secret_name: str, region_name: str = "us-east-1") -> dict | str: """Retrieve and parse secret from AWS Secrets Manager using IAM instance credentials.""" session = boto3.session.Session() client = session.client( service_name="secretsmanager", region_name=region_name, )

``` try:

   response = client.get_secret_value(SecretId=secret_name)

except ClientError as e:

   raise e

if "SecretString" in response:

   secret = response["SecretString"]
   try:
       return json.loads(secret)
   except json.JSONDecodeError:
       return secret

return response["SecretBinary"]

```

if **name** == "**main**": SECRET_ID = "arn:aws:secretsmanager:us-east-1:843771826066:secret:test/secret-cK45Ko" REGION = "us-east-1"

``` credentials = get_secret(SECRET_ID, region_name=REGION) print("Successfully retrieved credentials payload:") print(credentials)

```

Execution and Verification

(venv) [ec2-user@ip-10-0-0-5 secrets-lab]$ python fetch.py Successfully retrieved credentials payload: {'username': 'db_admin', 'password': 'SampleSecurePassword123!', 'host': 'db.internal'}


---

Step 5: Lab Teardown & Cost Management

AWS Secrets Manager incurs $0.40/secret/month (prorated hourly). To prevent ongoing charges after completing lab tests, force-delete the secret without entering the default recovery retention period: