Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Key Rotation. #24452

Merged
merged 8 commits into from
Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,23 @@
* <p> The minimal configuration options required by {@link KeyClientBuilder} to build {@link KeyAsyncClient} are
* {@link String vaultUrl} and {@link TokenCredential credential}. </p>
*
* {@codesnippet com.azure.security.keyvault.keys.async.keyclient.instantiation}
* {@codesnippet com.azure.security.keyvault.keys.KeyAsyncClient.instantiation}
*
* <p>The {@link HttpLogDetailLevel log detail level}, multiple custom {@link HttpLoggingPolicy policies} and custom
* {@link HttpClient http client} can be optionally configured in the {@link KeyClientBuilder}.</p>
*
* {@codesnippet com.azure.security.keyvault.keys.async.keyclient.withhttpclient.instantiation}
* {@codesnippet com.azure.security.keyvault.keys.KeyAsyncClient.instantiation.withHttpClient}
*
* <p>Alternatively, custom {@link HttpPipeline http pipeline} with custom {@link HttpPipelinePolicy} policies and
* {@link String vaultUrl} can be specified. It provides finer control over the construction of {@link KeyAsyncClient}
* and {@link KeyClient}</p>
*
* {@codesnippet com.azure.security.keyvault.keys.async.keyclient.pipeline.instantiation}
* {@codesnippet com.azure.security.keyvault.keys.KeyAsyncClient.instantiation.withHttpPipeline}
*
* <p> The minimal configuration options required by {@link KeyClientBuilder secretClientBuilder} to build {@link
* KeyClient} are {@link String vaultUrl} and {@link TokenCredential credential}. </p>
*
* {@codesnippet com.azure.security.keyvault.keys.keyclient.instantiation}
* {@codesnippet com.azure.security.keyvault.keys.KeyClient.instantiation}
*
* @see KeyAsyncClient
* @see KeyClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.azure.core.util.Context;
import com.azure.security.keyvault.keys.implementation.models.DeletedKeyPage;
import com.azure.security.keyvault.keys.implementation.models.KeyPropertiesPage;
import com.azure.security.keyvault.keys.implementation.models.KeyRotationPolicy;
import com.azure.security.keyvault.keys.implementation.models.GetRandomBytesRequest;
import com.azure.security.keyvault.keys.implementation.models.RandomBytes;
import com.azure.security.keyvault.keys.models.DeletedKey;
Expand Down Expand Up @@ -253,6 +254,7 @@ Mono<Response<RandomBytes>> getRandomBytes(@HostParam("url") String url,

@Post("keys/{key-name}/{key-version}/release")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(code = {404}, value = ResourceNotFoundException.class)
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<ReleaseKeyResult>> release(@HostParam("url") String url,
@PathParam("key-name") String keyName,
Expand All @@ -261,4 +263,35 @@ Mono<Response<ReleaseKeyResult>> release(@HostParam("url") String url,
@BodyParam("application/json") KeyReleaseParameters parameters,
@HeaderParam("Accept") String accept,
Context context);

@Post("/keys/{key-name}/rotate")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(code = {404}, value = ResourceNotFoundException.class)
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<KeyVaultKey>> rotateKey(@HostParam("url") String url,
@PathParam("key-name") String keyName,
@QueryParam("api-version") String apiVersion,
@HeaderParam("Accept") String accept,
Context context);

@Get("/keys/{key-name}/rotationpolicy")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(code = {404}, value = ResourceNotFoundException.class)
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<KeyRotationPolicy>> getKeyRotationPolicy(@HostParam("url") String url,
@PathParam("key-name") String keyName,
@QueryParam("api-version") String apiVersion,
@HeaderParam("Accept") String accept,
Context context);

@Put("/keys/{key-name}/rotationpolicy")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(code = {404}, value = ResourceNotFoundException.class)
@UnexpectedResponseExceptionType(HttpResponseException.class)
Mono<Response<KeyRotationPolicy>> updateKeyRotationPolicy(@HostParam("url") String url,
@PathParam("key-name") String keyName,
@QueryParam("api-version") String apiVersion,
@BodyParam("application/json") KeyRotationPolicy keyRotationPolicy,
@HeaderParam("Accept") String accept,
Context context);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.implementation.models;

import com.azure.core.annotation.Fluent;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.List;

/**
* Represents the rotation policy for a key.
*/
@Fluent
public final class KeyRotationPolicy {
@JsonProperty(value = "id", access = JsonProperty.Access.WRITE_ONLY)
private String id;

@JsonProperty(value = "lifetimeActions")
private List<LifetimeAction> lifetimeActions;

@JsonProperty(value = "attributes")
private KeyRotationPolicyAttributes attributes;

/**
* Get the {@link KeyRotationPolicy policy} id.
*
* @return The {@link KeyRotationPolicy policy} id.
*/
public String getId() {
return this.id;
}

/**
* Get the actions that will be performed by Key Vault over the lifetime of a key.
*
* @return The {@link LifetimeAction actions} in this {@link KeyRotationPolicy policy}.
*/
public List<LifetimeAction> getLifetimeActions() {
return this.lifetimeActions;
}

/**
* Set the actions that will be performed by Key Vault over the lifetime of a key.
*
* @param lifetimeActions The {@link LifetimeAction actions} to set.
*
* @return The updated {@link KeyRotationPolicy} object.
*/
public KeyRotationPolicy setLifetimeActions(List<LifetimeAction> lifetimeActions) {
this.lifetimeActions = lifetimeActions;

return this;
}

/**
* Get the {@link KeyRotationPolicyAttributes policy attributes}.
*
* @return The {@link KeyRotationPolicyAttributes policy attributes}.
*/
public KeyRotationPolicyAttributes getAttributes() {
return this.attributes;
}

/**
* Set the {@link KeyRotationPolicyAttributes policy attributes}.
*
* @param attributes The {@link KeyRotationPolicyAttributes policy attributes} to set.
*
* @return The updated {@link KeyRotationPolicy} object.
*/
public KeyRotationPolicy setAttributes(KeyRotationPolicyAttributes attributes) {
this.attributes = attributes;

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.implementation.models;

import com.azure.core.annotation.Fluent;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* The key rotation policy attributes.
*/
@Fluent
public final class KeyRotationPolicyAttributes {
@JsonProperty(value = "expiryTime")
private String expiryTime;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do other Java libraries use to model durations? we use string in JS because it's idiomatic for us, but Java might have a different way to model these types... consider checking with the service bus feature crew on how they model ISO8601 durations

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh feel free to ignore me if this is all internal / serialization / generated code... I really don't know Java 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Java SDK we do have a preferred datetime type: OffsetDateTime. For serialization/deserialization internal classes can keep using String for expiryTime and Long for createdOn and updatedOn, but I think it would be better to use OffsetDateTime in public classes like you suggest.


@JsonProperty(value = "created", access = JsonProperty.Access.WRITE_ONLY)
private Long createdOn;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Java have a better type for dates that we can use instead of a Long?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


@JsonProperty(value = "updated", access = JsonProperty.Access.WRITE_ONLY)
private Long updatedOn;

/**
* Get the optional key expiration period used to define the duration after which a newly rotated key will expire.
* It should be defined as an ISO 8601 duration. For example, 90 days would be formatted as follows: "P90D", 3
* months would be "P3M", 48 hours would be "PT48H" and 1 year and 10 days would be "P1Y10D".
*
* @return The expiry time in ISO 8601 format.
*/
public String getExpiryTime() {
return this.expiryTime;
}

/**
* Set the optional key expiration period used to define the duration after which a newly rotated key will expire.
* It should be defined as an ISO 8601 duration. For example, 90 days would be formatted as follows: "P90D", 3
* months would be "P3M", 48 hours would be "PT48H" and 1 year and 10 days would be "P1Y10D".
*
* @param expiryTime The expiry time to set in ISO 8601 format.
*
* @return The updated {@link KeyRotationPolicyAttributes} object.
*/
public KeyRotationPolicyAttributes setExpiryTime(String expiryTime) {
this.expiryTime = expiryTime;

return this;
}

/**
* Get the {@link KeyRotationPolicy policy's} created time in UTC.
*
* @return The {@link KeyRotationPolicy policy's} created time in UTC.
*/
public Long getCreatedOn() {
return this.createdOn;
}

/**
* Get the {@link KeyRotationPolicy policy's} last updated time in UTC.
*
* @return The the {@link KeyRotationPolicy policy's} last updated time in UTC.
*/
public Long getUpdatedOn() {
return this.updatedOn;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.implementation.models;

import com.azure.core.annotation.Fluent;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Represents an action that will be performed by Key Vault over the lifetime of a key.
*/
@Fluent
public final class LifetimeAction {
@JsonProperty(value = "trigger")
private LifetimeActionTrigger trigger;

@JsonProperty(value = "action")
private LifetimeActionsType action;

/**
* Get the {@link LifetimeActionTrigger action trigger}, the condition that will execute the action.
*
* @return The {@link LifetimeActionTrigger action trigger}.
*/
public LifetimeActionTrigger getTrigger() {
return this.trigger;
}

/**
* Set the {@link LifetimeActionTrigger action trigger}, the condition that will execute the action.
*
* @param trigger The {@link LifetimeActionTrigger action trigger} to set.
*
* @return The updated {@link LifetimeAction} object.
*/
public LifetimeAction setTrigger(LifetimeActionTrigger trigger) {
this.trigger = trigger;

return this;
}

/**
* Get the type of the action that will be executed.
*
* @return The {@link LifetimeActionsType action type}.
*/
public LifetimeActionsType getAction() {
return this.action;
}

/**
* Set the type of the action that will be executed.
*
* @param action The {@link LifetimeActionsType action type} to set.
*
* @return The updated {@link LifetimeAction} object.
*/
public LifetimeAction setAction(LifetimeActionsType action) {
this.action = action;

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.implementation.models;

import com.azure.core.annotation.Fluent;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* A condition to be satisfied for an action to be executed.
*/
@Fluent
public final class LifetimeActionTrigger {
@JsonProperty(value = "timeAfterCreate")
private String timeAfterCreate;

@JsonProperty(value = "timeBeforeExpiry")
private String timeBeforeExpiry;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed there might be a better type for this - Duration maybe or whatever servicebus queue is using. Whatever is idiomatic for Java to represent ISO8601 Durations.

I also know that this isn't the publicly exposed class but just calling it out here 👍

Same for timeAfterCreate and timeBeforeExpiry

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am refraining of using Duration for the time being since it doesn't play nice with durations longer than days. The alternative Period class is not meant for anything other than days/months/years. I'd rather keep using a String for now and hear what our architects have to say about this when we do the API review.


/**
* Get the time after creation to attempt to rotate in ISO 8601 duration format. For example, 90 days is represented
* as follows: "P90D".
*
* @return The time after creation to attempt to rotate.
*/
public String getTimeAfterCreate() {
return this.timeAfterCreate;
}

/**
* Set the time after creation to attempt to rotate in ISO 8601 duration format. For example, 90 days is represented
* as follows: "P90D".
*
* @param timeAfterCreate The time after creation to attempt to rotate.
*
* @return The updated {@link LifetimeActionTrigger} object.
*/
public LifetimeActionTrigger setTimeAfterCreate(String timeAfterCreate) {
this.timeAfterCreate = timeAfterCreate;

return this;
}

/**
* Get the time before expiry to attempt to rotate or notify in ISO 8601 duration format. For example, 90 days is
* represented as follows: "P90D".
*
* @return The time before expiry to attempt to rotate or notify.
*/
public String getTimeBeforeExpiry() {
return this.timeBeforeExpiry;
}

/**
* Set the time before expiry to attempt to rotate or notify in ISO 8601 duration format. For example, 90 days is
* represented as follows: "P90D".
*
* @param timeBeforeExpiry The time before expiry to attempt to rotate or notify.
*
* @return The updated {@link LifetimeActionTrigger} object.
*/
public LifetimeActionTrigger setTimeBeforeExpiry(String timeBeforeExpiry) {
this.timeBeforeExpiry = timeBeforeExpiry;

return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.security.keyvault.keys.implementation.models;

import com.azure.core.annotation.Fluent;
import com.azure.security.keyvault.keys.models.KeyRotationPolicyAction;
import com.fasterxml.jackson.annotation.JsonProperty;

/**
* The type of the action that will be executed.
*/
@Fluent
public final class LifetimeActionsType {
@JsonProperty(value = "type")
private KeyRotationPolicyAction type;

/**
* Get the {@link KeyRotationPolicyAction type} of the action.
*
* @return The {@link KeyRotationPolicyAction type} of the action.
*/
public KeyRotationPolicyAction getType() {
return this.type;
}

/**
* Set the {@link KeyRotationPolicyAction type} of the action.
*
* @param type The {@link KeyRotationPolicyAction type} to set.
*
* @return The updated {@link LifetimeActionsType} object.
*/
public LifetimeActionsType setType(KeyRotationPolicyAction type) {
this.type = type;

return this;
}
}
Loading