DEV Community

Python-T Point
Python-T Point

Posted on • Originally published at pythontpoint.in

☁️ Mastering aws iam roles with python boto3

💡 Understanding IAM Roles — What They Do

aws iam roles with python boto3

An IAM role is an AWS identity that contains a permission policy and a trust policy. Trusted entities such as EC2 instances, Lambda functions, or other AWS services can assume the role. When an EC2 instance assumes a role, AWS STS (Security Token Service) issues temporary credentials that are exposed through the instance metadata service. Boto3 reads those credentials automatically, eliminating long‑lived access keys from code or configuration files.

📑 Table of Contents

  • 💡 Understanding IAM Roles — What They Do
  • 📄 Role Trust Policy — Structure
  • 🛠 Configuring boto3 for Role Assumption — How to Use It
  • 🔐 Explicit Role Assumption with STS — When Needed
  • 📦 Deploying to EC2 with an Attached Role — Practical Setup
  • 🐍 Advanced boto3 Patterns — Reusable Credential Management
  • ⚙️ Custom Credential Provider — Extending botocore
  • 🟩 Final Thoughts
  • ❓ Frequently Asked Questions
  • How does boto3 know which role to use?
  • Can I use an IAM role from my local development machine?
  • What happens if the role’s policy changes while the instance is running?
  • 📚 References & Further Reading

🛠 Configuring boto3 for Role Assumption — How to Use It

Boto3 checks the instance metadata endpoint for role credentials. Creating a client without supplying explicit keys is sufficient to start using aws iam roles with python boto3.

# example.py
import boto3 # No credentials are passed; boto3 resolves them from the environment.
s3 = boto3.client('s3')
response = s3.list_buckets()
print("Buckets:", [b['Name'] for b in response['Buckets']])
Enter fullscreen mode Exit fullscreen mode

What this does:

  • Creates an S3 client using the default session.
  • Relies on boto3's credential provider chain to fetch temporary credentials from the metadata service.
  • Lists all buckets that the attached role is permitted to see.

🔐 Explicit Role Assumption with STS — When Needed

If a different role must be assumed than the one attached to the instance, use STS directly.

# assume_role.py
import boto3 sts = boto3.client('sts')
response = sts.assume_role( RoleArn='arn:aws:iam::123456789012:role/ReadOnlyS3', RoleSessionName='ReadOnlySession'
)
creds = response['Credentials'] s3 = boto3.client( 's3', aws_access_key_id=creds['AccessKeyId'], aws_secret_access_key=creds['SecretAccessKey'], aws_session_token=creds['SessionToken']
)
print(s3.list_buckets()['Buckets'])
Enter fullscreen mode Exit fullscreen mode

What this does:

  • Calls AssumeRole to obtain a fresh set of temporary credentials.
  • Builds a new client using those credentials.
  • Enables cross‑account or cross‑role access without exposing static keys.

To verify that the metadata service is providing credentials, query the endpoint directly:

$ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
MyEC2Role
Enter fullscreen mode Exit fullscreen mode

When the role name appears, the instance is correctly configured.

Key point: Boto3’s built‑in provider chain makes role‑based access seamless; explicit STS calls are required only for advanced scenarios such as cross‑account access. (Also read: 🚀 Building a helm chart for Python Flask API made easy)


📦 Deploying to EC2 with an Attached Role — Practical Setup

This section walks through role creation, policy attachment, and EC2 launch with the role attached. (Also read: 🔧 Automate AWS VPC route tables with a python script)

# Create the role
aws iam create-role -role-name MyEC2Role -assume-role-policy-document file://trust-policy.json
{ "Role": { "Path": "/", "RoleName": "MyEC2Role", "RoleId": "AROABCDEFGHIJKL", "Arn": "arn:aws:iam::123456789012:role/MyEC2Role", "CreateDate": "-05-01T12:34:56Z" }
}
Enter fullscreen mode Exit fullscreen mode

Attach a policy that grants read‑only S3 access: (Also read: 🐍 When to use global vs nonlocal python) (More onPythonTPoint tutorials)

# Attach the policy
aws iam attach-role-policy -role-name MyEC2Role -policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
{ "ResponseMetadata": { "RequestId": "abcd1234-5678-90ab-cdef-EXAMPLE11111", "HTTPStatusCode": 200, "HTTPHeaders": {...}, "RetryAttempts": 0 }
}
Enter fullscreen mode Exit fullscreen mode

Launch an EC2 instance with the role attached:

# Run instance
aws ec2 run-instances \ -image-id ami-0abcdef1234567890 \ -instance-type t3.micro \ -iam-instance-profile Name=MyEC2Role \ -count 1
{ "Instances": [ { "InstanceId": "i-0abcd1234efgh5678", "State": {"Name": "pending"}, ... } ]
}
Enter fullscreen mode Exit fullscreen mode

After the instance reaches the running state, the metadata endpoint serves temporary credentials tied to MyEC2Role.

Aspect Static Access Keys IAM Role (boto3)
Credential Rotation Manual, prone to leakage Automatic, every few hours
Least‑Privilege Enforcement Often overly broad Scoped to role policies
Auditability Hard to track usage CloudTrail records STS events
Operational Overhead Key distribution and rotation scripts Zero‑code, managed by AWS

Key point: Attaching an IAM role removes the need for any credential files, reducing both security risk and operational effort.


🐍 Advanced boto3 Patterns — Reusable Credential Management

Encapsulating session creation in a helper module keeps the codebase DRY while still using aws iam roles with python boto3.

# aws_session.py
import boto3
from botocore.config import Config def get_session(service_name, region='us-east-1'): """ Returns a boto3 client that automatically uses the role attached to the current environment. The Config object enables exponential backoff and a higher retry count for flaky services. """ cfg = Config( retries = { 'max_attempts': 10, 'mode': 'standard' }, region_name = region ) return boto3.client(service_name, config=cfg)
Enter fullscreen mode Exit fullscreen mode

What this does:

  • Creates a Config with a generous retry policy.
  • Relies on the default credential provider chain, so role credentials are fetched transparently.
  • Provides a single entry point for all service clients.

⚙️ Custom Credential Provider — Extending botocore

When the metadata endpoint is unavailable, a custom provider can read credentials from a secure vault.

# custom_provider.py
import boto3
from botocore.credentials import RefreshableCredentials
from botocore.session import get_session as botocore_session
import json, time def fetch_from_vault(): # Placeholder for secret retrieval logic. # Returns dict with AccessKeyId, SecretAccessKey, SessionToken, Expiration. resp = { "AccessKeyId": "ASIAEXAMPLE", "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "SessionToken": "IQoJb3JpZ2luX2VjE...", "Expiration": time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(time.time() + 3600)) } return resp def get_client(service): refreshable = RefreshableCredentials.create_from_metadata( metadata=fetch_from_vault(), refresh_using=fetch_from_vault, method='custom-vault' ) session = botocore_session() session._credentials = refreshable return boto3.client(service, botocore_session=session) s3 = get_client('s3')
print(s3.list_buckets()['Buckets'])
Enter fullscreen mode Exit fullscreen mode

What this does:

  • Implements a RefreshableCredentials object that pulls secrets from an external vault.
  • Injects the credentials into a botocore session, making them available to all boto3 clients.
  • Preserves automatic refresh semantics, matching native IAM role behavior.

Use a custom provider only when the metadata service cannot be reached; otherwise the built‑in role mechanism remains simpler and more reliable.

Key point: Centralizing session creation and optionally extending the provider chain keeps code maintainable while still benefiting from automatic role credential rotation.


🟩 Final Thoughts

Leveraging aws iam roles with python boto3 moves credential management from the application layer to the AWS control plane. STS‑issued temporary credentials are short‑lived, automatically rotated, and bound to the compute resource’s lifecycle, eliminating the most common source of credential leakage.

Developers gain a reduction in configuration files, fewer secrets to audit, and a uniform access method for any AWS service across EC2 instances, Lambda functions, and ECS tasks. The pattern scales without code changes.

Never store long‑lived AWS keys in source code; let IAM roles and boto3 handle credential rotation for you.

❓ Frequently Asked Questions

How does boto3 know which role to use?

Boto3 follows the default credential provider chain. On an EC2 instance, it queries the metadata service at http://169.254.169.254/latest/meta-data/iam/security-credentials/. The returned role name determines which temporary credentials are fetched.

Can I use an IAM role from my local development machine?

Local environments cannot retrieve role credentials from metadata. Use aws configure sso or aws sts assume-role to obtain temporary credentials, then export them as environment variables for boto3.

What happens if the role’s policy changes while the instance is running?

Existing temporary credentials remain valid until expiration (typically one hour). New API calls after expiration are evaluated against the updated policy, so permission changes take effect without restarting the instance.

💡 Want to practise this hands-on? DigitalOcean gives new accounts $200 free credit for 60 days — enough to spin up a full Linux/Docker/Kubernetes environment at no cost.

📚 Recommended reading: Best DevOps & cloud books on Amazon — from Linux fundamentals to Kubernetes in production, curated for working engineers.

📚 References & Further Reading

  • IAM role documentation — official guide to role creation and trust policies: docs.aws.amazon.com
  • STS AssumeRole API reference — official definition of the AssumeRole operation: docs.aws.amazon.com

Top comments (0)