【AWS】IAM認証を使用したREST APIの呼び出し

# はじめに
APIGatewayにはIAM認証機能といったものがあるのですがご存じでしょうか。
この機能を使用するとIAM認証情報(アクセスキー・シークレットアクセスキー)を指定しなければAPIを呼び出せないように制限をかけることができます。

ということでIAM認証を使用したAPIの呼び出しを検証したので、設定方法を記事にまとめてました。

# 目次
* [アクセスキー・シークレットアクセスキーとは](#アクセスキーシークレットアクセスキーとは)
* [IAMユーザの作成](#iamユーザの作成)
* [アクセスキーとシークレットキーをダウンロードする](#アクセスキーとシークレットキーをダウンロードする)
* [WEBサーバの作成](#webサーバの作成)
* [内部NLBの作成](#内部nlbの作成)
* [VPCリンクの作成](#vpcリンクの作成)
* [APIの作成](#apiの作成)
* [IAM認証を有効化する](#iam認証を有効化する)
* [APIのテスト](#apiのテスト)
* [APIをデプロイ](#apiをデプロイ)
* [APIを呼び出してみる](#apiを呼び出してみる)

# アクセスキー・シークレットアクセスキーとは
そもそもなんやねんそれって方に向けて軽く説明します。
AWSのコンソールにログインして何か操作を行うとき、IAMユーザが実行可能なアクションはユーザに関連付けられたIAM Roleによって定義されています。
AWSコンソール内でリソースを操作するにはIAMユーザとしてログインすればいいですが、コンソールにログインせず、リソースを操作したい(AWS CLIやプログラムからリソースを操作したい）場合はどのようにすればいいでしょうか。
このような時にアクセスキーとシークレットアクセスキーを使用します。

アクセスキー・シークレットアクセスキーはIAMユーザから作成され、
このキー情報(IAM認証情報)を使用したリクエストは、作成元のIAMユーザと同一の権限を有しているとみなされます。

例えば「EC2の起動・停止」をプログラムで操作したい場合は、「EC2の起動・停止」の権限を有したIAMユーザからアクセスキー・シークレットアクセスキーを生成し、プログラムに埋め込むことでEC2の操作ができるようになります。
今回の検証ではAPIの呼び出し許可ポリシーを付与したIAMユーザからキーを生成し、生成したキーをリクエストに埋め込んで使用します。

# IAMユーザの作成
APIの実行権限を付与したIAMユーザを作成します。
IAMユーザ作成時に、「アクセスキー・プログラムによるアクセス」を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/6a9566ff-be65-dd50-264c-dffa6aeef3d4.png)
ポリシーは「AmazonAPIGatewayInvokeFullAccess」で作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/811e74f6-a8d1-5f77-68ed-5eae131119c1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/53191b0c-6eab-4d9a-db4b-d3089e0f9a74.png)

# アクセスキーとシークレットキーをダウンロードする
シークレットアクセスキーはこの画面でしか確認することができません。
必ずcsvファイルのダウンロードを行ってください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/aeabaa59-f082-8083-ceab-924026ed1bae.png)
ダウンロードしたcsvファイルの中身は以下のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/f100af6a-db29-712a-39b7-bbf0214a4c02.png)

# WEBサーバの作成
以下の記事で紹介したCloudFormationテンプレートを使用することで、セッションマネージャによる接続が可能なEC2を起動することができます。
+ [【AWS】CloudFormationでセッションマネージャで接続可能なEC2を構築してみた(NATGateway編)](https://qiita.com/itkz1016/items/1c39f024a00b020c5bd7)
+ [【AWS】CloudFormationでセッションマネージャによる接続可能なEC2を構築してみた(VPCEndpoint編)](https://qiita.com/itkz1016/items/09af2ce3bf73943ab132)
今回の検証ではプライベートサブネットに起動したEC2にnginxをインストールし、デフォルト設定のまま起動しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/b7646d8d-eaeb-8bf5-06a4-a9c5a6ee5d1f.png)


# 内部NLBの作成
APIGatewayとプライベートサブネットをつなげるために内部NLBをプライベートサブネット内に作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/1d6ebbb7-a17c-7926-68be-02d4fddfa041.png)
NLBのターゲットグループにプライベートサブネットに起動したEC2を指定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/cb1a66dc-d724-f530-8ee3-ffd09a13518a.png)


# VPCリンクの作成
APIGatewayでVPCリンクを作成し内部NLBと接続します。
今回はRESTAPIの呼び出しを行うので、「REST APIのVPCリンク」を指定し、先ほど作成した内部NLBをターゲットに指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/d0d60584-440e-8897-bbf1-40d9759b0411.png)
作成完了まで数分かかりますが、成功すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/27f0df48-b19d-c1dc-08c6-beaabf7bfd28.png)


# APIの作成
画像のようにパブリックREST APIを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/eee30b12-7793-77a7-8816-4caba33a6aa2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/214a062e-b2ab-cb74-d7ad-1661c112f2fb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/e89a36ec-ca66-2494-6661-1f7560a7f22f.png)
メソッドを作成したら、統合タイプに「VPCリンク」を指定し、エンドポイントに「NLBのDNS名」を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/fe0d683f-10ad-5c20-77b5-1a06d3b4544f.png)


# IAM認証を有効化する
メソッドリクエストの「認可」に「AWS IAM」を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/cba1190d-e800-d14e-ec50-1def4853bb91.png)


# APIのテスト
テストを実行し、HTTSステータス200が返ってくることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/315bd2d1-8158-e168-d58b-401d606fb76e.png)
# APIをデプロイ
テストでステータス「200」が返ってきたことを確認したらAPIをデプロイします。
※デプロイ前にリソースポリシーが定義されている必要があります。今回はステージ名を「public」としてデプロイしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/ad3c519f-e996-132b-6222-97b87a7979d1.png)


# APIを呼び出してみる
Postmanを使用してAPIの呼び出しを行います。(Postmanの使い方については割愛します。
まずはアクセスキーを指定せず、APIを呼び出してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/75a440af-f487-cc81-2385-b2289556a836.png)
「{"message":"The security token included in the request is invalid."}」と表示され呼び出すことができませんでした。
つぎにアクセスキーとシークレットアクセスキーを指定して呼び出してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2615865/91ca8982-8b8c-5b1d-b350-757d428c2719.png)
今度はうまく表示されました！！


# さいごに
呼び出し元のアクセスキーに関する制御を行わなかったので、ポリシーの作り込み等が必要になるかと思いますが、大体の仕組みは理解できました。
やっぱ誰かの記事を読むだけじゃなくて、実際に動かさないと見えてこない課題ってありますね。。。
自分の場合、内部NLBとVPCリンクを使用した構築が初めてでしたので、非常に勉強になりました。
あと、API呼び出しに使用したpostmanってナニ？って感じでしたが、めちゃくちゃ便利だったので今後の検証でも重宝しそうです（笑）

今回の検証ではいじりませんでしたが、統合レスポンス・メソッドレスポンスのマッピングテンプレートの理解が浅いので別の機会で検証してみたいと思ってます。