シークレットエンジン

KVシークレット

Key-Valueシークレットエンジンの使い方
最終更新: 2026/2/17

KVシークレット

KV(Key-Value)シークレットエンジンは、Vaultで最も基本的なシークレット管理方法です。静的なシークレットを保存・取得するために使用します。

KVシークレットエンジンとは

KVシークレットエンジンは、キーと値のペアでシークレットを保存するシンプルなストレージです。

バージョン

バージョン特徴推奨用途
KV v1シンプル、バージョン管理なしレガシーシステム
KV v2バージョン管理、削除保護新規プロジェクト(推奨)
KV v2を推奨新規プロジェクトでは、バージョン管理機能を持つKV v2の使用を推奨します。開発サーバーではKV v2がデフォルトで有効化されています。

KV v2の特徴

1. バージョン管理

すべての変更履歴が保存されます。

# バージョン1
vault kv put secret/myapp/config password=old

# バージョン2
vault kv put secret/myapp/config password=new

# バージョン1を取得
vault kv get -version=1 secret/myapp/config

2. 削除保護

削除されたシークレットを復元できます。

# 削除
vault kv delete secret/myapp/config

# 復元
vault kv undelete -versions=2 secret/myapp/config

3. メタデータ管理

シークレットのメタデータを個別に管理できます。

# メタデータを確認
vault kv metadata get secret/myapp/config

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

KV v2の有効化

# KV v2を有効化
vault secrets enable -path=secret kv-v2

# カスタムパスで有効化
vault secrets enable -path=myapp kv-v2

KV v1の有効化

# KV v1を有効化
vault secrets enable -path=kv kv

有効化の確認

vault secrets list

出力例:

Path          Type         Description
----          ----         -----------
cubbyhole/    cubbyhole    per-token private secret storage
identity/     identity     identity store
secret/       kv           key/value secret storage
sys/          system       system endpoints used for control, policy and debugging

基本操作(KV v2)

シークレットの保存

# 単一のキー・バリュー
vault kv put secret/myapp/config \
  username=admin

# 複数のキー・バリュー
vault kv put secret/myapp/database \
  host=db.example.com \
  port=5432 \
  username=dbuser \
  password=dbpass123

シークレットの取得

# すべてのフィールドを取得
vault kv get secret/myapp/config

# 特定のフィールドのみ取得
vault kv get -field=username secret/myapp/config

# JSON形式で取得
vault kv get -format=json secret/myapp/config

シークレットの更新

# 完全な更新(既存の値を上書き)
vault kv put secret/myapp/config \
  username=admin \
  password=newpassword

# 部分的な更新(他のフィールドは保持)
vault kv patch secret/myapp/config \
  password=newpassword

シークレットの削除

# 最新バージョンを削除(復元可能)
vault kv delete secret/myapp/config

# 特定のバージョンを削除
vault kv delete -versions=1,2 secret/myapp/config

# 完全に削除(復元不可)
vault kv destroy -versions=1 secret/myapp/config

# すべてのバージョンとメタデータを削除
vault kv metadata delete secret/myapp/config

シークレットの一覧表示

# パスの一覧
vault kv list secret/

# サブパスの一覧
vault kv list secret/myapp/

バージョン管理

バージョン履歴の確認

# メタデータを取得
vault kv metadata get secret/myapp/config

出力例:

========== Metadata ==========
Key                     Value
---                     -----
cas_required            false
created_time            2024-01-15T10:30:45.123456Z
current_version         3
custom_metadata         <nil>
delete_version_after    0s
max_versions            0
oldest_version          0
updated_time            2024-01-15T11:45:30.789012Z

====== Version 1 ======
Key              Value
---              -----
created_time     2024-01-15T10:30:45.123456Z
deletion_time    n/a
destroyed        false

====== Version 2 ======
Key              Value
---              -----
created_time     2024-01-15T11:00:15.456789Z
deletion_time    n/a
destroyed        false

====== Version 3 ======
Key              Value
---              -----
created_time     2024-01-15T11:45:30.789012Z
deletion_time    n/a
destroyed        false

特定のバージョンを取得

# バージョン1を取得
vault kv get -version=1 secret/myapp/config

# バージョン2を取得
vault kv get -version=2 secret/myapp/config

バージョンの復元

# 削除されたバージョンを復元
vault kv undelete -versions=1,2 secret/myapp/config

バージョン数の制限

# 最大10バージョンまで保持
vault kv metadata put -max-versions=10 secret/myapp/config

自動削除の設定

# 30日後に自動削除
vault kv metadata put -delete-version-after=720h secret/myapp/config

Check-And-Set(CAS)

CASを使用すると、競合を防ぐことができます。

CASの有効化

# CASを必須にする
vault kv metadata put -cas-required=true secret/myapp/config

CASを使用した更新

# 現在のバージョンを確認
vault kv get secret/myapp/config

# バージョン3を基に更新
vault kv put -cas=3 secret/myapp/config \
  username=admin \
  password=newpassword

エラー例(バージョンが一致しない場合):

Error writing data to secret/data/myapp/config: Error making API request.
Code: 400. Errors:
* check-and-set parameter did not match the current version

カスタムメタデータ

メタデータの設定

# カスタムメタデータを設定
vault kv metadata put secret/myapp/config \
  custom_metadata=owner=team-a \
  custom_metadata=environment=production

メタデータの取得

vault kv metadata get secret/myapp/config

実践例

1. 環境ごとの設定管理

# 開発環境
vault kv put secret/myapp/dev \
  db_host=dev-db.example.com \
  db_username=dev_user \
  db_password=dev_pass \
  api_endpoint=https://dev-api.example.com

# ステージング環境
vault kv put secret/myapp/staging \
  db_host=staging-db.example.com \
  db_username=staging_user \
  db_password=staging_pass \
  api_endpoint=https://staging-api.example.com

# 本番環境
vault kv put secret/myapp/production \
  db_host=prod-db.example.com \
  db_username=prod_user \
  db_password=prod_pass \
  api_endpoint=https://api.example.com

2. アプリケーション設定の階層化

# 共通設定
vault kv put secret/myapp/common \
  log_level=info \
  timeout=30

# サービスA固有の設定
vault kv put secret/myapp/service-a \
  port=8080 \
  workers=4

# サービスB固有の設定
vault kv put secret/myapp/service-b \
  port=8081 \
  workers=2

3. 機密情報の分離

# データベース認証情報
vault kv put secret/myapp/database \
  host=db.example.com \
  username=dbuser \
  password=dbpass

# API認証情報
vault kv put secret/myapp/api \
  key=sk_live_abc123 \
  secret=secret_xyz789

# 証明書
vault kv put secret/myapp/certificates \
  tls_cert=@/path/to/cert.pem \
  tls_key=@/path/to/key.pem

4. ファイルからの一括登録

# JSONファイルを作成
cat > config.json <<EOF
{
  "database": {
    "host": "db.example.com",
    "port": 5432,
    "username": "dbuser",
    "password": "dbpass"
  },
  "api": {
    "endpoint": "https://api.example.com",
    "key": "sk_live_abc123"
  }
}
EOF

# ファイルから登録
vault kv put secret/myapp/config @config.json

APIでの使用

シークレットの保存

curl \
  --header "X-Vault-Token: $VAULT_TOKEN" \
  --request POST \
  --data '{"data":{"username":"admin","password":"secret"}}' \
  http://127.0.0.1:8200/v1/secret/data/myapp/config

シークレットの取得

curl \
  --header "X-Vault-Token: $VAULT_TOKEN" \
  http://127.0.0.1:8200/v1/secret/data/myapp/config

レスポンス:

{
  "request_id": "abc123-def456",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "data": {
      "password": "secret",
      "username": "admin"
    },
    "metadata": {
      "created_time": "2024-01-15T10:30:45.123456Z",
      "custom_metadata": null,
      "deletion_time": "",
      "destroyed": false,
      "version": 1
    }
  }
}

プログラミング言語での使用

Python

import hvac
import os

# Vaultクライアントの初期化
client = hvac.Client(
    url=os.environ['VAULT_ADDR'],
    token=os.environ['VAULT_TOKEN']
)

# シークレットの保存
client.secrets.kv.v2.create_or_update_secret(
    path='myapp/config',
    secret=dict(username='admin', password='secret')
)

# シークレットの取得
secret = client.secrets.kv.v2.read_secret_version(path='myapp/config')
username = secret['data']['data']['username']
password = secret['data']['data']['password']

print(f"Username: {username}")

Go

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    vault "github.com/hashicorp/vault/api"
)

func main() {
    // Vaultクライアントの初期化
    config := vault.DefaultConfig()
    config.Address = os.Getenv("VAULT_ADDR")
    
    client, err := vault.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }
    
    client.SetToken(os.Getenv("VAULT_TOKEN"))
    
    // シークレットの保存
    data := map[string]interface{}{
        "data": map[string]interface{}{
            "username": "admin",
            "password": "secret",
        },
    }
    
    _, err = client.Logical().Write("secret/data/myapp/config", data)
    if err != nil {
        log.Fatal(err)
    }
    
    // シークレットの取得
    secret, err := client.Logical().Read("secret/data/myapp/config")
    if err != nil {
        log.Fatal(err)
    }
    
    data = secret.Data["data"].(map[string]interface{})
    username := data["username"].(string)
    password := data["password"].(string)
    
    fmt.Printf("Username: %s\n", username)
}

Node.js

const vault = require('node-vault')({
  apiVersion: 'v1',
  endpoint: process.env.VAULT_ADDR,
  token: process.env.VAULT_TOKEN
});

// シークレットの保存
async function writeSecret() {
  await vault.write('secret/data/myapp/config', {
    data: {
      username: 'admin',
      password: 'secret'
    }
  });
}

// シークレットの取得
async function readSecret() {
  const result = await vault.read('secret/data/myapp/config');
  const { username, password } = result.data.data;
  console.log(`Username: ${username}`);
}

writeSecret().then(readSecret);

ベストプラクティス

1. 階層的な構造

secret/
├── myapp/
│   ├── common/          # 共通設定
│   ├── dev/             # 開発環境
│   ├── staging/         # ステージング環境
│   └── production/      # 本番環境
└── shared/
    └── certificates/    # 共有証明書

2. 命名規則

  • 小文字を使用: myapp/config
  • ケバブケース: my-app/db-config
  • 環境を明示: myapp/production/database

3. バージョン管理

# 最大バージョン数を制限
vault kv metadata put -max-versions=10 secret/myapp/config

# 古いバージョンを自動削除
vault kv metadata put -delete-version-after=2160h secret/myapp/config

4. アクセス制御

# 読み取り専用ポリシー
path "secret/data/myapp/*" {
  capabilities = ["read", "list"]
}

# 読み書き可能ポリシー
path "secret/data/myapp/*" {
  capabilities = ["create", "read", "update", "delete", "list"]
}

トラブルシューティング

シークレットが見つからない

エラー:

No value found at secret/data/myapp/config

確認事項:

# パスを確認
vault kv list secret/
vault kv list secret/myapp/

# 正しいパスで取得
vault kv get secret/myapp/config

CASエラー

エラー:

check-and-set parameter did not match the current version

解決策:

# 現在のバージョンを確認
vault kv get secret/myapp/config

# 正しいバージョンで更新
vault kv put -cas=<current-version> secret/myapp/config key=value

バージョンが削除されている

エラー:

deletion_time is set

解決策:

# バージョンを復元
vault kv undelete -versions=<version> secret/myapp/config

次のステップ

KVシークレットの基本を理解したら、次はデータベースシークレットで動的シークレットの生成を学びましょう。

KVシークレットの活用KVシークレットは、静的な設定情報の管理に最適です。パスワードやAPIキーなど、頻繁に変更されない情報を保存するために使用してください。
© 2026 IBM Corporation. Licensed under CC BY 4.0.