1. はじめに
概要
Cloud Run functions は、デベロッパーがサーバーやランタイム環境を管理することなく、HTTPS を使用してトリガーしたり、CloudEvents に応答したりできる単一目的のスタンドアロン関数を作成できる軽量なコンピューティング ソリューションです。Cloud Run functions の詳細については、ブログ投稿をご覧ください。
Cloud Run functions の関数呼び出しを制御するには、 ID に基づいてアクセスを保護する方法と、 ネットワーク ベースのアクセス制御を使用してアクセスを保護する方法の 2 つがあります。この Codelab では、最初の方法に焦点を当て、ID に基づいてアクセスを保護して関数を呼び出すための 3 つのシナリオについて説明します。
- gcloud ID トークンを使用して、ローカルでの開発とテストの目的で関数を呼び出す
- ローカルで開発とテストを行うときにサービス アカウントの権限を借用して、本番環境と同じ認証情報を使用する
- Google クライアント ライブラリを使用して、Google Cloud APIs の認証を処理する(サービスが関数を呼び出す必要がある場合など)
学習内容
- Cloud Run functions で認証を構成し、認証が正しく構成されていることを確認する方法
- gcloud ID のトークンを指定して、ローカル開発環境から認証済み関数を呼び出す方法
- サービス アカウントを作成し、関数を呼び出すための適切なロールを付与する方法
- 関数を呼び出すための適切なロールを持つローカル開発環境からサービス アカウントの権限を借用する方法
2. 設定と要件
前提条件
- Cloud Console にログインしていること
- HTTP トリガーの Cloud Run functions 関数をデプロイ済みであること。クイックスタートの例をご覧ください。
- (省略可)3 番目のシナリオでは、この Codelab では Node.js と npm を例として使用しますが、Google Auth クライアント ライブラリでサポートされているランタイムを使用できます。
Cloud Shell をアクティブにする
- Cloud Console で、[Cloud Shell をアクティブにする ] をクリックします
。

Cloud Shell を初めて起動した場合は、その内容を説明する画面が表示されます。その場合は、[続行] をクリックしてください。

すぐにプロビジョニングが実行され、Cloud Shell に接続されます。

この仮想マシンには、必要な開発ツールがすべてロードされています。永続的な 5 GB のホーム ディレクトリが用意されており、Google Cloud で実行されるため、ネットワーク パフォーマンスと認証が大幅に向上します。 この Codelab で行う作業のほとんどはブラウザから実行できます。
Cloud Shell に接続すると、認証が完了し、プロジェクトがプロジェクト ID に設定されていることがわかります。
- Cloud Shell で次のコマンドを実行して、認証されたことを確認します。
gcloud auth list
コマンド出力
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Cloud Shell で次のコマンドを実行して、gcloud コマンドがプロジェクトを認識していることを確認します。
gcloud config list project
コマンド出力
[core] project = <PROJECT_ID>
上記のようになっていない場合は、次のコマンドで設定できます。
gcloud config set project <PROJECT_ID>
コマンド出力
Updated property [core/project].
3. 認証済み Cloud Run functions 関数を作成してテストする
認証を必須にすると、関数を呼び出すプリンシパルに Cloud Run 起動元ロールが必要になります。そうでない場合、関数は 403 Forbidden エラーを返します。この Codelab では、適切な起動元ロールをプリンシパルに付与する方法について説明します。
gcloud コマンドを簡略化するためにローカル環境変数を設定する
まず、この Codelab で使用する gcloud コマンドの可読性を高めるために、いくつかの環境変数を作成します。
REGION=us-central1 PROJECT_ID=$(gcloud config get-value project)
関数のソースコードを作成する
この Codelab では Node.js を使用しますが、Google Auth クライアント ライブラリでサポートされているランタイムを使用できます。
まず、ディレクトリを作成してそのディレクトリに移動します。
mkdir auth-function-codelab && cd $_
次に、package.json ファイルを作成します。
touch package.json
echo '{
"dependencies": {
"@google-cloud/functions-framework": "^3.0.0"
}
}
' > package.json
次に、index.js ソースファイルを作成します。
touch index.js
echo 'const functions = require("@google-cloud/functions-framework");
functions.http("helloWorld", (req, res) => {
res.send(`Hello ${req.query.name || req.body.name || "World"}!`);
});' > index.js
認証済み関数を作成する
nodejs20 ランタイムの認証済み関数を作成する手順は次のとおりです。ただし、Google Auth クライアント ライブラリでサポートされているランタイムを使用できます。
FUNCTION_NAME=authenticated-function-codelab ENTRY_POINT=helloWorld
Cloud Run functions を Cloud Run に直接デプロイするには、次のコマンドを実行します。
gcloud beta run deploy $FUNCTION_NAME \
--source . \
--function helloWorld \
--region $REGION \
--no-allow-unauthenticated
後で使用するために、関数 URL を環境変数として保存できます。
FUNCTION_URL="$(gcloud run services describe $FUNCTION_NAME --region $REGION --format 'value(status.url)')"
Cloud Functions(第 2 世代)としてデプロイする場合は、次のコマンドを使用します。
gcloud functions deploy nodejs-http-function \ --gen2 \ --runtime=nodejs20 \ --region=$REGION \ --source=. \ --entry-point=helloWorld \ --trigger-http \ --no-allow-unauthenticated
後で使用するために、関数 URL を環境変数として保存できます。
FUNCTION_URL="$(gcloud functions describe $FUNCTION_NAME --gen2 --region us-central1 --format='get(serviceConfig.uri)')"
匿名呼び出し元として呼び出して、関数に認証が必要であることを確認する
認証なしで関数を呼び出して、想定どおりの 403 エラーを受け取ることを確認します。
コマンドラインから、次の curl コマンドを実行します。
curl -i $FUNCTION_URL
次の結果が表示されます。
<html><head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>403 Forbidden</title> </head> <body text=#000000 bgcolor=#ffffff> <h1>Error: Forbidden</h1> <h2>Your client does not have permission to get URL <code>/</code> from this server.</h2> <h2></h2> </body></html>
これで、認証を提供して関数を呼び出すことができる 3 つのシナリオを説明する準備ができました。
4. シナリオ 1: gcloud ID トークンを使用する
デベロッパーは、関数をローカルで開発しながらテストする方法を必要とします。このセクションでは、独自の ID を使用して関数が正しく認証されていることを確認するための簡単なテストを行います。
次のコマンドを実行して、gcloud を使用して認証されていることを確認します。
gcloud auth list
アクティブな ID の横にアスタリスクが表示されます。例:
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
gcloud init と gcloud auth login の設定の詳細については、ドキュメントをご覧ください。
次に、関数を呼び出して ID トークンを渡します。
curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token)"
次の結果が表示されます。
Hello World!
トラブルシューティング
403 Forbidden エラーが表示された場合は、ID に Cloud Run 起動元ロールがあることを確認してください。IAM コンソールを使用して、プリンシパルに付与されたロールを確認できます。
独自の ID トークンを使用すると、開発中に関数をすばやくテストできますが、認証済み関数の呼び出し元には適切なロールが必要です。そうでない場合、呼び出し元は 403 Forbidden エラーを受け取ります。
関数を呼び出すロールを持つ ID とサービス アカウントの数を制限して、最小権限の原則に従うことをおすすめします。次のシナリオでは、新しいサービス アカウントを作成し、関数を呼び出すための適切なロールを付与する方法について説明します。
5. シナリオ 2: サービス アカウントの権限を借用する
このシナリオでは、ローカルで開発とテストを行うときに、サービス アカウントの権限を借用して(つまり、権限を想定して)関数を呼び出します。サービス アカウントの権限を借用することで、本番環境と同じ認証情報で関数をテストできます。
これにより、ロールを確認するだけでなく、ローカル テストのみを目的として他の ID に Cloud Functions 起動元ロールを付与する必要がないため、最小権限の原則に従うことができます。
この Codelab では、この Codelab で作成した関数を呼び出すロールのみを持つ新しいサービス アカウントを作成します。
サービス アカウントを新規作成
まず、gcloud コマンドで使用するサービス アカウントを表すために、いくつかの追加の環境変数を作成します。
SERVICE_ACCOUNT_NAME="invoke-functions-codelab" SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com
次に、サービス アカウントを作成します。
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \ --display-name="Cloud Run function Authentication codelab"
サービス アカウントに Cloud Run 起動元ロールを付与します。
gcloud run services add-iam-policy-binding $FUNCTION_NAME \ --region=us-central1 \ --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \ --role='roles/run.invoker'
サービス アカウントの権限を借用して関数を呼び出す
これを行うには、ID トークンを取得して、新しく作成したサービス アカウントの権限を借用します。
権限借用に必要なロールを追加する
サービス アカウントの権限を借用するには、ユーザー アカウントに サービス アカウント トークン作成者(roles/iam.serviceAccountTokenCreator)のロールが必要です。このロールを使用して、サービス アカウントの ID トークンを生成します。
次のコマンドを実行して、アクティブなユーザー アカウントにこのロールを付与できます。
ACCOUNT_EMAIL=$(gcloud auth list --filter=status:ACTIVE --format="value(account)") gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT_ADDRESS \ --member user:$ACCOUNT_EMAIL \ --role='roles/iam.serviceAccountTokenCreator'
サービス アカウントの ID トークンを使用する
権限が伝播するまで数分待ちます。サービス アカウントの ID トークンを渡すことで、関数を呼び出すことができます。
curl $FUNCTION_URL -H "Authorization: bearer $(gcloud auth print-identity-token --impersonate-service-account $SERVICE_ACCOUNT_ADDRESS)"
次の結果が表示されます。
WARNING: This command is using service account impersonation. All API calls will be executed as [invoke-functions-codelab@<project-id>.iam.gserviceaccount.com]. Hello World!
6. シナリオ 3: Google クライアント ライブラリを使用する
この Codelab の最後の部分では、 小さなサービスをローカルで実行してサービス アカウントの ID トークンを生成し、 Google Auth クライアント ライブラリと アプリケーションのデフォルト認証情報(ADC)を使用して関数をプログラムで呼び出します。Google クライアント ライブラリの詳細については、ドキュメントの クライアント ライブラリの説明をご覧ください。
ADC の使用は、他の Google Cloud リソース(Cloud Storage、Vision API など)とやり取りしながら、関数をローカル(ノートパソコン、Cloud Shell など)で作成してテストする場合に特に重要です。この例では、サービスが認証を必要とする別の関数を呼び出す方法について説明します。ADC とローカル開発の詳細については、ブログ投稿 Cloud Functions をローカルで開発してテストする方法 | Google Cloud ブログをご覧ください。
gcloud コマンドを実行してサービス アカウントの権限を借用する
ADC はアプリケーション環境に基づいて認証情報を自動的に検索し、その認証情報を Google Cloud APIs の認証に使用します。–impersonate-service-account フラグを使用すると、Google Cloud APIs に対する認証にその ID を使用して、サービス アカウントの権限を借用できます。
サービス アカウントの権限を借用するには、次のコマンドを実行します。
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
これで、ID ではなく、そのサービス アカウントとして gcloud コマンドを実行できます。
認証済み関数を呼び出すサービスを作成して実行する
ランタイムごとに、インストールできる独自の Google Auth クライアント ライブラリ があります。この Codelab では、Node.js アプリをローカルで作成して実行する手順について説明します。
Node.js の手順は次のとおりです。
- 新しいディレクトリの作成
mkdir local-dev && cd $_
- 新しい Node.js アプリを作成する
npm init -y
- Google Auth クライアント ライブラリをインストールする
npm install google-auth-library
index.jsファイルを作成する- Cloud Run functions の URL を取得します。この URL は、次のステップでコードに追加します。
echo $FUNCTION_URL
- 次のコードを index.js に追加します。targetAudience 変数を Cloud Run functions の URL に変更してください。
index.js
// Cloud Functions uses your function's url as the `targetAudience` value
const targetAudience = '<YOUR-CLOUD-RUN-FUNCTION-URL>';
// For Cloud Functions, endpoint(`url`) and `targetAudience` should be equal
const url = targetAudience;
const { GoogleAuth } = require('google-auth-library');
const auth = new GoogleAuth();
async function request() {
console.info(`request ${url} with target audience ${targetAudience}`);
// this call retrieves the ID token for the impersonated service account
const client = await auth.getIdTokenClient(targetAudience);
const res = await client.request({ url });
console.info(res.data);
}
request().catch(err => {
console.error(err.message);
process.exitCode = 1;
});
- アプリを実行する
node index.js
「Hello World!」という結果が表示されます。
トラブルシューティング
エラー「Permission ‘iam.serviceAccounts.getOpenIdToken' denied on resource (or it may not exist).」が表示された場合は、サービス アカウント トークン作成者ロールが伝播するまで数分お待ちください。
エラー「Cannot fetch ID token in this environment, use GCE or set the GOOGLE_APPLICATION_CREDENTIALS 環境変数 to a サービス アカウント credentials JSON file」が表示された場合は、コマンドの実行を忘れている可能性があります。
gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS
7. 完了
以上で、この Codelab は完了です。
Cloud Run functions を保護する方法に関するドキュメントを確認することをおすすめします。
また、Cloud Run functions を使用したローカル開発に関するこちらのブログ投稿で、ローカル デベロッパー環境で Cloud Run functions を開発してテストする方法を確認することをおすすめします。
学習した内容
- Cloud Run functions で認証を構成し、認証が正しく構成されていることを確認する方法
- gcloud ID のトークンを指定して、ローカル開発環境から認証済み関数を呼び出す方法
- サービス アカウントを作成し、関数を呼び出すための適切なロールを付与する方法
- 関数を呼び出すための適切なロールを持つローカル開発環境からサービス アカウントの権限を借用する方法
8. クリーンアップ
意図しない料金が発生しないようにするには(たとえば、この Cloud Functions が 無料枠の月間 Cloud Run functions 呼び出し割り当てよりも多く呼び出された場合)、Cloud Functions を削除するか、ステップ 2 で作成したプロジェクトを削除します。
サービス アカウントの権限借用を停止するには、ID を使用して再ログインします。
gcloud auth application-default login
Cloud Run functions を削除するには、Cloud Run functions の Cloud Console(https://console.cloud.google.com/functions/)に移動します。ステップ 2 で作成したプロジェクトが現在選択されているプロジェクトであることを確認します。
先ほどデプロイした [my-authenticated-function] を選択します。[削除] をクリックします。
プロジェクト全体を削除する場合は、https://console.cloud.google.com/cloud-resource-manager に移動し、ステップ 2 で作成したプロジェクトを選択して、[削除] を選択します。プロジェクトを削除する場合は、Cloud SDK でプロジェクトを変更する必要があります。gcloud projects list を実行すると、使用可能なすべてのプロジェクトのリストが表示されます。