LoginSignup
19
25

More than 3 years have passed since last update.

AWS API Gateway+EC2でセキュアなREST APIを構築する

Posted at

背景

「AWSを使ってAPIを構築したい」という要望は山程あると思います。
その場合、API GatewayとLambdaを用いてサーバレスに構築することがほとんどです。
しかし、Lambdaにはメモリ・実行時間の制限があったり、Lambdaベースでコーディングしなければならなかったりといった不自由な点も存在します。
もしかしたらこれらの条件が理由でLambdaではなくEC2上にサーバを構築したいということがあるかもしれません。AWSに不慣れな場合、この方が手っ取り早い場合もあります。

そこで、今回はAPI Gatewayを通してEC2内に立てた任意のポートにリクエストを送る手順をご紹介します。

設計

API Gateway+EC2といいましたが、間にLambdaを噛ませています。
LambdaからこのEC2サーバにHTTP経由でリクエストを送信します。
通常、Lambdaはネットワーク接続不可能に設定されていますが、private subnet内に設置することによって同VPC内へのアクセスを実現しています。

Screen Shot 2020-04-22 at 16.42.42.png


前提

  • public subnet内に設置されたEC2サーバはすでに構築済みであること
  • まずはLambdaを張るためのprivate subnetが作成されていること(VPCのCIDRがa.b.0.0/14ならsubnetのCIDRをa.b.16.0/20とか)


Lambda

まずEC2にリクエストを送信するためのLambda関数を構築します。

関数の作成

関数を作成します。今回はNode.jsを選択しました(好きにやってください)。

Screen Shot 2020-04-22 at 16.18.22.png

関数は以下のように記述しています(好きにやってください)。
この場合、環境変数のURLにEC2のエンドポイントURLを設定してください。

index.js
var request = require('request-promise');

exports.handler = function(event, context) {
  console.log(process.env["URL"])

  var options = {
    uri: process.env["URL"],
    headers: {
      "Content-Type": "application/json",
      "Authorization": process.env["BASIC_TOKEN"]
    },
    body: JSON.stringify(event),
    method: 'POST'
  }

  return new Promise((resolve, reject) => {
    request(options)
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        resolve(err);
      });
  });
}

IAM Roleの付与

LambdaからVPCエンドポイントに接続するには以下のIAMポリシーが必要になります。
- DescribeNetworkInterface
- CreateNetworkInterface
- DeleteNetworkInterface

よって、LambdaのIAM Roleにこれを付与します。僕はEC2EnrollAccessというポリシーを作成し、LambdaのIAM Roleにアタッチしました。

Screen Shot 2020-04-22 at 16.20.07.png

VPCの設定

関数のVPCの設定からカスタムVPCを選択します。以下のように設定します。

VPC: EC2に使用されているもの
サブネット: 作成したprivate subnet(2つつけろって言われてるけど1つでもいけます)
セキュリティグループ: なんでもいいです(僕はEC2と同じルールをアタッチしています)

以前の項でIAM Roleを付与し忘れているとエラーになるので注意してください。

Screen Shot 2020-04-22 at 16.20.49.png

EC2のセキュリティルールの設定

EC2のセキュリティグループから、EC2で構築している任意のポート(僕の場合は80)を設定します。IPアドレスにLambdaのあるprivate subnetのCIDRブロックを設定してください。
セキュアにするため、他のソースからのアクセスは許可しないでください。

Screen Shot 2020-04-22 at 16.21.04.png

テスト

この時点でLambdaからテストしてみてください。LambdaからEC2への接続が確認できると思います。

Screen Shot 2020-04-22 at 16.22.58.png


API Gateway

次にAPI GatewayからLambdaにリクエストを送信するREST APIを構築します。以下を参考にAPIキーの設定まで行なってください。
統合リクエストに作成したLambda関数を設定することによって、API Gatewayのエンドポイントにリクエストを送信すればEC2のサーバにAPIを叩き、レスポンスが返ってきます。


最後に

これでAPI Gateway以外のエンドポイントからアクセスしようとしてもEC2までにはたどり着けず、かつAPI Gatewayの認証によって鍵を持っていないとアクセスできないセキュアなREST APIが設計できました。
もしこのAPIを使用する時間が限られているならば、EC2を極限までサーバレスにするために起動・停止もLambdaでコントロールしてあげましょう。

19
25
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
19
25