Source code for boto3_helpers.signed_requests

from json import loads

from boto3 import client as boto3_client
from botocore.awsrequest import AWSRequest


[docs] class SigV4RequestException(Exception): """Exception raised by :func:`sigv4_request` when an HTTP response indicates an error. """ def __init__(self, status_code, content): self.status_code = status_code self.content = content
[docs] def sigv4_request( service, method, endpoint, client=None, base_url=None, operation_name=None, **kwargs ): """Make a signed request to the AWS API and return the JSON payload. * *service* is the AWS API service code * *method* is an HTTP method like ``'GET'`` or ``'POST'`` * *endpoint* is the target API endpoint. If you need to supply parameters, put supply them as a query string here (e.g., ``?MaxResults=1``) * *client* is a ``boto3.client`` instance for the same account and region as your target. If not given, is created with ``boto3.client('sts')`` * *base_url* is the URL for the target AWS API. If not given, a guess will be made based on the service name and client region. * *operation_name* is the name of the API operation to use when signing the request * **kwargs** are passed on to an ``AWSRequest`` object. If the API response indicates an error, ``boto3_helpers.signed_requests.SigV4RequestException`` will be raised. This function is useful for accessing endpoints that aren't supported by ``boto3``. For example, ``botocore`` introduced support for the ``'scheduler'`` service in version 1.29.7. You could have used this function to interact with that API before this new version was available: .. code-block:: python from boto3_helpers.signed_requests import sigv4_request schedule_data = sigv4_request('scheduler', 'GET', 'schedules') Explanation: * The EventBridge Scheduler API Reference describes the ``ListSchedules`` API action. * The service code for EventBridge Scheduler is ``'scheduler'``. * The method for ``ListSchedules`` is ``'GET'``. * The endpoint is ``'/schedules'``. This function will strip off leading slashes. We could haved optionally supplied the ``operation_name`` as ``'ListSchedules'``. Example: Invoking a Lambda function URL that uses the ``AWS_IAM`` auth type: .. code-block:: python from boto3_helpers.signed_requests import sigv4_request resp = sigv4_request( 'lambda', 'POST', '/', base_url='https://660d26cd.lambda-url.test-region-1.on.aws', data=dumps({'payload_key_1': 'payload_value_1'}) ) """ client = client or boto3_client('sts') base_url = base_url or f'https://{service}.{client.meta.region_name}.amazonaws.com' endpoint = endpoint.lstrip('/') url = f'{base_url}/{endpoint}' request = AWSRequest(method=method, url=url, **kwargs) client._request_signer.sign(operation_name, request, signing_name=service) request.prepare() request.headers = dict(request.headers) resp = client._endpoint.http_session.send(request) if not (200 <= resp.status_code <= 299): raise SigV4RequestException(resp.status_code, resp.content) return loads(resp.content)