API Gayteway

AWS API Gatewayで特定のIAMロールからのみリクエストを許可する方法

背景

特定のユーザーだけがAPIを利用できるようにするため、AWS API Gatewayに設定を加えて、特定のIAMロールからのリクエストだけを受け付けるシステムを構築しました。

この記事では、AWS API Gatewayを使って、特定のIAMロールからのみリクエストを許可する方法を解説します。

前提条件

この記事の手順を実行するには、以下の環境が必要です。

開発環境
  • Python 3.x
  • AWS CLI
  • 以下のPythonパッケージ
    • boto3
    • requests
    • botocore
AWS環境
  • AWSアカウント
  • AWS API Gatewayの基本的な知識と利用経験
  • IAMの基本的な知識(ロール、ポリシーの概念)
認証情報と権限
  • AWS CLIの認証情報が設定済み
    • ~/.aws/credentials(Windows の場合は%UserProfile%\.aws\credentials
    • ~/.aws/config(Windows の場合は%UserProfile%\.aws\config)
  • 使用するIAMユーザー/ロールに必要な権限が付与されていること
    • API Gatewayへのアクセス権限(execute-api:Invoke
必要な情報
  • AWS API GatewayのID
  • 対象のIAMロール名
  • AWSアカウントID
  • API GatewayのエンドポイントURL
  • デプロイ先のリージョン情報

上記の環境が整っていることを確認してから、本文の手順に進んでください。

手順

1. API Gatewayでリソースポリシーを設定する

まず、API Gatewayのアクセスポリシーを以下のように設定します。この設定により、特定のIAMロール以外からのリクエストを拒否します。
具体的な方法は、AWSの公式サイト「API Gateway リソースポリシーを作成して API にアタッチする」に記載されています。

ポリシー例
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:<リージョン>:<AWSアカウントID>:<API ID>/*",
      "Condition": {
        "StringNotEquals": {
          "aws:PrincipalArn": "arn:aws:iam::<AWSアカウントID>:role/<IAMロール名>"
        }
      }
    }
  ]
}
補足(以下の項目を書き換えてください)
  • <リージョン> : API Gatewayが配置されているリージョンを入力します。
    • 例 : ap-northeast-1
  • <AWSアカウントID> : 対象IAMロールのAWSアカウントIDを入力します。
  • <API ID> : 対象のAPI GatewayのIDを入力します。
  • <IAMロール名> : 対象のIAMロール名を入力します。

2. AWS SigV4署名プロトコルを使用してリクエストをする

(1)でアクセスポリシーを設定すると、通常のcurlコマンドでAPIにアクセスすることはできません。
API Gatewayがリクエストを許可するためには、「このリクエストは正当なものだ」と示す署名が必要です。この署名はAWSのSigV4署名プロトコルを使います。

SigV4署名とは?

AWSのサービスにアクセスする際に、リクエストが正規のものであることを証明するための仕組みです。これにより、偽造されたリクエストや不正なアクセスを防ぐことができます。
詳しくは、AWS公式サイト「API リクエストに対する AWS Signature Version 4」にて解説されています。

Pythonコードによる実装

以下は、署名付きリクエストを作成し、API Gatewayに送信するPythonコードの例です。

import boto3
import requests
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

def make_api_request(method='GET', endpoint='', path='', params=None, body=None):
    """
    API Gatewayにリクエストを送信する関数。
    AWSの認証情報を使ってリクエストを署名し、API Gatewayに送信します。

    Args:
        method (str): HTTPメソッド (GET, POSTなど)
        endpoint (str): API GatewayのエンドポイントURL
        path (str): APIのパス
        params (dict): クエリパラメータ
        body (str): リクエストボディ

    Returns:
        Response: APIからのレスポンスオブジェクト
    """
    # AWSプロファイルを指定してセッションを作成
    # ローカルのAWS CLI設定で指定したプロファイルを使用します。
    session = boto3.Session(profile_name='<プロファイル名>')
    credentials = session.get_credentials()

    # リクエストのURLを構築
    url = f"{endpoint}{path}"

    # 必要なヘッダーを設定
    headers = {
        'Content-Type': 'application/json',  # JSON形式のデータを送信することを指定
    }

    # AWSRequestオブジェクトを作成
    # これによりリクエストの詳細を保持します。
    aws_request = AWSRequest(
        method=method,
        url=url,
        data=body,
        params=params,
        headers=headers
    )

    # SigV4署名を生成してリクエストに追加
    # AWSの認証情報を使ってリクエストに署名します。
    sigv4 = SigV4Auth(credentials, 'execute-api', '<リージョン>')
    sigv4.add_auth(aws_request)

    # リクエストを送信
    # requestsライブラリを使って実際にAPIを呼び出します。
    response = requests.request(
        method=method,
        url=url,
        headers=dict(aws_request.headers),
        params=params,
        data=body
    )
    return response

# このコードを実行する場合の例
if __name__ == "__main__":
    # APIエンドポイントとリクエストパスを設定
    API_ENDPOINT = "<APIのエンドポイントURL>"  # API GatewayのURLを指定
    API_PATH = "<APIのパス>"  # 実行したいAPIのパスを指定

    try:
        # GETメソッドでAPIを呼び出す
        response = make_api_request(method='GET', endpoint=API_ENDPOINT, path=API_PATH)

        # ステータスコードを表示
        print(f"ステータスコード: {response.status_code}")

        # APIレスポンスの内容を表示
        print(f"レスポンス: {response.text}")
    except Exception as e:
        # エラーハンドリング
        print(f"エラーが発生しました: {str(e)}")

コードのポイント

  1. <プロファイル名>: AWS CLIで設定したプロファイル名を指定します。
  2. <リージョン>: API Gatewayが配置されているリージョンを入力します(例: ap-northeast-1)。
  3. <APIのエンドポイントURL>: API GatewayのURLを入力します。
  4. <APIのパス>: APIの特定のエンドポイントを指定します。

初心者向け補足

  • API Gatewayとは?
    AWSが提供するマネージド型のAPI管理サービスです。APIの認証、アクセス制御、トラフィック管理を簡単に設定できます。
  • IAMロールとは?
    AWSリソースへのアクセスを制御するための仕組みです。特定のロールに必要なアクセス権を割り当てることができます。
  • SigV4署名プロトコルの必要性
    SigV4署名を使うことで、不正なリクエストを防ぎ、APIへの安全なアクセスを実現します。

注意点

  • 設定を変更した後は、必ず動作確認を行ってください。
  • アクセスポリシーの条件に誤りがあると、正当なリクエストでも拒否される場合があります。

まとめ

今回は、AWS API Gatewayを使って、特定のIAMロールからのみリクエストを許可する方法を解説しました。
他にも、送信元のIPアドレスなどで制限することも出来るので、AWS公式サイト「API Gateway リソースポリシーの例」を参考に適切なリソースポリシーを設定してみましょう!