AWS signature version 4 signing process for the python requests module
npx @tessl/cli install tessl/pypi-aws-requests-auth@0.4.0AWS signature version 4 signing process implementation for Python requests library. Enables secure authentication to AWS services with comprehensive support for temporary credentials and automatic credential discovery through botocore integration.
pip install aws-requests-authfrom aws_requests_auth.aws_auth import AWSRequestsAuthFor automatic credential discovery:
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth, get_credentialsFor low-level signing utilities (internal use):
from aws_requests_auth.aws_auth import sign, getSignatureKeyimport requests
from aws_requests_auth.aws_auth import AWSRequestsAuth
# Create authentication instance with explicit credentials
auth = AWSRequestsAuth(
aws_access_key='YOUR_ACCESS_KEY',
aws_secret_access_key='YOUR_SECRET_KEY',
aws_host='search-service-example.us-east-1.es.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)
# Use with requests
response = requests.get(
'https://search-service-example.us-east-1.es.amazonaws.com',
auth=auth
)import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
# Credentials auto-discovered from environment, config files, or IAM role
auth = BotoAWSRequestsAuth(
aws_host='search-service-example.us-east-1.es.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)
response = requests.get(
'https://search-service-example.us-east-1.es.amazonaws.com',
auth=auth
)from aws_requests_auth.aws_auth import AWSRequestsAuth
from elasticsearch import Elasticsearch, RequestsHttpConnection
auth = AWSRequestsAuth(
aws_access_key='YOUR_ACCESS_KEY',
aws_secret_access_key='YOUR_SECRET_KEY',
aws_host='search-service-example.us-east-1.es.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)
es_client = Elasticsearch(
host='search-service-example.us-east-1.es.amazonaws.com',
port=443,
connection_class=RequestsHttpConnection,
http_auth=auth,
use_ssl=True
)Primary authentication class for explicit credential management with full control over AWS signature version 4 signing process.
class AWSRequestsAuth(requests.auth.AuthBase):
"""
Auth class for AWS services using signature version 4 signing process.
Implements requests.auth.AuthBase interface.
"""
def __init__(self, aws_access_key, aws_secret_access_key, aws_host,
aws_region, aws_service, aws_token=None):
"""
Initialize authentication with explicit credentials.
Parameters:
- aws_access_key (str): AWS access key ID
- aws_secret_access_key (str): AWS secret access key
- aws_host (str): AWS service hostname (e.g., 'service.region.amazonaws.com')
- aws_region (str): AWS region name (e.g., 'us-east-1')
- aws_service (str): AWS service name (e.g., 'es', 'execute-api')
- aws_token (str, optional): STS temporary credentials token
"""
def __call__(self, r):
"""
Adds AWS signature headers to request.
Called automatically by requests library.
Parameters:
- r (requests.Request): Request object to be signed
Returns:
requests.Request: Modified request with AWS signature headers
"""
def get_aws_request_headers_handler(self, r):
"""
Override point for custom credential handling.
Default implementation uses instance credentials.
Parameters:
- r (requests.Request): Request object
Returns:
dict: Dictionary of AWS authorization headers
"""
def get_aws_request_headers(self, r, aws_access_key, aws_secret_access_key,
aws_token=None):
"""
Generates AWS signature version 4 headers.
Parameters:
- r (requests.Request): Request object
- aws_access_key (str): AWS access key ID
- aws_secret_access_key (str): AWS secret access key
- aws_token (str, optional): STS token
Returns:
dict: Dictionary with Authorization, x-amz-date, x-amz-content-sha256 headers
"""
@classmethod
def get_canonical_path(cls, r):
"""
Creates canonical URI path for AWS signing.
Uses urllib quote with safe chars '/-_.~'
Parameters:
- r (requests.Request): Request object
Returns:
str: URL-encoded canonical path
"""
@classmethod
def get_canonical_querystring(cls, r):
"""
Creates canonical query string for AWS signing.
Assumes query parameters are already URL-encoded.
Sorts parameters by name as required by AWS.
Parameters:
- r (requests.Request): Request object
Returns:
str: Sorted, encoded query string
"""Authentication class that automatically discovers and refreshes AWS credentials using botocore's credential chain.
class BotoAWSRequestsAuth(AWSRequestsAuth):
"""
Auto-refreshing authentication using botocore credential discovery.
Inherits from AWSRequestsAuth with automatic credential management.
Requires botocore package.
"""
def __init__(self, aws_host, aws_region, aws_service):
"""
Initialize with automatic credential discovery.
Credentials found via botocore credential chain:
- Environment variables
- AWS config files
- IAM role
- EC2 instance metadata
Parameters:
- aws_host (str): AWS service hostname
- aws_region (str): AWS region name
- aws_service (str): AWS service name
"""
def get_aws_request_headers_handler(self, r):
"""
Provides fresh credentials for each request.
Automatically refreshes expired credentials.
Parameters:
- r (requests.Request): Request object
Returns:
dict: Dictionary of AWS authorization headers with refreshed credentials
"""
def get_credentials(credentials_obj=None):
"""
Retrieves AWS credentials using botocore session.
Parameters:
- credentials_obj (botocore.credentials, optional): botocore credentials object
If None, creates new session
Returns:
dict: Dictionary with keys:
- aws_access_key (str): Access key ID
- aws_secret_access_key (str): Secret access key
- aws_token (str or None): Session token (None if not using temporary credentials)
"""Core signing functions used internally by AWSRequestsAuth. These are primarily for advanced users implementing custom AWS signature logic.
def sign(key, msg):
"""
HMAC-SHA256 signing utility function.
Used internally for AWS signature generation.
Parameters:
- key (bytes): Signing key as bytes
- msg (str): Message to sign as string
Returns:
bytes: HMAC digest as bytes
"""
def getSignatureKey(key, dateStamp, regionName, serviceName):
"""
Creates AWS Signature Version 4 signing key.
Used internally for AWS signature generation.
Parameters:
- key (str): AWS secret access key
- dateStamp (str): Date stamp in YYYYMMDD format
- regionName (str): AWS region name
- serviceName (str): AWS service name
Returns:
bytes: Signing key as bytes
"""from aws_requests_auth.aws_auth import AWSRequestsAuth
import requests
auth = AWSRequestsAuth(
aws_access_key='YOUR_KEY',
aws_secret_access_key='YOUR_SECRET',
aws_host='search-domain.us-east-1.es.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)
response = requests.get(
'https://search-domain.us-east-1.es.amazonaws.com/_cluster/health',
auth=auth
)from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
import requests
auth = BotoAWSRequestsAuth(
aws_host='api.example.com',
aws_region='us-east-1',
aws_service='execute-api'
)
response = requests.post(
'https://api.example.com/prod/endpoint',
json={'data': 'value'},
auth=auth
)import os
from aws_requests_auth.aws_auth import AWSRequestsAuth
def lambda_handler(event, context):
auth = AWSRequestsAuth(
aws_access_key=os.environ['AWS_ACCESS_KEY_ID'],
aws_secret_access_key=os.environ['AWS_SECRET_ACCESS_KEY'],
aws_token=os.environ['AWS_SESSION_TOKEN'],
aws_host='service.region.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)
# Use auth with requests...from aws_requests_auth.aws_auth import AWSRequestsAuth
# Include aws_token for STS temporary credentials
auth = AWSRequestsAuth(
aws_access_key='TEMP_ACCESS_KEY',
aws_secret_access_key='TEMP_SECRET_KEY',
aws_token='SESSION_TOKEN', # Required for STS
aws_host='service.region.amazonaws.com',
aws_region='us-east-1',
aws_service='es'
)The authentication classes integrate with requests' error handling. Common issues: