com.azure.security.keyvault.administration.KeyVaultBackupClient Maven / Gradle / Ivy
Show all versions of azure-security-keyvault-administration Show documentation
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.security.keyvault.administration;
import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.exception.HttpResponseException;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.ResponseBase;
import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.util.Context;
import com.azure.core.util.logging.ClientLogger;
import com.azure.core.util.polling.LongRunningOperationStatus;
import com.azure.core.util.polling.PollResponse;
import com.azure.core.util.polling.PollingContext;
import com.azure.core.util.polling.SyncPoller;
import com.azure.security.keyvault.administration.implementation.KeyVaultBackupClientImpl;
import com.azure.security.keyvault.administration.implementation.KeyVaultErrorCodeStrings;
import com.azure.security.keyvault.administration.implementation.models.FullBackupHeaders;
import com.azure.security.keyvault.administration.implementation.models.FullBackupOperation;
import com.azure.security.keyvault.administration.implementation.models.FullRestoreOperationHeaders;
import com.azure.security.keyvault.administration.implementation.models.RestoreOperation;
import com.azure.security.keyvault.administration.implementation.models.RestoreOperationParameters;
import com.azure.security.keyvault.administration.implementation.models.SASTokenParameter;
import com.azure.security.keyvault.administration.implementation.models.SelectiveKeyRestoreOperation;
import com.azure.security.keyvault.administration.implementation.models.SelectiveKeyRestoreOperationHeaders;
import com.azure.security.keyvault.administration.implementation.models.SelectiveKeyRestoreOperationParameters;
import com.azure.security.keyvault.administration.models.KeyVaultAdministrationException;
import com.azure.security.keyvault.administration.models.KeyVaultBackupOperation;
import com.azure.security.keyvault.administration.models.KeyVaultRestoreOperation;
import com.azure.security.keyvault.administration.models.KeyVaultRestoreResult;
import com.azure.security.keyvault.administration.models.KeyVaultSelectiveKeyRestoreOperation;
import com.azure.security.keyvault.administration.models.KeyVaultSelectiveKeyRestoreResult;
import java.net.URL;
import java.time.Duration;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Function;
import static com.azure.security.keyvault.administration.KeyVaultAdministrationUtil.enableSyncRestProxy;
import static com.azure.security.keyvault.administration.KeyVaultAdministrationUtil.toLongRunningOperationStatus;
import static com.azure.security.keyvault.administration.KeyVaultAdministrationUtil.transformToLongRunningOperation;
import static com.azure.security.keyvault.administration.KeyVaultBackupAsyncClient.restoreOperationToSelectiveKeyRestoreOperation;
/**
* The {@link KeyVaultBackupClient} provides synchronous methods to perform full a backup and restore of a key vault,
* as well as selectively restoring specific keys from a backup.
*
* Getting Started
*
* In order to interact with the Azure Key Vault service, you will need to create an instance of the
* {@link KeyVaultBackupClient} class, a vault url and a credential object.
*
* The examples shown in this document use a credential object named DefaultAzureCredential for authentication,
* which is appropriate for most scenarios, including local development and production environments. Additionally,
* we recommend using a
*
* managed identity for authentication in production environments.
* You can find more information on different ways of authenticating and their corresponding credential types in the
*
* Azure Identity documentation".
*
* Sample: Construct Asynchronous Backup Client
*
* The following code sample demonstrates the creation of a {@link KeyVaultBackupClient}, using the
* {@link KeyVaultBackupClientBuilder} to configure it.
*
*
*
* KeyVaultBackupClient keyVaultBackupClient = new KeyVaultBackupClientBuilder()
* .vaultUrl("<your-managed-hsm-url>")
* .credential(new DefaultAzureCredentialBuilder().build())
* .buildClient();
*
*
*
*
*
*
*
* Back Up a Collection of Keys
* The {@link KeyVaultBackupClient} can be used to back up the entire collection of keys from a key vault.
*
* Code Sample:
* The following code sample demonstrates how to synchronously back up an entire collection of keys using, using the
* {@link KeyVaultBackupClient#beginBackup(String, String)} API.
*
*
*
* String blobStorageUrl = "https://myaccount.blob.core.windows.net/myContainer";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
*
* SyncPoller<KeyVaultBackupOperation, String> backupPoller = client.beginBackup(blobStorageUrl, sasToken);
*
* PollResponse<KeyVaultBackupOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultBackupOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* String folderUrl = backupPoller.getFinalResult();
*
* System.out.printf("Backup completed. The storage location of this backup is: %s.%n", folderUrl);
* } else {
* KeyVaultBackupOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Backup failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* Note: For the asynchronous sample, refer to {@link KeyVaultBackupAsyncClient}.
*
*
*
*
*
* Restore a Collection of Keys
* The {@link KeyVaultBackupClient} can be used to restore an entire collection of keys from a backup.
*
* Code Sample:
* The following code sample demonstrates how to synchronously restore an entire collection of keys from a backup,
* using the {@link KeyVaultBackupClient#beginRestore(String, String)} API.
*
*
*
* String folderUrl = "https://myaccount.blob.core.windows.net/myContainer/mhsm-myaccount-2020090117323313";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
*
* SyncPoller<KeyVaultRestoreOperation, KeyVaultRestoreResult> backupPoller =
* client.beginRestore(folderUrl, sasToken);
*
* PollResponse<KeyVaultRestoreOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultRestoreOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* System.out.printf("Backup restored successfully.%n");
* } else {
* KeyVaultRestoreOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Restore failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* Note: For the asynchronous sample, refer to {@link KeyVaultBackupAsyncClient}.
*
*
*
*
*
* Selectively Restore a Key
* The {@link KeyVaultBackupClient} can be used to restore a specific key from a backup.
*
* Code Sample:
* The following code sample demonstrates how to synchronously restore a specific key from a backup, using
* the {@link KeyVaultBackupClient#beginSelectiveKeyRestore(String, String, String)} API.
*
*
*
* String folderUrl = "https://myaccount.blob.core.windows.net/myContainer/mhsm-myaccount-2020090117323313";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
* String keyName = "myKey";
*
* SyncPoller<KeyVaultSelectiveKeyRestoreOperation, KeyVaultSelectiveKeyRestoreResult> backupPoller =
* client.beginSelectiveKeyRestore(folderUrl, sasToken, keyName);
*
* PollResponse<KeyVaultSelectiveKeyRestoreOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultSelectiveKeyRestoreOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* System.out.printf("Key restored successfully.%n");
* } else {
* KeyVaultSelectiveKeyRestoreOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Key restore failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* Note: For the asynchronous sample, refer to {@link KeyVaultBackupAsyncClient}.
*
*
*
*
*
* @see com.azure.security.keyvault.administration
* @see KeyVaultBackupClientBuilder
*/
@ServiceClient(builder = KeyVaultBackupClientBuilder.class)
public final class KeyVaultBackupClient {
/**
* The logger to be used.
*/
private static final ClientLogger LOGGER = new ClientLogger(KeyVaultBackupClient.class);
private static final Duration DEFAULT_POLLING_INTERVAL = Duration.ofSeconds(1);
private final KeyVaultBackupAsyncClient asyncClient;
/**
* The underlying AutoRest client used to interact with the Key Vault service.
*/
private final KeyVaultBackupClientImpl clientImpl;
/**
* The Key Vault URL this client is associated to.
*/
private final String vaultUrl;
/**
* The Key Vault Administration Service version to use with this client.
*/
private final String serviceVersion;
/**
* The {@link HttpPipeline} powering this client.
*/
private final HttpPipeline pipeline;
Duration getDefaultPollingInterval() {
return DEFAULT_POLLING_INTERVAL;
}
/**
* Package private constructor to be used by {@link KeyVaultBackupClientBuilder}.
*/
KeyVaultBackupClient(URL vaultUrl, HttpPipeline httpPipeline,
KeyVaultAdministrationServiceVersion serviceVersion) {
Objects.requireNonNull(vaultUrl, KeyVaultErrorCodeStrings.VAULT_END_POINT_REQUIRED);
this.vaultUrl = vaultUrl.toString();
this.serviceVersion = serviceVersion.getVersion();
this.pipeline = httpPipeline;
this.asyncClient = null;
clientImpl = new KeyVaultBackupClientImpl(httpPipeline, this.serviceVersion);
}
/**
* Get the vault endpoint URL.
*
* @return The vault endpoint URL.
*/
public String getVaultUrl() {
return asyncClient.getVaultUrl();
}
/**
* Initiates a full backup of the Key Vault.
*
* Code Samples
* Starts a {@link KeyVaultBackupOperation backup operation}, polls for its status and waits for it to complete.
* Prints out the details of the operation's final result in case of success or prints out error details in case the
* operation fails.
*
*
* String blobStorageUrl = "https://myaccount.blob.core.windows.net/myContainer";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
*
* SyncPoller<KeyVaultBackupOperation, String> backupPoller = client.beginBackup(blobStorageUrl, sasToken);
*
* PollResponse<KeyVaultBackupOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultBackupOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* String folderUrl = backupPoller.getFinalResult();
*
* System.out.printf("Backup completed. The storage location of this backup is: %s.%n", folderUrl);
* } else {
* KeyVaultBackupOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Backup failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* @param blobStorageUrl The URL for the Blob Storage resource where the backup will be located.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
*
* @return A {@link SyncPoller} polling on the {@link KeyVaultBackupOperation backup operation} status.
*
* @throws KeyVaultAdministrationException If the given {@code blobStorageUrl} or {@code sasToken} are invalid.
* @throws NullPointerException If the {@code blobStorageUrl} is {@code null}.
*/
@ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
public SyncPoller beginBackup(String blobStorageUrl, String sasToken) {
if (blobStorageUrl == null) {
throw LOGGER.logExceptionAsError(
new NullPointerException(
String.format(KeyVaultErrorCodeStrings.PARAMETER_REQUIRED, "'blobStorageUrl'")));
}
Context context = Context.NONE;
return SyncPoller.createPoller(
getDefaultPollingInterval(),
cxt -> new PollResponse<>(LongRunningOperationStatus.NOT_STARTED, backupActivationOperation(blobStorageUrl, sasToken, context).apply(cxt)),
backupPollOperation(context),
(pollingContext, firstResponse) -> {
throw LOGGER.logExceptionAsError(new RuntimeException("Cancellation is not supported"));
},
backupFetchOperation());
}
/**
* Initiates a full backup of the Key Vault.
*
* @param blobStorageUrl The URL for the Blob Storage resource where the backup will be located.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
* @param context Additional context that is passed through the HTTP pipeline during the service call.
*
* @return A {@link Response} containing the {@link KeyVaultBackupOperation backup operation} status.
*
* @throws KeyVaultAdministrationException If the given {@code blobStorageUrl} or {@code sasToken} are invalid.
*/
Response backupWithResponse(String blobStorageUrl, String sasToken, Context context) {
SASTokenParameter sasTokenParameter = new SASTokenParameter(blobStorageUrl)
.setToken(sasToken)
.setUseManagedIdentity(sasToken == null);
context = enableSyncRestProxy(context);
try {
ResponseBase backupOperationResponse =
clientImpl.fullBackupWithResponse(vaultUrl, sasTokenParameter, context);
return new SimpleResponse<>(backupOperationResponse.getRequest(), backupOperationResponse.getStatusCode(),
backupOperationResponse.getHeaders(),
(KeyVaultBackupOperation) transformToLongRunningOperation(backupOperationResponse.getValue()));
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
}
private Function, KeyVaultBackupOperation> backupActivationOperation(
String blobStorageUrl, String sasToken, Context context) {
return (pollingContext) -> {
try {
return backupWithResponse(blobStorageUrl, sasToken, context).getValue();
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private Function, PollResponse> backupPollOperation(Context context) {
return (pollingContext) -> {
try {
PollResponse pollResponse = pollingContext.getLatestResponse();
if (pollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED
|| pollResponse.getStatus() == LongRunningOperationStatus.FAILED) {
return pollResponse;
}
final KeyVaultBackupOperation keyVaultBackupOperation = pollResponse.getValue();
if (keyVaultBackupOperation == null) {
LOGGER.warning("Backup operation does not exist. Activation operation failed.");
return new PollResponse(
LongRunningOperationStatus.fromString("BACKUP_START_FAILED", true), null);
}
final String jobId = keyVaultBackupOperation.getOperationId();
Context contextToUse = enableSyncRestProxy(context);
Response backupOperationResponse = clientImpl.fullBackupStatusWithResponse(vaultUrl, jobId,
contextToUse);
return processBackupOperationResponse(new SimpleResponse<>(backupOperationResponse,
(KeyVaultBackupOperation) transformToLongRunningOperation(backupOperationResponse.getValue())));
} catch (HttpResponseException e) {
//noinspection ThrowableNotThrown
LOGGER.logExceptionAsError(e);
return new PollResponse<>(LongRunningOperationStatus.FAILED, null);
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private Function, String> backupFetchOperation() {
return (pollingContext) -> {
try {
return pollingContext.getLatestResponse().getValue().getAzureStorageBlobContainerUrl();
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private static PollResponse processBackupOperationResponse(
Response response) {
String operationStatus = response.getValue().getStatus().toLowerCase(Locale.US);
return new PollResponse<>(
toLongRunningOperationStatus(operationStatus.toLowerCase(Locale.US)), response.getValue());
}
/**
* Initiates a full restore of the Key Vault.
*
* Code Samples
* Starts a {@link KeyVaultRestoreOperation restore operation}, polls for its status and waits for it to
* complete. Prints out error details in case the operation fails.
*
*
* String blobStorageUrl = "https://myaccount.blob.core.windows.net/myContainer";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
*
* SyncPoller<KeyVaultBackupOperation, String> backupPoller = client.beginBackup(blobStorageUrl, sasToken);
*
* PollResponse<KeyVaultBackupOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultBackupOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* String folderUrl = backupPoller.getFinalResult();
*
* System.out.printf("Backup completed. The storage location of this backup is: %s.%n", folderUrl);
* } else {
* KeyVaultBackupOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Backup failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* @param folderUrl The URL for the Blob Storage resource where the backup is located, including the path to
* the blob container where the backup resides. This would be the exact value that is returned as the result of a
* backup operation. An example of such a URL may look like the following:
* https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
*
* @return A {@link SyncPoller} to poll on the {@link KeyVaultRestoreOperation restore operation} status.
*
* @throws KeyVaultAdministrationException If the given {@code folderUrl} or {@code sasToken} are invalid.
* @throws NullPointerException If the {@code folderUrl} is {@code null}.
*/
@ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
public SyncPoller beginRestore(String folderUrl, String sasToken) {
if (folderUrl == null) {
throw LOGGER.logExceptionAsError(
new NullPointerException(String.format(KeyVaultErrorCodeStrings.PARAMETER_REQUIRED, "'folderUrl'")));
}
Context context = Context.NONE;
return SyncPoller.createPoller(getDefaultPollingInterval(),
cxt -> new PollResponse<>(LongRunningOperationStatus.NOT_STARTED, restoreActivationOperation(folderUrl, sasToken, context).apply(cxt)),
restorePollOperation(context),
(pollingContext, firstResponse) -> {
throw LOGGER.logExceptionAsError(new RuntimeException("Cancellation is not supported"));
},
(pollingContext) -> new KeyVaultRestoreResult());
}
/**
* Initiates a full restore of the Key Vault.
*
* @param folderUrl The URL for the Blob Storage resource where the backup is located, including the path to
* the blob container where the backup resides. This would be the exact value that is returned as the result of a
* backup operation. An example of such a URL may look like the following:
* https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
* @param context Additional context that is passed through the HTTP pipeline during the service call.
*
* @return A {@link Response} containing the {@link KeyVaultRestoreOperation backup operation} status.
*
* @throws KeyVaultAdministrationException If the given {@code folderUrl} or {@code sasToken} are invalid.
*/
Response restoreWithResponse(String folderUrl, String sasToken, Context context) {
String[] segments = folderUrl.split("/");
String folderName = segments[segments.length - 1];
String containerUrl = folderUrl.substring(0, folderUrl.length() - folderName.length());
SASTokenParameter sasTokenParameter = new SASTokenParameter(containerUrl)
.setToken(sasToken)
.setUseManagedIdentity(sasToken == null);
RestoreOperationParameters restoreOperationParameters =
new RestoreOperationParameters(sasTokenParameter, folderName);
context = enableSyncRestProxy(context);
try {
ResponseBase restoreOperationResponse =
clientImpl.fullRestoreOperationWithResponse(vaultUrl, restoreOperationParameters, context);
return new SimpleResponse<>(restoreOperationResponse.getRequest(),
restoreOperationResponse.getStatusCode(),
restoreOperationResponse.getHeaders(),
(KeyVaultRestoreOperation) transformToLongRunningOperation(restoreOperationResponse.getValue()));
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
}
private Function, KeyVaultRestoreOperation> restoreActivationOperation(String folderUrl, String sasToken, Context context) {
return (pollingContext) -> {
try {
return restoreWithResponse(folderUrl, sasToken, context).getValue();
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private Function, PollResponse> restorePollOperation(Context context) {
return (pollingContext) -> {
try {
PollResponse pollResponse = pollingContext.getLatestResponse();
if (pollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED
|| pollResponse.getStatus() == LongRunningOperationStatus.FAILED) {
return pollResponse;
}
final KeyVaultRestoreOperation keyVaultRestoreOperation = pollResponse.getValue();
if (keyVaultRestoreOperation == null) {
LOGGER.warning("Restore operation does not exist. Activation operation failed.");
return new PollResponse<>(LongRunningOperationStatus.fromString("RESTORE_START_FAILED", true), null);
}
final String jobId = keyVaultRestoreOperation.getOperationId();
Context contextToUse = enableSyncRestProxy(context);
Response response = clientImpl.restoreStatusWithResponse(vaultUrl, jobId,
contextToUse);
return processRestoreOperationResponse(new SimpleResponse<>(response,
(KeyVaultRestoreOperation) transformToLongRunningOperation(response.getValue())));
} catch (HttpResponseException e) {
//noinspection ThrowableNotThrown
LOGGER.logExceptionAsError(e);
return new PollResponse<>(LongRunningOperationStatus.FAILED, null);
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private static PollResponse processRestoreOperationResponse(
Response response) {
String operationStatus = response.getValue().getStatus().toLowerCase(Locale.US);
return new PollResponse<>(
toLongRunningOperationStatus(operationStatus.toLowerCase(Locale.US)), response.getValue());
}
/**
* Restores all versions of a given key using the supplied SAS token pointing to a previously stored Azure Blob
* storage backup folder.
*
* Code Samples
* Starts a {@link KeyVaultSelectiveKeyRestoreOperation selective key restore operation}, polls for its status
* and waits for it to complete. Prints out error details in case the operation fails.
*
*
* String folderUrl = "https://myaccount.blob.core.windows.net/myContainer/mhsm-myaccount-2020090117323313";
* String sasToken = "sv=2020-02-10&ss=b&srt=o&sp=rwdlactfx&se=2021-06-17T07:13:07Z&st=2021-06-16T23:13:07Z"
* + "&spr=https&sig=n5V6fnlkViEF9b7ij%2FttTHNwO2BdFIHKHppRxGAyJdc%3D";
* String keyName = "myKey";
*
* SyncPoller<KeyVaultSelectiveKeyRestoreOperation, KeyVaultSelectiveKeyRestoreResult> backupPoller =
* client.beginSelectiveKeyRestore(folderUrl, sasToken, keyName);
*
* PollResponse<KeyVaultSelectiveKeyRestoreOperation> pollResponse = backupPoller.poll();
*
* System.out.printf("The current status of the operation is: %s.%n", pollResponse.getStatus());
*
* PollResponse<KeyVaultSelectiveKeyRestoreOperation> finalPollResponse = backupPoller.waitForCompletion();
*
* if (finalPollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED) {
* System.out.printf("Key restored successfully.%n");
* } else {
* KeyVaultSelectiveKeyRestoreOperation operation = backupPoller.poll().getValue();
*
* System.out.printf("Key restore failed with error: %s.%n", operation.getError().getMessage());
* }
*
*
*
* @param keyName The name of the key to be restored.
* @param folderUrl The URL for the Blob Storage resource where the backup is located, including the path to
* the blob container where the backup resides. This would be the exact value that is returned as the result of a
* backup operation. An example of such a URL may look like the following:
* https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
*
* @return A {@link SyncPoller} to poll on the {@link KeyVaultRestoreOperation restore operation} status.
*
* @throws KeyVaultAdministrationException If the given {@code folderUrl} or {@code sasToken} are invalid.
* @throws NullPointerException If the {@code keyName} or {@code folderUrl} are {@code null}.
*/
@ServiceMethod(returns = ReturnType.LONG_RUNNING_OPERATION)
public SyncPoller beginSelectiveKeyRestore(String keyName, String folderUrl, String sasToken) {
if (keyName == null) {
throw LOGGER.logExceptionAsError(
new NullPointerException(String.format(KeyVaultErrorCodeStrings.PARAMETER_REQUIRED, "'keyName'")));
}
if (folderUrl == null) {
throw LOGGER.logExceptionAsError(
new NullPointerException(String.format(KeyVaultErrorCodeStrings.PARAMETER_REQUIRED, "'folderUrl'")));
}
Context context = Context.NONE;
return SyncPoller.createPoller(getDefaultPollingInterval(),
cxt -> new PollResponse<>(LongRunningOperationStatus.NOT_STARTED, selectiveKeyRestoreActivationOperation(keyName, folderUrl, sasToken, context).apply(cxt)),
selectiveKeyRestorePollOperation(context),
(pollingContext, firstResponse) -> {
throw LOGGER.logExceptionAsError(new RuntimeException("Cancellation is not supported"));
},
(pollingContext) -> new KeyVaultSelectiveKeyRestoreResult());
}
/**
* Restores all versions of a given key using the supplied SAS token pointing to a previously stored Azure Blob
* storage backup folder.
*
* @param keyName The name of the key to be restored.
* @param folderUrl The URL for the Blob Storage resource where the backup is located, including the path to
* the blob container where the backup resides. This would be the exact value that is returned as the result of a
* backup operation. An example of such a URL may look like the following:
* https://contoso.blob.core.windows.net/backup/mhsm-contoso-2020090117323313.
* @param sasToken Optional Shared Access Signature (SAS) token to authorize access to the blob. If {@code null},
* Managed Identity will be used to authenticate instead.
* @param context Additional context that is passed through the HTTP pipeline during the service call.
*
* @return A {@link Response} containing the {@link KeyVaultSelectiveKeyRestoreOperation backup operation} status.
*/
Response selectiveKeyRestoreWithResponse(String keyName, String folderUrl,
String sasToken, Context context) {
String[] segments = folderUrl.split("/");
String folderName = segments[segments.length - 1];
String containerUrl = folderUrl.substring(0, folderUrl.length() - folderName.length());
SASTokenParameter sasTokenParameter = new SASTokenParameter(containerUrl)
.setToken(sasToken)
.setUseManagedIdentity(sasToken == null);
SelectiveKeyRestoreOperationParameters selectiveKeyRestoreOperationParameters =
new SelectiveKeyRestoreOperationParameters(sasTokenParameter, folderName);
context = enableSyncRestProxy(context);
try {
ResponseBase restoreOperationResponse =
clientImpl.selectiveKeyRestoreOperationWithResponse(vaultUrl, keyName,
selectiveKeyRestoreOperationParameters, context);
return new SimpleResponse<>(restoreOperationResponse.getRequest(),
restoreOperationResponse.getStatusCode(),
restoreOperationResponse.getHeaders(),
(KeyVaultSelectiveKeyRestoreOperation) transformToLongRunningOperation(
restoreOperationResponse.getValue()));
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
}
private Function, KeyVaultSelectiveKeyRestoreOperation> selectiveKeyRestoreActivationOperation(String keyName, String folderUrl, String sasToken, Context context) {
return (pollingContext) -> {
try {
return selectiveKeyRestoreWithResponse(keyName, folderUrl, sasToken, context).getValue();
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private Function, PollResponse> selectiveKeyRestorePollOperation(Context context) {
return (pollingContext) -> {
try {
PollResponse pollResponse = pollingContext.getLatestResponse();
if (pollResponse.getStatus() == LongRunningOperationStatus.SUCCESSFULLY_COMPLETED
|| pollResponse.getStatus() == LongRunningOperationStatus.FAILED) {
return pollResponse;
}
final KeyVaultSelectiveKeyRestoreOperation keyVaultSelectiveKeyRestoreOperation = pollResponse.getValue();
if (keyVaultSelectiveKeyRestoreOperation == null) {
LOGGER.warning("Restore operation does not exist. Activation operation failed.");
return new PollResponse<>(LongRunningOperationStatus.fromString("SELECTIVE_RESTORE_START_FAILED", true), null);
}
final String jobId = keyVaultSelectiveKeyRestoreOperation.getOperationId();
Context contextToUse = enableSyncRestProxy(context);
Response response = clientImpl.restoreStatusWithResponse(vaultUrl, jobId,
contextToUse);
return processSelectiveKeyRestoreOperationResponse(new SimpleResponse<>(response,
(KeyVaultSelectiveKeyRestoreOperation) restoreOperationToSelectiveKeyRestoreOperation(response.getValue())));
} catch (HttpResponseException e) {
//noinspection ThrowableNotThrown
LOGGER.logExceptionAsError(e);
return new PollResponse<>(LongRunningOperationStatus.FAILED, null);
} catch (RuntimeException e) {
throw LOGGER.logExceptionAsError(e);
}
};
}
private static PollResponse processSelectiveKeyRestoreOperationResponse(
Response response) {
String operationStatus = response.getValue().getStatus().toLowerCase(Locale.US);
return new PollResponse<>(
toLongRunningOperationStatus(operationStatus.toLowerCase(Locale.US)), response.getValue());
}
}