APIGateway

IAM 認証 を有効にした API Gateway の Pre Signed URL

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 認証を有効にしたところ。

serverless.yml
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 ユーザーを追加し、最低限のポリシーをアタッチしておく。

Policy
{
    "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 を使った場合のサンプルを示す。クレデンシャルは環境変数にセットしている前提。

.envrc
export AWS_ACCESS_KEY_ID=********************
export AWS_SECRET_ACCESS_KEY=****************************************
export AWS_REGION=ap-northeast-1
Gemfile
source 'https://rubygems.org'

gem 'aws-sigv4'
sign.rb
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.

Authenticating Requests: Using Query Parameters (AWS Signature Version 4) - Amazon Simple Storage Service