Firebase Functionsを編集者アカウントで使う

Firebase関連の開発を行う場合、
・限られた数名は「オーナー」権限
・それ以外の開発者は「編集者」権限
と設定するかと思います。

「編集者」権限で、Firebase Functionsのデプロイが出来なかったので、その記録です。

## 準備

`firebase-tools`のバージョンは 8.10.0 で確認しています。

「編集者」権限のアカウントを用意します。
そして、 `firebase login` コマンドで、そのアカウントでログインしておきます。

## 実行とエラー

FunctionsがFirebase上に存在していない状態（一度もデプロイしていない状態）で、 `firebase deploy --only functions` を実行します。

すると、Node.jsのバージョンによって、それぞれ別のエラー・状態になりました。

### Node.js 8 の場合

package.json が `"engines": {"node": "8"}` となっている場合。

```
✔  functions: required API cloudfunctions.googleapis.com is enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (34.94 KB) for uploading

Error: Missing required permission on project <project-id> to deploy new HTTPS functions. The permission cloudfunctions.functions.setIamPolicy is required to deploy the following functions:

- helloWorld
- addMessage

To address this error, please ask a project Owner to assign your account the "Cloud Functions Admin" role at the following URL:

https://console.cloud.google.com/iam-admin/iam?project=<project-id>
```

このとき、Firebaseのコンソールを確認しても、Functionは作成されていませんでした。

もちろん、実行もできない状態。

### Node.js 10 の場合

package.json が `"engines": {"node": "10"}` となっている場合。

```
i  functions: creating Node.js 10 function helloWorld(us-central1)...
i  functions: creating Node.js 10 function addMessage(us-central1)...
i  functions: creating Node.js 10 function makeUppercase(us-central1)...
✔  functions[makeUppercase(us-central1)]: Successful create operation.


Functions deploy had errors with the following functions:




To try redeploying those functions, run:
    firebase deploy --only "functions:,functions:"


To continue deploying other features (such as database), run:
    firebase deploy --except functions

Error: Functions did not deploy properly.
```

Firebaseの画面上、Functionは作成されたように見えます。
ただし、ブラウザなどから実行してみると403エラーとなり、
> Your client does not have permission to get URL /addMessage?text=uppercaseme from this server.

といったレスポンスが返却されます。

この状態で、再度 `firebase deploy --only functions` を実行すると、 "Deploy complete!" となりますが、状況は変わらず403エラー。

GCPのコンソールで確認すると、"Authentication" が空になっているため、たしかに実行できないようになっています。
試しに、オーナー権限を持っているアカウントで、 「allUsers」 に 「Cloud Functions 起動元」権限を追加すると、ブラウザからの実行に成功しました。

## 解決法

Google Cloud Platform側で、権限を追加してあげる必要がありました。

Firebaseのプロジェクト設定画面より、「ユーザーと権限」タブの下部にある「権限に関する詳細設定」を選択します。
すると、GCPのコンソールが表示されます。
そこで、対象のユーザに対して「編集者」と追加する形で「Cloud Functions 管理者」を設定します。

既存のFunctionsを一度削除して、再度デプロイコマンドを実行すると、外部から呼び出せるFunctionが作成できました。

（厳密には `cloudfunctions.functions.setIamPolicy` を追加したら良さそうですが、今回は面倒なので「Cloud Functions 管理者」を与えました。）

※ ただ、この解決方法が正しいのかは、自信が無いです。。。

## 何が起こっているか推測

いくつかの記事でも言及されていましたが、2020年1月15日ごろから状況が変わったようです。
https://qiita.com/toshiaki_takase/items/ce65cd5582a80917b52f
https://qiita.com/tekunikaruza/items/c068506ca0d6d648cc50#%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%B3%95

https://cloud.google.com/functions/docs/securing/managing-access-iam#allowing_unauthenticated_function_invocation
> 注: 2020 年 1 月 15 日時点では、HTTP 関数はデフォルトで認証が必要です。デプロイ時またはデプロイ後に関数が未認証の呼び出しを実行できるかどうか指定できます。

Cloud Functions側のデフォルトの動作が変わってしまい、それがFirebaseの期待している動作と合っていないという印象を受けました。
Firebaseとしては、かんたんにFunctionsを使ってもらうために "allUsers" をデフォルトで設定したいが、GCP的にはセキュリティを強化したい、、、みたいな。