[サンプルコード付き]IAM認証をかけたAmazon API Gatewayにアクセスする
Amazon API Gateway(以下、API Gateway)の HTTP API で IAM 認証をかけてアクセスする方法について紹介します。
IAM 認証の設定
API Gateway のマネジメントコンソールから API の詳細に行き、「認可」選択して、下図のようにオーソライザーに「IAM(組込み型)」をアタッチします。
設定後 API Gateway の URL をたたくと Forbidden になります(設定前は誰でもアクセスできる状態でした)。
必要な権限
管理ポリシー AmazonAPIGatewayInvokeFullAccess
をアタッチしておく必要があります。最低でも execute-api:Invoke
が必要です。
Postman でアクセスする
ローカル環境でアクセスする場合 Postman を使うと簡単です。前もって AWS アクセスキーとシークレットキーを取得して控えておいてください。スイッチロールなどでアクセスキーを発行していない場合は aws sts assume-role
で表示された AccessKeyId
、SecretAccessKey
、SessionToken
を控えておいてください。
$ aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/SwitchRoleName \
--role-session-name "SwitchRole" \
--query 'Credentials'
Postman を開き、以下のように Authorization タブから「AWS Signature」を選択します。
AccessKey
, SecretKey
に先ほど控えたアドレスとシークレットキーを入力します。スイッチロールの場合は Session Token
も入力します(Expire される度に変わるので毎回入力する必要があります)。AWS Region は API Gateway があるリージョンを入力します。
「Send」ボタンを押下すると画面下部にレスポンス結果が表示されていることが確認できます。
Python でアクセスする
プログラムから API Gateway をアクセスしたい場合、署名バージョン4によるリクエストをする必要があります。自分で署名を生成してHTTPリクエストできますが、Python ではライブラリが提供されているのでそれを利用したほうが楽です。
- https://github.com/sam-washington/requests-aws4auth
- https://github.com/DavidMuller/aws-requests-auth
以下にいくつかサンプルコードを載せておきます。
ローカル環境からアクセスする場合
Postman でアクセスしたのと同じように AWS アクセスキーとシークレットキーを取得して控えておいてください。スイッチロールなどでアクセスキーを発行していない場合は aws sts assume-role
に出力表示された AccessKeyId
、SecretAccessKey
、SessionToken
を控えておいてください。
requests-aws4auth
import os
import requests
from requests_aws4auth import AWS4Auth
url = 'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/'
auth = AWS4Auth(
os.environ.get('AWS_ACCESS_KEY_ID'),
os.environ.get('AWS_SECRET_ACCESS_KEY'),
os.environ.get('AWS_REGION'),
'execute-api',
session_token=os.environ.get('AWS_SESSION_TOKEN'),
)
response = requests.get(url, auth=auth)
print(response.text)
aws-requests-auth
import os
import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth
aws_host = 'xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com'
url = 'https://{}'.format(aws_host)
auth = AWSRequestsAuth(aws_access_key=os.environ.get('AWS_ACCESS_KEY_ID'),
aws_secret_access_key=os.environ.get(
'AWS_SECRET_ACCESS_KEY'),
aws_token=os.environ.get('AWS_SESSION_TOKEN'),
aws_host=aws_host,
aws_region=os.environ.get('AWS_REGION'),
aws_service='execute-api')
response = requests.get(url, auth=auth)
print(response.text)
EC2/AWS Lambda からアクセスする場合
API Gateway と同じ AWS アカウントで IAM ロールがアタッチされている EC2/AWS Lambda から API Gateway にアクセスする場合です。
requests-aws4auth
import boto3
import requests
from requests_aws4auth import AWS4Auth
session = boto3.Session()
credentials = session.get_credentials()
region = 'ap-northeast-1'
url = 'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/'
auth = AWS4Auth(
credentials.access_key,
credentials.secret_key,
region,
'execute-api',
session_token=credentials.token,
)
response = requests.get(url, auth=auth)
print(response.text)
aws-requests-auth
import requests
from aws_requests_auth.boto_utils import BotoAWSRequestsAuth
region = 'ap-northeast-1'
aws_host = 'xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com'
url = 'https://{}'.format(aws_host)
auth = BotoAWSRequestsAuth(aws_host=aws_host,
aws_region=region,
aws_service='execute-api')
response = requests.get(url, auth=auth)
print(response.text)
別 AWS アカウントからアクセスする場合
API Gateway がある AWS アカウントとは異なる AWS アカウントからアクセスするには、AssumeRole によるクロスアカウントで API Gateway への Invoke 権限を使えるようにします。
requests-aws4auth
import boto3
import requests
from requests_aws4auth import AWS4Auth
sts_client = boto3.client('sts')
response = sts_client.assume_role(
# AssumeRole先(API Gatewayがある側)のIAMロールのARN
RoleArn="arn:aws:iam::123456789012:role/api_gateway_invoke_role",
RoleSessionName="assume_role_api_gateway",
)
session = boto3.Session()
credentials = session.get_credentials()
region = 'ap-northeast-1'
url = 'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/'
auth = AWS4Auth(
response['Credentials']['AccessKeyId'],
response['Credentials']['SecretAccessKey'],
region,
'execute-api',
session_token=response['Credentials']['SessionToken'],
)
response = requests.get(url, auth=auth)
print(response.text)
aws-requests-auth
import boto3
import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth
sts_client = boto3.client('sts')
response = sts_client.assume_role(
# AssumeRole先(API Gatewayがある側)のIAMロールのARN
RoleArn="arn:aws:iam::123456789012:role/api_gateway_invoke_role",
RoleSessionName="assume_role_api_gateway",
)
region = 'ap-northeast-1'
aws_host = 'xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com'
url = 'https://{}'.format(aws_host)
auth = AWSRequestsAuth(
aws_access_key=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_token=response['Credentials']['SessionToken'],
aws_host=aws_host,
aws_region=region,
aws_service='execute-api'
)
response = requests.get(url, auth=auth)
print(response.text)
Discussion