关于 azure-keyvault
用于在 Azure Key Vault 中管理机密、加密密钥和证书的技能,提供 Azure CLI、SDK、Kubernetes 与 Terraform 示例,涵盖保管库配置、访问控制、应用集成和故障排查。
主要功能
- 01管理机密、密钥和证书
- 02使用 Azure CLI 配置保管库
- 03RBAC 与访问策略示例
- 04Python 和 .NET SDK 集成
- 05配置 AKS CSI 驱动
- 06Terraform 配置指导
适用场景
- 01集中管理 Azure 应用机密
- 02为托管标识授予保管库访问权
- 03在 AKS 中挂载 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命令) - 用于管理保管库的 Contributor 或 Key Vault Administrator 角色
- 已配置用于应用访问的托管标识
- 了解 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
}
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 读取机密时出现“Access denied” | 缺少 RBAC 角色或访问策略 | 分配 Key Vault Secrets User 角色;或添加具有 get 权限的访问策略 |
| “Vault not found” | 网络访问受限 | 检查防火墙规则;启用专用终结点;将 IP 添加到允许列表 |
| 软删除的机密阻止创建 | 与已删除的机密名称冲突 | 先恢复并更新,或清除已删除的机密 |
| 托管标识无法访问保管库 | 标识未处于正确的范围 | 验证标识主体 ID;检查角色分配范围是否与保管库匹配 |
| 证书续订失败 | 未配置自动续订策略 | 在证书策略中使用 AutoRenew 操作设置 lifetimeActions |
| CSI 驱动程序无法装载机密 | 提供程序配置错误 | 确认 tenantId、userAssignedIdentityID 和对象名称完全匹配 |
| 检索机密时延迟较高 | 未进行客户端缓存 | 在应用中实现缓存;对 K8s 使用 CSI 驱动程序(按间隔同步) |
最佳实践
- 使用 RBAC 授权而非访问策略,以实现精细控制
- 启用软删除和清除保护(合规要求)
- 所有服务访问均使用托管标识(无需管理凭据)
- 启用专用终结点,消除公共网络暴露
- 为所有机密和证书设置到期日期
- 启用诊断日志记录并转发到 SIEM
- 使用高级 SKU 执行由 HSM 支持的密钥操作
- 为所有加密密钥实施密钥轮换策略
- 定期使用 Azure Activity 日志审计访问情况
- 为所有保管库资源添加标记,以跟踪成本和所有权
相关技能
- hashicorp-vault - 多云机密管理
- azure-networking - 网络安全
- aws-secrets-manager - AWS 机密管理
- gcp-secret-manager - GCP 机密管理
评论
支持 Markdown