概要
認証付きGoogle Cloud Functionsを呼ぶ方法が中々分かり辛かったたので、メモとして残しておきます。
手順
おおまかな手順は以下の通りです。
- Cloud Functionsの認証用のサービスアカウントを作成する
- サービスアカウントにcloudfunctions.invokerロールを付与する
- サービスアカウントの秘密鍵を作成する
- 秘密鍵からJWTを生成する
- 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>"
以上です。