Serverless Frameworkで作成したAPI GatewayにIAMによるアクセス制御を行う
はじめに
API GatewayにはIAMでアクセスを制限する機能があります。
Serveress Frameworkで作成したAPIに、この機能によるアクセス制限を追加し、動作を確認するまでの手順について書いていきます。
手順について
LambdaとAPI Gatewayの構築
まずはServerless Frameworkでアクセス制限なしのLambdaとAPI Gatewayを作成します。Lambdaの言語はPython3系とします。
Serverless Frameworkをインストールします。今回は作業するローカルフォルダにインストールしました。
$ npm install serverless
バージョンを確認します。
$ ./node_modules/.bin/serverless --version 1.24.1
テンプレートを作成します。
$ ./node_modules/.bin/serverless create --template aws-python3
Lambdaのhandlerは自動生成されるものをそのまま使います。
import json def hello(event, context): body = { "message": "Go Serverless v1.0! Your function executed successfully!", "input": event } response = { "statusCode": 200, "body": json.dumps(body) } return response # Use this code if you don't use the http event with the LAMBDA-PROXY # integration """ return { "message": "Go Serverless v1.0! Your function executed successfully!", "event": event } """
serverless.ymlを編集し、リージョンとAPI Gatewayの設定を行います。
provider: name: aws runtime: python3.6 # you can overwrite defaults here # stage: dev region: ap-northeast-1 # リージョン指定 (中略) functions: hello: handler: handler.hello events: # ここから4行をAPI GatewayのGETメソッドを作成するために追加 - http: path: hello method: get
デプロイを行います。
$ ./node_modules/.bin/serverless deploy
動作確認を行います。
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello | jq . { "message": "Go Serverless v1.0! Your function executed successfully!", "input": { "resource": "/hello", "path": "/hello", "httpMethod": "GET", (以下略) } }
ここではまだIAMによるアクセス制御は行なっていないため、curlでGETをできています。
IAMでのアクセス制御を追加
serverless.ymlのAPI Gatewayの設定に、IAMでのアクセス制御を追加します。
functions: hello: handler: handler.hello events: - http: path: hello method: get authorizer: aws_iam # これを追加
デプロイを行います。
$ ./node_modules/.bin/serverless deploy
動作確認を行います。
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello | jq . { "message": "Missing Authentication Token" }
先ほどと異なり、今度はcurlでのGETをできません。
署名バージョン 4を使用してAPIにアクセスする
上記のAPIにアクセスするには署名バージョン 4による署名が必要となります。今回はRubyのaws-sigv4と言うgemを使って実行してみました。
gemのインストールを行います。
Gemfile
# A sample Gemfile source "https://rubygems.org" # gem "rails" gem 'aws-sigv4' gem 'aws-sdk', '~> 2'
$ bundle install --path vendor/bundle
APIにアクセスするプログラムは以下のようになります。
main.rb
require 'aws-sigv4' require 'open-uri' require 'aws-sdk' ec2 = Aws::EC2::Client.new credentials = ec2.config[:credentials].credentials signer = Aws::Sigv4::Signer.new( service: 'execute-api', region: 'ap-northeast-1', access_key_id: credentials.access_key_id, secret_access_key: credentials.secret_access_key, ) url = signer.presign_url( http_method: 'GET', url: 'https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello', ) open(url){|io| puts io.read }
以下のコマンドで実行します。
$ bundle exec ruby main.rb | jq . { "message": "Go Serverless v1.0! Your function executed successfully!", "input": { "resource": "/hello", "path": "/hello", "httpMethod": "GET", (以下略)
無事、APIにアクセスすることができました。