目次
はじめに
本記事は備忘録として、不確かな情報を含め記載する。
言語はpythonで説明する。
ベストプラクティスみたいなものは見つけられなかったので、一例として紹介する。
aws-samplesにコードがありました。(別解)
API GatewayのIAM認証でググると、直にAWS credentialsを利用するサンプルが多かったので、本記事ではLambdaのRoleからcerdentialsを取得してそれを利用するコードを示す。
コード
import os
import boto3
import requests
from requests_aws4auth import AWS4Auth
def lambda_handler(event, context):
credentials = boto3.Session().get_credentials()
v4auth = AWS4Auth(
credentials.access_key,
credentials.secret_key,
os.environ['AWS_REGION'],
'execute-api',
session_token=credentials.token,
)
res = requests.get('url',
auth=v4auth)
res.raise_for_status()
print(res.text)
return {}
refreshable_credentials
を使う別案。詳細な検証はしていないので、想定とは異なるかもしれないが、こっちのほうがよいかも。
import os
import boto3
import requests
from requests_aws4auth import AWS4Auth
# グルーバル定義(コールドスタート時)
credentials = boto3.Session().get_credentials()
def lambda_handler(event, context):
# 有効期限はいい感じにやってくれるかも?
v4auth = AWS4Auth(
region=os.environ['AWS_REGION'],
service='execute-api',
refreshable_credentials=credentials,
)
res = requests.get('url',
auth=v4auth)
res.raise_for_status()
print(res.text)
return {}
ちょっと解説
get_credentials()
- このlambdaの実行Roleを
boto3.Session()
で参照される - 返り値としてアクセストークンなどが取得される
- このlambdaの実行Roleを
AWS4Auth
AuthBase
を継承しているので、requests
ライブラリと互換あり
- 対象のlambdaの実行ロールに、
Allow: execute-api:Invoke
が必要- この記事では、不要になってる?
requests.get
のauth
引数に指定- よしなに認証ヘッダーを作成してくれているはず。。(SigV4がよくわかってない)
Signature Version 4 分かる範囲で
こんな感じのヘッダーを最終的には作られているはず。ハッシュや細かい挙動は理解できていない。
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature
PostmanでIAM認証をつけたとき
AWS Signatureで設定する。
ヘッダーが自動的に生成される。
上記コードでも同じようなことをしていると思っている。
aws-samples/sigv4a-signing-examples
sigv4a-signing-examples/python at main · aws-samples/sigv4a-signing-examples
from sigv4a_sign import SigV4ASign
# pip install requests
import requests
service = 's3'
region = '*'
method = 'GET'
url = 'https://<MRAP_alias>.accesspoint.s3-global.amazonaws.com/<s3-object-key>'
headers = SigV4ASign().get_headers_basic(service, region, method, url)
r = requests.get(url, headers=headers)
print(f'status_code: {r.status_code} \\nobject text: {r.text}')
import boto3
from botocore import crt, awsrequest
class SigV4ASign:
def __init__(self, boto3_session=boto3.Session()):
self.session = boto3_session
def get_headers(self, service, region, aws_request_config):
sigV4A = crt.auth.CrtS3SigV4AsymAuth(self.session.get_credentials(), service, region)
request = awsrequest.AWSRequest(**aws_request_config)
sigV4A.add_auth(request)
prepped = request.prepare()
return prepped.headers
def get_headers_basic(self, service, region, method, url):
sigV4A = crt.auth.CrtS3SigV4AsymAuth(self.session.get_credentials(), service, region)
request = awsrequest.AWSRequest(method=method, url=url)
sigV4A.add_auth(request)
prepped = request.prepare()
return prepped.headers
SigV4ASign
を自作requests.get
のheaders
にセット- SigV4A。マルチリージョン対応っぽい。
終わりに
requests_aws4auth
と sigv4a-signing-examples
の2通りを説明した。
どちらを使うべきかの判断基準はわからないので、今後考えたい。
参考
[サンプルコード付き]IAM認証をかけたAmazon API Gatewayにアクセスする