概要

認証付きGoogle Cloud Functionsを呼ぶ方法が中々分かり辛かったたので、メモとして残しておきます。

手順

おおまかな手順は以下の通りです。

  1. Cloud Functionsの認証用のサービスアカウントを作成する
  2. サービスアカウントにcloudfunctions.invokerロールを付与する
  3. サービスアカウントの秘密鍵を作成する
  4. 秘密鍵からJWTを生成する
  5. JWTを使ってCloud Functionsにアクセスする

1. Cloud Functionsの認証用のサービスアカウントを作成する

$ gcloud iam service-accounts create <SERVICE_ACCOUNT_NAME> --display-name "<SERVICE_ACCOUNT_NAME>"

2. サービスアカウントにcloudfunctions.invokerロールを付与する

$ gcloud functions add-iam-policy-binding <FUNCTION_NAME> \
    --region="<REGION_NAME>" \
    --member="serviceAccount:<SERVICE_ACCOUNT_NAME>@<PROJECT_ID>.iam.gserviceaccount.com" \
    --role="roles/cloudfunctions.invoker"

3. サービスアカウントの秘密鍵を作成する

最初にサービスアカウントの秘密鍵を作成します。

$ gcloud iam service-accounts keys create <KEY_FILE_NAME>.json \
    --iam-account="<SERVICE_ACCOUNT_NAME>@<PROJECT_ID>.iam.gserviceaccount.com"

次に、秘密鍵をPEM形式に変換します。

$ jq .private_key <KEY_FILE_NAME>.json | sed -e 's/\\n/\'$'\n/g' -e "s/\"//g" > <KEY_FILE_NAME>.pem

5. 秘密鍵からJWTを生成する

秘密鍵からJWTを生成します。

今回は、PyJWTを利用して生成します。

# PyJWTのインストール
$ pip install PyJWT
# generate_jwt.py
import jwt
import datetime
import requests
import json

payload = {
  "target_audience": "https://<REGION_NAME>-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>",
  "iss": "<SERVICE_ACCOUNT_NAME>@<PROJECT_ID>.iam.gserviceaccount.com",
  "sub": "<SERVICE_ACCOUNT_NAME>@<PROJECT_ID>.iam.gserviceaccount.com",
  "aud": "https://www.googleapis.com/oauth2/v4/token",
  "exp": datetime.datetime.utcnow() + datetime.timedelta(minutes=10),
  "iat": datetime.datetime.utcnow()
}

key = open("<KEY_FILE_NAME>.pem").read()

token = jwt.encode(
    payload=payload, 
    key=key, 
    algorithm="RS256"
)

ret = requests.post(
        url="https://www.googleapis.com/oauth2/v4/token", headers={"Authorization": "Bearer " + token}, 
        data={"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": token}
    )
token = json.loads(ret.text)["id_token"]

print(token)

もし環境構築が面倒であれば、jwt.ioのデモを利用して生成することもできます。

6. JWTを使ってCloud Functionsにアクセスする

JWTを使ってCloud Functionsにアクセスします。

今回はcurlを利用してアクセスします。

$ curl -X GET -H "Authorization: Bearer $(python create_jwt.py)" "https://<REGION_NAME>-<PROJECT_ID>.cloudfunctions.net/<FUNCTION_NAME>"

以上です。