ページの先頭です

ページ内を移動するためのリンク
本文へ (c)

ここから本文です。

HashiCorp Vaultでgeminiのキー管理をためしてみた

社内のLLM利用が拡大する中、開発者への長期キー配布は漏洩リスクや利用管理の煩雑さを招きます。本記事ではHashiCorp VaultのGCPシークレットエンジンを用い、開発者がLLMを使用するためのキーを取得できる仕組み・設定手順・運用上の留意点を検証を交えて整理します。

ライター:田村 勝
2010年にネットワンシステムズに入社。
データセンターネットワークの製品担当として、技術検証や技術サポートに従事。
その後クラウド接続サービスの立ち上げを経て、現在は社内向けのAI活用サービスの開発運用を行っている。

目次

はじめに

昨今、社内での生成AI(LLM)の活用が急速に広がっています。弊社ネットワンシステムズでも、社内向けのチャットや情報検索、ナレッジ作成を支援するサービス「Nelmo」をはじめ、PoCやR&D、営業・技術支援向けのデモ用途などでLLMを活用する機会が増えています。こうした理由から、社内向けのサービスだけでなく、開発者がローカル環境から直接外部のLLMにアクセスするニーズも高まっています。

一方で、開発者個々に単一、長期的なキーを配布すると、鍵漏洩リスク、利用量/課金の把握困難、キーの発行や廃止などによる運用工数増大といった問題が出てきます。特に多人数に渡る配布や短期プロジェクトでの利用では、「誰が何をどれだけ使ったか」を正しく追跡できることが重要です。

本記事では、こうした課題へのアプローチとして、HashiCorp VaultのGCPシークレットエンジンを利用し、ユーザーの要求ごとに短期間だけ有効なサービスアカウントキー(エフェメラルキー)を発行する検証を紹介します。実際の手順、得られた挙動、運用上の注意点を技術者視点で整理します。

解決方法の比較

開発者個々にLLMを使うためのキーを配布する場合、キー管理方法は表のような選択肢があります。

説明 特徴
A)実キーを払い出す

プロバイダ(OpenAI/GCP/Azure等)の実際の認証情報(APIキーやサービスアカウントキー)をユーザーに渡す方式。

実現方法(例)
・HashiCorp vaultによる鍵管理機能の活用

・既存クライアントやライブラリと互換性が高く、アプリケーションに変更を加える必要がない。

・LLMプロバイダにキーを登録する必要があるため、キー追加の権限が必要になる。

B)仮想キーを払い出す

プロキシとLLMとの間の通信のみで実キーが使われ、利用者とプロキシ間は仮想キーが使用される方式。

実現方法(例)
LiteLLM Proxyのバーチャルキー機能の活用

・実キーをユーザーに渡す必要がないため、漏洩リスクが低い。

・通信が必ずプロキシを通るためボトルネックになる可能性がある。

今回はGCP環境の制御が可能で、複数のサービスアカウントを発行できるため、GCP環境のVertex AIを対象に、Vaultを使用し、A) の実キーを払い出す機能を検証しました。

HashiCorp Vaultとは

HashiCorp Vaultはシークレットの安全な保管・配布・動的生成・リース管理を行う秘密管理基盤です。認証(多様なAuthメソッド)、アクセス制御(ポリシー)、監査ログ、シークレットエンジン(各種クラウド/DB等)を備えます。

GCP(Vertex AI)で使うサービスアカウントキーの管理には2つのアプローチが考えられます。

A.静的に配布する(事前に作成したキーをVaultで配布/保管)

GCPコンソールやgcloudでサービスアカウントキー(JSON)を作成しておき、それをVaultのkvシークレットエンジン等に格納してユーザーに配布する方法です。この方法ではキーの事前準備などが必要になるため、GCP上で手動で鍵を管理する場合と比べ工数の省力化などを見込むことはできません。

B.動的に払い出す(VaultのGCPシークレットエンジンでエフェメラルキーを発行)

VaultがGCPのAPIを使って要求ごとに新しいサービスアカウントキーを作成し、ユーザーに配布する方法です。ユーザーからのリクエストで自動的にキーが作成され、リース期限が切れるとVaultはGCPに対してキーの削除を行うため、キーの管理にかかる工数を大幅に低減することができます。

ためしてみた

今回はB. 動的に払い出す方法を使用して、ユーザーがリクエストするたびにキーを発行する動作を確認します。ここで取得できるキーはGCPのコンソール上でダウンロードできるキーと同じなので、geminiなど、GCPのSAキーを使うAPIで使用できます。

前提条件

  • Vaultが起動していること

本検証はVaultを開発モード(VAULT_DEV_ROOT_TOKEN_ID)で実行しています。開発モードは認証・永続化が無効になっています。本番環境では絶対に使用しないでください。

$ docker run -p 8200:8200 -e 'VAULT_DEV_ROOT_TOKEN_ID=PASSWORD' hashicorp/vault
  • Vaultコマンドが使用できること

下記の方法でVaultコマンドをインストールしています。

$ wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(grep -oP '(?<=UBUNTU_CODENAME=).*' /etc/os-release || lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
$ sudo apt update && sudo apt install vault
  • GCPにアクセスできること

下記のロールを持ったSAを作成し、json形式のキーを発行してダウンロードしておきます。

権限 role
サービス アカウント 管理者 roles/iam.serviceAccountAdmin
サービス アカウント キー管理者 roles/iam.serviceAccountKeyAdmin
Project IAM 管理者 roles/resourcemanager.projectIamAdmin
  • GCP上で下記のAPIを有効にしておくこと 
    • Identity and Access Management (IAM) API (iam.googleapis.com)
    • Cloud Resource Manager API (cloudresourcemanager.googleapis.com)

設定手順

1. GCPのシークレットエンジンの有効化

下記コマンドでGCP用のシークレットエンジンを有効化し、キーの削除までの時間を300秒に設定します。また、VaultがGCP上のSAを操作するためのSAのキーを登録します

$ vault secrets enable gcp
$ vault secrets tune -default-lease-ttl=300s -max-lease-ttl=300s gcp/
$ vault write gcp/config credentials=@vault-key.json

2. ロールセットの設定

払い出すSAの設定をします。ここで設定したroleを持つSAが作成されます。ユーザーはこのSAに登録されたキーを使用することになります。

$ vault write gcp/roleset/vertex-ai-user \
    project=${PROJECT_ID} \
    secret_type="service_account_key" \
    bindings=- <<EOF
resource "//cloudresourcemanager.googleapis.com/projects/${PROJECT_ID}" {
  roles = ["roles/aiplatform.user"]
}
EOF

3. ポリシーの作成

作成したロールセットを使用するためのポリシーを作成します。

$ vault policy write vertex-ai-access - <<EOF
path "gcp/key/vertex-ai-user" {
  capabilities = ["read"]
}
EOF

4. Vaultユーザーの設定(SAを払い出すユーザーの作成と設定)

今回はユーザー/パスワードで使用できるユーザーを作成してテストをします。userpassによる認証を有効にしたうえで、先ほど作成したポリシーを設定したユーザーを作成します。

$ vault auth enable userpass
$ vault write auth/userpass/users/userA password=passwordA policies=vertex-ai-access
$ vault write auth/userpass/users/userB password=passwordB policies=vertex-ai-access

これでVaultの設定は完了です。

動作テスト

設定手順の2. ロールセットの設定が完了すると、SAが一つ作成されています。まだSAにキーは作成されていません。

作成したユーザでVaultからキーをリクエストしてみます。

ms-tamura@gpt-front-dev01:~$ vault login -method=userpass username=userA password=passwordA
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key                    Value
---                    -----
token                  hvs.CAESIGDWni9ibexrYpNkyYo0l0f47NQYSlktrxfplPtDdLB5Gh4KHGh2cy5sTUl2NWhKeG9PbGtBaXh2U0NwMHBFNzA
token_accessor         VAQdY7da8ZoePCuXnsGNJBNl
token_duration         768h
token_renewable        true
token_policies         ["default" "vertex-ai-access"]
identity_policies      []
policies               ["default" "vertex-ai-access"]
token_meta_username    usera
ms-tamura@gpt-front-dev01:~$ vault read gcp/key/vertex-ai-user
Key                 Value
---                 -----
lease_id            gcp/key/vertex-ai-user/MTIttVqWHXNnt9Kdmy9elarG
lease_duration      5m
lease_renewable     true
key_algorithm       KEY_ALG_RSA_2048
key_type            TYPE_GOOGLE_CREDENTIALS_FILE
private_key_data    ewogICJ0~~~省略~~o=
ms-tamura@gpt-front-dev01:~$

5分間だけ有効なキーが払い出されました。

実際に使用する場合はprivate_key_dataにBASE64でエンコードされています。下記でjsonファイルとして保存できます。

ms-tamura@gpt-front-dev01:~$ vault read -format=json gcp/key/vertex-ai-user | jq -r .data.private_key_data | base64 -d > new-key.json
ms-tamura@gpt-front-dev01:~$ cat new-key.json
{
  "type": "service_account",
  "project_id": "r*********5",
  "private_key_id": "c2054*********32f6",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANB******jvD1dZAan5dNjk4=\n-----END PRIVATE KEY-----\n",
  "client_email": "vaultvertex-ai-user-1765947136@*********.iam.gserviceaccount.com",
  "client_id": "100**********774",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/vaultvertex-ai-user-1765947136%40********.iam.gserviceaccount.com",
  "universe_domain": "googleapis.com"
}
ms-tamura@gpt-front-dev01:~$

GCPのコンソール上でもキーが払い出されていることが確認できます。

払いだされた情報は下記で確認できます。Vault は発行時にのみ private_key_data を返しますが、発行後は Vault 側で private key を保持/再表示しないため、キーは受け取った時点で安全に保存してください。

5分間経過すると自動的にキーが削除されます。

ms-tamura@gpt-front-dev01:~$ vault lease lookup gcp/key/vertex-ai-user/MTIttVqWHXNnt9Kdmy9elarG
Key             Value
---             -----
expire_time     2025-12-17T05:20:57.186435051Z
id              gcp/key/vertex-ai-user/MTIttVqWHXNnt9Kdmy9elarG
issue_time      2025-12-17T05:15:57.186434654Z
last_renewal    
renewable       true
ttl             4m21s
ms-tamura@gpt-front-dev01:~$
~~~5分後~~~
ms-tamura@gpt-front-dev01:~$ vault lease lookup gcp/key/vertex-ai-user/MTIttVqWHXNnt9Kdmy9elarG
error looking up lease id gcp/key/vertex-ai-user/MTIttVqWHXNnt9Kdmy9elarG: Error making API request.
URL: PUT http://10.44.195.85:8200/v1/sys/leases/lookup
Code: 400. Errors:
* invalid lease
ms-tamura@gpt-front-dev01:~$

GCPからも削除されたことが確認できます。

次は同様の方法でユーザーAとユーザーBでキーを作成した結果です。

ユーザーAとBでキーを作成しましたが、SAは共有されていることが確認できます。

結果

Vaultを使ってユーザーが必要なタイミングでキーが生成され、あらかじめ指定したリース時間が経過すると自動的にキーが無効になることを確認ができました。

また、複数ユーザーがキーを払い出しても単一のサービスアカウントに紐づくことが確認できました。

サービスアカウントに作成できるキーの数は制限があるため、利用者が多い場合、チームごとにrolesetを作るなどの対策が必要になりそうです。

GCPでは利用料などはプロジェクト単位でみることができますが、利用者・キー単位での可視化は監査ログとの突合やラベル運用といった工夫が必要となります。そのため、利用者ごとの利用料の可視化は課題になりそうです。

まとめ

本検証では、HashiCorp Vaultを使ってGCPのサービスアカウントキーを要求ごとに短時間だけ発行する仕組みを確認しました。

Vaultを使用した場合、開発者に長期キーを配布する代わりに、エフェメラルキーでアクセスを制御することで、鍵漏洩リスクの低減、発行/廃止の運用負荷削減、ガバナンス強化が期待できます。一方で、サービスアカウントあたりのキー数制限や利用課金のユーザー別可視化といった運用上の課題も明らかになりました。

弊社ではInnovation Showcaseにて生成AIをテーマとした展示やデモを実施しています。ぜひ直接ご体験いただき、より具体的なお話ができればと存じます。

また、公開可能なデータを利用して、お客様が直接体験することができるデモ環境もご用意していますので、一緒に試すことから始めませんか?

お問い合わせやご相談は、下記問い合わせフォームまたは担当営業までお寄せください。

※本記事の内容は執筆者個人の見解であり、所属する組織の見解を代表するものではありません。

RECOMMEND