高度な使い方

HashiCorp Vaultとの連携

最終更新: 2026/2/17

HashiCorp Vaultとの連携

このページで学べること

  • HashiCorp Vaultとは何か
  • TerraformでVaultを使用する理由
  • Vaultプロバイダーの基本設定
  • 認証方法とベストプラクティス
  • 実践的な使用例

HashiCorp Vaultとは

概要

HashiCorp Vaultは、シークレット(機密情報)を安全に管理するための専用ツールです。

主な機能:

  • シークレット管理: APIキー、パスワード、証明書などの安全な保管
  • 動的シークレット: 必要な時に一時的な認証情報を生成
  • 暗号化サービス: データの暗号化・復号化
  • アクセス制御: きめ細かい権限管理
  • 監査ログ: すべてのアクセスを記録

Terraformで使用する理由

  1. セキュリティの向上
    • 認証情報をコードに含めない
    • 集中管理されたシークレット
    • アクセスログの記録
  2. 動的シークレット
    • 必要な時に生成
    • 自動的に失効
    • 最小権限の原則
  3. コンプライアンス
    • 監査ログ
    • アクセス制御ポリシー
    • シークレットのローテーション
  4. チーム協業
    • 認証情報の共有が不要
    • 環境ごとの権限管理
    • 一元的なシークレット管理

前提条件

必要な環境

  • Terraform 1.0以上
  • HashiCorp Vault(クラウド版またはセルフホスト版)
  • 基本的なTerraformの知識(プロバイダーの設定を参照)

Vaultのセットアップ

Vaultを使用するには、以下のいずれかの方法でVaultサーバーを用意する必要があります:

  1. HCP Vault(推奨): HashiCorp Cloud Platformのマネージドサービス
  2. セルフホスト: 自社環境でVaultサーバーを構築
Vaultのセットアップ方法については、HashiCorp Vault公式ドキュメントを参照してください。

Vaultプロバイダーの設定

基本設定

まず、Terraformの設定ファイルでVaultプロバイダーを宣言します。

terraform {
  required_providers {
    vault = {
      source  = "hashicorp/vault"
      version = "~> 4.0"
    }
  }
}

provider "vault" {
  address = "https://vault.example.com:8200"
}

設定項目の説明:

  • address: VaultサーバーのURL
  • version: Vaultプロバイダーのバージョン制約

認証方法

Vaultには複数の認証方法があります。環境に応じて適切な方法を選択してください。

1. トークン認証(開発環境)

開発環境では、環境変数を使用したトークン認証が簡単です。

export VAULT_TOKEN="hvs.CAESIJ..."
export VAULT_ADDR="https://vault.example.com:8200"
provider "vault" {
  address = var.vault_addr
  # VAULT_TOKEN環境変数が自動的に使用されます
}
トークン認証は開発環境のみで使用してください。本番環境では、より安全な認証方法を使用してください。

2. AppRole認証(本番環境推奨)

本番環境では、AppRole認証を使用することを推奨します。

provider "vault" {
  address = "https://vault.example.com:8200"
  
  auth_login {
    path = "auth/approle/login"
    
    parameters = {
      role_id   = var.vault_role_id
      secret_id = var.vault_secret_id
    }
  }
}

AppRoleの設定例:

# AppRoleの有効化
vault auth enable approle

# ロールの作成
vault write auth/approle/role/terraform \
  token_policies="terraform-policy" \
  token_ttl=1h \
  token_max_ttl=4h

# Role IDの取得
vault read auth/approle/role/terraform/role-id

# Secret IDの生成
vault write -f auth/approle/role/terraform/secret-id

3. Kubernetes認証(Kubernetes環境)

Kubernetes環境で実行する場合は、Kubernetes認証を使用できます。

provider "vault" {
  address = "https://vault.example.com:8200"
  
  auth_login_jwt {
    role = "terraform"
    path = "auth/kubernetes/login"
  }
}

Vaultからシークレットを取得

KV v2エンジンの使用

Vault KV(Key-Value)v2エンジンは、最も一般的なシークレット保管方法です。

# Vaultからシークレットを読み取る
data "vault_kv_secret_v2" "aws_creds" {
  mount = "secret"
  name  = "aws/credentials"
}

# AWSプロバイダーで使用
provider "aws" {
  region     = "ap-northeast-1"
  access_key = data.vault_kv_secret_v2.aws_creds.data["access_key"]
  secret_key = data.vault_kv_secret_v2.aws_creds.data["secret_key"]
}

Vaultにシークレットを保存:

vault kv put secret/aws/credentials \
  access_key="AKIAIOSFODNN7EXAMPLE" \
  secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

汎用シークレットの使用(KV v1)

KV v1エンジンを使用する場合は、vault_generic_secretを使用します。

data "vault_generic_secret" "aws_credentials" {
  path = "secret/aws/credentials"
}

provider "aws" {
  region     = "ap-northeast-1"
  access_key = data.vault_generic_secret.aws_credentials.data["access_key"]
  secret_key = data.vault_generic_secret.aws_credentials.data["secret_key"]
}

動的シークレットの使用

動的シークレットは、必要な時に一時的な認証情報を生成する機能です。

AWS動的シークレット

# Vaultから動的なAWS認証情報を取得
data "vault_aws_access_credentials" "creds" {
  backend = "aws"
  role    = "terraform-role"
}

provider "aws" {
  region     = "ap-northeast-1"
  access_key = data.vault_aws_access_credentials.creds.access_key
  secret_key = data.vault_aws_access_credentials.creds.secret_key
}

動的シークレットのメリット:

  • 一時的な認証情報(自動的に失効)
  • 最小権限の付与
  • 使用後の自動クリーンアップ
  • 監査ログによる追跡

Vaultでの設定例:

# AWSシークレットエンジンの有効化
vault secrets enable aws

# AWS認証情報の設定
vault write aws/config/root \
  access_key="AKIAIOSFODNN7EXAMPLE" \
  secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \
  region="ap-northeast-1"

# ロールの作成
vault write aws/roles/terraform-role \
  credential_type=iam_user \
  policy_document=-<<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ec2:*",
      "Resource": "*"
    }
  ]
}
EOF

実践例:複数クラウドの統合管理

複数のクラウドプロバイダーの認証情報をVaultで一元管理する例です。

terraform {
  required_providers {
    vault = {
      source  = "hashicorp/vault"
      version = "~> 4.0"
    }
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.0"
    }
  }
}

# Vaultプロバイダー
provider "vault" {
  address = var.vault_addr
}

# AWS認証情報をVaultから取得
data "vault_kv_secret_v2" "aws" {
  mount = "secret"
  name  = "aws/credentials"
}

provider "aws" {
  region     = "ap-northeast-1"
  access_key = data.vault_kv_secret_v2.aws.data["access_key"]
  secret_key = data.vault_kv_secret_v2.aws.data["secret_key"]
}

# Azure認証情報をVaultから取得
data "vault_kv_secret_v2" "azure" {
  mount = "secret"
  name  = "azure/credentials"
}

provider "azurerm" {
  features {}
  
  client_id       = data.vault_kv_secret_v2.azure.data["client_id"]
  client_secret   = data.vault_kv_secret_v2.azure.data["client_secret"]
  subscription_id = data.vault_kv_secret_v2.azure.data["subscription_id"]
  tenant_id       = data.vault_kv_secret_v2.azure.data["tenant_id"]
}

# リソースの作成
resource "aws_instance" "example" {
  ami           = "ami-0c3fd0f5d33134a76"
  instance_type = "t2.micro"
}

resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "Japan East"
}

ベストプラクティス

1. 環境ごとの設定分離

環境(開発、ステージング、本番)ごとにシークレットを分離します。

# variables.tf
variable "environment" {
  description = "Environment name (dev, staging, prod)"
  type        = string
}

# main.tf
data "vault_kv_secret_v2" "credentials" {
  mount = "secret"
  name  = "${var.environment}/aws/credentials"
}

Vaultでの構造例:

secret/
├── dev/
│   └── aws/credentials
├── staging/
│   └── aws/credentials
└── prod/
    └── aws/credentials

2. ポリシーの最小権限化

Vaultポリシーで最小限の権限のみを付与します。

# terraform-dev-policy.hcl
path "secret/data/dev/*" {
  capabilities = ["read", "list"]
}

# terraform-prod-policy.hcl
path "secret/data/prod/*" {
  capabilities = ["read"]
}

ポリシーの適用:

vault policy write terraform-dev terraform-dev-policy.hcl
vault policy write terraform-prod terraform-prod-policy.hcl

3. 変数の使用

Vault関連の設定は変数化して、柔軟性を持たせます。

# variables.tf
variable "vault_addr" {
  description = "Vault server address"
  type        = string
  default     = "https://vault.example.com:8200"
}

variable "vault_role_id" {
  description = "Vault AppRole Role ID"
  type        = string
  sensitive   = true
}

variable "vault_secret_id" {
  description = "Vault AppRole Secret ID"
  type        = string
  sensitive   = true
}

# main.tf
provider "vault" {
  address = var.vault_addr
  
  auth_login {
    path = "auth/approle/login"
    parameters = {
      role_id   = var.vault_role_id
      secret_id = var.vault_secret_id
    }
  }
}

4. エラーハンドリング

Vaultが利用できない場合のフォールバック処理を実装します。

variable "use_vault" {
  description = "Whether to use Vault for secrets"
  type        = bool
  default     = true
}

variable "aws_access_key" {
  description = "AWS Access Key (fallback when Vault is not used)"
  type        = string
  default     = ""
  sensitive   = true
}

variable "aws_secret_key" {
  description = "AWS Secret Key (fallback when Vault is not used)"
  type        = string
  default     = ""
  sensitive   = true
}

data "vault_kv_secret_v2" "aws" {
  count = var.use_vault ? 1 : 0
  mount = "secret"
  name  = "aws/credentials"
}

locals {
  aws_access_key = var.use_vault ? data.vault_kv_secret_v2.aws[0].data["access_key"] : var.aws_access_key
  aws_secret_key = var.use_vault ? data.vault_kv_secret_v2.aws[0].data["secret_key"] : var.aws_secret_key
}

provider "aws" {
  region     = "ap-northeast-1"
  access_key = local.aws_access_key
  secret_key = local.aws_secret_key
}

トラブルシューティング

よくある問題と解決方法

1. 認証エラー

エラーメッセージ:

Error: error reading from Vault: Error making API request

原因と解決方法:

  1. トークンの有効期限切れ
# トークンの確認
vault token lookup

# トークンの更新
vault login
  1. 環境変数の未設定
# 環境変数の確認
echo $VAULT_TOKEN
echo $VAULT_ADDR

# 環境変数の設定
export VAULT_TOKEN="hvs.CAESIJ..."
export VAULT_ADDR="https://vault.example.com:8200"

2. パーミッションエラー

エラーメッセージ:

Error: permission denied

原因と解決方法:

Vaultポリシーで必要な権限が付与されていない可能性があります。

# ポリシーの確認
vault policy read terraform-policy

# ポリシーの更新
vault policy write terraform-policy policy.hcl

必要な権限の例:

# 読み取り権限
path "secret/data/aws/*" {
  capabilities = ["read"]
}

# リスト権限(ディレクトリ一覧)
path "secret/metadata/aws/*" {
  capabilities = ["list"]
}

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

エラーメッセージ:

Error: secret not found

原因と解決方法:

  1. シークレットの存在確認
# シークレットの確認
vault kv get secret/aws/credentials

# シークレットの一覧表示
vault kv list secret/aws
  1. シークレットの作成
vault kv put secret/aws/credentials \
  access_key="AKIAIOSFODNN7EXAMPLE" \
  secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

4. 接続エラー

エラーメッセージ:

Error: error checking seal status: Get "https://vault.example.com:8200/v1/sys/seal-status": dial tcp: lookup vault.example.com: no such host

原因と解決方法:

  1. Vaultサーバーのアドレス確認
# 接続テスト
curl https://vault.example.com:8200/v1/sys/health
  1. ネットワーク設定の確認
    • ファイアウォール設定
    • DNS設定
    • プロキシ設定

セキュリティ上の注意事項

やるべきこと ✅

  • 環境変数でVaultトークンを管理: コードにトークンを含めない
  • 最小権限の原則を適用: 必要最小限の権限のみを付与
  • 定期的なシークレットローテーション: 定期的に認証情報を更新
  • 監査ログの有効化: すべてのアクセスを記録
  • TLS/HTTPSの使用: 通信を暗号化
  • トークンのTTL設定: トークンに有効期限を設定
  • 動的シークレットの活用: 可能な限り動的シークレットを使用

やってはいけないこと ❌

  • Vaultトークンをコードにハードコーディング: 絶対に避ける
  • 過度に広い権限の付与: 必要以上の権限を与えない
  • 本番環境でrootトークンを使用: 開発環境のみで使用
  • シークレットをログに出力: ログにシークレットを含めない
  • 平文での通信: 必ずHTTPSを使用
  • トークンの共有: 個人ごとにトークンを発行
  • 長期間有効なトークン: 適切なTTLを設定

次のステップ

Vaultとの連携を理解したら、以下のトピックも確認してください:

今後追加予定のトピック

  • Terraform Cloud/Enterpriseとの連携
  • CI/CDパイプラインでの使用
  • モジュール開発のベストプラクティス

参考リンク

© 2026 IBM Corporation. Licensed under CC BY 4.0.