GoogleAppEngineにデプロイしたStrapiにIAPを設置して認証を設ける

## はじめに

StrapiをGoogle App Engne (GAE) にデプロイし、IAPを設置することでGoogleアカウントで認証を要求できるようにします。
ほかにも複数あるcloud環境の中でGAEを選んだ理由は、タダで利用できるからです。

こんな記事書いておいてデプロイ先は有料ってなると一貫性に欠けますからね。

https://qiita.com/ikea_shark_jk/items/695c4ab7df80dc20ee97

また、IAPを設けたかったというのも理由の一つです。
ID/Passの認証は無敵ではないですし、そもそも何のアプリがデプロイされているのかを周回しているであろうBotなどに探らせてくないですからね。
セキュリティまるで詳しくないですが、詳しくないなりにも対策はしたいものです。

## StrapiをGAEにデプロイする

まず、GAEにStrapiをデプロイします。
本来はIAPを先に設置できれば良いのですが、GCPの設定的に何もない場所にIAPは設置できないようなので仕方ありません。
一応ID/PASSによる認証があるので即座に突破なんてことはないと思いますが、心配であれば`create-react-app`やらなんやらのデフォルトアプリか何かを先にデプロイしておいて、IAPを設置後にその内容を上書きする形式をとっても良いと思います。

### 環境

- Almalinux 8
- node 18.12.1
- fish shell

### gcloudの設定


GCPのcliツールであるGoogle Cloud CLIを入れます。

```bash
> bash
> sudo tee -a /etc/yum.repos.d/google-cloud-sdk.repo << EOM
[google-cloud-cli]
name=Google Cloud CLI
baseurl=https://packages.cloud.google.com/yum/repos/cloud-sdk-el8-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=0
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOM
> exit
> sudo dnf install google-cloud-cli
```

RHEL 7 互換の場合は、baseUrl の値で el8 を el7 に置き換える必要があるみたいです。

initします
色々案内が出るので、案内に従ってぽちぽちしましょう。

```
> gcloud init
```

終わったら GAE の設定ファイルである `app.yaml`を作成し、以下の内容を書き込みます。
各項目の意味が気になるのであれば、こちらを参照してください。

https://cloud.google.com/appengine/docs/standard/nodejs/config/appref?hl=ja

```app.yaml
runtime: nodejs18

instance_class: F1 # インスタンス、F1は28h/dayまで無料

service: default #サービス名、最初はdefaultにしないと怒られる

env_variables:
  NODE_ENV: "production"

automatic_scaling:
  min_instances: 1 # 最小インスタンス数 おそらく0でもよい
  max_instances: 1

includes: # 環境変数だけ別のファイルに切り出してinclude
  - secret.yaml

```

↑の設定ファイルでは環境変数を別ファイルに切り出していますが、常にローカルからデプロイし続けるのであれば切り出す必要はないです。
その場合は、後述する`.gcloudignore`に`.env`を含めないようにしてください。
個人的に、将来GihubActionsなどのCD環境を用意してその中でseacretからseacret.yamlを生成したいと考えているために別ファイルに切り出しています。
seacret.yamlを用意する場合は、`.gitignore`への追加を忘れないようにしましょう。

終わったら、`.gcloudignore`に以下を記載します。
これは、deploy時にこれらのファイルを含まないとする設定ファイルです。

```.gcloudignore
.editorconfig
.env
.env.example
.git
.gitignore
.gcloudignore
README.md
node_modules/
```

書き終わったらデプロイします。
`pacage.json`にdeployのscroptを追加します。

```package.json
{
// ...
  "scripts": {
// ...
    "deploy": "NODE_ENV=production run-s build && gcloud app deploy --appyaml=app.yaml",
  },
// ...
  "devDependencies": {
// ...
    "npm-run-all": "^4.1.5",
  },
// ...
```

buildコマンドの箇所を、将来的に`pnpm`に切り替えることを視野に入れて`npm-run-all`を入れて`run-s`としていますが、ここはyarnでも問題ないです。
デプロイ前にはbuildを実行する必要があるので、そうなるようにしておきましょう。

ではいざデプロイ

```
yarn deploy
```

だいたい2~3分ほど待たされます。初回であればもしかしたらもう少し長く待たされるかもしれません。

案内されたURLからアプリが見れれば完了です。
見れない場合は、Cloud Buildにログが吐かれているので確認しましょう。
わたしの場合一度Cloud Buildの権限不足でGAEにデプロイできなかったので、そのあたりも確認しておいた方がよいです。
(Cloud Build > 設定 > App Engine.status disable -> enable)

## IAPを設定する

`https://console.cloud.google.com/security/iap/` で設定できます。
ドキュメントへのリンクも載せておきます

https://cloud.google.com/iap/docs/authenticate-users-google-accounts?hl=ja

ドキュメントに従い`OAuth 同意画面の構成`の項目をクリアしたのち、上記のURLに遷移して設定を進めていきます。

IAPの画面に行くと、App EngineのIAPのトグルが無効になっているので、これを有効化します。
次に、AppEngineのチェックボックスをクリックし、`プリンシパルを追加`をさらにクリックします。

出てきたパネルの`新しいプリンシバル`の項目にGoogleアカウントのメアドを入れ、ロールを選択で`IAP-secured Web App User`を選択します。
**管理者のアカウントはデフォルトでownerになっていますが、ownerだからといって認証を突破できるわけではないのでこれを明示的に追加する必要があります**。

それではデプロイ時に表示されたURLをクリックしてみましょう。
認証が挟まり、該当のユーザーを選択すれば問題なく使用できるはずです。

成功したら、今度はシークレットウィンドウを開いて同じURLに遷移します。
別のアカウントでログインし、以下の画面が表示されれば権限を持たないユーザーを弾くことに成功しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532032/cf091f36-8427-9b68-118f-66d3bf89fa20.png)