Cybersecurity/AWS Cybersecurity papers/AWS Secrets Example: Difference between revisions
(No difference)
| |||
Revision as of 02:06, 6 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
- 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
- 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
- Amazon Linux 2023:
sudo dnf update -y sudo dnf install -y python3 python3-pip
- Amazon Linux 2:
- sudo yum update -y && sudo yum install -y python3 python3-pip
- Set up project workspace
mkdir ~/secrets-lab && cd ~/secrets-lab python3 -m venv venv source venv/bin/activate
- 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: