LoginSignup
25
11

More than 3 years have passed since last update.

GitHub Actionsを使ってGCP Cloud Functionsをデプロイする(IAMエラーの解消方法)

Last updated at Posted at 2020-04-23

TL;DR;

  • GitHub ActionsでCloud Functionsをデプロイしようとした
  • 単純に「Cloud Functions開発者」ロールを付与したサービスアカウント( ci-deploy@PROJECT_ID.iam.gserviceaccount.com とする )でデプロイしようとしたらエラーになった
  • 下記コマンドでデフォルトのサービスアカウント PROJECT_ID@appspot.gserviceaccount.comci-deploy@PROJECT_ID.iam.gserviceaccount.com にバインドして実行したら無事デプロイできた。
gcloud iam service-accounts add-iam-policy-binding PROJECT_ID@appspot.gserviceaccount.com \
  --member='serviceAccount:ci-deploy@PROJECT_ID.iam.gserviceaccount.com' \
  --role=roles/iam.serviceAccountUser

実現したいこと

devブランチにマージしたときに、GitHub ActionsでCloud Functionsをデプロイすること。

IAMエラー発生

サービスアカウントを作成

  1. GitHub Actionsでデプロイを実行するサービスアカウントとして ci-deploy@PROJECT_ID.iam.gserviceaccount.com を作成
  2. 「Cloud Functions開発者(roles/cloudfunctions.developer)」ロールを付与
  3. サービスアカウントのJSONキーを作成

GitHub Secretsの設定

  • サービスアカウントのJSONキーの中身を GCP_SA_KEY_DEV という名前でセット

GitHub ActionsのWorkflowを定義

下記Workflowを定義します。
Actionsの中身の説明は本旨ではないので割愛します。
gcloudを実行するために使っている GoogleCloudPlatform/github-actions/setup-gcloud については、リポジトリを参照してください。
https://github.com/GoogleCloudPlatform/github-actions/tree/master/setup-gcloud

name: Deploy Cloud Functions(Dev)

on:
  push:
    branches:
      - dev

jobs:
  build-deploy:
    name: Deploy Functions
    runs-on: ubuntu-latest

    env:
      REGION: asia-northeast1

    steps:
      - uses: actions/checkout@v2
      - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          # OSSであれば project_id や service_account_email もsecretsに入れるのが良いでしょう
          project_id: PROJECT_ID
          service_account_email: ci-deploy@PROJECT_ID.iam.gserviceaccount.com
          service_account_key: ${{ secrets.GCP_SA_KEY_DEV }}
      - name: Deploy Functions
        run: |
          gcloud functions deploy FUNCTION1_NAME --source ./src/FUNCTION1_NAME --region=${REGION}
          gcloud functions deploy FUNCTION2_NAME --source ./src/FUNCTION2_NAME --region=${REGION}

GitHub Actionsの実行

任意のfeatureブランチからdevにマージしてGitHub Actionsを起動します。
すると、gcloud functions deploy で下記エラーが発生します。

[Missing necessary permission iam.serviceAccounts.actAs for  on the service account PROJECT_ID@appspot.gserviceaccount.com. 
Ensure that service account PROJECT_ID@appspot.gserviceaccount.com is a member of the project PROJECT_ID, and then grant  the roles/iam.serviceAccountUser role. 
You can do that by running 'gcloud iam service-accounts add-iam-policy-binding PROJECT_ID@appspot.gserviceaccount.com --member= --role=roles/iam.serviceAccountUser' 
In case the member is a service account please use the prefix 'serviceAccount:' instead of 'user:'.]

IAMエラー解消

IAMアカウントにロールを追加

エラーメッセージを見て、え? PROJECT_ID@appspot.gserviceaccount.com とかお呼びじゃないんだけど?
いや、実行するのに使ってるのは ci-deploy@PROJECT_ID.iam.gserviceaccount.com なんだけど?
などと思いながらも、メッセージの指示通り下記コマンドを実行します。

gcloud iam service-accounts add-iam-policy-binding PROJECT_ID@appspot.gserviceaccount.com \
  --member='serviceAccount:ci-deploy@PROJECT_ID.iam.gserviceaccount.com' \
  --role=roles/iam.serviceAccountUser

これにより、 PROJECT_ID@appspot.gserviceaccount.com にroles/iam.serviceAccountUserロールが付き、かつ ci-deploy@PROJECT_ID.iam.gserviceaccount.com がバインドされるようです。

なお、バインド情報は下記コマンドで確認できます。
(GCPコンソールで確認する方法は不明です)

> gcloud iam service-accounts get-iam-policy PROJECT_ID@appspot.gserviceaccount.com
bindings:
- members:
  - serviceAccount:ci-deploy@PROJECT_ID.iam.gserviceaccount.com
  role: roles/iam.serviceAccountUser
etag: xxxxxxxxxx
version: 1

GitHub Actionsの再実行

上記コマンドを実行した上で、再度、GitHub Actionsを実行(GitHub上でRe-run)すると、無事、Cloud Functionsのデプロイに成功しました。

IAMエラーの原因究明(半分くらい)

しかし、この時点では、結局、何が問題であって、なぜ上手くいったのか理解できていませんでした。
人に聞いたり、調べたりしてみたところ、リファレンスに

デフォルトでは、Cloud Functions はランタイムに App Engine のデフォルトのサービス アカウント(PROJECT_ID@appspot.gserviceaccount.com)を使用します。

という記述を見つけます。
ここで gcloud functions deploy のエラーコマンドに立ち戻ってみると、

Missing necessary permission iam.serviceAccounts.actAs for  on the service account PROJECT_ID@appspot.gserviceaccount.com.

つまり、 PROJECT_ID@appspot.gserviceaccount.com が、指定したサービスアカウントとして振る舞う(iam.serviceAccounts.actAs)権限が無い、ということを言っています(たぶん)。
この権限を与えるのが先ほどのコマンド(再掲)

gcloud iam service-accounts add-iam-policy-binding PROJECT_ID@appspot.gserviceaccount.com \
  --member='serviceAccount:ci-deploy@PROJECT_ID.iam.gserviceaccount.com' \
  --role=roles/iam.serviceAccountUser

のようです。

まだ残る疑問

ただ、 PROJECT_ID@appspot.gserviceaccount.com は、あくまでFunctionsのランタイムのIAMユーザであって、デプロイ時のものではないと、私は認識しています。
むしろ、こちらに記述のある、

Cloud Functions サービスでは、関数の作成、更新または削除中にプロジェクトの管理アクションを実行するため、Google Cloud Functions サービス エージェント アカウント(service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com)を使用します。

service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com がデプロイに使うIAMユーザなのではないかと。
だとすれば、権限を付けるべきユーザはこちらなのでは……しかし、デプロイは上手く動いてるし……謎。
GCPのIAM周り、難しいですね。

謝辞

エラー原因について相談の乗ってくれて、いろいろな情報をくれた @inductor さん、@0Delta さん、ありがとうございました。
おかげで「何か知らんが動いた」で終わらせずに済みました。

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