azure-keyvault について
Azure Key Vaultでシークレット、暗号化キー、証明書を管理するスキルです。Azure CLI、SDK、Kubernetes、Terraformの例を用いて、保管庫の設定、アクセス制御、アプリ連携、トラブルシューティングを扱います。
主な機能
- 01シークレット、キー、証明書の管理
- 02Azure CLIによる保管庫設定
- 03RBACとアクセス ポリシーの例
- 04Pythonおよび.NET SDK連携
- 05AKS CSIドライバーの設定
- 06Terraform設定ガイド
活用シーン
- 01Azureアプリのシークレット一元管理
- 02マネージドIDへの保管庫アクセス付与
- 03AKSでのKey Vaultシークレットのマウント
- 04カスタマーマネージド暗号化キーの管理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill azure-keyvaultインストール後、Claude Code で/azure-keyvaultを入力して読み込まれたか確認します。
詳細
Azure Key Vault
Azure でシークレット、キー、証明書を安全に保存、管理します。
このスキルを使用する場面
次の場合にこのスキルを使用します:
- Azure でシークレット、暗号化キー、証明書を管理する
- Azure サービス向けに一元的なシークレット管理を実装する
- AKS、App Service、Azure Functions にシークレットを統合する
- カスタマー マネージド キー(CMK)でデータを暗号化する
- キー管理に関するコンプライアンス要件(FIPS 140-2)を満たす
前提条件
- 適切なアクセス許可を持つ Azure サブスクリプション
- Azure CLI がインストールされていること(
azコマンド) - ボールト管理用の共同作成者または Key Vault 管理者ロール
- アプリケーションからのアクセス用にマネージド ID が構成されていること
- Azure RBAC と Key Vault アクセス ポリシーの違いを理解していること
ボールトの作成と構成
# Create a resource group
az group create --name rg-secrets --location eastus
# Create Key Vault with RBAC authorization (recommended)
az keyvault create \
--name myapp-vault-prod \
--resource-group rg-secrets \
--location eastus \
--enable-rbac-authorization true \
--enable-soft-delete true \
--retention-days 90 \
--enable-purge-protection true \
--sku premium # Use premium for HSM-backed keys
# Create Key Vault with access policies (legacy)
az keyvault create \
--name myapp-vault-dev \
--resource-group rg-secrets \
--location eastus \
--enable-soft-delete true \
--retention-days 30
# Enable private endpoint (no public access)
az keyvault update \
--name myapp-vault-prod \
--resource-group rg-secrets \
--public-network-access Disabled
# Enable diagnostics logging
az monitor diagnostic-settings create \
--name kv-diagnostics \
--resource "/subscriptions/{sub}/resourceGroups/rg-secrets/providers/Microsoft.KeyVault/vaults/myapp-vault-prod" \
--workspace "/subscriptions/{sub}/resourceGroups/rg-monitor/providers/Microsoft.OperationalInsights/workspaces/security-logs" \
--logs '[{"category":"AuditEvent","enabled":true,"retentionPolicy":{"enabled":true,"days":365}}]'
シークレット管理
# Set a secret
az keyvault secret set \
--vault-name myapp-vault-prod \
--name db-password \
--value "S3cur3P@ssw0rd!" \
--content-type "text/plain" \
--tags Environment=production Team=platform
# Set a multi-line secret (JSON credentials)
az keyvault secret set \
--vault-name myapp-vault-prod \
--name db-credentials \
--value '{"username":"dbadmin","password":"S3cur3P@ss!","host":"db.postgres.database.azure.com","port":5432}'
# Get secret value
az keyvault secret show \
--vault-name myapp-vault-prod \
--name db-password \
--query value -o tsv
# Get specific version
az keyvault secret show \
--vault-name myapp-vault-prod \
--name db-password \
--version abc123def456
# List all secrets
az keyvault secret list --vault-name myapp-vault-prod -o table
# List secret versions
az keyvault secret list-versions \
--vault-name myapp-vault-prod \
--name db-password -o table
# Set expiration date
az keyvault secret set-attributes \
--vault-name myapp-vault-prod \
--name api-key \
--expires "2026-01-01T00:00:00Z"
# Disable a secret (without deleting)
az keyvault secret set-attributes \
--vault-name myapp-vault-prod \
--name old-api-key \
--enabled false
# Delete a secret (soft-delete)
az keyvault secret delete \
--vault-name myapp-vault-prod \
--name old-api-key
# Recover a deleted secret
az keyvault secret recover \
--vault-name myapp-vault-prod \
--name old-api-key
# Purge a deleted secret (permanent, requires purge protection to be off)
az keyvault secret purge \
--vault-name myapp-vault-prod \
--name old-api-key
# Backup and restore
az keyvault secret backup \
--vault-name myapp-vault-prod \
--name db-password \
--file db-password.backup
az keyvault secret restore \
--vault-name myapp-vault-prod \
--file db-password.backup
キー管理
# Create an RSA key for encryption
az keyvault key create \
--vault-name myapp-vault-prod \
--name data-encryption-key \
--kty RSA \
--size 4096 \
--ops encrypt decrypt wrapKey unwrapKey
# Create an EC key for signing
az keyvault key create \
--vault-name myapp-vault-prod \
--name signing-key \
--kty EC \
--curve P-256 \
--ops sign verify
# Import an existing key
az keyvault key import \
--vault-name myapp-vault-prod \
--name imported-key \
--pem-file key.pem
# Encrypt data
az keyvault key encrypt \
--vault-name myapp-vault-prod \
--name data-encryption-key \
--algorithm RSA-OAEP-256 \
--value "base64-encoded-plaintext"
# Rotate a key
az keyvault key rotate \
--vault-name myapp-vault-prod \
--name data-encryption-key
# Set key rotation policy
az keyvault key rotation-policy update \
--vault-name myapp-vault-prod \
--name data-encryption-key \
--value '{
"lifetimeActions": [
{
"trigger": {"timeBeforeExpiry": "P30D"},
"action": {"type": "Notify"}
},
{
"trigger": {"timeAfterCreate": "P90D"},
"action": {"type": "Rotate"}
}
],
"attributes": {"expiryTime": "P180D"}
}'
証明書管理
# Create a self-signed certificate
az keyvault certificate create \
--vault-name myapp-vault-prod \
--name app-tls-cert \
--policy '{
"issuerParameters": {"name": "Self"},
"keyProperties": {"exportable": true, "keySize": 4096, "keyType": "RSA"},
"secretProperties": {"contentType": "application/x-pkcs12"},
"x509CertificateProperties": {
"subject": "CN=app.example.com",
"subjectAlternativeNames": {"dnsNames": ["app.example.com", "*.app.example.com"]},
"validityInMonths": 12,
"keyUsage": ["digitalSignature", "keyEncipherment"],
"ekus": ["1.3.6.1.5.5.7.3.1"]
},
"lifetimeActions": [
{"trigger": {"daysBeforeExpiry": 30}, "action": {"actionType": "AutoRenew"}}
]
}'
# Import a certificate
az keyvault certificate import \
--vault-name myapp-vault-prod \
--name imported-cert \
--file certificate.pfx \
--password "pfx-password"
# Download certificate
az keyvault certificate download \
--vault-name myapp-vault-prod \
--name app-tls-cert \
--file cert.pem \
--encoding PEM
# List certificates
az keyvault certificate list --vault-name myapp-vault-prod -o table
アクセス ポリシーと RBAC
RBAC(推奨)
# Grant secret reader access to a managed identity
az role assignment create \
--role "Key Vault Secrets User" \
--assignee-object-id "$(az identity show -g rg-app -n myapp-identity --query principalId -o tsv)" \
--scope "/subscriptions/{sub}/resourceGroups/rg-secrets/providers/Microsoft.KeyVault/vaults/myapp-vault-prod"
# Grant admin access to security team
az role assignment create \
--role "Key Vault Administrator" \
--assignee "[email protected]" \
--scope "/subscriptions/{sub}/resourceGroups/rg-secrets/providers/Microsoft.KeyVault/vaults/myapp-vault-prod"
# Available Key Vault RBAC roles:
# - Key Vault Administrator (full management)
# - Key Vault Secrets Officer (manage secrets)
# - Key Vault Secrets User (read secrets)
# - Key Vault Certificates Officer (manage certs)
# - Key Vault Crypto Officer (manage keys)
# - Key Vault Crypto User (use keys for encrypt/decrypt)
# - Key Vault Reader (read metadata only)
アクセス ポリシー(レガシ)
# Grant secret access via access policy
az keyvault set-policy \
--name myapp-vault-prod \
--object-id "$(az identity show -g rg-app -n myapp-identity --query principalId -o tsv)" \
--secret-permissions get list
# Grant key access
az keyvault set-policy \
--name myapp-vault-prod \
--object-id "$OBJECT_ID" \
--key-permissions get unwrapKey wrapKey
# Grant certificate access
az keyvault set-policy \
--name myapp-vault-prod \
--object-id "$OBJECT_ID" \
--certificate-permissions get list
アプリケーション統合
Python SDK
from azure.identity import DefaultAzureCredential, ManagedIdentityCredential
from azure.keyvault.secrets import SecretClient
from azure.keyvault.keys import KeyClient
from azure.keyvault.certificates import CertificateClient
# Use DefaultAzureCredential (works locally and in Azure)
credential = DefaultAzureCredential()
vault_url = "https://myapp-vault-prod.vault.azure.net/"
# Secrets
secret_client = SecretClient(vault_url=vault_url, credential=credential)
db_password = secret_client.get_secret("db-password")
print(f"Secret value: {db_password.value}")
# Get specific version
specific = secret_client.get_secret("db-password", version="abc123")
# List secrets
for secret_properties in secret_client.list_properties_of_secrets():
print(f"Secret: {secret_properties.name}, Enabled: {secret_properties.enabled}")
# Keys
key_client = KeyClient(vault_url=vault_url, credential=credential)
from azure.keyvault.keys.crypto import CryptographyClient, EncryptionAlgorithm
key = key_client.get_key("data-encryption-key")
crypto_client = CryptographyClient(key, credential=credential)
# Encrypt data
plaintext = b"sensitive data"
result = crypto_client.encrypt(EncryptionAlgorithm.rsa_oaep_256, plaintext)
ciphertext = result.ciphertext
# Decrypt data
decrypted = crypto_client.decrypt(EncryptionAlgorithm.rsa_oaep_256, ciphertext)
.NET SDK
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
var credential = new DefaultAzureCredential();
var client = new SecretClient(new Uri("https://myapp-vault-prod.vault.azure.net/"), credential);
KeyVaultSecret secret = await client.GetSecretAsync("db-password");
string password = secret.Value;
Kubernetes 統合(AKS)
Secrets Store CSI Driver
# SecretProviderClass for AKS with managed identity
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: azure-keyvault-secrets
namespace: production
spec:
provider: azure
parameters:
usePodIdentity: "false"
useVMManagedIdentity: "true"
userAssignedIdentityID: "<managed-identity-client-id>"
keyvaultName: "myapp-vault-prod"
cloudName: ""
objects: |
array:
- |
objectName: db-password
objectType: secret
objectVersion: ""
- |
objectName: api-key
objectType: secret
- |
objectName: app-tls-cert
objectType: secret
tenantId: "<azure-tenant-id>"
secretObjects:
- secretName: db-secrets
type: Opaque
data:
- objectName: db-password
key: password
- objectName: api-key
key: api-key
- secretName: tls-secret
type: kubernetes.io/tls
data:
- objectName: app-tls-cert
key: tls.crt
---
# Pod using the secrets
apiVersion: v1
kind: Pod
metadata:
name: myapp
namespace: production
spec:
serviceAccountName: myapp-sa
containers:
- name: myapp
image: ghcr.io/acme/myapp:v1.0.0
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
volumeMounts:
- name: secrets-store
mountPath: "/mnt/secrets-store"
readOnly: true
volumes:
- name: secrets-store
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "azure-keyvault-secrets"
Terraform の構成
resource "azurerm_key_vault" "main" {
name = "myapp-vault-prod"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "premium"
enable_rbac_authorization = true
purge_protection_enabled = true
soft_delete_retention_days = 90
public_network_access_enabled = false
network_acls {
bypass = "AzureServices"
default_action = "Deny"
ip_rules = ["203.0.113.0/24"]
virtual_network_subnet_ids = [azurerm_subnet.app.id]
}
}
resource "azurerm_key_vault_secret" "db_password" {
name = "db-password"
value = var.db_password
key_vault_id = azurerm_key_vault.main.id
content_type = "text/plain"
expiration_date = "2026-01-01T00:00:00Z"
tags = {
environment = "production"
rotation = "enabled"
}
}
resource "azurerm_role_assignment" "app_secrets_user" {
scope = azurerm_key_vault.main.id
role_definition_name = "Key Vault Secrets User"
principal_id = azurerm_user_assigned_identity.app.principal_id
}
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| シークレットの読み取り時に「アクセスが拒否されました」と表示される | RBAC ロールまたはアクセス ポリシーが不足している | Key Vault Secrets User ロールを割り当てるか、get アクセス許可を付与したアクセス ポリシーを追加します |
| 「ボールトが見つかりません」と表示される | ネットワーク アクセスが制限されている | ファイアウォール規則を確認し、プライベート エンドポイントを有効にして、許可リストに IP を追加します |
| 論理削除されたシークレットが作成を妨げる | 削除済みシークレットとの名前の重複 | 復元して更新するか、まず削除済みシークレットを完全に消去します |
| マネージド ID からボールトにアクセスできない | ID のスコープが正しくない | ID のプリンシパル ID を確認し、ロールの割り当てスコープがボールトと一致することを確認します |
| 証明書の更新に失敗する | 自動更新ポリシーが構成されていない | 証明書ポリシーで AutoRenew アクションを指定した lifetimeActions を設定します |
| CSI ドライバーでシークレットのマウントに失敗する | プロバイダーの構成が正しくない | tenantId、userAssignedIdentityID、オブジェクト名が完全に一致することを確認します |
| シークレット取得のレイテンシが高い | クライアント側のキャッシュがない | アプリケーションにキャッシュを実装します。K8s では CSI ドライバーを使用します(一定間隔で同期されます) |
ベストプラクティス
- 細かな制御にはアクセス ポリシーより RBAC 認可を使用します
- 論理削除と消去保護を有効にします(コンプライアンス要件)
- すべてのサービスアクセスにマネージド ID を使用します(管理が必要な資格情報をなくします)
- プライベート エンドポイントを有効にして、パブリック ネットワークへの露出をなくします
- すべてのシークレットと証明書に有効期限を設定します
- 診断ログを有効にして SIEM に転送します
- HSM を使用したキー操作には Premium SKU を使用します
- すべての暗号化キーにキー ローテーション ポリシーを実装します
- Azure Activity ログでアクセスを定期的に監査します
- コストと所有者の追跡のために、すべてのボールト リソースにタグを付けます
関連スキル
- hashicorp-vault - マルチクラウドのシークレット
- azure-networking - ネットワーク セキュリティ
- aws-secrets-manager - AWS のシークレット管理
- gcp-secret-manager - GCP のシークレット管理
コメント
Markdown 対応