Azure Key Vault Secrets (Java)
Stockez et gérez de manière sécurisée les secrets tels que les mots de passe, les clés API et les chaînes de connexion.
Installation
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-secrets</artifactId>
<version>4.9.0</version>
</dependency>
Création du client
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.identity.DefaultAzureCredentialBuilder;
// Client synchrone
SecretClient secretClient = new SecretClientBuilder()
.vaultUrl("https://<vault-name>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
// Client asynchrone
SecretAsyncClient secretAsyncClient = new SecretClientBuilder()
.vaultUrl("https://<vault-name>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildAsyncClient();
Créer/Définir un secret
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
// Secret simple
KeyVaultSecret secret = secretClient.setSecret("database-password", "P@ssw0rd123!");
System.out.println("Secret name: " + secret.getName());
System.out.println("Secret ID: " + secret.getId());
// Secret avec options
KeyVaultSecret secretWithOptions = secretClient.setSecret(
new KeyVaultSecret("api-key", "sk_live_abc123xyz")
.setProperties(new SecretProperties()
.setContentType("application/json")
.setExpiresOn(OffsetDateTime.now().plusYears(1))
.setNotBefore(OffsetDateTime.now())
.setEnabled(true)
.setTags(Map.of(
"environment", "production",
"service", "payment-api"
))
)
);
Obtenir un secret
// Obtenir la dernière version
KeyVaultSecret secret = secretClient.getSecret("database-password");
String value = secret.getValue();
System.out.println("Secret value: " + value);
// Obtenir une version spécifique
KeyVaultSecret specificVersion = secretClient.getSecret("database-password", "<version-id>");
// Obtenir uniquement les propriétés (pas la valeur)
SecretProperties props = secretClient.getSecret("database-password").getProperties();
System.out.println("Enabled: " + props.isEnabled());
System.out.println("Created: " + props.getCreatedOn());
Mettre à jour les propriétés du secret
// Obtenir le secret
KeyVaultSecret secret = secretClient.getSecret("api-key");
// Mettre à jour les propriétés (impossible de mettre à jour la valeur - créer une nouvelle version à la place)
secret.getProperties()
.setEnabled(false)
.setExpiresOn(OffsetDateTime.now().plusMonths(6))
.setTags(Map.of("status", "rotating"));
SecretProperties updated = secretClient.updateSecretProperties(secret.getProperties());
System.out.println("Updated: " + updated.getUpdatedOn());
Lister les secrets
import com.azure.core.util.paging.PagedIterable;
import com.azure.security.keyvault.secrets.models.SecretProperties;
// Lister tous les secrets (propriétés uniquement, pas les valeurs)
for (SecretProperties secretProps : secretClient.listPropertiesOfSecrets()) {
System.out.println("Secret: " + secretProps.getName());
System.out.println(" Enabled: " + secretProps.isEnabled());
System.out.println(" Created: " + secretProps.getCreatedOn());
System.out.println(" Content-Type: " + secretProps.getContentType());
// Obtenir la valeur si nécessaire
if (secretProps.isEnabled()) {
KeyVaultSecret fullSecret = secretClient.getSecret(secretProps.getName());
System.out.println(" Value: " + fullSecret.getValue().substring(0, 5) + "...");
}
}
// Lister les versions d'un secret
for (SecretProperties version : secretClient.listPropertiesOfSecretVersions("database-password")) {
System.out.println("Version: " + version.getVersion());
System.out.println("Created: " + version.getCreatedOn());
System.out.println("Enabled: " + version.isEnabled());
}
Supprimer un secret
import com.azure.core.util.polling.SyncPoller;
import com.azure.security.keyvault.secrets.models.DeletedSecret;
// Commencer la suppression (retourne un enquêteur pour les coffres avec soft-delete activé)
SyncPoller<DeletedSecret, Void> deletePoller = secretClient.beginDeleteSecret("old-secret");
// Attendre la suppression
DeletedSecret deletedSecret = deletePoller.poll().getValue();
System.out.println("Deleted on: " + deletedSecret.getDeletedOn());
System.out.println("Scheduled purge: " + deletedSecret.getScheduledPurgeDate());
deletePoller.waitForCompletion();
Récupérer un secret supprimé
// Lister les secrets supprimés
for (DeletedSecret deleted : secretClient.listDeletedSecrets()) {
System.out.println("Deleted: " + deleted.getName());
System.out.println("Deletion date: " + deleted.getDeletedOn());
}
// Récupérer le secret supprimé
SyncPoller<KeyVaultSecret, Void> recoverPoller = secretClient.beginRecoverDeletedSecret("old-secret");
recoverPoller.waitForCompletion();
KeyVaultSecret recovered = recoverPoller.getFinalResult();
System.out.println("Recovered: " + recovered.getName());
Purger un secret supprimé
// Supprimer définitivement (ne peut pas être récupéré)
secretClient.purgeDeletedSecret("old-secret");
// Obtenir d'abord les informations du secret supprimé
DeletedSecret deleted = secretClient.getDeletedSecret("old-secret");
System.out.println("Will purge: " + deleted.getName());
secretClient.purgeDeletedSecret("old-secret");
Sauvegarde et restauration
// Sauvegarder le secret (toutes les versions)
byte[] backup = secretClient.backupSecret("important-secret");
// Enregistrer dans un fichier
Files.write(Paths.get("secret-backup.blob"), backup);
// Restaurer à partir de la sauvegarde
byte[] backupData = Files.readAllBytes(Paths.get("secret-backup.blob"));
KeyVaultSecret restored = secretClient.restoreSecretBackup(backupData);
System.out.println("Restored: " + restored.getName());
Opérations asynchrones
SecretAsyncClient asyncClient = new SecretClientBuilder()
.vaultUrl("https://<vault>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildAsyncClient();
// Définir un secret de façon asynchrone
asyncClient.setSecret("async-secret", "async-value")
.subscribe(
secret -> System.out.println("Created: " + secret.getName()),
error -> System.out.println("Error: " + error.getMessage())
);
// Obtenir un secret de façon asynchrone
asyncClient.getSecret("async-secret")
.subscribe(secret -> System.out.println("Value: " + secret.getValue()));
// Lister les secrets de façon asynchrone
asyncClient.listPropertiesOfSecrets()
.doOnNext(props -> System.out.println("Found: " + props.getName()))
.subscribe();
Modèles de configuration
Charger plusieurs secrets
public class ConfigLoader {
private final SecretClient client;
public ConfigLoader(String vaultUrl) {
this.client = new SecretClientBuilder()
.vaultUrl(vaultUrl)
.credential(new DefaultAzureCredentialBuilder().build())
.buildClient();
}
public Map<String, String> loadSecrets(List<String> secretNames) {
Map<String, String> secrets = new HashMap<>();
for (String name : secretNames) {
try {
KeyVaultSecret secret = client.getSecret(name);
secrets.put(name, secret.getValue());
} catch (ResourceNotFoundException e) {
System.out.println("Secret not found: " + name);
}
}
return secrets;
}
}
// Utilisation
ConfigLoader loader = new ConfigLoader("https://my-vault.vault.azure.net");
Map<String, String> config = loader.loadSecrets(
Arrays.asList("db-connection-string", "api-key", "jwt-secret")
);
Modèle de rotation de secret
public void rotateSecret(String secretName, String newValue) {
// Obtenir le secret actuel
KeyVaultSecret current = secretClient.getSecret(secretName);
// Désactiver l'ancienne version
current.getProperties().setEnabled(false);
secretClient.updateSecretProperties(current.getProperties());
// Créer une nouvelle version avec la nouvelle valeur
KeyVaultSecret newSecret = secretClient.setSecret(secretName, newValue);
System.out.println("Rotated to version: " + newSecret.getProperties().getVersion());
}
Gestion des erreurs
import com.azure.core.exception.HttpResponseException;
import com.azure.core.exception.ResourceNotFoundException;
try {
KeyVaultSecret secret = secretClient.getSecret("my-secret");
System.out.println("Value: " + secret.getValue());
} catch (ResourceNotFoundException e) {
System.out.println("Secret not found");
} catch (HttpResponseException e) {
int status = e.getResponse().getStatusCode();
if (status == 403) {
System.out.println("Access denied - check permissions");
} else if (status == 429) {
System.out.println("Rate limited - retry later");
} else {
System.out.println("HTTP error: " + status);
}
}
Propriétés du secret
| Propriété | Description |
|---|---|
name |
Nom du secret |
value |
Valeur du secret (chaîne) |
id |
URL de l'identifiant complet |
contentType |
Indication de type MIME |
enabled |
Si le secret peut être récupéré |
notBefore |
Heure d'activation |
expiresOn |
Heure d'expiration |
createdOn |
Horodatage de création |
updatedOn |
Horodatage de la dernière mise à jour |
recoveryLevel |
Niveau de récupération soft-delete |
tags |
Métadonnées définies par l'utilisateur |
Variables d'environnement
AZURE_KEYVAULT_URL=https://<vault-name>.vault.azure.net
Meilleures pratiques
- Activer la suppression réversible - Protège contre la suppression accidentelle
- Utiliser les tags - Taguez les secrets avec l'environnement, le service, le propriétaire
- Définir une expiration - Utilisez
setExpiresOn()pour les identifiants qui doivent être renouvelés - Type de contenu - Définissez
contentTypepour indiquer le format (par ex.application/json) - Gestion des versions - Ne supprimez pas les anciennes versions immédiatement lors de la rotation
- Journalisation des accès - Activez la journalisation des diagnostics sur Key Vault
- Privilège minimum - Utilisez des coffres séparés pour différents environnements
Types de secrets courants
// Chaîne de connexion à la base de données
secretClient.setSecret(new KeyVaultSecret("db-connection",
"Server=myserver.database.windows.net;Database=mydb;...")
.setProperties(new SecretProperties()
.setContentType("text/plain")
.setTags(Map.of("type", "connection-string"))));
// Clé API
secretClient.setSecret(new KeyVaultSecret("stripe-api-key", "sk_live_...")
.setProperties(new SecretProperties()
.setContentType("text/plain")
.setExpiresOn(OffsetDateTime.now().plusYears(1))));
// Configuration JSON
secretClient.setSecret(new KeyVaultSecret("app-config",
"{\"endpoint\":\"https://...\",\"key\":\"...\"}")
.setProperties(new SecretProperties()
.setContentType("application/json")));
// Mot de passe de certificat
secretClient.setSecret(new KeyVaultSecret("cert-password", "CertP@ss!")
.setProperties(new SecretProperties()
.setContentType("text/plain")
.setTags(Map.of("certificate", "my-cert"))));
Expressions déclencheurs
- "Key Vault secrets Java", "secret management Java"
- "store password", "store API key", "connection string"
- "retrieve secret", "rotate secret"
- "Azure secrets", "vault secrets"