```python
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
client = SecretClient(
vault_url="https://YOUR-VAULT.vault.azure.net/",
credential=DefaultAzureCredential(),
)
secret value client.get_secret("[secret-name]")
print(secret.value)
```
Traps:
- **Two permission models.** New vaults use Azure RBAC: assign "Key Vault Secrets User" (get/list) or "Key Vault Secrets Officer" (manage). Old vaults use access policies: the identity needs Get/List on secrets. A 403 means you are in one model and granted in the other. Check the vault's permission model in the portal first.
- **Firewall.** Vaults with firewall rules deny public network access by default. From a locked-down VNet you need a private endpoint; from your laptop you need your IP allow-listed or "allow trusted services" for the Azure service calling.
- **Soft delete + purge protection.** Deleted secrets go to soft-delete for 90 days. Recreating with the same name before purge gives a conflict. `az keyvault secret purge` if you really need the name back, or wait.
- **Secret versioning.** `get_secret` without a version returns the latest ENABLED version. Disabled versions are skipped silently; if rotation disabled the newest version, you get the older one with no error.
- **Do not print secrets.** Obvious, but agents do it in debug logs. Read into memory, use, never log.
Verify: `az keyvault secret show --vault-name [vault] --name [secret-name]` with the same identity your code uses. If the CLI works and the code 403s, the code is using a different identity (chain order problem).