Skip to content
Back to skills

Azure Key Vault

BSecurity

Expert agent for Azure Key Vault and Azure Managed HSM. Covers keys (RSA, EC, oct-HSM), secrets, certificates, RBAC vs. access policies, soft-delete, purge protection, managed identity integration, and Key Vault references. WHEN: \"Azure Key Vault\", \"AKV\", \"Azure Managed HSM\", \"Key Vault secret\", \"Key Vault certificate\", \"key vault reference\", \"soft-delete\", \"purge protection\", \"Azure HSM\".

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 24, 2026
securitygobashkubernetesazureterraformgitapi

Works with

  • cli
  • api

Security analysis

B88/100
  • criticalSends environment variables or credentials to an external URL

Pro scans all 2 files and shows the line behind each finding

Scanned September 24, 2026

npx -y skills add chrishuffman5/domain-expert --skill azure-key-vault --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Azure Key Vault?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Azure Key Vault
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/chrishuffman5-azure-key-vault/badge)](https://www.skillsdirectory.com/skills/chrishuffman5-azure-key-vault)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: azure-key-vault
description: "Expert agent for Azure Key Vault and Azure Managed HSM. Covers keys (RSA, EC, oct-HSM), secrets, certificates, RBAC vs. access policies, soft-delete, purge protection, managed identity integration, and Key Vault references. WHEN: \"Azure Key Vault\", \"AKV\", \"Azure Managed HSM\", \"Key Vault secret\", \"Key Vault certificate\", \"key vault reference\", \"soft-delete\", \"purge protection\", \"Azure HSM\"."
license: MIT
---

# Azure Key Vault

This skill covers Azure Key Vault and Azure Managed HSM. It has deep knowledge of Key Vault object types, access models, lifecycle management, networking, and integration patterns across Azure services.

## How to Approach Tasks

When you receive a request:

1. **Classify** the request:
   - **Key operations** (create, wrap/unwrap, sign/verify, import) — Apply keys guidance
   - **Secret management** — Apply secrets guidance
   - **Certificate lifecycle** — Apply certificates guidance
   - **Access control** — RBAC vs. access policies guidance
   - **Architecture** — Load `references/architecture.md`
   - **Integration** — App Service, Functions, AKS, VM guidance below
   - **Compliance** — Load `references/architecture.md` for HSM/FIPS details

2. **Identify tier** — Standard (software-protected) vs. Premium (HSM-backed) vs. Managed HSM.

3. **Provide specific guidance** — Include Azure CLI, ARM/Bicep, or Terraform examples.

## Key Vault Object Types

### Keys

Cryptographic keys used for encrypt, decrypt, sign, verify, wrap, unwrap operations.

**Key types and allowed operations**:

| Type | Algorithms | Use Cases |
|---|---|---|
| RSA 2048/3072/4096 | RSA-OAEP, RSA-OAEP-256, PS256/384/512, RS256/384/512 | TDE, envelope encryption, signing |
| EC P-256/P-384/P-521/K-256 | ES256, ES384, ES521 | ECDSA signing, ECDH key agreement |
| oct-HSM (Premium/MHSM only) | AES-128/192/256-KW | Symmetric key wrapping |

**Software-protected** (Standard tier): Key operations performed in software; key material can be exported (if allowed).

**HSM-protected** (Premium tier): Key material generated and stored in shared HSM pool; FIPS 140-3 Level 3.

**Managed HSM**: Dedicated single-tenant HSM pool; FIPS 140-3 Level 3; keys never leave HSM.

```bash
# Create RSA key (software)
az keyvault key create --vault-name MyVault --name my-key --kty RSA --size 2048

# Create RSA key (HSM-backed, Premium vault)
az keyvault key create --vault-name MyVaultPremium --name my-hsm-key --kty RSA-HSM --size 4096

# Key operations
az keyvault key encrypt --vault-name MyVault --name my-key --algorithm RSA-OAEP-256 --value "dGVzdA=="
az keyvault key decrypt --vault-name MyVault --name my-key --algorithm RSA-OAEP-256 --value "<ciphertext>"

# Import existing key (BYOK)
az keyvault key import --vault-name MyVault --name imported-key --pem-file mykey.pem
```

### Secrets

Arbitrary string values: connection strings, API keys, passwords.

```bash
# Set a secret
az keyvault secret set --vault-name MyVault --name db-password --value "s3cr3t"

# Set with expiry and content type
az keyvault secret set \
    --vault-name MyVault \
    --name api-key \
    --value "abc123" \
    --expires "2025-12-31T00:00:00Z" \
    --content-type "application/json"

# Get a secret
az keyvault secret show --vault-name MyVault --name db-password --query value -o tsv

# Get specific version
az keyvault secret show --vault-name MyVault --name db-password --version <version-id>

# List all versions
az keyvault secret list-versions --vault-name MyVault --name db-password

# Soft-delete a secret
az keyvault secret delete --vault-name MyVault --name db-password
# After soft-delete: can recover (purge protection window)
az keyvault secret recover --vault-name MyVault --name db-password
```

### Certificates

Full certificate lifecycle management: generation, renewal, import, and integration with DigiCert, GlobalSign, or self-signed/custom CA.

```bash
# Create self-signed certificate
az keyvault certificate create \
    --vault-name MyVault \
    --name my-cert \
    --policy "$(az keyvault certificate get-default-policy)"

# Create certificate with custom policy
az keyvault certificate create \
    --vault-name MyVault \
    --name tls-cert \
    --policy @cert-policy.json

# Import existing certificate (PFX)
az keyvault certificate import \
    --vault-name MyVault \
    --name imported-cert \
    --file mycert.pfx \
    --password "pfx-password"

# Download certificate (public cert only)
az keyvault certificate download --vault-name MyVault --name my-cert --file cert.pem

# Get certificate secret (includes private key, PEM format, accessible via secret API)
az keyvault secret show --vault-name MyVault --name my-cert --query value
```

**Certificate policy JSON**:
```json
{
  "issuerParameters": {
    "name": "Self"
  },
  "keyProperties": {
    "keyType": "RSA",
    "keySize": 2048,
    "exportable": true,
    "reuseKey": false
  },
  "secretProperties": {
    "contentType": "application/x-pkcs12"
  },
  "x509CertificateProperties": {
    "subject": "CN=my-service.internal.example.com",
    "subjectAlternativeNames": {
      "dnsNames": ["my-service.internal.example.com", "my-service"]
    },
    "validityInMonths": 12,
    "keyUsage": ["digitalSignature", "keyEncipherment"]
  },
  "lifetimeActions": [
    {
      "trigger": { "daysBeforeExpiry": 30 },
      "action": { "actionType": "AutoRenew" }
    }
  ]
}
```

## Access Control

### RBAC (Recommended)

Azure RBAC is the recommended access model. Roles are assigned at vault, resource group, or subscription scope.

**Built-in roles**:

| Role | Permissions |
|---|---|
| Key Vault Administrator | All data plane + management plane |
| Key Vault Certificates Officer | Certificates CRUD |
| Key Vault Crypto Officer | Keys CRUD + operations |
| Key Vault Crypto User | Key operations only (no CRUD) |
| Key Vault Secrets Officer | Secrets CRUD |
| Key Vault Secrets User | Secret get only (read value) |
| Key Vault Reader | Read metadata, no data access |
| Key Vault Crypto Service Encryption User | get, wrapKey, unwrapKey only (for Azure services) |

```bash
# Enable RBAC on vault
az keyvault update --name MyVault --enable-rbac-authorization true

# Assign role to managed identity
az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee-object-id $(az identity show -n my-identity -g my-rg --query principalId -o tsv) \
    --scope $(az keyvault show --name MyVault --query id -o tsv)
```

### Access Policies (Legacy)

Access policies are a flat model: one policy per identity, specifying which operations are permitted on keys, secrets, and certificates separately.

```bash
# Set access policy for a service principal
az keyvault set-policy \
    --name MyVault \
    --object-id <service-principal-object-id> \
    --secret-permissions get list \
    --key-permissions get decrypt \
    --certificate-permissions get list
```

**Migrate from access policies to RBAC**:
1. Enable RBAC: `az keyvault update --name MyVault --enable-rbac-authorization true`
2. Assign RBAC roles to all identities that had access policies
3. Validate access before removing access policies (access policies are ignored when RBAC is enabled)

## Soft-Delete and Purge Protection

### Soft-Delete

Soft-delete is **enabled by default** and cannot be disabled. When a vault or an object is deleted:
- It enters a soft-deleted state for a retention period (7-90 days, default 90)
- The object is not accessible but the name is reserved
- Can be recovered within the retention period

```bash
# Show soft-deleted secrets
az keyvault secret list-deleted --vault-name MyVault

# Recover a soft-deleted secret
az keyvault secret recover --vault-name MyVault --name my-secret

# Purge (permanently delete, only if purge protection is OFF)
az keyvault secret purge --vault-name MyVault --name my-secret
```

### Purge Protection

When enabled, purge operations are blocked for the full retention period — neither you nor Microsoft Support can purge. Required for BYOK and some compliance mandates.

```bash
# Enable purge protection (cannot be disabled)
az keyvault update --name MyVault --enable-purge-protection true
```

**Implications**: If you rotate keys or certificates, old versions cannot be purged immediately. Plan retention policy accordingly.

## Networking

### Private Endpoints

Access Key Vault only via private endpoint (recommended for production):

```bash
# Create private endpoint
az network private-endpoint create \
    --name vault-pe \
    --resource-group my-rg \
    --vnet-name my-vnet \
    --subnet private-endpoints \
    --private-connection-resource-id $(az keyvault show --name MyVault --query id -o tsv) \
    --group-id vault \
    --connection-name vault-connection
```

### Firewall Rules

Restrict to specific IPs or VNets when private endpoint is not used:

```bash
# Allow specific IP range
az keyvault network-rule add --name MyVault --ip-address 203.0.113.0/24

# Allow VNet subnet
az keyvault network-rule add --name MyVault \
    --vnet-name my-vnet --subnet app-subnet

# Set default action to deny (after adding rules)
az keyvault update --name MyVault --default-action Deny --bypass AzureServices
```

## Azure Service Integrations

### Managed Identity (Recommended)

Managed Identity eliminates credentials for Azure resources:

```bash
# Enable system-assigned managed identity on App Service
az webapp identity assign --name my-app --resource-group my-rg

# Get the principal ID
az webapp identity show --name my-app --resource-group my-rg --query principalId -o tsv

# Grant Key Vault Secrets User role
az role assignment create \
    --role "Key Vault Secrets User" \
    --assignee <principal-id> \
    --scope $(az keyvault show --name MyVault --query id -o tsv)
```

### Key Vault References (App Service / Azure Functions)

Reference Key Vault secrets directly in App Service application settings without code changes:

```
Syntax: @Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/db-password/)

Or with specific version:
@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/db-password/abc123def456/)

Or using VaultName/SecretName syntax:
@Microsoft.KeyVault(VaultName=myvault;SecretName=db-password)
```

In Bicep:
```bicep
resource appSettings 'Microsoft.Web/sites/config@2022-09-01' = {
  name: 'appsettings'
  properties: {
    DB_PASSWORD: '@Microsoft.KeyVault(SecretUri=${keyVaultSecret.properties.secretUriWithVersion})'
  }
}
```

The App Service resolves the reference at runtime using the app's managed identity. If the identity lacks permission, the reference shows as `Secret reference not valid`.

### AKS / Kubernetes — Secrets Store CSI Driver

```yaml
# SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: azure-kv-secrets
spec:
  provider: azure
  parameters:
    usePodIdentity: "false"
    useVMManagedIdentity: "true"
    userAssignedIdentityID: "<client-id>"
    keyvaultName: "MyVault"
    objects: |
      array:
        - |
          objectName: db-password
          objectType: secret
          objectVersion: ""
        - |
          objectName: tls-cert
          objectType: certificate
          objectVersion: ""
    tenantId: "<tenant-id>"
  secretObjects:
  - secretName: db-credentials
    type: Opaque
    data:
    - objectName: db-password
      key: password
```

## Monitoring and Diagnostics

```bash
# Enable diagnostic settings (send to Log Analytics)
az monitor diagnostic-settings create \
    --name vault-diagnostics \
    --resource $(az keyvault show --name MyVault --query id -o tsv) \
    --workspace <log-analytics-workspace-id> \
    --logs '[{"category":"AuditEvent","enabled":true}]' \
    --metrics '[{"category":"AllMetrics","enabled":true}]'
```

Key Log Analytics queries:
```kusto
// All operations on Key Vault
AzureDiagnostics
| where ResourceType == "VAULTS"
| where OperationName != "VaultGet"
| project TimeGenerated, OperationName, ResultType, CallerIPAddress, identity_claim_oid_g

// Failed access (potential unauthorized access)
AzureDiagnostics
| where ResourceType == "VAULTS" and ResultType == "Unauthorized"
| summarize count() by CallerIPAddress, bin(TimeGenerated, 1h)

// Secret access audit
AzureDiagnostics
| where ResourceType == "VAULTS" and OperationName == "SecretGet"
| project TimeGenerated, requestUri_s, identity_claim_oid_g
```

## Reference Files

- `references/architecture.md` — Key Vault internals: Standard vs. Premium vs. Managed HSM, soft-delete/purge mechanics, RBAC vs. access policy internals, network architecture, BYOK patterns, geo-redundancy, SLA details.

Files in this skill

  • SKILL.md12.4 KB
  • references/architecture.md10.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…