Control Groups
Control Groups
Control Groupsとは
Control Groupsは、特定の操作に対して複数の承認者による承認を必要とする機能です。重要なシークレットへのアクセスや機密操作に対して、多段階の承認ワークフローを実装できます。
主な用途
機密シークレットの保護
- 本番環境のデータベース認証情報
- APIキーやトークン
- 暗号化キー
コンプライアンス要件
- 4-eyes原則(2人承認)の実装
- 監査証跡の確保
- 職務分離の実現
リスク軽減
- 意図しないアクセスの防止
- 内部不正の抑止
- セキュリティインシデントの削減
Control Groupsの仕組み
基本フロー
1. ユーザーA → Vaultにリクエスト
2. Vault → Control Group要求を返す
3. ユーザーA → 承認者に通知
4. 承認者B → 承認
5. 承認者C → 承認(必要な場合)
6. ユーザーA → 承認済みトークンでリクエスト
7. Vault → シークレットを返す
アーキテクチャ
┌─────────────────────────────────────────┐
│ リクエスター(ユーザーA) │
└──────────────┬──────────────────────────┘
│ 1. シークレット要求
▼
┌─────────────────────────────────────────┐
│ Vault Server │
│ ┌─────────────────────────────────┐ │
│ │ Control Group Policy │ │
│ │ - 必要な承認者数: 2 │ │
│ │ - 承認者グループ: approvers │ │
│ └─────────────────────────────────┘ │
└──────────────┬──────────────────────────┘
│ 2. 承認要求トークン
▼
┌─────────────────────────────────────────┐
│ 承認者(ユーザーB、C) │
│ 3. 承認トークンで承認 │
└──────────────┬──────────────────────────┘
│ 4. 承認完了
▼
┌─────────────────────────────────────────┐
│ リクエスター(ユーザーA) │
│ 5. 承認済みトークンでアクセス │
└─────────────────────────────────────────┘
Control Groupsの設定
1. 承認者グループの作成
まず、承認者のグループを作成します。
# 承認者グループの作成
vault write identity/group name="approvers" \
policies="approver-policy" \
member_entity_ids="entity-id-1,entity-id-2"
2. Control Group Policyの作成
Control Groupを定義するポリシーを作成します。
control-group-policy.hcl:
# 本番環境のシークレットにControl Groupを適用
path "secret/data/prod/*" {
capabilities = ["read"]
control_group = {
# 必要な承認者数
factor "approvers" {
identity {
group_names = ["approvers"]
approvals = 2
}
}
}
}
# ポリシーの適用
vault policy write control-group-policy control-group-policy.hcl
3. ユーザーへのポリシー割り当て
# リクエスターにポリシーを割り当て
vault write auth/userpass/users/requester \
password=password \
policies="control-group-policy"
Control Groupsの使用
リクエスターの操作
1. シークレットへのアクセス試行
# シークレットへのアクセスを試行
vault kv get secret/prod/database
# 出力例(Control Group要求)
Key Value
--- -----
wrapping_token: hvs.CAESIJ...
wrapping_accessor: abc123...
wrapping_token_ttl: 24h
wrapping_token_creation_time: 2024-01-15 10:30:00 +0000 UTC
wrapping_token_creation_path: secret/data/prod/database
2. 承認リクエストの確認
# Control Groupの詳細を確認
vault write sys/wrapping/unwrap \
token=hvs.CAESIJ...
# 出力例
Key Value
--- -----
request_path secret/data/prod/database
request_entity entity-id-requester
authorizations []
approved false
request_time 2024-01-15T10:30:00Z
承認者の操作
1. 承認リクエストの確認
# 承認待ちのリクエストを確認
vault list sys/control-group/requests
# 特定リクエストの詳細
vault read sys/control-group/request/<accessor>
2. 承認の実行
# 承認を実行
vault write sys/control-group/authorize \
accessor=<accessor>
# 出力例
Key Value
--- -----
approved true
リクエスターの最終アクセス
必要な承認が揃ったら、リクエスターは再度アクセスします。
# 承認済みトークンでアクセス
VAULT_TOKEN=<wrapping-token> vault kv get secret/prod/database
# 成功: シークレットが返される
Key Value
--- -----
username prod_user
password prod_password
高度な設定
例1: 複数の承認者グループ
異なるグループから承認を得る設定です。
multi-group-policy.hcl:
path "secret/data/prod/*" {
capabilities = ["read"]
control_group = {
# セキュリティチームから1名
factor "security" {
identity {
group_names = ["security-team"]
approvals = 1
}
}
# 運用チームから1名
factor "operations" {
identity {
group_names = ["ops-team"]
approvals = 1
}
}
}
}
例2: 時間制限付きControl Group
承認の有効期限を設定します。
time-limited-policy.hcl:
path "secret/data/prod/*" {
capabilities = ["read"]
control_group = {
ttl = "1h" # 承認リクエストの有効期限
factor "approvers" {
identity {
group_names = ["approvers"]
approvals = 2
}
}
}
}
例3: 特定ユーザーによる承認
特定のユーザーIDで承認を要求します。
specific-user-policy.hcl:
path "secret/data/finance/*" {
capabilities = ["read"]
control_group = {
factor "cfo-approval" {
identity {
entity_ids = ["entity-id-cfo"]
approvals = 1
}
}
}
}
例4: 条件付きControl Group
Sentinelと組み合わせて、条件付きでControl Groupを適用します。
conditional-control-group.sentinel:
import "time"
# 営業時間外のみControl Groupを適用
hour = time.now.hour
is_after_hours = hour < 9 or hour >= 18
# 営業時間外の場合のみControl Group必須
main = rule when is_after_hours {
request.control_group.approved
}
実践例
例1: 本番データベース認証情報へのアクセス
シナリオ: 本番データベースの認証情報にアクセスするには、セキュリティチームとDBAチームの承認が必要。
1. ポリシーの作成:
# prod-db-access-policy.hcl
path "database/creds/prod-db" {
capabilities = ["read"]
control_group = {
factor "security" {
identity {
group_names = ["security-team"]
approvals = 1
}
}
factor "dba" {
identity {
group_names = ["dba-team"]
approvals = 1
}
}
}
}
2. リクエスター(開発者):
# データベース認証情報を要求
vault read database/creds/prod-db
# Control Groupトークンを取得
# wrapping_token: hvs.CAESIJ...
# accessor: abc123...
3. セキュリティチーム承認者:
# 承認リクエストを確認
vault read sys/control-group/request/abc123
# 承認
vault write sys/control-group/authorize accessor=abc123
4. DBAチーム承認者:
# 承認
vault write sys/control-group/authorize accessor=abc123
5. リクエスター(開発者):
# 承認済みトークンでアクセス
VAULT_TOKEN=hvs.CAESIJ... vault read database/creds/prod-db
# 成功: 一時的なDB認証情報を取得
例2: 緊急時のアクセス
シナリオ: 緊急時は承認者数を減らす。
emergency-access-policy.hcl:
path "secret/data/prod/*" {
capabilities = ["read"]
control_group = {
# 通常時: 2名の承認が必要
factor "normal" {
identity {
group_names = ["approvers"]
approvals = 2
}
}
}
}
# 緊急時用のポリシー(別途作成)
path "secret/data/prod/*" {
capabilities = ["read"]
control_group = {
# 緊急時: 1名の承認で可
factor "emergency" {
identity {
group_names = ["emergency-approvers"]
approvals = 1
}
}
}
}
監査とレポート
承認履歴の確認
# 承認履歴の確認
vault read sys/control-group/request/<accessor>
# 出力例
Key Value
--- -----
request_path secret/data/prod/database
request_entity entity-id-requester
authorizations [
{
"entity_id": "entity-id-approver1",
"entity_name": "approver1",
"time": "2024-01-15T10:35:00Z"
},
{
"entity_id": "entity-id-approver2",
"entity_name": "approver2",
"time": "2024-01-15T10:40:00Z"
}
]
approved true
request_time 2024-01-15T10:30:00Z
監査ログ
Control Groupの操作はすべて監査ログに記録されます。
{
"time": "2024-01-15T10:35:00Z",
"type": "response",
"auth": {
"display_name": "approver1"
},
"request": {
"operation": "update",
"path": "sys/control-group/authorize"
},
"response": {
"data": {
"approved": true
}
}
}
ベストプラクティス
1. 適切な承認者数の設定
| リスクレベル | 推奨承認者数 | 例 |
|---|---|---|
| 低 | 1名 | 開発環境 |
| 中 | 2名 | ステージング環境 |
| 高 | 2-3名 | 本番環境 |
| 最高 | 3名以上 | 金融データ |
2. 承認者グループの分離
異なる役割のグループから承認を得ます。
control_group = {
# セキュリティチーム
factor "security" {
identity {
group_names = ["security-team"]
approvals = 1
}
}
# ビジネスオーナー
factor "business" {
identity {
group_names = ["business-owners"]
approvals = 1
}
}
}
3. 適切なTTL設定
承認リクエストの有効期限を設定します。
control_group = {
ttl = "4h" # 営業時間内に承認を得る
factor "approvers" {
identity {
group_names = ["approvers"]
approvals = 2
}
}
}
4. 通知の自動化
承認リクエストを自動的に通知します。
#!/bin/bash
# notify-approvers.sh
ACCESSOR=$1
APPROVERS="approver1@example.com approver2@example.com"
for EMAIL in $APPROVERS; do
echo "承認リクエスト: $ACCESSOR" | \
mail -s "Vault承認リクエスト" $EMAIL
done
5. ドキュメント化
Control Groupの設定と手順をドキュメント化します。
# 本番環境アクセス手順
## 必要な承認
- セキュリティチーム: 1名
- DBAチーム: 1名
## 手順
1. リクエスター: アクセス要求
2. 承認者: 承認実行
3. リクエスター: 承認済みトークンでアクセス
## 緊急時
緊急時は on-call 承認者に連絡
トラブルシューティング
承認が完了しない
問題: 必要な承認が揃わない
解決策:
# 承認状況を確認
vault read sys/control-group/request/<accessor>
# 必要な承認者グループを確認
vault read identity/group/name/approvers
承認トークンの期限切れ
問題: 承認前にトークンが期限切れ
解決策:
# TTLを延長
control_group = {
ttl = "24h" # 1日に延長
factor "approvers" {
identity {
group_names = ["approvers"]
approvals = 2
}
}
}
承認者が不在
問題: 承認者が休暇中
解決策:
# 代理承認者を追加
vault write identity/group/name/approvers \
member_entity_ids="entity-id-1,entity-id-2,entity-id-backup"
次のステップ
Control Groupsの基本を理解したら、次は以下を学びましょう:
- Sentinel Policies - Control Groupsと組み合わせた高度な制御
- 高度なSentinel使用例 - 条件付きControl Groups