AWS Lambda オーソライザーを使用して HTTP API へのアクセスを制御する
Lambda オーソライザーを使用し、Lambda 関数を使用して HTTP API へのアクセスを制御します。次に、クライアントが API を呼び出すと、API Gateway が Lambda 関数を呼び出します。API Gateway は、Lambda 関数からのレスポンスを使用して、クライアントが API にアクセスできるかどうかを判断します。
オーソライザーの’ペイロード形式バージョンでは、API Gateway が Lambda 認証に送信するデータの形式と、API Gateway が Lambda からのレスポンスをどのように解釈するかを指定します。ペイロード形式バージョンを指定しない場合、AWS Management Console はデフォルトで最新バージョンを使用します。AWS CLI、AWS CloudFormation、または SDK を使用して Lambda オーソライザーを作成する場合は、authorizerPayloadFormatVersion
を指定する必要があります。サポートされる値は 1.0
と 2.0
です。
REST APIとの互換性が必要な場合は、バージョン 1.0
を使用してください。
次の例は、各ペイロード形式バージョンの構造を示しています。
- 2.0
-
{
"version": "2.0",
"type": "REQUEST",
"routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
"identitySource": ["user1", "123"],
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": ["cookie1", "cookie2"],
"headers": {
"header1": "value1",
"header2": "value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authentication": {
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"pathParameters": { "parameter1": "value1" },
"stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}
- 1.0
-
{
"version": "1.0",
"type": "REQUEST",
"methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
"identitySource": "user1,123",
"authorizationToken": "user1,123",
"resource": "/request",
"path": "/request",
"httpMethod": "GET",
"headers": {
"X-AMZ-Date": "20170718T062915Z",
"Accept": "*/*",
"HeaderAuth1": "headerValue1",
"CloudFront-Viewer-Country": "US",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Is-Mobile-Viewer": "false",
"User-Agent": "..."
},
"queryStringParameters": {
"QueryString1": "queryValue1"
},
"pathParameters": {},
"stageVariables": {
"StageVar1": "stageValue1"
},
"requestContext": {
"path": "/request",
"accountId": "123456789012",
"resourceId": "05c7jb",
"stage": "test",
"requestId": "...",
"identity": {
"apiKey": "...",
"sourceIp": "...",
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"resourcePath": "/request",
"httpMethod": "GET",
"apiId": "abcdef123"
}
}
ペイロード形式バージョンによって、Lambda 関数から返す必要のあるレスポンスの構造も決まります。
Lambda 関数レスポンス形式 1.0
1.0
形式バージョンを選択した場合、Lambda オーソライザーは API ルートへのアクセスを許可または拒否する IAM ポリシーを返す必要があります。ポリシーでは、標準の IAM ポリシー構文を使用できます。IAM ポリシーの例については、「API を呼び出すためのアクセスの制御」を参照してください。$context.authorizer.property
を使用して、コンテキストプロパティを Lambda 統合に渡したり、ログにアクセスしたりできます。context
オブジェクトはオプションです。claims
は予約されたプレースホルダーであり、コンテキストオブジェクトとしては使用できません。詳細については、「HTTP API アクセスログをカスタマイズする」を参照してください。
{
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
]
},
"context": {
"exampleKey": "exampleValue"
}
}
Lambda 関数レスポンス形式 2.0
2.0
形式バージョンを選択した場合は、Lambda 関数から、ブール値を返すか、標準の IAM ポリシー構文を使用する IAM ポリシーを返すことができます。ブール値を返すには、オーソライザーの簡易レスポンスを有効にします。以下の例では、Lambda 関数から返すようにコーディングする必要のある形式を示しています。context
オブジェクトはオプションです。$context.authorizer.property
を使用して、コンテキストプロパティを Lambda 統合に渡したり、ログにアクセスしたりできます。詳細については、「HTTP API アクセスログをカスタマイズする」を参照してください。
- Simple response
-
{
"isAuthorized": true/false,
"context": {
"exampleKey": "exampleValue"
}
}
- IAM policy
-
{
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
]
},
"context": {
"exampleKey": "exampleValue"
}
}
Lambda オーソライザー関数の例
以下のサンプルの Node.js Lambda 関数では、2.0
ペイロード形式バージョンの場合に Lambda 関数から返す必要のあるレスポンスの形式を示しています。
- Simple response - Node.js
-
export const handler = async(event) => {
let response = {
"isAuthorized": false,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
};
if (event.headers.authorization === "secretToken") {
console.log("allowed");
response = {
"isAuthorized": true,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
};
}
return response;
};
- Simple response - Python
import json
def lambda_handler(event, context):
response = {
"isAuthorized": False,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
try:
if (event["headers"]["authorization"] == "secretToken"):
response = {
"isAuthorized": True,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
print('allowed')
return response
else:
print('denied')
return response
except BaseException:
print('denied')
return response
- IAM policy - Node.js
-
export const handler = async(event) => {
if (event.headers.authorization == "secretToken") {
console.log("allowed");
return {
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": event.routeArn
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": { "value1": "value2" }
}
};
}
else {
console.log("denied");
return {
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": event.routeArn
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": { "value1": "value2" }
}
};
}
};
- IAM policy - Python
import json
def lambda_handler(event, context):
response = {
# The principal user identification associated with the token sent by
# the client.
"principalId": "abcdef",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": event["routeArn"]
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
try:
if (event["headers"]["authorization"] == "secretToken"):
response = {
# The principal user identification associated with the token
# sent by the client.
"principalId": "abcdef",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": event["routeArn"]
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
print('allowed')
return response
else:
print('denied')
return response
except BaseException:
print('denied')
return response
ID ソース
オプションで、Lambda オーソライザーの ID ソースを指定できます。ID ソースは、リクエストを認可するために必要なデータの場所を指定します。例えば、ヘッダーまたはクエリ文字列の値を ID ソースとして指定できます。ID ソースを指定する場合、クライアントはそれらのソースをリクエストに含める必要があります。クライアントのリクエストに ID ソースが含まれていない場合、API Gateway は Lambda オーソライザーを呼び出さず、クライアントは 401
エラーを受け取ります。
次の表は、Lambda オーソライザーでサポートされている ID ソースを示しています。
タイプ |
例 |
Notes (メモ) |
ヘッダー値 |
$request.header.name |
ヘッダー名では大文字と小文字は区別されません。 |
クエリ文字列値 |
$request.querystring.name |
クエリ文字列名では大文字と小文字が区別されます。 |
コンテキスト変数 |
$context.variableName |
サポートされているコンテキスト変数の値。 |
ステージ変数 |
$stageVariables.variableName |
ステージ変数の値。 |
オーソライザーのレスポンスのキャッシュ
authorizerResultTtlInSeconds を指定することで、Lambda オーソライザーのキャッシュを有効にすることができます。オーソライザーのキャッシュが有効になっていると、API Gateway はオーソライザーの ID ソースをキャッシュキーとして使用します。クライアントが設定済みの TTL 内の ID ソースで同じパラメータを指定した場合、API Gateway は、Lambda 関数を呼び出すのではなく、キャッシュされたオーソライザーの結果を使用します。
キャッシュを有効にするには、オーソライザーに 1 つ以上の ID ソースが必要です。
オーソライザーの簡易レスポンスを有効にすると、オーソライザーのレスポンスは、キャッシュされた ID ソース値に一致するすべての API リクエストを完全に許可するか、拒否するかになります。より詳細なアクセス許可が必要な場合は、簡易レスポンスを無効にし、IAM ポリシーが返されるようにします。
デフォルトでは、API Gateway は、オーソライザーを使用する API のすべてのルートに対して、キャッシュされたオーソライザーのレスポンスを使用します。ルートごとにレスポンスをキャッシュするには、オーソライザーの ID ソースに $context.routeKey
を追加します。
Lambda オーソライザーの作成
Lambda オーソライザーを作成するときは、API Gateway で使用する Lambda 関数を指定します。関数のリソースポリシーまたは IAM ロールを使用して Lambda 関数を呼び出すには、API Gateway のアクセス許可を付与する必要があります。この例では、Lambda 関数を呼び出すアクセス許可を API Gateway に付与するように関数のリソースポリシーを更新します。
aws apigatewayv2 create-authorizer \
--api-id abcdef123
\
--authorizer-type REQUEST \
--identity-source '$request.header.Authorization
' \
--name lambda-authorizer \
--authorizer-uri 'arn:aws:apigateway:us-west-2
:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:my-function
/invocations' \
--authorizer-payload-format-version '2.0
' \
--enable-simple-responses
次のコマンドは、Lambda 関数を呼び出すためのアクセス許可を API Gateway に付与します。API Gateway に関数を呼び出すアクセス許可がない場合、クライアントは 500 Internal
Server Error
を受け取ります。
aws lambda add-permission \
--function-name my-authorizer-function
\
--statement-id apigateway-invoke-permissions-abc123 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/
authorizers/authorizer-id
"
オーソライザーを作成し、呼び出すアクセス許可を API Gateway に付与したら、オーソライザーを使用するようにルートを更新します。
aws apigatewayv2 update-route \
--api-id abcdef123
\
--route-id acd123
\
--authorization-type CUSTOM \
--authorizer-id def123
Lambda オーソライザーのトラブルシューティング
API Gateway が Lambda オーソライザーを呼び出せない場合、または Lambda オーソライザーが無効な形式のレスポンスを返す場合、クライアントは 500 Internal Server
Error
を受け取ります。
エラーのトラブルシューティングを行うには、API ステージのアクセスログを有効にします。ログ形式に $context.authorizer.error
ログ記録変数を含めます。
API Gateway に関数を呼び出すアクセス許可がないことがログに示されている場合は、関数のリソースポリシーを更新するか、IAM ロールを提供して API Gateway にオーソライザーを呼び出すアクセス許可を付与します。
Lambda 関数が無効なレスポンスを返すことがログに示されている場合は、Lambda 関数が必要な形式でレスポンスを返すことを確認してください。