Skip to content

Instantly share code, notes, and snippets.

@AllanGH
Last active April 12, 2024 10:16
Show Gist options
  • Save AllanGH/654ced4214a6a9e3fa9d32168cad6644 to your computer and use it in GitHub Desktop.
Save AllanGH/654ced4214a6a9e3fa9d32168cad6644 to your computer and use it in GitHub Desktop.
Make an AWS SIGV4 signed request to AWS
import hmac
import hashlib
from datetime import datetime
import httpx
# Define the AWS request details, url is defined as the API Gateway endpoint where host is the actual host of the API
method = "GET"
url = "<vpce-dns-name>"
host = "<api-id>.execute-api.eu-west-1.amazonaws.com"
path = "/sandbox/test"
# Get the current date and time in the required formats
now = datetime.utcnow()
timestamp = now.strftime('%Y%m%dT%H%M%SZ')
date = now.strftime('%Y%m%d')
# Define the AWS service details
service = "execute-api"
region = "eu-west-1"
access_key_id = "<iam-access-key-id>"
secret_access_key = "<iam-secret-access-key>"
# Define the headers for the AWS request, keys must be lowercase
headers = {'host': host, 'x-amz-date': timestamp}
# Prepare the headers for signing
signed_headers = ';'.join(sorted(headers.keys()))
canonical_headers = ''.join([f"{k}:{v}\n" for k, v in sorted(headers.items())])
# Function to sign a message with a key
def sign(key, msg, return_hex=False):
if return_hex:
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).hexdigest()
else:
return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest()
# Function to get the signature key
def get_signature_key():
k_date = sign(("AWS4" + secret_access_key).encode('utf-8'), date)
k_region = sign(k_date, region)
k_service = sign(k_region, service)
k_signing = sign(k_service, "aws4_request")
return k_signing
# Hash the payload (empty in this case)
hashed_payload = hashlib.sha256("".encode('utf-8')).hexdigest()
# Prepare the canonical request
canonical_request = f"""{method}
{path}
{canonical_headers}
{signed_headers}
{hashed_payload}"""
# Hash the canonical request
hashed_canonical_request = hashlib.sha256(canonical_request.encode('utf-8')).hexdigest()
# Prepare the string to sign
sts = f"""AWS4-HMAC-SHA256
{timestamp}
{date}/{region}/{service}/aws4_request
{hashed_canonical_request}"""
# Sign the string to sign
signature = sign(get_signature_key(), sts, return_hex=True)
# Prepare the authorization header
auth_header = f"AWS4-HMAC-SHA256 Credential={access_key_id}/{date}/{region}/{service}/aws4_request,SignedHeaders={signed_headers},Signature={signature}"
headers['Authorization'] = auth_header
# Print the canonical request, string to sign, and cURL command for debugging
print(f'\ncanonical_request:\n-----------\n{canonical_request}\n-----------')
print(f'\nsts:\n-----------\n{sts}\n-----------')
print(f'\ncURL command:\n-----------\ncurl -X {method} "{url+path}" \\')
for header in headers:
print(f' -H "{header}: {headers[header]}" \\')
print('-----------')
# Send the request and print the response
response = httpx.Client().get(url=url + path, headers=headers)
print(response.text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment