From ec65c91f2d1e1fca70e20af8ecf02c2619c792fd Mon Sep 17 00:00:00 2001 From: vcolin7 Date: Wed, 11 Nov 2020 11:29:40 -0800 Subject: [PATCH] Added support for key export. (#17183) * Added support for exporting keys from an Azure Key Vault. * Removed ExportKeyOptions. * Fixed build error. * Added samples. * Fixed test issues. * Fixed samples issues. * Fixed checkstyle issues. * Fixed spotbugs issues. * Applied PR feedback: renamed KeyReleasePolicy to ReleasePolicy and removed it from KeyVaultKey. * Fixed spotbugs issues. * Added unit tests. * Renamed ReleasePolicy to KeyReleasePolicy. Added tests for creating an RSA key with publicExponent. --- .../keyvault/keys/KeyAsyncClient.java | 109 +++++++++++++++++- .../security/keyvault/keys/KeyClient.java | 63 ++++++++++ .../keys/KeyExportRequestParameters.java | 39 +++++++ .../keys/KeyImportRequestParameters.java | 27 +++++ .../keyvault/keys/KeyRequestAttributes.java | 28 +++++ .../keyvault/keys/KeyRequestParameters.java | 53 +++++++++ .../security/keyvault/keys/KeyService.java | 11 ++ .../keys/models/CreateKeyOptions.java | 50 ++++++++ .../keys/models/CreateRsaKeyOptions.java | 25 ++++ .../keys/models/ImportKeyOptions.java | 24 ++++ .../keyvault/keys/models/KeyOperation.java | 5 + .../keyvault/keys/models/KeyProperties.java | 51 ++++++++ .../keys/models/KeyReleasePolicy.java | 66 +++++++++++ .../keyvault/keys/models/KeyVaultKey.java | 14 +++ .../KeyAsyncClientJavaDocCodeSnippets.java | 39 ++++++- .../keys/KeyClientJavaDocCodeSnippets.java | 27 +++++ .../keyvault/keys/KeyAsyncClientTest.java | 57 +++++++++ .../security/keyvault/keys/KeyClientTest.java | 49 ++++++++ .../keyvault/keys/KeyClientTestBase.java | 36 +++++- 19 files changed, 763 insertions(+), 10 deletions(-) create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyExportRequestParameters.java create mode 100644 sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyReleasePolicy.java diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyAsyncClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyAsyncClient.java index 0bc373bfa8e0e..01f2ce9a78e02 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyAsyncClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyAsyncClient.java @@ -213,7 +213,8 @@ Mono> createKeyWithResponse(CreateKeyOptions createKeyOpti KeyRequestParameters parameters = new KeyRequestParameters() .setKty(createKeyOptions.getKeyType()) .setKeyOps(createKeyOptions.getKeyOperations()) - .setKeyAttributes(new KeyRequestAttributes(createKeyOptions)); + .setKeyAttributes(new KeyRequestAttributes(createKeyOptions)) + .setReleasePolicy(createKeyOptions.getReleasePolicy()); return service.createKey(vaultUrl, createKeyOptions.getName(), apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Creating key - {}", createKeyOptions.getName())) @@ -293,7 +294,9 @@ Mono> createRsaKeyWithResponse(CreateRsaKeyOptions createR .setKty(createRsaKeyOptions.getKeyType()) .setKeySize(createRsaKeyOptions.getKeySize()) .setKeyOps(createRsaKeyOptions.getKeyOperations()) - .setKeyAttributes(new KeyRequestAttributes(createRsaKeyOptions)); + .setKeyAttributes(new KeyRequestAttributes(createRsaKeyOptions)) + .setReleasePolicy(createRsaKeyOptions.getReleasePolicy()) + .setPublicExponent(createRsaKeyOptions.getPublicExponent()); return service.createKey(vaultUrl, createRsaKeyOptions.getName(), apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Creating Rsa key - {}", createRsaKeyOptions.getName())) @@ -379,7 +382,8 @@ Mono> createEcKeyWithResponse(CreateEcKeyOptions createEcK .setKty(createEcKeyOptions.getKeyType()) .setCurve(createEcKeyOptions.getCurveName()) .setKeyOps(createEcKeyOptions.getKeyOperations()) - .setKeyAttributes(new KeyRequestAttributes(createEcKeyOptions)); + .setKeyAttributes(new KeyRequestAttributes(createEcKeyOptions)) + .setReleasePolicy(createEcKeyOptions.getReleasePolicy()); return service.createKey(vaultUrl, createEcKeyOptions.getName(), apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Creating Ec key - {}", createEcKeyOptions.getName())) @@ -492,7 +496,8 @@ Mono> importKeyWithResponse(ImportKeyOptions importKeyOpti KeyImportRequestParameters parameters = new KeyImportRequestParameters() .setKey(importKeyOptions.getKey()) .setHsm(importKeyOptions.isHardwareProtected()) - .setKeyAttributes(new KeyRequestAttributes(importKeyOptions)); + .setKeyAttributes(new KeyRequestAttributes(importKeyOptions)) + .setReleasePolicy(importKeyOptions.getReleasePolicy()); return service.importKey(vaultUrl, importKeyOptions.getName(), apiVersion, ACCEPT_LANGUAGE, parameters, CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) .doOnRequest(ignored -> logger.info("Importing key - {}", importKeyOptions.getName())) @@ -500,6 +505,99 @@ Mono> importKeyWithResponse(ImportKeyOptions importKeyOpti .doOnError(error -> logger.warning("Failed to import key - {}", importKeyOptions.getName(), error)); } + /** + * Exports the latest version of a key from the key vault. The export key operation may be used to import any key + * from the Azure Key Vault as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String} + * + * @param name The name of the key to be exported. + * @param environment The target environment assertion. + * @return A {@link Mono} containing the {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name} or {@code environment} are {@code null}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono exportKey(String name, String environment) { + try { + return exportKeyWithResponse(name, "", environment).flatMap(FluxUtil::toMono); + } catch (RuntimeException ex) { + return monoError(logger, ex); + } + } + + /** + * Exports a key from the key vault. The export key operation may be used to import any key from the Azure Key Vault + * as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String-String} + * + * @param name The name of the key to be exported. + * @param version The key version. + * @param environment The target environment assertion. + * @return A {@link Mono} containing the {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name}, {@code version} or {@code environment} are + * {@code null}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono exportKey(String name, String version, String environment) { + try { + return exportKeyWithResponse(name, version, environment).flatMap(FluxUtil::toMono); + } catch (RuntimeException ex) { + return monoError(logger, ex); + } + } + + /** + * Exports a key from the key vault. The export key operation may be used to import any key from the Azure Key Vault + * as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyasyncclient.exportKeyWithResponse#String-String-String} + * + * @param name The name of the key to be exported. + * @param version The key version. + * @param environment The target environment assertion. + * @return A {@link Mono} containing a {@link Response} whose {@link Response#getValue() value} contains the + * {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name}, {@code version} or {@code environment} are + * {@code null}. + */ + @ServiceMethod(returns = ReturnType.SINGLE) + public Mono> exportKeyWithResponse(String name, String version, String environment) { + try { + return withContext(context -> exportKeyWithResponse(name, version, environment, context)); + } catch (RuntimeException ex) { + return monoError(logger, ex); + } + } + + Mono> exportKeyWithResponse(String name, String version, String environment, + Context context) { + Objects.requireNonNull(name, "The key name cannot be null."); + Objects.requireNonNull(version, "The key version cannot be null."); + Objects.requireNonNull(environment, "The environment parameter cannot be null."); + + context = context == null ? Context.NONE : context; + KeyExportRequestParameters parameters = new KeyExportRequestParameters().setEnvironment(environment); + + return service.exportKey(vaultUrl, name, version, apiVersion, ACCEPT_LANGUAGE, parameters, + CONTENT_TYPE_HEADER_VALUE, context.addData(AZ_TRACING_NAMESPACE_KEY, KEYVAULT_TRACING_NAMESPACE_VALUE)) + .doOnRequest(ignored -> logger.info("Exporting key - {}", name)) + .doOnSuccess(response -> logger.info("Exported key - {}", response.getValue().getName())) + .doOnError(error -> logger.warning("Failed to export key - {}", name, error)); + } + /** * Gets the public part of the specified key and key version. The get key operation is applicable to all key types * and it requires the {@code keys/get} permission. @@ -659,7 +757,8 @@ Mono> updateKeyPropertiesWithResponse(KeyProperties keyPro context = context == null ? Context.NONE : context; KeyRequestParameters parameters = new KeyRequestParameters() .setTags(keyProperties.getTags()) - .setKeyAttributes(new KeyRequestAttributes(keyProperties)); + .setKeyAttributes(new KeyRequestAttributes(keyProperties)) + .setReleasePolicy(keyProperties.getReleasePolicy()); if (keyOperations.length > 0) { parameters.setKeyOps(Arrays.asList(keyOperations)); } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyClient.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyClient.java index e9cfc25064232..7e62798f4bfe5 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyClient.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyClient.java @@ -319,6 +319,69 @@ public Response importKeyWithResponse(ImportKeyOptions importKeyOpt return client.importKeyWithResponse(importKeyOptions, context).block(); } + /** + * Exports the latest version of a key from the key vault. The export key operation may be used to import any key + * from the Azure Key Vault as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyclient.exportKey#String-String} + * + * @param name The name of the key to be exported. + * @param environment The target environment assertion. + * @return The {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name} or {@code environment} are {@code null}. + */ + public KeyVaultKey exportKey(String name, String environment) { + return client.exportKey(name, environment).block(); + } + + /** + * Exports a key from the key vault. The export key operation may be used to import any key from the Azure Key Vault + * as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyclient.exportKey#String-String-String} + * + * @param name The name of the key to be exported. + * @param version The key version. + * @param environment The target environment assertion. + * @return The {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name}, {@code version} or {@code environment} are + * {@code null}. + */ + public KeyVaultKey exportKey(String name, String version, String environment) { + return client.exportKey(name, version, environment).block(); + } + + /** + * Exports a key from the key vault. The export key operation may be used to import any key from the Azure Key Vault + * as long as it is marked as exportable and its release policy is satisfied. + * + *

Code Samples

+ *

Exports a key from a key vault. Subscribes to the call asynchronously and prints out the newly exported key + * details when a response has been received.

+ * + * {@codesnippet com.azure.security.keyvault.keys.keyclient.exportKeyWithResponse#String-String-String-Context} + * + * @param name The name of the key to be exported. + * @param version The key version. + * @param environment The target environment assertion. + * @param context Additional context that is passed through the HTTP pipeline during the service call. + * @return A {@link Response} whose {@link Response#getValue() value} contains the {@link KeyVaultKey exported key}. + * @throws NullPointerException If the specified {@code name}, {@code version} or {@code environment} are + * {@code null}. + */ + public Response exportKeyWithResponse(String name, String version, String environment, + Context context) { + return client.exportKeyWithResponse(name, version, environment, context).block(); + } + /** * Gets the public part of the specified key and key version. The get key operation is applicable to all key types * and it requires the {@code keys/get} permission. diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyExportRequestParameters.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyExportRequestParameters.java new file mode 100644 index 0000000000000..7ccd37f6de0de --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyExportRequestParameters.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys; + +import com.azure.core.annotation.Fluent; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The parameters for the key export operation. + */ +@Fluent +class KeyExportRequestParameters { + /** + * The target environment assertion. + */ + @JsonProperty(value = "env") + private String environment; + + /** + * Get the target environment assertion. + * + * @return The environment. + */ + public String getEnvironment() { + return this.environment; + } + + /** + * Set the target environment assertion. + * + * @param environment The environment value to set. + * @return The updated {@link KeyExportRequestParameters} object. + */ + public KeyExportRequestParameters setEnvironment(String environment) { + this.environment = environment; + return this; + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyImportRequestParameters.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyImportRequestParameters.java index 64b0285c3cf71..46b6a56e32dfd 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyImportRequestParameters.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyImportRequestParameters.java @@ -5,6 +5,7 @@ import com.azure.core.annotation.Fluent; import com.azure.security.keyvault.keys.models.JsonWebKey; +import com.azure.security.keyvault.keys.models.KeyReleasePolicy; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Map; @@ -36,6 +37,12 @@ class KeyImportRequestParameters { @JsonProperty(value = "tags") private Map tags; + /** + * The policy rules under which the key can be exported. + */ + @JsonProperty(value = "release_policy") + private KeyReleasePolicy releasePolicy; + /** * Get the keyAttributes value. * @@ -115,4 +122,24 @@ public KeyImportRequestParameters setKey(JsonWebKey key) { this.key = key; return this; } + + /** + * Get the policy rules under which the key can be exported. + * + * @return The release policy. + */ + public KeyReleasePolicy getReleasePolicy() { + return releasePolicy; + } + + /** + * Set the policy rules under which the key can be exported. + * + * @param releasePolicy The release policy to set. + * @return The updated {@link KeyImportRequestParameters} object. + */ + public KeyImportRequestParameters setReleasePolicy(KeyReleasePolicy releasePolicy) { + this.releasePolicy = releasePolicy; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestAttributes.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestAttributes.java index 45bd4de2605a2..1e0a736de8076 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestAttributes.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestAttributes.java @@ -26,6 +26,7 @@ class KeyRequestAttributes { this.expires = keyProperties.getExpiresOn().toEpochSecond(); } this.enabled = keyProperties.isEnabled(); + this.exportable = keyProperties.isExportable(); } /** @@ -42,6 +43,7 @@ class KeyRequestAttributes { this.expires = keyOptions.getExpiresOn().toEpochSecond(); } this.enabled = keyOptions.isEnabled(); + this.exportable = keyOptions.isExportable(); } /** @@ -74,6 +76,12 @@ class KeyRequestAttributes { @JsonProperty(value = "updated", access = JsonProperty.Access.WRITE_ONLY) private Long updated; + /** + * Indicates if the private key can be exported. + */ + @JsonProperty(value = "exportable") + private Boolean exportable; + /** * Get the enabled value. * @@ -171,4 +179,24 @@ public OffsetDateTime getUpdated() { } return OffsetDateTime.ofInstant(Instant.ofEpochMilli(this.updated * 1000L), ZoneOffset.UTC); } + + /** + * Indicates if the private key can be exported. + * + * @return The exportable value. + */ + public Boolean isExportable() { + return this.exportable; + } + + /** + * Set a value that indicates if the private key can be exported. + * + * @param exportable The exportable value to set. + * @return The updated {@link KeyRequestAttributes} object. + */ + public KeyRequestAttributes setExportable(Boolean exportable) { + this.exportable = exportable; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestParameters.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestParameters.java index 1c53bd421ed55..aa787b5218d67 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestParameters.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyRequestParameters.java @@ -6,6 +6,7 @@ import com.azure.core.annotation.Fluent; import com.azure.security.keyvault.keys.models.KeyCurveName; import com.azure.security.keyvault.keys.models.KeyOperation; +import com.azure.security.keyvault.keys.models.KeyReleasePolicy; import com.azure.security.keyvault.keys.models.KeyType; import com.fasterxml.jackson.annotation.JsonProperty; @@ -52,6 +53,18 @@ class KeyRequestParameters { @JsonProperty(value = "crv") private KeyCurveName curve; + /** + * The policy rules under which the key can be exported. + */ + @JsonProperty(value = "release_policy") + private KeyReleasePolicy releasePolicy; + + /** + * The public exponent for an RSA key. + */ + @JsonProperty(value = "public_exponent") + private int publicExponent; + /** * Get the keyType value. * @@ -171,4 +184,44 @@ public KeyRequestParameters setCurve(KeyCurveName curve) { this.curve = curve; return this; } + + /** + * Get the policy rules under which the key can be exported. + * + * @return The release policy. + */ + public KeyReleasePolicy getReleasePolicy() { + return releasePolicy; + } + + /** + * Set the policy rules under which the key can be exported. + * + * @param releasePolicy The release policy to set. + * @return The updated {@link KeyRequestParameters} object. + */ + public KeyRequestParameters setReleasePolicy(KeyReleasePolicy releasePolicy) { + this.releasePolicy = releasePolicy; + return this; + } + + /** + * Get the public exponent for the key. + * + * @return The public exponent. + */ + public int getPublicExponent() { + return publicExponent; + } + + /** + * Set the public exponent for the key. + * + * @param publicExponent The public exponent to set. + * @return The updated {@link KeyRequestParameters} object. + */ + public KeyRequestParameters setPublicExponent(int publicExponent) { + this.publicExponent = publicExponent; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyService.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyService.java index c87d0b3b781a9..4c6f3db7b07a4 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyService.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/KeyService.java @@ -89,6 +89,17 @@ Mono> importKey(@HostParam("url") String url, @HeaderParam("Content-Type") String type, Context context); + @Post("keys/{key-name}/{key-version}/export") + @ExpectedResponses({200}) + @UnexpectedResponseExceptionType(HttpResponseException.class) + Mono> exportKey(@HostParam("url") String url, + @PathParam("key-name") String keyName, + @PathParam("key-version") String keyVersion, + @QueryParam("api-version") String apiVersion, + @HeaderParam("accept-language") String acceptLanguage, + @BodyParam("application/json") KeyExportRequestParameters parameters, + @HeaderParam("Content-Type") String type, + Context context); @Delete("keys/{key-name}") @ExpectedResponses({200}) diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateKeyOptions.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateKeyOptions.java index 6ef9e52226e43..072fdd8e41365 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateKeyOptions.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateKeyOptions.java @@ -50,6 +50,16 @@ public class CreateKeyOptions { */ private Boolean enabled; + /** + * Indicates if the private key can be exported. + */ + private Boolean exportable; + + /** + * The policy rules under which the key can be exported. + */ + private KeyReleasePolicy releasePolicy; + /** * Creates instance of KeyCreateOptions with {@code name} as key name and {@code keyType} as type of the key. * @param name The name of the key to create. @@ -173,6 +183,46 @@ public Boolean isEnabled() { return this.enabled; } + /** + * Indicates if the private key can be exported. + * + * @return The exportable value. + */ + public Boolean isExportable() { + return this.exportable; + } + + /** + * Set a value that indicates if the private key can be exported. + * + * @param exportable The exportable value to set. + * @return The updated {@link CreateKeyOptions} object. + */ + public CreateKeyOptions setExportable(Boolean exportable) { + this.exportable = exportable; + return this; + } + + /** + * Get the policy rules under which the key can be exported. + * + * @return The release policy. + */ + public KeyReleasePolicy getReleasePolicy() { + return releasePolicy; + } + + /** + * Set the policy rules under which the key can be exported. + * + * @param releasePolicy The release policy to set. + * @return The updated {@link CreateKeyOptions} object. + */ + public CreateKeyOptions setReleasePolicy(KeyReleasePolicy releasePolicy) { + this.releasePolicy = releasePolicy; + return this; + } + /** * Get the key name. * diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateRsaKeyOptions.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateRsaKeyOptions.java index d563c796a6c84..1990e0b5fb513 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateRsaKeyOptions.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/CreateRsaKeyOptions.java @@ -24,6 +24,11 @@ public class CreateRsaKeyOptions extends CreateKeyOptions { */ private boolean hardwareProtected; + /** + * The public exponent for the key. + */ + private int publicExponent; + /** * Creates a RsaKeyCreateOptions with {@code name} as name of the Rsa key. * @param name The name of the key. @@ -130,4 +135,24 @@ public CreateRsaKeyOptions setHardwareProtected(Boolean hardwareProtected) { public Boolean isHardwareProtected() { return this.hardwareProtected; } + + /** + * Get the public exponent for the key. + * + * @return The public exponent. + */ + public int getPublicExponent() { + return publicExponent; + } + + /** + * Set the public exponent for the key. + * + * @param publicExponent The public exponent to set. + * @return The updated {@link CreateRsaKeyOptions} object. + */ + public CreateRsaKeyOptions setPublicExponent(int publicExponent) { + this.publicExponent = publicExponent; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/ImportKeyOptions.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/ImportKeyOptions.java index a20f155db4275..bca96205259d7 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/ImportKeyOptions.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/ImportKeyOptions.java @@ -95,4 +95,28 @@ public ImportKeyOptions setNotBefore(OffsetDateTime notBefore) { this.notBefore = notBefore; return this; } + + /** + * Set a value that indicates if the private key can be exported. + * + * @param exportable The exportable value to set. + * @return The updated {@link ImportKeyOptions} object. + */ + @Override + public ImportKeyOptions setExportable(Boolean exportable) { + this.exportable = exportable; + return this; + } + + /** + * Set the policy rules under which the key can be exported. + * + * @param releasePolicy The release policy to set. + * @return The updated {@link ImportKeyOptions} object. + */ + @Override + public ImportKeyOptions setReleasePolicy(KeyReleasePolicy releasePolicy) { + this.releasePolicy = releasePolicy; + return this; + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyOperation.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyOperation.java index 1cc663ea4c93b..3669b029285bb 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyOperation.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyOperation.java @@ -49,6 +49,11 @@ public final class KeyOperation extends ExpandableStringEnum { */ public static final KeyOperation IMPORT = fromString("import"); + /** + * Static value Export for KeyOperation. + */ + public static final KeyOperation EXPORT = fromString("export"); + /** * Creates or finds a KeyOperation from its string representation. * diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyProperties.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyProperties.java index 9c2a587fc9f77..d4648fb81ebd4 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyProperties.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyProperties.java @@ -98,6 +98,17 @@ public class KeyProperties { @JsonProperty(value = "recoverableDays", access = JsonProperty.Access.WRITE_ONLY) private Integer recoverableDays; + /** + * Indicates if the private key can be exported. + */ + @JsonProperty(value = "exportable") + Boolean exportable; + + /** + * The policy rules under which the key can be exported. + */ + KeyReleasePolicy releasePolicy; + /** * Gets the number of days a key is retained before being deleted for a soft delete-enabled Key Vault. * @return the recoverable days. @@ -251,6 +262,46 @@ public String getVersion() { return this.version; } + /** + * Indicates if the private key can be exported. + * + * @return The exportable value. + */ + public Boolean isExportable() { + return this.exportable; + } + + /** + * Set a value that indicates if the private key can be exported. + * + * @param exportable The exportable value to set. + * @return The updated {@link KeyProperties} object. + */ + public KeyProperties setExportable(Boolean exportable) { + this.exportable = exportable; + return this; + } + + /** + * Get the policy rules under which the key can be exported. + * + * @return The release policy. + */ + public KeyReleasePolicy getReleasePolicy() { + return releasePolicy; + } + + /** + * Set the policy rules under which the key can be exported. + * + * @param releasePolicy The release policy to set. + * @return The updated {@link KeyProperties} object. + */ + public KeyProperties setReleasePolicy(KeyReleasePolicy releasePolicy) { + this.releasePolicy = releasePolicy; + return this; + } + /** * Unpacks the attributes JSON response and updates the variables in the Key Attributes object. Uses Lazy Update to * set values for variables id, contentType, and id as these variables are part of main JSON body and not attributes diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyReleasePolicy.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyReleasePolicy.java new file mode 100644 index 0000000000000..046f7ba374e9e --- /dev/null +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyReleasePolicy.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.security.keyvault.keys.models; + +import com.azure.core.annotation.Fluent; +import com.azure.core.util.Base64Url; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Class that contains the policy rules under which the key can be exported. + */ +@Fluent +public class KeyReleasePolicy { + /** + * Content type and version of key release policy. + */ + @JsonProperty(value = "contentType") + private String contentType; + + /** + * Blob encoding the policy rules under which the key can be exported. + */ + @JsonProperty(value = "data") + private Base64Url data; + + /** + * Get the content type of the release policy. + * + * @return The content type. + */ + public String getContentType() { + return contentType; + } + + /** + * Set the content type of the release policy. + * + * @param contentType The content type to set. + * @return The updated {@link KeyReleasePolicy} object. + */ + public KeyReleasePolicy setContentType(String contentType) { + this.contentType = contentType; + return this; + } + + /** + * Set the blob encoding the policy rules under which the key can be exported. + * + * @param data Blob encoding the policy rules under which the key can be exported. + * @return The updated {@link KeyReleasePolicy} object. + */ + public KeyReleasePolicy setData(byte[] data) { + this.data = Base64Url.encode(data); + return this; + } + + /** + * Get the policy rules under which the key can be exported. + * + * @return The policy rules represented by a blob. + */ + public byte[] getData() { + return this.data == null ? null : this.data.decodedBytes(); + } +} diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyVaultKey.java b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyVaultKey.java index 5e94d450707b5..1abdb2568df4c 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyVaultKey.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/models/KeyVaultKey.java @@ -97,6 +97,15 @@ public List getKeyOperations() { return key.getKeyOps(); } + /** + * Get the policy rules under which the key can be exported. + * + * @return The release policy. + */ + public KeyReleasePolicy getReleasePolicy() { + return properties.getReleasePolicy(); + } + /** * Unpacks the key material json response and updates the variables in the Key Base object. * @param key The key value mapping of the key material @@ -121,4 +130,9 @@ private void setTags(Map tags) { private void setManaged(boolean managed) { properties.setManaged(managed); } + + @JsonProperty(value = "release_policy") + private void setReleasePolicy(KeyReleasePolicy releasePolicy) { + properties.setReleasePolicy(releasePolicy); + } } diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyAsyncClientJavaDocCodeSnippets.java b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyAsyncClientJavaDocCodeSnippets.java index 84389cd3f3aeb..6e9d998ddfd31 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyAsyncClientJavaDocCodeSnippets.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyAsyncClientJavaDocCodeSnippets.java @@ -11,16 +11,17 @@ import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.http.policy.RetryPolicy; import com.azure.security.keyvault.keys.implementation.KeyVaultCredentialPolicy; +import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.security.keyvault.keys.models.CreateEcKeyOptions; import com.azure.security.keyvault.keys.models.CreateKeyOptions; import com.azure.security.keyvault.keys.models.CreateRsaKeyOptions; +import com.azure.security.keyvault.keys.models.ImportKeyOptions; +import com.azure.security.keyvault.keys.models.JsonWebKey; import com.azure.security.keyvault.keys.models.KeyCurveName; import com.azure.security.keyvault.keys.models.KeyOperation; -import com.azure.security.keyvault.keys.models.KeyType; import com.azure.security.keyvault.keys.models.KeyProperties; -import com.azure.security.keyvault.keys.models.ImportKeyOptions; -import com.azure.security.keyvault.keys.models.JsonWebKey; -import com.azure.identity.DefaultAzureCredentialBuilder; +import com.azure.security.keyvault.keys.models.KeyType; +import com.azure.security.keyvault.keys.models.KeyVaultKey; import reactor.util.context.Context; import java.time.Duration; @@ -185,6 +186,36 @@ public void importKeySnippets() { // END: com.azure.security.keyvault.keys.keyasyncclient.importKeyWithResponse#options-response } + /** + * Generates code samples for using {@link KeyAsyncClient#exportKey(String, String)}, + * {@link KeyAsyncClient#exportKey(String, String, String)} and + * {@link KeyAsyncClient#exportKeyWithResponse(String, String, String)} + */ + public void exportKeySnippets() { + KeyAsyncClient keyAsyncClient = createAsyncClient(); + + // BEGIN: com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String + keyAsyncClient.exportKey("keyName", "environment").subscribe(exportedKey -> + System.out.printf("Key was exported with name: %s and id: %s. \n", exportedKey.getName(), + exportedKey.getId())); + // END: com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String + + // BEGIN: com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String-String + keyAsyncClient.exportKey("keyName", "version", "environment").subscribe(exportedKey -> + System.out.printf("Key was exported with name: %s and id: %s. \n", exportedKey.getName(), + exportedKey.getId())); + // END: com.azure.security.keyvault.keys.keyasyncclient.exportKey#String-String-String + + // BEGIN: com.azure.security.keyvault.keys.keyasyncclient.exportKeyWithResponse#String-String-String + keyAsyncClient.exportKeyWithResponse("keyName", "version", "environment") + .subscribe(exportKeyResponse -> { + KeyVaultKey exportedKey = exportKeyResponse.getValue(); + System.out.printf("Key was exported with name: %s and id: %s. \n", exportedKey.getName(), + exportedKey.getId()); + }); + // END: com.azure.security.keyvault.keys.keyasyncclient.exportKeyWithResponse#String-String-String + } + /** * Generates a code sample for using {@link KeyAsyncClient#getDeletedKey(String)} */ diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyClientJavaDocCodeSnippets.java b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyClientJavaDocCodeSnippets.java index f3555fa803ebf..3b2dd0346bf1a 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyClientJavaDocCodeSnippets.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/samples/java/com/azure/security/keyvault/keys/KeyClientJavaDocCodeSnippets.java @@ -116,6 +116,33 @@ public void importKeySnippets() { // END: com.azure.security.keyvault.keys.keyclient.importKeyWithResponse#options-response } + /** + * Generates code samples for using {@link KeyClient#exportKey(String, String)}, + * {@link KeyClient#exportKey(String, String, String)} and + * {@link KeyClient#exportKeyWithResponse(String, String, String, Context)} + */ + public void exportKeySnippets() { + KeyClient keyClient = createClient(); + + // BEGIN: com.azure.security.keyvault.keys.keyclient.exportKey#String-String + KeyVaultKey exportedKey = keyClient.exportKey("keyName", "environment"); + System.out.printf("Key was exported with name: %s and id: %s. \n", exportedKey.getName(), exportedKey.getId()); + // END: com.azure.security.keyvault.keys.keyclient.exportKey#String-String + + // BEGIN: com.azure.security.keyvault.keys.keyclient.exportKey#String-String-String + KeyVaultKey exportKey = keyClient.exportKey("keyName", "version", "environment"); + System.out.printf("Key was exported with name: %s and id: %s. \n", exportKey.getName(), + exportKey.getId()); + // END: com.azure.security.keyvault.keys.keyclient.exportKey#String-String-String + + // BEGIN: com.azure.security.keyvault.keys.keyclient.exportKeyWithResponse#String-String-String-Context + KeyVaultKey exportedKeyFromResponse = keyClient.exportKeyWithResponse("keyName", "version", "environment", + new Context(key1, value1)).getValue(); + System.out.printf("Key was exported with name: %s and id: %s. \n", exportedKeyFromResponse.getName(), + exportedKeyFromResponse.getId()); + // END: com.azure.security.keyvault.keys.keyclient.exportKeyWithResponse#String-String-String-Context + } + /** * Generates a code sample for using {@link KeyClient#beginDeleteKey(String)} and * {@link KeyClient#beginDeleteKey(String, Duration)}. diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyAsyncClientTest.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyAsyncClientTest.java index 1768b397d11a0..ef1d3792c6779 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyAsyncClientTest.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyAsyncClientTest.java @@ -15,11 +15,13 @@ import com.azure.security.keyvault.keys.models.KeyProperties; import com.azure.security.keyvault.keys.models.KeyType; import com.azure.security.keyvault.keys.models.KeyVaultKey; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import reactor.test.StepVerifier; import java.net.HttpURLConnection; +import java.nio.ByteBuffer; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -494,6 +496,61 @@ public void listKeys(HttpClient httpClient, KeyServiceVersion serviceVersion) { }); } + /** + * Tests that an RSA key with a public exponent can be created in the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void createRsaKeyWithPublicExponent(HttpClient httpClient, KeyServiceVersion serviceVersion) { + createKeyAsyncClient(httpClient, serviceVersion); + createRsaKeyWithPublicExponentRunner((createRsaKeyOptions) -> + StepVerifier.create(client.createRsaKey(createRsaKeyOptions)) + .assertNext(rsaKey -> assertKeyEquals(createRsaKeyOptions, rsaKey)) + .assertNext(rsaKey -> { + ByteBuffer wrappedArray = ByteBuffer.wrap(rsaKey.getKey().getE()); // Big-endian by default + assertEquals(createRsaKeyOptions.getPublicExponent(), wrappedArray.getInt()); + }) + .verifyComplete()); + } + + /** + * Tests that a key can be exported from the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void exportKey(HttpClient httpClient, KeyServiceVersion serviceVersion) { + createKeyAsyncClient(httpClient, serviceVersion); + exportKeyRunner((createKeyOptions) -> { + StepVerifier.create(client.createKey(createKeyOptions)) + .assertNext(response -> assertKeyEquals(createKeyOptions, response)) + .verifyComplete(); + + StepVerifier.create(client.exportKey(createKeyOptions.getName(), "testEnvironment")) + .assertNext(response -> assertKeyEquals(createKeyOptions, response)) + .verifyComplete(); + }); + } + + /** + * Tests that a specific key version can be exported from the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void exportKeyVersion(HttpClient httpClient, KeyServiceVersion serviceVersion) { + createKeyAsyncClient(httpClient, serviceVersion); + exportKeyRunner((createKeyOptions) -> { + StepVerifier.create(client.createKey(createKeyOptions)) + .assertNext(response -> assertKeyEquals(createKeyOptions, response)) + .consumeNextWith(originalKey -> client.exportKey(createKeyOptions.getName(), + originalKey.getProperties().getVersion(), "testEnvironment")) + .assertNext(response -> assertKeyEquals(createKeyOptions, response)) + .verifyComplete(); + }); + } + private void pollOnKeyDeletion(String keyName) { int pendingPollCount = 0; while (pendingPollCount < 30) { diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTest.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTest.java index 28e3e82ca27e3..0d47173c46963 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTest.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTest.java @@ -14,10 +14,12 @@ import com.azure.security.keyvault.keys.models.KeyProperties; import com.azure.security.keyvault.keys.models.KeyType; import com.azure.security.keyvault.keys.models.KeyVaultKey; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import java.net.HttpURLConnection; +import java.nio.ByteBuffer; import java.time.Duration; import java.util.ArrayList; import java.util.HashMap; @@ -438,6 +440,53 @@ public void listKeyVersions(HttpClient httpClient, KeyServiceVersion serviceVers }); } + /** + * Tests that an RSA key with a public exponent can be created in the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void createRsaKeyWithPublicExponent(HttpClient httpClient, KeyServiceVersion serviceVersion) { + getKeyClient(httpClient, serviceVersion); + createRsaKeyWithPublicExponentRunner((createRsaKeyOptions) -> { + KeyVaultKey rsaKey = client.createRsaKey(createRsaKeyOptions); + assertKeyEquals(createRsaKeyOptions, rsaKey); + ByteBuffer wrappedArray = ByteBuffer.wrap(rsaKey.getKey().getE()); // Big-endian by default + assertEquals(createRsaKeyOptions.getPublicExponent(), wrappedArray.getInt()); + }); + } + + /** + * Tests that a key can be exported from the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void exportKey(HttpClient httpClient, KeyServiceVersion serviceVersion) { + getKeyClient(httpClient, serviceVersion); + exportKeyRunner((createKeyOptions) -> { + client.createKey(createKeyOptions); + KeyVaultKey exportedKey = client.exportKey(createKeyOptions.getName(), "testEnvironment"); + assertKeyEquals(createKeyOptions, exportedKey); + }); + } + + /** + * Tests that a specific key version can be exported from the key vault. + */ + @Disabled // Service issue: https://github.com/Azure/azure-sdk-for-java/issues/17382 + @ParameterizedTest(name = DISPLAY_NAME_WITH_ARGUMENTS) + @MethodSource("getTestParameters") + public void exportKeyVersion(HttpClient httpClient, KeyServiceVersion serviceVersion) { + getKeyClient(httpClient, serviceVersion); + exportKeyRunner((createKeyOptions) -> { + KeyVaultKey originalKey = client.createKey(createKeyOptions); + KeyVaultKey exportedKey = + client.exportKey(originalKey.getName(), originalKey.getProperties().getVersion(), "testEnvironment"); + assertKeyEquals(createKeyOptions, exportedKey); + }); + } + private DeletedKey pollOnKeyPurge(String keyName) { int pendingPollCount = 0; while (pendingPollCount < 10) { diff --git a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTestBase.java b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTestBase.java index 0fde7356781a4..39c9afd6ae1bc 100644 --- a/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTestBase.java +++ b/sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyClientTestBase.java @@ -30,12 +30,19 @@ import com.azure.security.keyvault.keys.models.KeyVaultKey; import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; import java.util.stream.Stream; + import org.junit.jupiter.api.Test; import java.time.OffsetDateTime; import java.time.ZoneOffset; -import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.junit.jupiter.params.provider.Arguments; @@ -318,6 +325,33 @@ void listDeletedKeysRunner(Consumer> testRunne testRunner.accept(keys); } + @Test + public abstract void createRsaKeyWithPublicExponent(HttpClient httpClient, KeyServiceVersion keyServiceVersion); + + void createRsaKeyWithPublicExponentRunner(Consumer testRunner) { + final Map tags = new HashMap<>(); + + tags.put("foo", "baz"); + + final CreateRsaKeyOptions keyOptions = new CreateRsaKeyOptions(generateResourceId("testRsaKey")) + .setExpiresOn(OffsetDateTime.of(2050, 1, 30, 0, 0, 0, 0, ZoneOffset.UTC)) + .setNotBefore(OffsetDateTime.of(2000, 1, 30, 12, 59, 59, 0, ZoneOffset.UTC)) + .setTags(tags) + .setPublicExponent(3); + + testRunner.accept(keyOptions); + } + + @Test + public abstract void exportKey(HttpClient httpClient, KeyServiceVersion keyServiceVersion); + + void exportKeyRunner(Consumer testRunner) { + CreateKeyOptions createKeyOptions = new CreateKeyOptions(generateResourceId(KEY_NAME), KeyType.RSA) + .setExportable(true); + + testRunner.accept(createKeyOptions); + } + String generateResourceId(String suffix) { if (interceptorManager.isPlaybackMode()) { return suffix;