Intro
One of the authorization methods that AWS supports for the API Gateway endpoints is
IAM authorization.
Two things are required to use IAM auth:
- signed request using Signature Version 4
-
execute-api
permission set up for the client for invoked endpoint
There are other authorization methods available like: Lambda authorizers
or JWT authorizers
you can read more about them
here.
In today’s blog post, I will show you how to request a microservice that is protected by IAM auth.
The problem
For the blog post purpose, let’s imagine we have two microservices: Microservice A
and Microservice B
.
Both of them were built using AWS lambda and API Gateway.
We own Microservice A
, and some other team owns Microservice B
.
We want to call Microservice B
to get the response, it exposes the endpoint GET /items
, and this endpoint is protected by IAM auth
.
Solution
<span>import</span> <span>os</span><span>from</span> <span>urllib.parse</span> <span>import</span> <span>urlparse</span><span>from</span> <span>logging</span> <span>import</span> <span>Logger</span><span>import</span> <span>requests</span><span>from</span> <span>aws_requests_auth.boto_utils</span> <span>import</span> <span>BotoAWSRequestsAuth</span><span>from</span> <span>requests.exceptions</span> <span>import</span> <span>RequestException</span><span>class</span> <span>MicroserviceBClientClientError</span><span>(</span><span>Exception</span><span>):</span><span>pass</span><span>class</span> <span>MicroserviceBClient</span><span>:</span><span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>base_url</span><span>:</span> <span>str</span><span>,</span> <span>logger</span><span>:</span> <span>Logger</span><span>)</span> <span>-></span> <span>None</span><span>:</span><span>self</span><span>.</span><span>_base_url</span> <span>=</span> <span>base_url</span><span>self</span><span>.</span><span>_logger</span> <span>=</span> <span>logger</span><span>@</span><span>property</span><span>def</span> <span>auth</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>BotoAWSRequestsAuth</span><span>:</span><span>return</span> <span>BotoAWSRequestsAuth</span><span>(</span><span>aws_host</span><span>=</span><span>urlparse</span><span>(</span><span>self</span><span>.</span><span>_base_url</span><span>).</span><span>hostname</span><span>,</span> <span>aws_region</span><span>=</span><span>os</span><span>.</span><span>environ</span><span>[</span><span>"AWS_REGION"</span><span>],</span> <span>aws_service</span><span>=</span><span>"execute-api"</span><span>)</span><span>def</span> <span>get_items</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span><span>try</span><span>:</span><span>self</span><span>.</span><span>_logger</span><span>.</span><span>info</span><span>(</span><span>"Getting items from MicroserviceB!"</span><span>)</span><span>response</span> <span>=</span> <span>requests</span><span>.</span><span>post</span><span>(</span><span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>_base_url</span><span>}</span><span>/items"</span><span>,</span> <span>auth</span><span>=</span><span>self</span><span>.</span><span>auth</span><span>)</span><span>response</span><span>.</span><span>raise_for_status</span><span>()</span><span>self</span><span>.</span><span>_logger</span><span>.</span><span>info</span><span>(</span><span>f</span><span>"Successful request! Response = </span><span>{</span><span>response</span><span>.</span><span>json</span><span>()</span><span>}</span><span>"</span><span>)</span><span>except</span> <span>RequestException</span> <span>as</span> <span>error</span><span>:</span><span>self</span><span>.</span><span>_logger</span><span>.</span><span>error</span><span>(</span><span>f</span><span>"An error occurred during request to `MicroserviceB` service! Error = </span><span>{</span><span>error</span><span>}</span><span>"</span><span>)</span><span>raise</span> <span>MicroserviceBClientClientError</span><span>import</span> <span>os</span> <span>from</span> <span>urllib.parse</span> <span>import</span> <span>urlparse</span> <span>from</span> <span>logging</span> <span>import</span> <span>Logger</span> <span>import</span> <span>requests</span> <span>from</span> <span>aws_requests_auth.boto_utils</span> <span>import</span> <span>BotoAWSRequestsAuth</span> <span>from</span> <span>requests.exceptions</span> <span>import</span> <span>RequestException</span> <span>class</span> <span>MicroserviceBClientClientError</span><span>(</span><span>Exception</span><span>):</span> <span>pass</span> <span>class</span> <span>MicroserviceBClient</span><span>:</span> <span>def</span> <span>__init__</span><span>(</span><span>self</span><span>,</span> <span>base_url</span><span>:</span> <span>str</span><span>,</span> <span>logger</span><span>:</span> <span>Logger</span><span>)</span> <span>-></span> <span>None</span><span>:</span> <span>self</span><span>.</span><span>_base_url</span> <span>=</span> <span>base_url</span> <span>self</span><span>.</span><span>_logger</span> <span>=</span> <span>logger</span> <span>@</span><span>property</span> <span>def</span> <span>auth</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>BotoAWSRequestsAuth</span><span>:</span> <span>return</span> <span>BotoAWSRequestsAuth</span><span>(</span> <span>aws_host</span><span>=</span><span>urlparse</span><span>(</span><span>self</span><span>.</span><span>_base_url</span><span>).</span><span>hostname</span><span>,</span> <span>aws_region</span><span>=</span><span>os</span><span>.</span><span>environ</span><span>[</span><span>"AWS_REGION"</span><span>],</span> <span>aws_service</span><span>=</span><span>"execute-api"</span> <span>)</span> <span>def</span> <span>get_items</span><span>(</span><span>self</span><span>)</span> <span>-></span> <span>None</span><span>:</span> <span>try</span><span>:</span> <span>self</span><span>.</span><span>_logger</span><span>.</span><span>info</span><span>(</span><span>"Getting items from MicroserviceB!"</span><span>)</span> <span>response</span> <span>=</span> <span>requests</span><span>.</span><span>post</span><span>(</span> <span>f</span><span>"</span><span>{</span><span>self</span><span>.</span><span>_base_url</span><span>}</span><span>/items"</span><span>,</span> <span>auth</span><span>=</span><span>self</span><span>.</span><span>auth</span> <span>)</span> <span>response</span><span>.</span><span>raise_for_status</span><span>()</span> <span>self</span><span>.</span><span>_logger</span><span>.</span><span>info</span><span>(</span><span>f</span><span>"Successful request! Response = </span><span>{</span><span>response</span><span>.</span><span>json</span><span>()</span><span>}</span><span>"</span><span>)</span> <span>except</span> <span>RequestException</span> <span>as</span> <span>error</span><span>:</span> <span>self</span><span>.</span><span>_logger</span><span>.</span><span>error</span><span>(</span><span>f</span><span>"An error occurred during request to `MicroserviceB` service! Error = </span><span>{</span><span>error</span><span>}</span><span>"</span><span>)</span> <span>raise</span> <span>MicroserviceBClientClientError</span>import os from urllib.parse import urlparse from logging import Logger import requests from aws_requests_auth.boto_utils import BotoAWSRequestsAuth from requests.exceptions import RequestException class MicroserviceBClientClientError(Exception): pass class MicroserviceBClient: def __init__(self, base_url: str, logger: Logger) -> None: self._base_url = base_url self._logger = logger @property def auth(self) -> BotoAWSRequestsAuth: return BotoAWSRequestsAuth( aws_host=urlparse(self._base_url).hostname, aws_region=os.environ["AWS_REGION"], aws_service="execute-api" ) def get_items(self) -> None: try: self._logger.info("Getting items from MicroserviceB!") response = requests.post( f"{self._base_url}/items", auth=self.auth ) response.raise_for_status() self._logger.info(f"Successful request! Response = {response.json()}") except RequestException as error: self._logger.error(f"An error occurred during request to `MicroserviceB` service! Error = {error}") raise MicroserviceBClientClientError
Enter fullscreen mode Exit fullscreen mode
The aws-requests-auth does most of the things for us.
We need to provide the hostname of the service we want to call, the AWS region,
and the service – in our case it is execute-api
as we are working in a serverless lambda environment.
BotoAWSRequestsAuth
generates the appropriate headers and adds them to the requests
object.
All we need to do is to add it as a auth
param to the requests method.
Summary
It is as simple as that I hope you enjoyed it.
There are other methods that you can use to make such a request.
The one I showed you is simple and easy.
I have tested it on production, it is working .
原文链接:How to make an API request to an AWS microservice that is protected by IAM auth
暂无评论内容