Last active
April 12, 2024 10:16
-
-
Save AllanGH/654ced4214a6a9e3fa9d32168cad6644 to your computer and use it in GitHub Desktop.
Make an AWS SIGV4 signed request to AWS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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