tools/keyvault.py (44 lines of code) (raw):
import os
import logging
from azure.identity.aio import ManagedIdentityCredential, AzureCliCredential, ChainedTokenCredential
from azure.keyvault.secrets.aio import SecretClient as AsyncSecretClient
from azure.core.exceptions import ResourceNotFoundError, ClientAuthenticationError
class KeyVaultClient:
"""
KeyVaultClient provides methods to retrieve secrets from an Azure Key Vault.
"""
def __init__(self):
self.key_vault_name = os.getenv("AZURE_KEY_VAULT_NAME")
if not self.key_vault_name:
logging.error("[keyvault] AZURE_KEY_VAULT_NAME environment variable not set.")
raise ValueError("AZURE_KEY_VAULT_NAME environment variable not set.")
self.kv_uri = f"https://{self.key_vault_name}.vault.azure.net"
# Initialize the ChainedTokenCredential with ManagedIdentityCredential and AzureCliCredential
try:
self.credential = ChainedTokenCredential(
ManagedIdentityCredential(),
AzureCliCredential()
)
logging.debug("[keyvault] Initialized ChainedTokenCredential with ManagedIdentityCredential and AzureCliCredential.")
except Exception as e:
logging.error(f"[keyvault] Failed to initialize ChainedTokenCredential: {e}")
raise
self.clients = {} # Cache SecretClient instances if needed
async def get_secret(self, secret_name):
"""
Retrieves the value of a secret from Azure Key Vault.
Parameters:
secret_name (str): The name of the secret to retrieve.
Returns:
str: The value of the secret, or None if not found or an error occurs.
"""
if not self.key_vault_name:
logging.error("[keyvault] Key Vault name is not configured.")
return None
try:
async with AsyncSecretClient(vault_url=self.kv_uri, credential=self.credential) as client:
retrieved_secret = await client.get_secret(secret_name)
logging.debug(f"[keyvault] Successfully retrieved secret '{secret_name}'.")
return retrieved_secret.value
except ClientAuthenticationError:
logging.error(f"[keyvault] Authentication failed when reading '{secret_name}'. Please check your credentials.")
return None
except ResourceNotFoundError:
logging.debug(f"[keyvault] Secret '{secret_name}' not found in the Key Vault.")
return None
except Exception as e:
logging.error(f"[keyvault] An unexpected error occurred when reading '{secret_name}': {e}")
return None
async def close(self):
"""
Closes the credential client session.
"""
if self.credential:
await self.credential.close()
logging.debug("[keyvault] Credential has been closed.")