🐈

なぜサービスアカウントの借用は、セキュアで効率的なクラウド開発に不可欠なのか

に公開

ローカル開発環境の保護からオンコール時のインシデント対応まで、クラウドプロバイダーへの安全かつ効果的な認証は共通の課題です。シークレットキーのような長期間有効な認証情報や、過剰な権限を持つユーザーアカウントを使用する代わりに、サービスアカウントを借用する方がより安全な方法です。このアプローチにより、私たちは必要な権限のみで操作できるため、最小権限の原則を開発ワークフローに効果的に適用できます。この方法には、セキュリティ上の利点に加え、誤ったコマンドや意図しない操作による潜在的な損害を最小限に抑える効果もあります。これは、オンコール時の本番環境へのアクセスにおいても同じ原則であり、常にデフォルトで閲覧専用の権限とし、必要な場合にのみ権限を昇格させるべきです。

Google Cloud でエージェントアプリケーションを開発した最近の経験は、このプロセスを再認識する良い機会となりました。強力なユーザーアカウントを使用する場合と比較して、借用の初期設定にはある程度のオーバーヘッドが伴いますが、これまでの経験から、この先行投資は非常に価値があることがわかっています。ベストプラクティスに従う際の初期の摩擦はすぐに無視できるほど小さくなりますが、便利なだけの方法は、将来的にメンテナンスの悪夢へと発展することがあまりにも多いのです。本記事では、サービスアカウントの借用について、私が長年かけて学んできた主なメリットを共有します。

メリット 1:権限のプロアクティブな適正化

サービスアカウントの借用がもたらす重要なメリットの一つは、本番環境の権限を適切に設定できる点です。開発中にこの手法を用いることで、アプリケーションが機能するために必要な正確な権限を自然に特定できます。この事前対応的なプロセスにより、最終的なサービスや CI/CD パイプライン向けに、専用の最小権限サービスアカウントを構成するために使用できる、明確で検証済みの権限セットが生成されます。これにより、不確実性から過度に広範な権限を割り当ててしまうというよくある落とし穴を回避し、時間のかかる試行錯誤によるセキュリティポリシーの確立プロセスを不要にします。

アクセスレコメンダーセキュリティスキャナーのようなツールは監査に役立ちますが、その事後対応的な性質上、是正措置が遅れ、エラーが発生しやすくなることがよくあります。権限の削除は迅速にできますが、不注意で微妙かつ必須な権限を消してしまうリスクがあり、特にテストカバレッジが不十分な場合、リリースがリスクの高いイベントに変わりかねません。この問題は、年に一度のイベントや災害復旧など、必要とされながらも使用頻度が低い権限を考慮する際には、さらに大きな注意を要します。たった一つでも権限が欠けていると、最も必要なときに深刻な本番環境のインシデントやボトルネックになり得ます。このような理由から、最初から正しいポリシーを構築することが、本質的に安全で信頼性の高い方法なのです。

メリット 2:ワークフローの自動化でオンコール対応をセキュアにする

サービスアカウントの借用がもたらす運用上の重要なメリットの一つは、ヒューマンエラーによるブラスト・ラディウス(被害範囲)を劇的に縮小できる点です。オンコールと開発業務を並行して行う場合、誤ったクラウドコンソールを使用したり、間違ったターミナルでスクリプトを実行したりといったミスは残念ながら頻繁に起こります。こうしたリスクを軽減するため、プロフェッショナルなチームでは、コンソールのテーマカラーを分けたり、手動での変更にセカンドエンジニアの承認を義務付けたりといった手続き上の安全策を講じることがよくあります。しかし、これらの安全策は依然として人間の規律に根本的に依存しています。

対照的に、より良いアプローチは、一般的なオンコール操作のための自動化されたワークフローを事前に準備することです。ユーザーはデフォルトで閲覧専用の権限を持つべきです。本番環境でアラートが発生した際、事前に承認されたこれらのワークフローを実行する権限を持つサービスアカウントを借用できます。これにより、複数の安全層が生まれます。たとえば、開発用のコマンドを誤って本番環境のターミナルで実行しても、ユーザーの制限された権限によって単に失敗するだけです。必要な介入を行う場合、ユーザーはサービスアカウントの借用を通じて、特定のテスト済みワークフローをトリガーします。最後に、真の緊急事態や稀なイベントの場合には、別の権限昇格プロセスによって、より広範な手動アクセスが可能になり、最後の手段であっても効率的に、かつ完全なトレーサビリティを持って対処されることが保証されます。このシステムによって強制されるガードレールは、ヒューマンエラーの可能性を減らすだけでなく、本番環境のインシデントにおけるストレスも軽減する、追加の保護層を私たちにもたらします。

メリット 3:明確な監査証跡

サービスアカウントの借用を利用する最も説得力のある理由の一つは、それによって作成される明確な監査証跡です。ユーザーがサービスアカウントを借用すると、Cloud Audit Logs にどのユーザーがアクションを開始したかが正確に記録され、説明責任の明確な記録が提供されます。これは、一般的でありながらセキュリティレベルが低い、以下の 2 つのパターンに比べて大きな進歩です。

  • 特権ユーザーアカウント: 強力なユーザーアカウントを管理タスクと開発タスクの両方に使用すると、監査ログが曖昧になります。記録されたアクションが管理コマンドによるものなのか、ローカルアプリケーションの活動によるものなのかを判別することは、ほぼ不可能です。

  • 静的サービスアカウントキー:これは最も安全性が低い選択肢であり、ログにユーザー ID が提供されません。この完全なトレーサビリティの喪失は、セキュリティおよびコンプライアンス上の大きなリスクとなります。

この洗練されたアプローチは、ユーザー認証とタスク固有の権限を分離することで、両方の問題を解決します。広範な権限を直接付与するのではなく、ユーザーにサービスアカウントを借用するための狭い権限を付与します。これにより、ユーザーレベルでは多要素認証(MFA)のような厳格な制御を強制する一方、サービスアカウントは実行するタスクに対するきめ細かな権限を持つことができます。

この挙動を確認するため、監査ログの例を見ていきましょう。しかしその前に、重要な注意点です。追跡したい API の監査ログを有効化しておく必要がありますGenerateContent API への呼び出しのように、アプリケーションによってアクションが実行されたと仮定します。この場合、監査ログの authenticationInfo ブロックには、principalEmail がサービスアカウントであったとしても、私たちのユーザーアカウントが serviceAccountDelegationInfo ブロックにも記録されていることが示されます。

"authenticationInfo": {
  "principalEmail": "local-dev@service-account-email",
  "principalSubject": "serviceAccount:local-dev@service-account-email",
  "serviceAccountDelegationInfo": [
    0: {
      "firstPartyPrincipal": {
        "principalEmail": "[USER ACCOUNT]"
      }
    }
  ]
}

このログエントリーは、API 呼び出しのソースも特定することで、さらに多くのコンテキストを提供します。callerSuppliedUserAgent フィールドを確認することで、アクションがどのように開始されたかを判断できます。例えば、アプリケーション SDK は明確な足跡を残します。

"requestMetadata": {
  "callerIp": "[IP ADDRESS]",
  "callerSuppliedUserAgent": "google-genai-sdk/1.27.0 gl-python/3.13.5 google-adk/1.8.0 gl-python/3.13.5,gzip(gfe)"
}

アクションが代わりに gcloud コマンドラインツールを使用して実行されていた場合、ユーザーエージェントは明確に gcloud ツールを識別します。

"requestMetadata": {
  "callerIp": "[IP ADDRESS]",
  "callerSuppliedUserAgent": "google-cloud-sdk gcloud/531.0.0 command/gcloud.storage.ls ... ,gzip(gfe)"
}

これらのフィールドを合わせることで、アクションを開始したユーザーと、その際に使用されたツール(アプリケーション SDK かコマンドラインツールか)を特定する完全なストーリーが得られます。対照的に、静的サービスアカウントキーを使用する場合、監査ログにはサービスアカウントと使用された特定のキーしか識別できず、この豊富で追跡可能な情報は完全に失われます。

"authenticationInfo": {
  "principalEmail": "local-dev@service-account-email",
  "serviceAccountKeyName": "[SERVICE ACCOUNT KEY PATH]"
}

借用ワークフロー:CLI とアプリケーション

Google Cloud におけるサービスアカウントの借用設定には、共通の混乱点があります。gcloud CLI とローカルアプリケーションの SDK では、手順がわずかに異なります。gcloud コマンドをサービスアカウントの ID で実行するには、CLI に対して借用を構成する必要があります。しかし、ローカルアプリケーションを実行し、その SDK がサービスアカウントの ID でサービスにアクセスできるようにするには、借用を用いて Application Default Credentials (ADC)を設定する必要があります。両方の機能が必要な場合は、両方のセットアップ手順を完了させる必要がある点に注意することが重要です

このプロセスを示す例を見ていきましょう。最初のステップは、必要な IAM 権限を付与するための前提条件として、gcloud CLI ツールを認証することです。以下のコマンドを実行すると、認証情報を求められます。この完了後、以降のすべての gcloud コマンドは、私たちのユーザーアカウントの ID を使用することになります。 なお、Cloud Shell を使用している場合は、このステップは不要です。

gcloud auth login

次に、サービスアカウントを借用するための権限、つまり Service Account Token Creator ロールを、私たちのユーザーアカウントに付与する必要があります。これは、プロジェクトの Owner ロールでさえデフォルトではこの権限を含んでいないため、非常に重要なステップです。 特定のサービスアカウントに対してこのロールを付与するには、以下のコマンドを使用します。

gcloud iam service-accounts add-iam-policy-binding "[SERVICE_ACCOUNT_EMAIL]" \
    --member="user:[USER_ACCOUNT_EMAIL]" \
    --role="roles/iam.serviceAccountTokenCreator"

ロールが付与されたことを確認するため、以下のコマンドを使用して、このロールを持つプリンシパルをリストアップできます。出力に、このロールを持つプリンシパルとして、私たちのユーザーアカウントが表示されるはずです。

gcloud iam service-accounts get-iam-policy "[SERVICE_ACCOUNT_EMAIL]" \
    --flatten="bindings[].members" \
    --filter="bindings.role:roles/iam.serviceAccountTokenCreator"

私たちのユーザーアカウントがサービスアカウントを借用する権限を持ったので、ここから先の借用プロセスは gcloud CLI とアプリケーション SDK で分岐します。

パス A:gcloud CLI の設定

gcloud CLI の借用を使用するように設定するには、以下のコマンドを実行します。完了後、私たちが実行する以降のすべての gcloud コマンドは、指定されたサービスアカウントを使用することになります。

gcloud config set auth/impersonate_service_account "[SERVICE_ACCOUNT_EMAIL]"

参考として、単一の gcloud コマンドに対してのみ借用が必要な場合は、--impersonate-service-account パラメーターを使用してデフォルト設定を上書きすることができます。

gcloud storage ls --impersonate-service-account "[SERVICE_ACCOUNT_EMAIL]"

また、借用が不要になった際には、以下のコマンドで gcloud CLI のサービスアカウント借用を無効化できます。

gcloud config unset auth/impersonate_service_account

パス B:Application Default Credentials (ADC) の設定

ここでは、ローカルのアプリケーション SDK 向けにサービスアカウントの借用を設定するプロセスを見ていきましょう。以下のコマンドを実行すると、指定されたサービスアカウントを使用してローカルの Application Default Credentials (ADC)ファイルが作成されます。その後、私たちのアプリケーション SDK は、借用された ID を使用して Google Cloud サービスにアクセスします。

gcloud auth application-default login \
    --impersonate-service-account "[SERVICE_ACCOUNT_EMAIL]"

なお、最も一般的なライブラリはサポートしていますが、すべてのクライアントライブラリが借用によって生成されたローカルの ADC ファイルからの認証情報をサポートしているわけではない点に注意してください。サポートされているライブラリの完全なリストについては、以下の Google Cloud ドキュメントを参照してください。

Reference: Google Cloud Documentation

まとめ

本番環境へのアクセスを許可されることは、開発者にとって大きな責任を伴う特権であり、高いレベルの信頼を示すものです。オンコール対応の経験から、セキュリティに加えて、特にストレス下にある時、自身のミスから身を守るための堅牢なシステムが必要であると学びました。多くの人がセキュリティポリシーは効率を妨げると不満を漏らしますが、私たち自身の過ちを防ぐことで得られる保護は、その不便さを上回ることがよくあります。事実、内部的な不手際による損害は、外部からのサイバー攻撃によるものよりも大きい場合があります。この原則は、自律的なエージェントが私たちの代わりにタスクを実行するエージェントアプリケーションの時代において、さらに重要になります。本番環境のインシデントに関する意思決定を支援するために、これらのエージェントワークフローを使用し始めるにあたり、サービスアカウントの借用のようなデフォルトでセキュアなワークフローを採用することは、これらの新しいツールが提供する効率性を享受しつつ、リスクを管理するために不可欠となるでしょう。

セキュリティとクラウドネイティブデザインの学生としての私の旅は続きます。今後の記事では、必要に応じて透過的に権限昇格を要求できる、特権アクセス管理のプロセスについて探求する予定です。

お読みいただきありがとうございました!

Discussion