Amazon API GatewayのHTTP API使ってみた

# はじめに
lambdaをさわっててAPIGatewayのコンソールを覗いてみたら見覚えのない選択肢がありました。
この`HTTP API`なるもの、新機能らしいです。
しかも出たばかり。
ホットなので使ってみました。

※検証時点ではプレビュー版となります。

# HTTP API
クラスメソッドさんが解説してくれてます。
いつも助かります。
https://dev.classmethod.jp/cloud/aws/amazon-api-gateway-http-or-rest/

なにやら従来のREST APIよりも簡単に使えそうな雰囲気ですね。

# やりたい事
curlでapi叩いてlambda動かしたい。
認証も噛ませたい。

# やってみた
## lambda作る
* ウィザードに従い、ぽちぽち作る。
* 言語はpython3.7を指定。
* ソースはこんな感じ。

```
import json

def lambda_handler(event, context):

    return {
      'isBase64Encoded': False,
      'statusCode': 200,
      'headers': {},
      'body': '{"message": "Hello Lambda"}'
    }
```
* `トリガーを追加`からAPI Gatewayを追加する。
    * `HTTP API`を指定する。  
<img width="834" alt="スクリーンショット 2020-01-17 21.45.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/c5c5ce72-e41b-21e7-9a6e-5bb9de2fe479.png">

## Cognitoの設定
非公開のlambdaを作りたかったので認証必須。
HTTP APIはCognito使うのが良さそう。
認証不要なAPIの場合は、この手順不要かと思います。

### ユーザープールを作る
* デフォルトでユーザープール作成する。
* ユーザーを1人作成する。
    * メールが送られてくる。
* アプリクライアントを作成する。
    * 次のチェックボックスだけONにする。
       * `認証用の管理 API のユーザー名パスワード認証を有効にする (ALLOW_ADMIN_USER_PASSWORD_AUTH)`
       * `更新トークンベースの認証を有効にする (ALLOW_REFRESH_TOKEN_AUTH)`（OFFにできなかった）

### フェデレーティッドアイデンティティ
* 先ほど作ったユーザープールの画面で下記をメモります。
    * `ユーザープールID`  
<img width="1396" alt="スクリーンショット 2020-01-17 22.08.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/64702c9b-aab4-c741-9ef6-030051e87fc0.png">
    * `アプリクライアントID`  
    <img width="802" alt="スクリーンショット 2020-01-17 22.26.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/3f890021-3744-93f1-04f9-898d1ee3e34c.png">
* フェデレーティッドアイデンティティを開きます。  
<img width="415" alt="スクリーンショット 2020-01-17 22.28.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/ec585a8b-3066-efdb-07ac-26b731202099.png">
* `新しいIDプールの作成`ボタンを押して、メモった情報を入力し、作成します。  
<img width="1165" alt="スクリーンショット 2020-01-17 22.30.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/e206a2ff-c27c-9b66-736f-ca44015bf2d1.png">

## API Gatewayの設定
公式資料はこれかな？
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-examples.html

認証を有効にしたいので、下記の設定を行う。
公式資料はこれ。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/http-api-jwt-authorizer.html

* API Gatewayのコンソールから、lambdaから作成したAPIを開く。
* `認可`からオーソライザーを作成する。  
<img width="725" alt="スクリーンショット 2020-01-18 19.53.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/038873cd-4ed4-54cd-9263-ce20c8162502.png">  
 * こんな感じでつくる。  
<img width="874" alt="スクリーンショット 2020-01-19 12.22.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/ca05d267-c583-f492-5d17-a9f74085e143.png">
* 作ったオーソライザーをルートにアタッチする。  
<img width="1146" alt="スクリーンショット 2020-01-18 20.02.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/e2383939-7824-cd33-d238-6b0d2c52b3d1.png">

## APIを叩いてみる
とりあえず、叩いてみる。
URLはlambdaのAPI Gatewayの箇所に書いてある。  
<img width="1013" alt="スクリーンショット 2020-01-19 12.23.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472216/8288b73a-6be7-c61f-bf78-a8529d49855f.png">

```
$ curl https://mnh3XXXXXX.execute-api.ap-northeast-1.amazonaws.com/default/http-api-test
{"message":"Unauthorized"}
```
認証作ったし動かなくて正解。

### 認証情報の取得
JWTなる認証はJSON形式のトークンを使って認証をやりとりするそうな。
まずはトークン取得。
* `--user-pool-id`はユーザープールIDを指定。
* `--client-id`はアプリクライアントIDを指定。
* `--auth-parameters`はcognitoで作成したユーザーの名前とパスワードを指定。

```
$ aws cognito-idp admin-initiate-auth --user-pool-id ap-northeast-1_ItJXXXXXX --client-id 6fflXXXXXXXXXXXXXXXXXXXXXX --auth-flow ADMIN_USER_PASSWORD_AUTH --auth-parameters "USERNAME=tsuyoshi,PASSWORD=password"
{
    "ChallengeName": "NEW_PASSWORD_REQUIRED",
    "Session": "MktQ~（長いので省略）~Qoj9zrYg-lsWI",
    "ChallengeParameters": {
        "USER_ID_FOR_SRP": "tsuyoshi",
        "requiredAttributes": "[]",
        "userAttributes": "{\"email_verified\":\"true\",\"email\":\"hori@hogehoge.jp\"}"
    }
}
```
https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-initiate-auth.html
まずはパスワード変更してね。って事らしい。

https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/admin-respond-to-auth-challenge.html
パスワード変更する
* `--user-pool-id`はユーザープールIDを指定。
* `--client-id`はアプリクライアントIDを指定。
* `--challenge-responses`でユーザーの名前と新しいパスワードを指定。
* `--session`は直前に実行したコマンドで返ってきた`Sessions`の値をコピペ。

```
$ aws cognito-idp admin-respond-to-auth-challenge --user-pool-id ap-northeast-1_ItJXXXXXX --client-id 6fflXXXXXXXXXXXXXXXXXXXXXX --challenge-name NEW_PASSWORD_REQUIRED --challenge-responses NEW_PASSWORD='P@55w0rd',USERNAME=tsuyoshi --session "MktQk~(長いので省略)~Qoj9zrYg-lsWI"
```
改めてトークンの取得。

```
$ aws cognito-idp admin-initiate-auth --user-pool-id ap-northeast-1_ItJXXXXXX --client-id 6fflXXXXXXXXXXXXXXXXXXXXXX --auth-flow ADMIN_USER_PASSWORD_AUTH --auth-parameters "USERNAME=tsuyoshi,PASSWORD=P@55w0rd"
{
    "ChallengeParameters": {},
    "AuthenticationResult": {
        "AccessToken": "eyJr~(省略)~MaT_g",
        "ExpiresIn": 3600,
        "TokenType": "Bearer",
        "RefreshToken": "eyJ~(省略)~KVw",
        "IdToken": "eyJr~(省略)~uXg"
    }
}
```
認証につかうのは`AuthenticationResult.IdToken`っぽい。

### 証情報をつかってAPIを叩く
```
$ curl -H 'Authorization: eyJr~(省略)~uXg' https://mnh3XXXXXX.execute-api.ap-northeast-1.amazonaws.com/default/http-api-test
{"message": "Hello Lambda"}
```
うごいた！

# 備考
* オーソライザーをデタッチしたら、認証介さずアクセスできた。オープンなAPI。
* urlはdefaultを省略できるので`https://mnh3XXXXXX.execute-api.ap-northeast-1.amazonaws.com/http-api-test`でもアクセスできる。
* パスパラメータ等はまだつかえないのかな・・・？