24
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

API Gateway Lambdaオーソライザーでアクセス制御する

Last updated at Posted at 2019-02-14

API Gateway Lambdaオーソライザーを使ってAPIのアクセス制御を行う方法についてのメモです。実行環境はnode.js(8.10)を使用しました。

アーキテクチャ

API Gatewayを介してオーソライザー用関数(認証する関数)を呼び、認証が通ればAPI(アクセスを制御したい関数)を呼び出す、というフローになります。 ## 構築手順 #### アクセスを制御したいLambda関数を作成 APIにあたるLambda関数を作成しておきます。ここでは「test_api」という関数を作成しました。
index.js
exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

(自動で生成されるコードから何も変更してません...)

API Gatewayを作成

作成したLambda関数のトリガーとしてAPI Gatewayを選択します。
1_lambda_auth.png
新規APIを追加します。
2_lambda_auth.png
以下のようなAPIが自動生成されました。

API
api-gateway/{api-id}/\*/\*/test_apiAPI
エンドポイント
https://{api-id}.execute-api.{region}.amazonaws.com/default/test_api
API名
test_api-API
#### オーソライザー用関数を作成 公式ドキュメントのサンプル[^1] を参考に以下のような関数を作成します。
auth.js
exports.handler = function(event, context, callback) {
    // HTTPヘッダで送られてくるトークンを取得して...
    var token = event.authorizationToken;
    // 値が allow だったらAPI実行するためのIAMポリシーを生成して返す
    if (token.toLowerCase() == 'allow') {
        callback(null, generatePolicy('user', 'Allow', event.methodArn));
    } else {
        callback(null, generatePolicy('user', 'Deny', event.methodArn));
    } 
};

// IAMポリシーを生成し返却します
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    
    return authResponse;
}

オーソライザー用関数はIAMポリシーを返却します。
認証が通り、APIの実行を許可する場合は、そのLambda関数を実行するためのIAMポリシーを生成して返してあげる必要があります。
生成したポリシーを受け取った API Gateway がAPIのLambda関数を実行します。
ここでは認証用トークンが「allow」であれば許可し、それ以外は拒否するというBasic認証のようなシンプルな処理になっています。
(トークンはHTTPヘッダとして送信されますが、後ほどAPI Gatewayでヘッダの設定をします。)

API Gatewayのオーソライザーを作成

追加したAPI GatewayのAPI(test_api-API)を開き、オーソライザー > + 新しいオーソライザーの作成 をクリックして、以下のような設定で作成します。

名前
sample-auth
タイプ
Lambda
Lambda呼び出しロール
<空欄のまま>
Lambda イベントペイロード
トークン
トークンのソース(ヘッダキーになります。)
Auth

オーソライザーをテストする

オーソライザーを作成したら、オーソライザー用関数を呼び出すテストをしてみます。API Gatewayで作成したオーソライザーに「テスト」というボタンがあるので、それをクリックすると、テスト用のウィンドウがでてきました。
認証トークン(上記の トークンのソース: Auth と設定したやつ)を入力するフィールドがあるので、そちらに「allow」と入力すると、以下のようなレスポンスが返ってきます。上記サンプルコードauth.jsgeneratePolicyで生成したやつですね。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "execute-api:Invoke",
      "Effect": "Allow",
      "Resource": "arn:aws:execute-api:{region}:{accountId}:{appId}/ESTestInvoke-stage/GET/"
    }
  ]
}

APIの実行を許可するIAMポリシーが返ってきたみたいです。
「allow」以外の値を送信すると、

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "execute-api:Invoke",
      "Effect": "Deny",
      "Resource": "arn:aws:execute-api:{region}:{accountId}:{appId}/ESTestInvoke-stage/GET/"
    }
  ]
}

拒否するポリシーが返ってきました。

API Gateway リソースの設定

ところで、Lambdaにおけるトリガーの追加で自動生成したAPIのリソースを見てみると、以下のようになっています。
3_lambda_auth.png
しかし前項でテストした際に返ってきた"Resource"は.../ステージ(ESTestInvoke-stage)/GET/に対して許可していますが、リソースのルート「/」直下にGETメソッドはありませんね...。
オーソライザー用関数を変更してもいいですが、ここではIAMポリシーにあわせてリソースを変更しちゃいましょう。

4_lambda_auth.png

/*/test_apiリソースはとりあえず使用しないので削除しました。
作成したANYメソッドの設定にて、認証を作成したオーソライザーを選択します。

5_lambda_auth.png

設定したらAPIをデプロイしましょう!これで完成です!

動作確認

API Gateway のステージから確認できる呼び出しURLを実行してみます。

ヘッダに設定した認証用トークンを入れて実行すると、正常に実行されました!

$ curl -H "Auth: allow" https://{api-id}.execute-api.{region}.amazonaws.com/default
"Hello from Lambda!"

不正な認証用トークンをいれてみると、ちゃんと拒否されました。

$ curl -H "Auth: hoge" https://{api-id}.execute-api.{region}.amazonaws.com/default
{"Message":"User is not authorized to access this resource with an explicit deny"}

ヘッダになにも設定せずに呼び出すとUnauthorizedになります。

$ curl https://{api-id}.execute-api.{region}.amazonaws.com/default
{"message":"Unauthorized"}

以上です。

24
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?