Created
April 12, 2025 00:18
-
-
Save mtippett/dea33e80c6980e2c46978933b909c583 to your computer and use it in GitHub Desktop.
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
Sample code for generating a presigned URL for getCallerIdentity | |
import botocore.session | |
from botocore.awsrequest import AWSRequest | |
from botocore.auth import SigV4Auth | |
import urllib.parse | |
def generate_presigned_sts_url(region_name="us-east-1"): | |
""" | |
Generate a pre-signed URL for STS GetCallerIdentity in the given region. | |
Returns the fully signed URL as a string. | |
""" | |
# Create a new botocore session and get credentials. | |
session = botocore.session.get_session() | |
credentials = session.get_credentials().get_frozen_credentials() | |
# The STS endpoint for the given region. STS is a global service, but | |
# you can specify a region anyway (e.g. "us-east-1"). | |
sts_endpoint = f"https://sts.{region_name}.amazonaws.com" | |
# The STS request parameters for GetCallerIdentity | |
query_params = { | |
"Action": "GetCallerIdentity", | |
"Version": "2011-06-15" | |
} | |
# Construct the AWSRequest | |
request = AWSRequest( | |
method="GET", | |
url=sts_endpoint, | |
params=query_params | |
) | |
# Sign the request using Signature Version 4 | |
signer = SigV4Auth(credentials, "sts", region_name) | |
signer.add_auth(request) | |
# request.url now contains the fully signed URL with query parameters (including Signature). | |
presigned_url = request.url | |
return presigned_url | |
if __name__ == "__main__": | |
# Generate the pre-signed URL | |
url = generate_presigned_sts_url(region_name="us-east-1") | |
print("Pre-signed STS URL:", url) | |
Calling the pre-signed URL from the server | |
import requests | |
import xml.etree.ElementTree as ET | |
def verify_caller_identity(presigned_url): | |
""" | |
Given a pre-signed STS GetCallerIdentity URL, call STS and parse | |
the returned identity details. | |
""" | |
response = requests.get(presigned_url) | |
if response.status_code != 200: | |
raise Exception(f"Error calling STS: {response.status_code} - {response.text}") | |
# The response is XML. For example: | |
# <GetCallerIdentityResponse> | |
# <GetCallerIdentityResult> | |
# <Arn>arn:aws:sts::123456789012:assumed-role/...</Arn> | |
# <UserId>...</UserId> | |
# <Account>123456789012</Account> | |
# </GetCallerIdentityResult> | |
# ... | |
# </GetCallerIdentityResponse> | |
root = ET.fromstring(response.text) | |
# We can navigate to GetCallerIdentityResult | |
namespace = {"sts": "https://sts.amazonaws.com/doc/2011-06-15/"} # Not strictly required to define in this minimal example if you parse by tag name directly. | |
# Parse out the relevant fields | |
arn = root.find(".//Arn") | |
account = root.find(".//Account") | |
user_id = root.find(".//UserId") | |
# Return them for further use | |
return { | |
"Arn": arn.text if arn is not None else None, | |
"Account": account.text if account is not None else None, | |
"UserId": user_id.text if user_id is not None else None | |
} | |
if __name__ == "__main__": | |
# Typically, you'd receive the URL from the client | |
# For demonstration, paste the pre-signed URL here: | |
presigned_sts_url = "<REPLACE_WITH_PRESIGNED_STS_URL_FROM_CLIENT>" | |
identity = verify_caller_identity(presigned_sts_url) | |
print("Retrieved identity from STS:", identity) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment