GitHub Copilot
ChatGPT
Claude
Codex CLI
Cursor
opencode
Skill
Text
azure-security-keyvault-secrets-java
Azure Key Vault Secrets Java SDK for secret management. Use when storing, retrieving, or managing passwords, API keys, connection strings, or other sensitive configuration data.
Virus-scanned
Reviewed automatically before listing.
Download
microsoft-skills-.github_plugins_azure-sdk-java_skills_azure-security-keyvault-secrets-java-e58528d.zip · 6 KB
Install
skills CLI
npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-java/skills/azure-security-keyvault-secrets-java
Claude Code
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git
git clone https://github.com/microsoft/skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Azure Key Vault Secrets (Java)
Securely store and manage secrets like passwords, API keys, and connection strings.
Installation
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-secrets</artifactId>
<version>4.9.0</version>
</dependency>
Client Creation
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;
import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
.requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
.build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
// Sync client
SecretClient secretClient = new SecretClientBuilder()
.vaultUrl("https://<vault-name>.vault.azure.net")
.credential(credential)
.buildClient();
// Async client
SecretAsyncClient secretAsyncClient = new SecretClientBuilder()
.vaultUrl("https://<vault-name>.vault.azure.net")
.credential(credential)
.buildAsyncClient();
Create/Set Secret
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
// Simple secret
KeyVaultSecret secret = secretClient.setSecret("database-password", "P@ssw0rd123!");
System.out.println("Secret name: " + secret.getName());
System.out.println("Secret ID: " + secret.getId());
// Secret with 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"
))
)
);
Get Secret
// Get latest version
KeyVaultSecret secret = secretClient.getSecret("database-password");
String value = secret.getValue();
System.out.println("Secret value: " + value);
// Get specific version
KeyVaultSecret specificVersion = secretClient.getSecret("database-password", "<version-id>");
// Get only properties (no value)
SecretProperties props = secretClient.getSecret("database-password").getProperties();
System.out.println("Enabled: " + props.isEnabled());
System.out.println("Created: " + props.getCreatedOn());
Update Secret Properties
// Get secret
KeyVaultSecret secret = secretClient.getSecret("api-key");
// Update properties (cannot update value - create new version instead)
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());
List Secrets
import com.azure.core.util.paging.PagedIterable;
import com.azure.security.keyvault.secrets.models.SecretProperties;
// List all secrets (properties only, no values)
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());
// Get value if needed
if (secretProps.isEnabled()) {
KeyVaultSecret fullSecret = secretClient.getSecret(secretProps.getName());
System.out.println(" Value: " + fullSecret.getValue().substring(0, 5) + "...");
}
}
// List versions of a 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());
}
Delete Secret
import com.azure.core.util.polling.SyncPoller;
import com.azure.security.keyvault.secrets.models.DeletedSecret;
// Begin delete (returns poller for soft-delete enabled vaults)
SyncPoller<DeletedSecret, Void> deletePoller = secretClient.beginDeleteSecret("old-secret");
// Wait for deletion
DeletedSecret deletedSecret = deletePoller.poll().getValue();
System.out.println("Deleted on: " + deletedSecret.getDeletedOn());
System.out.println("Scheduled purge: " + deletedSecret.getScheduledPurgeDate());
deletePoller.waitForCompletion();
Recover Deleted Secret
// List deleted secrets
for (DeletedSecret deleted : secretClient.listDeletedSecrets()) {
System.out.println("Deleted: " + deleted.getName());
System.out.println("Deletion date: " + deleted.getDeletedOn());
}
// Recover deleted secret
SyncPoller<KeyVaultSecret, Void> recoverPoller = secretClient.beginRecoverDeletedSecret("old-secret");
recoverPoller.waitForCompletion();
KeyVaultSecret recovered = recoverPoller.getFinalResult();
System.out.println("Recovered: " + recovered.getName());
Purge Deleted Secret
// Permanently delete (cannot be recovered)
secretClient.purgeDeletedSecret("old-secret");
// Get deleted secret info first
DeletedSecret deleted = secretClient.getDeletedSecret("old-secret");
System.out.println("Will purge: " + deleted.getName());
secretClient.purgeDeletedSecret("old-secret");
Backup and Restore
// Backup secret (all versions)
byte[] backup = secretClient.backupSecret("important-secret");
// Save to file
Files.write(Paths.get("secret-backup.blob"), backup);
// Restore from backup
byte[] backupData = Files.readAllBytes(Paths.get("secret-backup.blob"));
KeyVaultSecret restored = secretClient.restoreSecretBackup(backupData);
System.out.println("Restored: " + restored.getName());
Async Operations
SecretAsyncClient asyncClient = new SecretClientBuilder()
.vaultUrl("https://<vault>.vault.azure.net")
.credential(new DefaultAzureCredentialBuilder().build())
.buildAsyncClient();
// Set secret async
asyncClient.setSecret("async-secret", "async-value")
.subscribe(
secret -> System.out.println("Created: " + secret.getName()),
error -> System.out.println("Error: " + error.getMessage())
);
// Get secret async
asyncClient.getSecret("async-secret")
.subscribe(secret -> System.out.println("Value: " + secret.getValue()));
// List secrets async
asyncClient.listPropertiesOfSecrets()
.doOnNext(props -> System.out.println("Found: " + props.getName()))
.subscribe();
Configuration Patterns
Load Multiple 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;
}
}
// Usage
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")
);
Secret Rotation Pattern
public void rotateSecret(String secretName, String newValue) {
// Get current secret
KeyVaultSecret current = secretClient.getSecret(secretName);
// Disable old version
current.getProperties().setEnabled(false);
secretClient.updateSecretProperties(current.getProperties());
// Create new version with new value
KeyVaultSecret newSecret = secretClient.setSecret(secretName, newValue);
System.out.println("Rotated to version: " + newSecret.getProperties().getVersion());
}
Error Handling
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);
}
}
Secret Properties
| Property | Description |
|---|---|
name |
Secret name |
value |
Secret value (string) |
id |
Full identifier URL |
contentType |
MIME type hint |
enabled |
Whether secret can be retrieved |
notBefore |
Activation time |
expiresOn |
Expiration time |
createdOn |
Creation timestamp |
updatedOn |
Last update timestamp |
recoveryLevel |
Soft-delete recovery level |
tags |
User-defined metadata |
Environment Variables
AZURE_KEYVAULT_URL=https://<vault-name>.vault.azure.net # Required for vault URL
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
Best Practices
- Enable Soft Delete - Protects against accidental deletion
- Use Tags - Tag secrets with environment, service, owner
- Set Expiration - Use
setExpiresOn()for credentials that should rotate - Content Type - Set
contentTypeto indicate format (e.g.,application/json) - Version Management - Don't delete old versions immediately during rotation
- Access Logging - Enable diagnostic logging on Key Vault
- Least Privilege - Use separate vaults for different environments
Common Secret Types
// Database connection string
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"))));
// API key
secretClient.setSecret(new KeyVaultSecret("stripe-api-key", "sk_live_...")
.setProperties(new SecretProperties()
.setContentType("text/plain")
.setExpiresOn(OffsetDateTime.now().plusYears(1))));
// JSON configuration
secretClient.setSecret(new KeyVaultSecret("app-config",
"{\"endpoint\":\"https://...\",\"key\":\"...\"}")
.setProperties(new SecretProperties()
.setContentType("application/json")));
// Certificate password
secretClient.setSecret(new KeyVaultSecret("cert-password", "CertP@ss!")
.setProperties(new SecretProperties()
.setContentType("text/plain")
.setTags(Map.of("certificate", "my-cert"))));
Trigger Phrases
- "Key Vault secrets Java", "secret management Java"
- "store password", "store API key", "connection string"
- "retrieve secret", "rotate secret"
- "Azure secrets", "vault secrets"
Files (skills)
-
references
-
examples.md 11.7 KB
# Azure Key Vault Secrets SDK for Java - Examples Comprehensive code examples for the Azure Key Vault Secrets SDK for Java. ## Table of Contents - [Maven Dependency](#maven-dependency) - [Client Creation](#client-creation) - [Setting Secrets](#setting-secrets) - [Getting Secrets](#getting-secrets) - [Listing Secrets](#listing-secrets) - [Updating Secret Properties](#updating-secret-properties) - [Deleting and Recovering Secrets](#deleting-and-recovering-secrets) - [Purging Deleted Secrets](#purging-deleted-secrets) - [Backup and Restore](#backup-and-restore) - [Async Client Patterns](#async-client-patterns) - [Error Handling](#error-handling) ## Maven Dependency ```xml <dependency> <groupId>com.azure</groupId> <artifactId>azure-security-keyvault-secrets</artifactId> <version>4.11.0-beta.1</version> </dependency> <!-- Required for authentication --> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.18.2</version> </dependency> ``` ## Client Creation ### Sync SecretClient ```java import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.security.keyvault.secrets.SecretClient; import com.azure.security.keyvault.secrets.SecretClientBuilder; SecretClient secretClient = new SecretClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) .vaultUrl("<your-key-vault-url>") .buildClient(); ``` ### Async SecretClient ```java import com.azure.security.keyvault.secrets.SecretAsyncClient; SecretAsyncClient secretAsyncClient = new SecretClientBuilder() .credential(new DefaultAzureCredentialBuilder().build()) .vaultUrl("<your-key-vault-url>") .buildAsyncClient(); ``` ## Setting Secrets ### Simple Secret ```java import com.azure.security.keyvault.secrets.models.KeyVaultSecret; KeyVaultSecret secret = secretClient.setSecret("<secret-name>", "<secret-value>"); System.out.printf("Secret created with name \"%s\" and value \"%s\"%n", secret.getName(), secret.getValue()); ``` ### Secret with Properties (Expiration) ```java import com.azure.security.keyvault.secrets.models.SecretProperties; import java.time.OffsetDateTime; KeyVaultSecret newSecret = new KeyVaultSecret("secretName", "secretValue") .setProperties(new SecretProperties().setExpiresOn(OffsetDateTime.now().plusDays(60))); KeyVaultSecret returnedSecret = secretClient.setSecret(newSecret); System.out.printf("Secret created with name %s and value %s%n", returnedSecret.getName(), returnedSecret.getValue()); ``` ### With Response (includes HTTP metadata) ```java import com.azure.core.util.Context; KeyVaultSecret newSecret = new KeyVaultSecret("secretName", "secretValue") .setProperties(new SecretProperties().setExpiresOn(OffsetDateTime.now().plusDays(60))); KeyVaultSecret secret = secretClient.setSecretWithResponse(newSecret, new Context("key1", "value1")) .getValue(); System.out.printf("Secret created with name %s%n", secret.getName()); ``` ## Getting Secrets ### Get Current Version ```java KeyVaultSecret secret = secretClient.getSecret("secretName"); System.out.printf("Secret returned with name %s and value %s%n", secret.getName(), secret.getValue()); ``` ### Get Specific Version ```java String secretVersion = "6A385B124DEF4096AF1361A85B16C204"; KeyVaultSecret secretWithVersion = secretClient.getSecret("secretName", secretVersion); System.out.printf("Secret returned with name %s and value %s%n", secretWithVersion.getName(), secretWithVersion.getValue()); ``` ### Get with Response ```java import com.azure.core.util.Context; String secretVersion = "6A385B124DEF4096AF1361A85B16C204"; KeyVaultSecret secret = secretClient.getSecretWithResponse( "secretName", secretVersion, new Context("key1", "value1") ).getValue(); System.out.printf("Secret returned with name %s%n", secret.getName()); ``` ## Listing Secrets ### List All Secrets ```java import com.azure.security.keyvault.secrets.models.SecretProperties; // Note: List operations don't return secret values - call getSecret for each for (SecretProperties secretProps : secretClient.listPropertiesOfSecrets()) { KeyVaultSecret secretWithValue = secretClient.getSecret( secretProps.getName(), secretProps.getVersion() ); System.out.printf("Secret: %s = %s%n", secretWithValue.getName(), secretWithValue.getValue()); } ``` ### List with Pagination ```java secretClient.listPropertiesOfSecrets().iterableByPage().forEach(page -> { System.out.printf("Status code: %d, URL: %s%n", page.getStatusCode(), page.getRequest().getUrl()); page.getItems().forEach(secretProps -> { KeyVaultSecret secret = secretClient.getSecret( secretProps.getName(), secretProps.getVersion() ); System.out.printf("Secret: %s%n", secret.getName()); }); }); ``` ### List Secret Versions ```java for (SecretProperties secretProps : secretClient.listPropertiesOfSecretVersions("secretName")) { KeyVaultSecret secret = secretClient.getSecret( secretProps.getName(), secretProps.getVersion() ); System.out.printf("Version: %s, Value: %s%n", secretProps.getVersion(), secret.getValue()); } ``` ## Updating Secret Properties ```java // Get the secret first SecretProperties secretProperties = secretClient.getSecret("secretName").getProperties(); // Update the expiry time secretProperties.setExpiresOn(OffsetDateTime.now().plusDays(60)); SecretProperties updatedProperties = secretClient.updateSecretProperties(secretProperties); // Get the updated secret KeyVaultSecret updatedSecret = secretClient.getSecret(updatedProperties.getName()); System.out.printf("Updated secret expires: %s%n", updatedSecret.getProperties().getExpiresOn()); ``` **Note**: `updateSecretProperties()` cannot change the secret value - only metadata like expiration, enabled status, tags, etc. To change the value, call `setSecret()` which creates a new version. ## Deleting and Recovering Secrets ### Delete Secret (with Polling) ```java import com.azure.core.util.polling.PollResponse; import com.azure.core.util.polling.SyncPoller; import com.azure.security.keyvault.secrets.models.DeletedSecret; SyncPoller<DeletedSecret, Void> deleteSecretPoller = secretClient.beginDeleteSecret("secretName"); // Deleted Secret is accessible as soon as polling begins PollResponse<DeletedSecret> pollResponse = deleteSecretPoller.poll(); // Deletion date only works for SoftDelete-enabled Key Vault System.out.printf("Deleted Date: %s%n", pollResponse.getValue().getDeletedOn()); System.out.printf("Recovery Id: %s%n", pollResponse.getValue().getRecoveryId()); // Wait for deletion to complete on server deleteSecretPoller.waitForCompletion(); ``` ### Get Deleted Secret ```java DeletedSecret deletedSecret = secretClient.getDeletedSecret("secretName"); System.out.printf("Recovery Id: %s%n", deletedSecret.getRecoveryId()); ``` ### List Deleted Secrets ```java for (DeletedSecret deletedSecret : secretClient.listDeletedSecrets()) { System.out.printf("Deleted secret: %s, Recovery Id: %s%n", deletedSecret.getName(), deletedSecret.getRecoveryId()); } ``` ### Recover Deleted Secret ```java SyncPoller<KeyVaultSecret, Void> recoverPoller = secretClient.beginRecoverDeletedSecret("deletedSecretName"); // Recovered secret accessible as soon as polling begins PollResponse<KeyVaultSecret> pollResponse = recoverPoller.poll(); System.out.printf("Recovered secret: %s%n", pollResponse.getValue().getName()); // Wait for recovery to complete on server recoverPoller.waitForCompletion(); ``` ## Purging Deleted Secrets ```java // Permanently delete (cannot be recovered after this) secretClient.purgeDeletedSecret("secretName"); System.out.println("Secret purged permanently"); ``` ## Backup and Restore ### Backup Secret ```java byte[] secretBackup = secretClient.backupSecret("secretName"); System.out.printf("Secret backup size: %d bytes%n", secretBackup.length); // Store the backup securely (e.g., to a file or blob storage) ``` ### Restore Secret ```java // Restore from backup bytes KeyVaultSecret restoredSecret = secretClient.restoreSecretBackup(secretBackup); System.out.printf("Restored secret: %s%n", restoredSecret.getName()); ``` ## Async Client Patterns ### Set Secret Async ```java secretAsyncClient.setSecret("asyncSecretName", "asyncSecretValue") .subscribe( secret -> System.out.printf("Created secret: %s%n", secret.getName()), error -> System.err.println("Error: " + error.getMessage()), () -> System.out.println("Operation completed") ); ``` ### Get Secret Async ```java secretAsyncClient.getSecret("secretName") .subscribe( secret -> System.out.printf("Secret value: %s%n", secret.getValue()), error -> System.err.println("Error: " + error.getMessage()) ); ``` ### List Secrets Async ```java secretAsyncClient.listPropertiesOfSecrets() .flatMap(secretProps -> secretAsyncClient.getSecret( secretProps.getName(), secretProps.getVersion() )) .subscribe( secret -> System.out.printf("Secret: %s%n", secret.getName()), error -> System.err.println("Error: " + error.getMessage()) ); ``` ### Delete Secret Async ```java secretAsyncClient.beginDeleteSecret("secretName") .subscribe(pollResponse -> { System.out.printf("Delete status: %s%n", pollResponse.getStatus()); System.out.printf("Deleted secret: %s%n", pollResponse.getValue().getName()); }); ``` ### Chain Operations ```java secretAsyncClient.setSecret("mySecret", "myValue") .flatMap(created -> { System.out.printf("Created: %s%n", created.getName()); return secretAsyncClient.getSecret(created.getName()); }) .flatMap(retrieved -> { System.out.printf("Retrieved: %s%n", retrieved.getValue()); retrieved.getProperties().setExpiresOn(OffsetDateTime.now().plusDays(30)); return secretAsyncClient.updateSecretProperties(retrieved.getProperties()); }) .subscribe( updated -> System.out.printf("Updated, expires: %s%n", updated.getExpiresOn()), error -> System.err.println("Error: " + error.getMessage()) ); ``` ## Error Handling ### Sync Error Handling ```java import com.azure.core.exception.HttpResponseException; import com.azure.core.exception.ResourceNotFoundException; try { KeyVaultSecret secret = secretClient.getSecret("nonexistent-secret"); } catch (ResourceNotFoundException e) { System.err.println("Secret not found: " + e.getMessage()); } catch (HttpResponseException e) { System.err.println("HTTP error: " + e.getResponse().getStatusCode()); System.err.println("Message: " + e.getMessage()); } catch (Exception e) { System.err.println("Unexpected error: " + e.getMessage()); } ``` ### Async Error Handling ```java secretAsyncClient.getSecret("nonexistent-secret") .subscribe( secret -> System.out.println("Secret: " + secret.getName()), error -> { if (error instanceof ResourceNotFoundException) { System.err.println("Secret not found"); } else if (error instanceof HttpResponseException) { HttpResponseException httpError = (HttpResponseException) error; System.err.println("HTTP error: " + httpError.getResponse().getStatusCode()); } else { System.err.println("Error: " + error.getMessage()); } } ); ``` ### Common Error Scenarios | Status Code | Exception | Cause | |-------------|-----------|-------| | 401 | ClientAuthenticationException | Invalid credentials | | 403 | HttpResponseException | Access denied (missing permissions) | | 404 | ResourceNotFoundException | Secret not found | | 409 | HttpResponseException | Conflict (secret already exists/deleted) | | 429 | HttpResponseException | Rate limited |
-
-
SKILL.md 11.9 KB
--- name: azure-security-keyvault-secrets-java description: Azure Key Vault Secrets Java SDK for secret management. Use when storing, retrieving, or managing passwords, API keys, connection strings, or other sensitive configuration data. license: MIT metadata: author: Microsoft version: "1.0.0" package: com.azure:azure-security-keyvault-secrets --- # Azure Key Vault Secrets (Java) Securely store and manage secrets like passwords, API keys, and connection strings. ## Installation ```xml <dependency> <groupId>com.azure</groupId> <artifactId>azure-security-keyvault-secrets</artifactId> <version>4.9.0</version> </dependency> ``` ## Client Creation ```java import com.azure.core.credential.TokenCredential; import com.azure.identity.AzureIdentityEnvVars; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.identity.ManagedIdentityCredentialBuilder; import com.azure.security.keyvault.secrets.SecretClient; import com.azure.security.keyvault.secrets.SecretClientBuilder; // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential> TokenCredential credential = new DefaultAzureCredentialBuilder() .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS) .build(); // Or use a specific credential directly in production: // See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes // TokenCredential credential = new ManagedIdentityCredentialBuilder().build(); // Sync client SecretClient secretClient = new SecretClientBuilder() .vaultUrl("https://<vault-name>.vault.azure.net") .credential(credential) .buildClient(); // Async client SecretAsyncClient secretAsyncClient = new SecretClientBuilder() .vaultUrl("https://<vault-name>.vault.azure.net") .credential(credential) .buildAsyncClient(); ``` ## Create/Set Secret ```java import com.azure.security.keyvault.secrets.models.KeyVaultSecret; // Simple secret KeyVaultSecret secret = secretClient.setSecret("database-password", "P@ssw0rd123!"); System.out.println("Secret name: " + secret.getName()); System.out.println("Secret ID: " + secret.getId()); // Secret with 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" )) ) ); ``` ## Get Secret ```java // Get latest version KeyVaultSecret secret = secretClient.getSecret("database-password"); String value = secret.getValue(); System.out.println("Secret value: " + value); // Get specific version KeyVaultSecret specificVersion = secretClient.getSecret("database-password", "<version-id>"); // Get only properties (no value) SecretProperties props = secretClient.getSecret("database-password").getProperties(); System.out.println("Enabled: " + props.isEnabled()); System.out.println("Created: " + props.getCreatedOn()); ``` ## Update Secret Properties ```java // Get secret KeyVaultSecret secret = secretClient.getSecret("api-key"); // Update properties (cannot update value - create new version instead) 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()); ``` ## List Secrets ```java import com.azure.core.util.paging.PagedIterable; import com.azure.security.keyvault.secrets.models.SecretProperties; // List all secrets (properties only, no values) 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()); // Get value if needed if (secretProps.isEnabled()) { KeyVaultSecret fullSecret = secretClient.getSecret(secretProps.getName()); System.out.println(" Value: " + fullSecret.getValue().substring(0, 5) + "..."); } } // List versions of a 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()); } ``` ## Delete Secret ```java import com.azure.core.util.polling.SyncPoller; import com.azure.security.keyvault.secrets.models.DeletedSecret; // Begin delete (returns poller for soft-delete enabled vaults) SyncPoller<DeletedSecret, Void> deletePoller = secretClient.beginDeleteSecret("old-secret"); // Wait for deletion DeletedSecret deletedSecret = deletePoller.poll().getValue(); System.out.println("Deleted on: " + deletedSecret.getDeletedOn()); System.out.println("Scheduled purge: " + deletedSecret.getScheduledPurgeDate()); deletePoller.waitForCompletion(); ``` ## Recover Deleted Secret ```java // List deleted secrets for (DeletedSecret deleted : secretClient.listDeletedSecrets()) { System.out.println("Deleted: " + deleted.getName()); System.out.println("Deletion date: " + deleted.getDeletedOn()); } // Recover deleted secret SyncPoller<KeyVaultSecret, Void> recoverPoller = secretClient.beginRecoverDeletedSecret("old-secret"); recoverPoller.waitForCompletion(); KeyVaultSecret recovered = recoverPoller.getFinalResult(); System.out.println("Recovered: " + recovered.getName()); ``` ## Purge Deleted Secret ```java // Permanently delete (cannot be recovered) secretClient.purgeDeletedSecret("old-secret"); // Get deleted secret info first DeletedSecret deleted = secretClient.getDeletedSecret("old-secret"); System.out.println("Will purge: " + deleted.getName()); secretClient.purgeDeletedSecret("old-secret"); ``` ## Backup and Restore ```java // Backup secret (all versions) byte[] backup = secretClient.backupSecret("important-secret"); // Save to file Files.write(Paths.get("secret-backup.blob"), backup); // Restore from backup byte[] backupData = Files.readAllBytes(Paths.get("secret-backup.blob")); KeyVaultSecret restored = secretClient.restoreSecretBackup(backupData); System.out.println("Restored: " + restored.getName()); ``` ## Async Operations ```java SecretAsyncClient asyncClient = new SecretClientBuilder() .vaultUrl("https://<vault>.vault.azure.net") .credential(new DefaultAzureCredentialBuilder().build()) .buildAsyncClient(); // Set secret async asyncClient.setSecret("async-secret", "async-value") .subscribe( secret -> System.out.println("Created: " + secret.getName()), error -> System.out.println("Error: " + error.getMessage()) ); // Get secret async asyncClient.getSecret("async-secret") .subscribe(secret -> System.out.println("Value: " + secret.getValue())); // List secrets async asyncClient.listPropertiesOfSecrets() .doOnNext(props -> System.out.println("Found: " + props.getName())) .subscribe(); ``` ## Configuration Patterns ### Load Multiple Secrets ```java 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; } } // Usage 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") ); ``` ### Secret Rotation Pattern ```java public void rotateSecret(String secretName, String newValue) { // Get current secret KeyVaultSecret current = secretClient.getSecret(secretName); // Disable old version current.getProperties().setEnabled(false); secretClient.updateSecretProperties(current.getProperties()); // Create new version with new value KeyVaultSecret newSecret = secretClient.setSecret(secretName, newValue); System.out.println("Rotated to version: " + newSecret.getProperties().getVersion()); } ``` ## Error Handling ```java 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); } } ``` ## Secret Properties | Property | Description | |----------|-------------| | `name` | Secret name | | `value` | Secret value (string) | | `id` | Full identifier URL | | `contentType` | MIME type hint | | `enabled` | Whether secret can be retrieved | | `notBefore` | Activation time | | `expiresOn` | Expiration time | | `createdOn` | Creation timestamp | | `updatedOn` | Last update timestamp | | `recoveryLevel` | Soft-delete recovery level | | `tags` | User-defined metadata | ## Environment Variables ```bash AZURE_KEYVAULT_URL=https://<vault-name>.vault.azure.net # Required for vault URL AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production ``` ## Best Practices 1. **Enable Soft Delete** - Protects against accidental deletion 2. **Use Tags** - Tag secrets with environment, service, owner 3. **Set Expiration** - Use `setExpiresOn()` for credentials that should rotate 4. **Content Type** - Set `contentType` to indicate format (e.g., `application/json`) 5. **Version Management** - Don't delete old versions immediately during rotation 6. **Access Logging** - Enable diagnostic logging on Key Vault 7. **Least Privilege** - Use separate vaults for different environments ## Common Secret Types ```java // Database connection string 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")))); // API key secretClient.setSecret(new KeyVaultSecret("stripe-api-key", "sk_live_...") .setProperties(new SecretProperties() .setContentType("text/plain") .setExpiresOn(OffsetDateTime.now().plusYears(1)))); // JSON configuration secretClient.setSecret(new KeyVaultSecret("app-config", "{\"endpoint\":\"https://...\",\"key\":\"...\"}") .setProperties(new SecretProperties() .setContentType("application/json"))); // Certificate password secretClient.setSecret(new KeyVaultSecret("cert-password", "CertP@ss!") .setProperties(new SecretProperties() .setContentType("text/plain") .setTags(Map.of("certificate", "my-cert")))); ``` ## Trigger Phrases - "Key Vault secrets Java", "secret management Java" - "store password", "store API key", "connection string" - "retrieve secret", "rotate secret" - "Azure secrets", "vault secrets"
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.