Intelligent Technology's Technical Blog

株式会社インテリジェントテクノロジーの技術情報ブログです。

Amazon API Gateway で IAM 認証つきの REST API を作成して、Python コードからアクセスする

こんにちは。中山です。

いろいろ便利な世の中になったもので、ちょっと REST API を作りたいなぁと思ったら、AWS の API Gateway や Lambda のサービスを使って、パパーっと提供することができるようになりました。
一方でこの REST API を、しっかりしたセキュリティのもとで提供してほしい、というのはよくある話です。
こういう場合の対策として、たとえばこの API Gateway へのリクエストの際に、AWS の IAM 認証が必要となるように設定しておき、「IAM の認証情報(アクセスキー、シークレットキー)を知っている人だけが API にアクセスできるようにする」、という方法があります。
しかしこの IAM 認証付きの API Gateway というもの、設定してから実際に呼び出すまで、意外といろいろな手順がありましたので、ここにその記録を残しておきたいと思います。

REST API を新規作成する

REST API の新規作成

まずは API Gateway を用いて、REST API を新しく作成します。
Amazon API Gateway」のコンソールページを開いて、「API タイプを選択」のところから「REST API」を選んで、その「構築」ボタンをクリックします。

  • f:id:IntelligentTechnology:20211102104850p:plain

次に表示されたページの、「プロトコルを選択する」の部分では「REST」をチェック、「新しい API の作成」は「新しい API」をチェックします。
名前と説明」欄には、任意の API 名、説明を入力します。「エンドポイントタイプ」は「リージョン」とします。
これらを選択・入力したのち、「API の作成」をクリックします。

  • f:id:IntelligentTechnology:20211102110728p:plain

API にメソッドを追加

API の「枠」が作成できたところで、その API に「メソッド」を追加します。
アクション」から「メソッドの作成」を選択します。

  • f:id:IntelligentTechnology:20211102113335p:plain

今回は「GET」メソッドを追加します。
ドロップダウンリストの中から「GET」を選択し、更新アイコン(チェックマークのアイコン)をクリックします。

  • f:id:IntelligentTechnology:20211102113711p:plain

GET メソッドの設定

追加した「GET」メソッドのセットアップのページで「統合タイプ」を設定します。
本来はここで「Lambda 関数」などを選択することになると思いますが、今回は検証用として「Mock」を選択します。

※ Lambda 関数を指定して、API を構築する手順については、以下のページなどをご参照ください。

統合タイプ」を選択したのち、「保存」をクリックします。

  • f:id:IntelligentTechnology:20211102115336p:plain

メソッドリクエストの認可の設定

「GET」メソッド追加後、以下のようなページが表示されますので、その中の「メソッドリクエスト」をクリックします。

  • f:id:IntelligentTechnology:20211102130059p:plain

表示された「GET メソッドリクエスト」の設定ページで「認可」の部分の編集アイコン(鉛筆マークのアイコン)をクリックします。
表示されたドロップダウンリストの中から「AWS IAM」を選択します。(選択後、更新アイコン(チェックマークのアイコン)をクリックして変更を確定します。)

  • f:id:IntelligentTechnology:20211102131216p:plain

API のデプロイ

作成した API をデプロイします。
アクション」から「API のデプロイ」を選択します。

  • f:id:IntelligentTechnology:20211102131848p:plain

デプロイされるステージ」は「新しいステージ」、「ステージ名」は、今回は「test」とし、「ステージの説明」「デプロイメントの説明」には任意の説明文を入力します。選択・入力完了後、「デプロイ」をクリックします。
(ステージ名:「test」としたことで、この API にアクセスする URL のパスは「/test」となるようです。)

  • f:id:IntelligentTechnology:20211102132452p:plain

API のアクセス URL の確認

ステージ」のページで、作成した API へアクセスする URL を確認します。
URL の呼び出し」欄に、アクセス URL が表示されます。
のちほど、この URL に実際にアクセスして、API にリクエストしますので、コピーして保管しておきます。

  • f:id:IntelligentTechnology:20211102133028p:plain

IAM ユーザ・グループの作成

IAM グループの作成

次に、API Gateway の実行権限を持つ IAM グループを新規に作成します。
AWS の「IAM」コンソールページに移動して、「ユーザーグループ」ページから「グループを作成」をクリックします。

  • f:id:IntelligentTechnology:20211102142501p:plain

グループの設定

ユーザーグループ名」に、任意の名称を入力します。

  • f:id:IntelligentTechnology:20211102142831p:plain

「ユーザーをグループに追加」はここでは行わず、その下の「アクセス許可ポリシーをアタッチ」の部分を編集します。
検索欄に「 APIGateway」などと入力し、表示されたリストの中から「AmazonAPIGatewayInvokeFullAccess」にチェックをつけて「グループを作成」をクリックします。

  • f:id:IntelligentTechnology:20211102143603p:plain

IAM ユーザの作成

続いて、「IAM」コンソールページの、「ユーザー」ページから「ユーザーを追加」をクリックします。

  • f:id:IntelligentTechnology:20211102140009p:plain

ユーザの設定(AWS 認証情報タイプの選択)

ユーザー名」に任意のユーザー名を入力します。
AWS 認証情報タイプの選択」の部分では、「アクセスキー - プログラムによるアクセス」にチェックをつけます。
入力・選択ののち、「次のステップ」をクリックします。

  • f:id:IntelligentTechnology:20211102141112p:plain

ユーザの設定(アクセス許可の設定)

アクセス許可の設定」の部分で、「ユーザーをグループに追加」を選択します。
「ユーザーをグループに追加」の下のリストから、先ほど作成したグループ(今回は「api-test-group」)にチェックをつけ、「次のステップ」をクリックします。
ユーザを「api-test-group」に所属させることで、このユーザが API Gateway の実行権限を持つことになります。

  • f:id:IntelligentTechnology:20211102144038p:plain

ユーザの設定(タグの追加)

「タグの追加」は、そのまま何もせず「次のステップ」をクリックします。

  • f:id:IntelligentTechnology:20211102144322p:plain

ユーザの設定(設定内容の確認)

設定内容が想定どおりであることを確認して、「ユーザーの作成」をクリックします。

  • f:id:IntelligentTechnology:20211102144540p:plain

アクセスキーとシークレットキーの保存

ユーザーが作成され、そのユーザーに関連づけられるアクセスキーシークレットキーが発行されます。
.csv のダウンロード」ボタンをクリックして、発行されたアクセスキーとシークレットキーの情報をファイルとして保管します。

  • f:id:IntelligentTechnology:20211102145042p:plain

Postman からのリクエスト

Postman ツールから認証情報なしでリクエスト

Postman ツールを使って、まずはそのまま、先ほど保管した API の URL にリクエストしてみます。
この状態では、認証のための情報を何もリクエストに含めていないため、403(Forbidden)レスポンスが返されます。

  • f:id:IntelligentTechnology:20211102135516p:plain

Postman ツールから認証情報付きでリクエスト

再度 Postman ツールを使って、API にリクエストを行います。
今度は以下のように、発行したアクセスキー、シークレットキーの値を、認証情報としていっしょに渡してリクエストします。
具体的には、Postman ツールの「Authorization」タブのところで、以下のように設定します。

  • TYPE: AWS Signature
  • AccessKey: 発行したアクセスキーの値
  • SecretKey: 発行したシークレットキーの値
  • AWS Region: API が稼働しているリージョン情報。今回の場合は「ap-northeast-1」
  • f:id:IntelligentTechnology:20211102150053p:plain

これにより、正しく認証が行われ、無事に、API から 200(OK)レスポンスが返ってくることが確認できました。

Python スクリプトからのリクエスト

Postman ツールを使わずに API にリクエストする

Postman ツールに、アクセスキー、シークレットキーを指定することで、IAM 認証付きの REST API にリクエストし、結果を取得することができました。
しかしこのアクセスキー、シークレットキーをそのままリクエストヘッダなどに渡しているわけではありません。
これらの値を元に、毎回、動的に認証情報を生成し、それをリクエストしている、という仕組みです。(具体的には Signature Version 4 (SigV4) によるリクエストを行う、ということになります。Postman が、このあたりの認証情報生成を、うまいことやってくれている、というわけです。)

したがって、この IAM 認証付きの REST API に、Postman などのツールを使わずにリクエストする場合は、自分でこの認証情報を作成する必要があります。
今回は、Python でこの認証情報生成の仕組みを実装し、その Python スクリプトから、IAM 認証付きの REST API にリクエストしてみたいと思います。

必要なライブラリのインストール

今回、Python はバージョン 3.9 を利用しています。
まず、requests ライブラリを(まだインストールしてなければ)インストールします。

pip install requests

次に、Signature Version 4 (SigV4) によるリクエストを簡単に構築してくれるライブラリとして、今回は aws-requests-auth というライブラリを利用します。
このライブラリも同様にインストールします。

pip install aws-requests-auth

スクリプトの作成

以下のようなスクリプト「request_api.py」を作成します。

import requests
from aws_requests_auth.aws_auth import AWSRequestsAuth

# アクセスキー
access_key = 'AKIAxxxxxxxx'
# シークレットキー
secret_key = 'wnWyxxxxxxxxxxxx'
# リージョン
region = 'ap-northeast-1'
# ホスト名
hostname = 'xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com'
# API の URL パス
api_path = '/test'

def request_api():
    # 認証情報を生成
    auth = AWSRequestsAuth(aws_access_key=access_key,
                    aws_secret_access_key=secret_key,
                    aws_host=hostname,
                    aws_region=region,
                    aws_service='execute-api')

    # API にリクエスト
    api_url = f'https://{hostname}{api_path}'
    response = requests.get(api_url, auth=auth)

    # レスポンスステータスコードを表示
    print(f'response status: {response.status_code}')

if __name__ == '__main__':
    request_api()

スクリプトの実行

以下のように実行します。

python request_api.py

以下のように、レスポンスステータスコード 200(OK)が出力されたら成功です。

response status: 200

まとめ

手順としては少なくはありませんが、一度実行できれば、あとは簡単にセキュアな API をどんどん作成していけるでしょう。
セキュリティ面もしっかり意識した、スマートな API を、ご一緒に作ってまいりましょう!