API Gateway には IAM 認証機能があり、HTTP ヘッダかクエリを通じて署名を渡す事で認証させる事ができる。この署名の仕組み自体は署名バージョン4を利用している。
API Gateway の IAM 認証機能を署名付きURLで使った事がなかったので、それを試した時のメモを整理する。
1. API Gateway で API を作成
Serverless Framework のテンプレートを利用して API Gateway と AWS Lambda 関数をセットアップする。
$ serverless create --template aws-python3 --path example-api-gateway
若干手を加えた serverless.yml
は以下の通り。ハンドラ関数には手を加えていない。ポイントは authorizer: aws_iam
で IAM 認証を有効にしたところ。
service: api
provider:
name: aws
runtime: python3.6
region: ap-northeast-1
profile: koshigoe
functions:
hello:
handler: handler.hello
events:
- http:
path: sample
method: get
authorizer: aws_iam
準備ができたらデプロイする。
$ serverless deploy
2. IAM ユーザーを作りポリシーをアタッチ
API Gateway の認証用に IAM ユーザーを追加し、最低限のポリシーをアタッチしておく。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:ap-northeast-1:{AWS ACCOUNT ID}:{API ID}/*/GET/sample"
]
}
]
}
この IAM ユーザーのアクセスキーとシークレットを利用して署名を作る事になるので、アクセスキーの発行を忘れずに。
3. 署名付き URL を組み立てる
Ruby の AWS SDK を使った場合のサンプルを示す。クレデンシャルは環境変数にセットしている前提。
export AWS_ACCESS_KEY_ID=********************
export AWS_SECRET_ACCESS_KEY=****************************************
export AWS_REGION=ap-northeast-1
source 'https://rubygems.org'
gem 'aws-sigv4'
require 'aws-sigv4'
require 'open-uri'
signer = Aws::Sigv4::Signer.new(
service: 'execute-api',
region: 'ap-northeast-1',
access_key_id: ENV['AWS_ACCESS_KEY_ID'],
secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
)
presigned_url = signer.presign_url(
http_method: 'GET',
url: 'https://x8j638cwtf.execute-api.ap-northeast-1.amazonaws.com/dev/sample',
)
open(presigned_url) do |f|
puts f.read
end
※ 署名付きURLの有効期限は最大7日間であるとのこと。
X-Amz-Expires
Provides the time period, in seconds, for which the generated presigned URL is valid. For example, 86400 (24 hours). This value is an integer. The minimum value you can set is 1, and the maximum is 604800 (seven days).
A presigned URL can be valid for a maximum of seven days because the signing key you use in signature calculation is valid for up to seven days.