サービスアカウントの権限借用について

サービスアカウントの権限借用について

Google Cloudにおけるサービスアカウントの権限借用について解説と実際にサービスアカウントへの権限借用を試してCloud Storageへのアクセスを検証してみました。
2026.08.05

はじめに

こんにちは。
クラウド事業本部コンサルティング部の渡邉です。

Google Cloud を利用していると、サービスアカウントを使って各Google Cloudサービスへの認証する場面が頻繁にあります。認証の手段として、 サービスアカウントキー(JSON キーファイル) を発行して利用されている方もまだ一定数いらっしゃるのではないでしょうか?
サービスアカウントキーの利用には、以下のような課題があります。

  • 漏洩リスク: サービスアカウントキーは永続的な認証情報であり、事前認証なしで誰でも使用できます。キーファイルが漏洩すると、そのサービスアカウントの権限で自由にGoogle Cloudサービスの呼び出しが行われてしまいます。
  • 追跡性の欠如: サービスアカウントキーで認証した場合、監査ログにはサービスアカウントの ID のみが記録され、「誰がキーを使ったのか」を追跡することができません。これにより権限昇格のリスクや、否認防止(誰が操作したかの証明)が困難になる問題が生じます。
  • 運用負荷: サービスアカウントキーを利用するにしても、キーのローテーション、安全な保管、アクセス制御の管理が必要になります。

今回紹介するサービスアカウントの権限借用を利用することで、事前に認証されたプリンシパル(ユーザーまたはサービスアカウント)がサービスアカウントの短期認証情報を取得し、そのサービスアカウントとして操作を行うことができます。キーファイルが不要なため漏洩リスクがなく、認証情報はデフォルト1時間で失効し、監査ログに呼び出し元の ID が記録されるため追跡性も確保されます。

本記事では、サービスアカウントの権限借用の仕組み・ユースケース・必要な権限を整理した上で、gcloud CLI を使った具体的な検証手順をご紹介します。

サービスアカウントとは

サービスアカウントは、人ではなくアプリケーションやワークロードが Google Cloud リソースにアクセスするために使用する特別なアカウントです。ユーザーアカウントとは以下の点で異なります。

項目 ユーザーアカウント (Googleアカウント) サービスアカウント
用途 人間のユーザーによる操作 アプリケーション・ワークロード
パスワード あり なし(パスワードによるログイン不可)
管理単位 Cloud Identity / Google Workspace Google Cloud プロジェクト

サービスアカウントは リソース でもあるという点が重要です。リソースであるため、他のプリンシパル(ユーザーやサービスアカウント)に対して「このサービスアカウントを使ってよい」という権限を付与できます。これが権限借用となります。

サービスアカウントの権限借用とは

サービスアカウントの権限借用(Impersonation) とは、認証済みのプリンシパル(ユーザーまたは別のサービスアカウント)が、サービスアカウントの短期認証情報(Short-lived credentials)を取得し、そのサービスアカウントとして振る舞う機能でAWS における AssumeRole に相当する機能です。

権限借用の仕組み

サービスアカウントの権限借用では、常に2つの IDが関与します。

  1. 認証済みプリンシパル(呼び出し元): 権限借用を要求するユーザーまたはサービスアカウント
  2. 権限借用対象のサービスアカウント: 実際に操作を行う際の ID となるサービスアカウント

呼び出し元は、対象のサービスアカウントの短期認証情報(OAuth 2.0 アクセストークン)を取得し、そのトークンを使って API リクエストを認証します。

サービスアカウントの権限借用
サービスアカウントの権限借用

権限借用ではない認証方法との違い

サービスアカウントとして認証する方法はいくつかありますが、すべてが「権限借用」に該当するわけではありません。

認証方法 権限借用か? 監査ログに記録される ID
サービスアカウントキーで認証 いいえ サービスアカウントのみ
アタッチされたサービスアカウント(VM、Cloud Run 等) いいえ サービスアカウントのみ
--impersonate-service-account フラグ はい 呼び出し元 + サービスアカウント
Service Account Credentials API はい 呼び出し元 + サービスアカウント

権限借用の最大のメリットは、監査ログ(Cloud Audit Logs)に呼び出し元の ID とサービスアカウントの ID の両方が記録されることです。サービスアカウントキーでは「誰がキーを使ったのか」が追跡できないため、否認防止の観点で大きな差があります。

権限借用のユースケース

サービスアカウントの権限借用は、以下のようなシナリオで活用できます。

1. 一時的な権限昇格

インシデント対応時や、限定的な期間だけ特権アクセスが必要な場合に、IAM ポリシーを直接変更することなく、サービスアカウントを経由して必要な権限を付与できます。

2. 権限のテスト

特定の IAM ロールが十分かどうかを検証したい場合に、テスト用サービスアカウントに対象ロールを付与し、そのサービスアカウントを権限借用することで、自分のアカウントの IAM を変更せずにテストできます。

3. ローカル開発環境での認証

ローカル開発で、本番環境と同じサービスアカウントの権限でアプリケーションをテストしたい場合に、Application Default Credentials (ADC) と権限借用を組み合わせることで、サービスアカウントキーを発行せずに開発できます。

4. 外部アプリケーションの認証

Google Cloud 外で動作するアプリケーションを認証する場合、Workload Identity Federation と権限借用を組み合わせることで、サービスアカウントキーなしで認証を実現できます。

必要な権限

権限借用を行うには、対象サービスアカウントへの適切な権限を呼び出し元に付与する必要があります。

ロール ロール ID 含まれる主な権限 用途
Service Account Token Creator roles/iam.serviceAccountTokenCreator iam.serviceAccounts.getAccessToken
iam.serviceAccounts.getOpenIdToken
iam.serviceAccounts.signBlob
iam.serviceAccounts.signJwt
iam.serviceAccounts.implicitDelegation
アクセストークン、ID トークン、署名付き JWT/Blob の生成

このロールを、呼び出し元のプリンシパルに対して対象サービスアカウントのリソースレベルで付与します。

権限借用における権限昇格のリスク

権限借用はサービスアカウントキーよりも安全な認証手法ですが、Token Creator ロールの付与管理を誤ると権限昇格のリスクが生じます

Token Creator ロール = サービスアカウントと同等のアクセス権

Service Account Token Creator ロールを付与されたユーザーは、対象サービスアカウントの短期認証情報を自由に生成できるため、そのサービスアカウントが持つすべてのリソースにアクセスできます

つまり、サービスアカウントがユーザーよりも強い権限を持っている場合、Token Creator ロールの付与そのものが権限昇格となります。

権限借用における権限昇格のリスク
権限借用における権限昇格のリスク

Token Creator ロールを付与する前に、「そのユーザーがサービスアカウントを経由してアクセスできるようになるリソース」を必ず確認してください。ユーザー自身の権限よりも強い権限を持つサービスアカウントに対して Token Creator ロールを付与してはいけません。

setIamPolicy 権限による間接的な権限昇格

iam.serviceAccounts.setIamPolicy 権限を持つユーザーは、サービスアカウントの IAM ポリシーを変更できます。つまり、自分自身に Token Creator ロールを付与して権限借用を行うことが可能です。この権限は以下のロールに含まれます。

  • Owner(roles/owner
  • Security Admin(roles/iam.securityAdmin
  • Service Account Admin(roles/iam.serviceAccountAdmin

これらのロールを付与する際は、対象ユーザーがサービスアカウントを経由して間接的にアクセスできるリソースの範囲を考慮する必要があります。

リスクへの対策

上記のようなリスクへの対策として以下のような手法が考えられるかと思います。

対策 説明
最小権限の原則 Token Creator ロールはプロジェクトレベルではなく、特定のサービスアカウントのリソースレベルで付与する
IAM Recommender の活用 過剰な権限を持つロールの付与を検出・修正する
Security Command Center の活用 Event Threat Detection の「Anomalous Service Account Impersonator」ルールで、異常な権限借用リクエストを検知できる
IAM データアクセスログの有効化 IAM API のデータアクセスログを有効にし、誰がいつ Token Creator ロールを付与したか、誰が短期認証情報を生成したかを記録する

実際に試してみる

ここからは、gcloud CLI を使ってサービスアカウントの権限借用を実際に試してみます。

前提条件

  • Google Cloud プロジェクトが作成済みであること
  • gcloud CLI がインストール・認証済みであること
  • IAM API と Service Account Credentials API が有効化されていること
  • 操作するユーザーがプロジェクトに対して roles/iam.serviceAccountAdmin(サービスアカウント管理者)を持っていること

ステップ1: 環境変数の設定

検証で使用するプロジェクト ID などを環境変数に設定します。

# プロジェクト ID を設定
export PROJECT_ID=YOUR_PROJECT_ID

# 現在の認証ユーザーを確認
gcloud auth list --filter=status:ACTIVE --format="value(account)"

user@example.com

ステップ2: サービスアカウントの作成

権限借用の対象となるサービスアカウントを作成します。

# サービスアカウントを作成
gcloud iam service-accounts create sa-impersonation-demo \
  --display-name="Impersonation Demo SA" \
  --project=$PROJECT_ID

Created service account [sa-impersonation-demo].
Service account email: sa-impersonation-demo@my-project.iam.gserviceaccount.com

作成されたサービスアカウントを確認します。

# サービスアカウントの確認
gcloud iam service-accounts describe \
  sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com \
  --project=$PROJECT_ID

displayName: Impersonation Demo SA
email: sa-impersonation-demo@my-project.iam.gserviceaccount.com
etag: MDEwMjE5MjA=
name: projects/my-project/serviceAccounts/sa-impersonation-demo@my-project.iam.gserviceaccount.com
oauth2ClientId: '012345678901234567890'
projectId: my-project
uniqueId: '012345678901234567890'

ステップ3: サービスアカウントに IAM ロールを付与

権限借用対象のサービスアカウントに、操作に必要なロールを付与します。ここでは例として Cloud Storage の閲覧権限を付与します。

# サービスアカウントに Storage 閲覧者ロールを付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/storage.viewer"

ステップ4: 呼び出し元に Service Account Token Creator ロールを付与

自身のユーザーアカウントに対して、サービスアカウントの権限借用に必要なロールを付与します。
ここで注目すべきは、ロールの付与先がプロジェクトレベルではなく、サービスアカウントのリソースレベルであることです。

# 現在のユーザーアカウントを取得
export CALLER_ACCOUNT=$(gcloud auth list --filter=status:ACTIVE --format="value(account)")

# Service Account Token Creator ロールを付与
gcloud iam service-accounts add-iam-policy-binding \
  sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com \
  --member="user:$CALLER_ACCOUNT" \
  --role="roles/iam.serviceAccountTokenCreator"

Updated IAM policy for serviceAccount [sa-impersonation-demo@my-project.iam.gserviceaccount.com].
bindings:
- members:
  - user:user@example.com
  role: roles/iam.serviceAccountTokenCreator
etag: BwZYPpqB25Y=
version: 1

ステップ5: 権限借用で gcloud コマンドを実行

--impersonate-service-account フラグを使って、サービスアカウントの権限でコマンドを実行します。

# 権限借用で Cloud Storage バケット一覧を取得
gcloud storage buckets list \
  --impersonate-service-account=sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com \
  --project=$PROJECT_ID

WARNING: This command is using service account impersonation. All API calls will be executed as [sa-impersonation-demo@my-project.iam.gserviceaccount.com].
---
creation_time: 2026-04-22T21:14:03+0000
default_storage_class: STANDARD
generation: 1776892443634164645
location: US-CENTRAL1
location_type: region
metageneration: 3
name: example-data-bucket
public_access_prevention: inherited
soft_delete_policy:
  effectiveTime: '2026-04-22T21:14:03.762000+00:00'
  retentionDurationSeconds: '604800'
storage_url: gs://example-data-bucket/
uniform_bucket_level_access: true
update_time: 2026-04-22T22:36:38+0000

正常に実行されると、WARNING: This command is using service account impersonation. という警告メッセージが表示された後、サービスアカウントの権限でコマンドが実行されます。

ステップ6: デフォルト設定での権限借用

毎回 --impersonate-service-account フラグを指定する代わりに、gcloud CLI のデフォルト設定として権限借用を有効化できます。

# デフォルトの権限借用設定を有効化
gcloud config set auth/impersonate_service_account \
  sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com

Updated property [auth/impersonate_service_account].

# 以降のコマンドは自動的に権限借用で実行される
gcloud storage buckets list --project=$PROJECT_ID

---
creation_time: 2026-04-22T21:14:03+0000
default_storage_class: STANDARD
generation: 1776892443634164645
location: US-CENTRAL1
location_type: region
metageneration: 3
name: example-data-bucket
public_access_prevention: inherited
soft_delete_policy:
  effectiveTime: '2026-04-22T21:14:03.762000+00:00'
  retentionDurationSeconds: '604800'
storage_url: gs://example-data-bucket/
uniform_bucket_level_access: true
update_time: 2026-04-22T22:36:38+0000

設定を解除する場合は以下のコマンドを実行します。

# 設定を解除する場合
gcloud config unset auth/impersonate_service_account

Unset property [auth/impersonate_service_account].

ステップ7: Application Default Credentials(ADC)で権限借用を使う

ローカル開発でクライアントライブラリが自動的に権限借用を利用するように、ADC を設定します。

# ADC に権限借用を設定
gcloud auth application-default login \
  --impersonate-service-account=sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com

Your browser has been opened to visit:

    https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=xxxxxxxxxxxxx-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8085%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform&state=XXXXX&access_type=offline&code_challenge=XXXXX&code_challenge_method=S256

Credentials saved to file: [~/.config/gcloud/application_default_credentials.json]

These credentials will be used by any library that requests Application Default Credentials (ADC).

生成された ADC ファイルの内容を確認してみます。

cat ~/.config/gcloud/application_default_credentials.json
{
  "delegates": [],
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-impersonation-demo@my-project.iam.gserviceaccount.com:generateAccessToken",
  "source_credentials": {
    "account": "",
    "client_id": "xxxxxxxxx-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com",
    "client_secret": "d-FL95Q19q7MQmFpd7hHD0Ty",
    "refresh_token": "1//0eXXXXXXXXXXXXXX",
    "type": "authorized_user",
    "universe_domain": "googleapis.com"
  },
  "type": "impersonated_service_account"
}

各フィールドから権限借用の仕組みがわかります。

フィールド 意味
type impersonated_service_account この認証情報が権限借用タイプであることを示す。通常のユーザー認証では authorized_user になる
service_account_impersonation_url https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/sa-impersonation-demo@...:generateAccessToken クライアントライブラリがアクセストークンを取得する際に呼び出す Service Account Credentials API のエンドポイント。権限借用対象のサービスアカウントが指定されている
source_credentials.type authorized_user トークン取得時の認証に使われる呼び出し元の認証情報。ここではユーザーアカウントの OAuth 2.0 リフレッシュトークンが格納されている
source_credentials.client_id / client_secret Google Cloud SDK の OAuth クライアント情報 gcloud CLI が OAuth フローで使用するクライアント ID。gcloud CLI 共通の値
source_credentials.refresh_token (トークン文字列) ユーザーの認証状態を維持するリフレッシュトークン。これを使って Service Account Credentials API に認証し、SA の短期アクセストークンを取得する
delegates [](空配列) 委任チェーンを使用する場合に中間サービスアカウントを指定する。今回は直接の権限借用のため空

つまり、クライアントライブラリは以下の流れで自動的に権限借用を行います。

  1. source_credentials のリフレッシュトークンでユーザーとして認証
  2. service_account_impersonation_url の API エンドポイントを呼び出し、サービスアカウントの短期アクセストークンを取得
  3. 取得したアクセストークンで Google Cloud API にリクエスト

この設定により、ADC をサポートするクライアントライブラリ(Python、Java、Go、Node.js、C#)が自動的にサービスアカウントの権限借用を利用して認証します。

ステップ8: 権限借用が機能していることを確認

権限借用が正しく機能しているか、以下のコマンドで確認します。

# 権限借用なしでの認証情報を確認
gcloud auth print-access-token

ya29.a0XXXXXXXXXXXXXXX...

# 権限借用ありでの認証情報を確認(異なるトークンが返される)
gcloud auth print-access-token \
  --impersonate-service-account=sa-impersonation-demo@$PROJECT_ID.iam.gserviceaccount.com

WARNING: This command is using service account impersonation. All API calls will be executed as [sa-impersonation-demo@my-project.iam.gserviceaccount.com].
ya29.c.c0XXXXXXXXXXXXXXX...

ステップ9: 監査ログで権限借用を確認

権限借用を利用した場合、Cloud Audit Logs には呼び出し元と権限借用対象の両方の ID が記録されます。Cloud Logging で確認してみましょう。

{
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "status": {},
    "authenticationInfo": {
      "principalEmail": "sa-impersonation-demo@my-project.iam.gserviceaccount.com",
      "serviceAccountDelegationInfo": [
        {
          "firstPartyPrincipal": {
            "principalEmail": "user@example.com"
          }
        }
      ],
      "oauthInfo": {
        "oauthClientId": "012345678901234567890"
      }
    },
    "requestMetadata": {
      "callerIp": "XXX.XXX.XXX.XXX",
      "callerSuppliedUserAgent": "google-cloud-sdk gcloud/575.0.1 command/gcloud.storage.buckets.list invocation-id/XXXXX environment/None environment-version/None client-os/LINUX client-os-ver/6.6.87 client-pltf-arch/x86_64 interactive/True from-script/False python/3.14.5 term/xterm-256color  (Linux 6.6.87.2-microsoft-standard-WSL2),gzip(gfe)",
      "requestAttributes": {
        "time": "2026-08-04T20:48:20.065782019Z",
        "auth": {}
      },
      "destinationAttributes": {}
    },
    "serviceName": "storage.googleapis.com",
    "methodName": "storage.buckets.list",
    "authorizationInfo": [
      {
        "permission": "storage.buckets.getIamPolicy",
        "granted": false,
        "resourceAttributes": {}
      },
      {
        "resource": "projects/_/buckets/example-deploy-bucket",
        "permission": "storage.buckets.getIamPolicy",
        "granted": false,
        "resourceAttributes": {}
      },
      {
        "resource": "projects/_/buckets/example-data-bucket",
        "permission": "storage.buckets.getIamPolicy",
        "granted": false,
        "resourceAttributes": {}
      }
    ],
    "resourceLocation": {
      "currentLocations": [
        "global"
      ]
    }
  },
  "insertId": "mtf5soeczw0v",
  "resource": {
    "type": "gcs_bucket",
    "labels": {
      "location": "global",
      "project_id": "my-project",
      "bucket_name": ""
    }
  },
  "timestamp": "2026-08-04T20:48:19.889815759Z",
  "severity": "INFO",
  "logName": "projects/my-project/logs/cloudaudit.googleapis.com%2Fdata_access",
  "receiveTimestamp": "2026-08-04T20:48:21.065422622Z"
}

この監査ログから、以下のことがわかります。

フィールド わかること
authenticationInfo.principalEmail sa-impersonation-demo@... API リクエストの認証主体はサービスアカウント
serviceAccountDelegationInfo[].firstPartyPrincipal.principalEmail user@example.com 実際に操作を行った呼び出し元のユーザー
serviceName storage.googleapis.com 操作対象のサービス
methodName storage.buckets.list 実行された API メソッド
requestMetadata.callerIp XXX.XXX.XXX.XXX 呼び出し元の IP アドレス
requestMetadata.callerSuppliedUserAgent google-cloud-sdk gcloud/575.0.1 command/gcloud.storage.buckets.list ... 使用したツールとコマンド
logName ...cloudaudit.googleapis.com%2Fdata_access データアクセス監査ログに分類

ポイントは serviceAccountDelegationInfo セクションです。権限借用を使った場合、このセクションに firstPartyPrincipal として実際の操作者が記録されます。サービスアカウントキーで認証した場合はこのセクションが存在しないため、「誰がそのサービスアカウントを使ったのか」を追跡できません。

ベストプラクティス

サービスアカウントの権限借用を安全に活用するために、以下のポイントを理解しておきましょう。

ベストプラクティス 説明
サービスアカウントキーより権限借用を優先する キーの漏洩リスクがなく、監査ログに呼び出し元が記録されるため、権限借用の方がセキュリティ面で優れています
サービスアカウントキー作成を組織ポリシーで制限する constraints/iam.disableServiceAccountKeyCreation ポリシーでキー作成自体を禁止できます
最小権限の原則を守る 権限借用対象のサービスアカウントに付与するロールは、必要最小限にとどめてください
IAM データアクセスログを有効化する IAM API のデータアクセスログを有効にすることで、権限借用イベントを漏れなく記録できます
Token Creator ロールの付与を慎重に行う このロールを持つユーザーはサービスアカウントと同等のアクセス権を得られるため、付与対象を厳密に管理してください
Google Cloud コンソールでは権限借用が使えない コンソール操作は常にユーザー自身の認証情報で行われます。権限借用は gcloud CLI、クライアントライブラリ、REST API でのみ利用可能です

まとめ

今回は、サービスアカウントの権限借用について解説しました。

サービスアカウントの権限借用(Impersonation)は、サービスアカウントキーを発行せずに安全にサービスアカウントの権限を利用できる認証手法です。

権限借用の最大の利点はセキュリティです。サービスアカウントキーは漏洩すると誰でもそのサービスアカウントとして認証できてしまいますが、権限借用では短期認証情報(デフォルト1時間で失効)を利用するため、長期的な認証情報の漏洩リスクを排除できます。さらに、監査ログに呼び出し元の ID が記録されるため、「誰が」「いつ」操作したかを追跡できます。

権限借用に必要なのは Service Account Token Creator ロールroles/iam.serviceAccountTokenCreator)です。このロールはサービスアカウントのリソースレベルで付与するため、プロジェクト全体のサービスアカウントではなく、特定のサービスアカウントに対してのみ権限借用を許可するといった細かな制御が可能です。

サービスアカウントキーの管理に課題を感じている方や、よりセキュアな認証方式への移行を検討されている方は、サービスアカウントの権限借用の導入を検討してみてはいかがでしょうか。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部コンサルティング部の渡邉でした!

この記事をシェアする

関連記事