diff --git a/src/CosmosDB/CosmosDB/CosmosDB.csproj b/src/CosmosDB/CosmosDB/CosmosDB.csproj
index c2064331a71a..7793d9804c5b 100644
--- a/src/CosmosDB/CosmosDB/CosmosDB.csproj
+++ b/src/CosmosDB/CosmosDB/CosmosDB.csproj
@@ -6,7 +6,7 @@
-
+
diff --git a/src/KeyVault/KeyVault.Test/Resources/rotationpolicy.json b/src/KeyVault/KeyVault.Test/Resources/rotationpolicy.json
new file mode 100644
index 000000000000..23f607467748
--- /dev/null
+++ b/src/KeyVault/KeyVault.Test/Resources/rotationpolicy.json
@@ -0,0 +1,24 @@
+{
+ "lifetimeActions": [
+ {
+ "trigger": {
+ "timeAfterCreate": "P18M",
+ "timeBeforeExpiry": null
+ },
+ "action": {
+ "type": "Rotate"
+ }
+ },
+ {
+ "trigger": {
+ "timeBeforeExpiry": "P30D"
+ },
+ "action": {
+ "type": "Notify"
+ }
+ }
+ ],
+ "attributes": {
+ "expiryTime": "P2Y"
+ }
+ }
\ No newline at end of file
diff --git a/src/KeyVault/KeyVault/ChangeLog.md b/src/KeyVault/KeyVault/ChangeLog.md
index 221fc7497976..b3afd31cb0ad 100644
--- a/src/KeyVault/KeyVault/ChangeLog.md
+++ b/src/KeyVault/KeyVault/ChangeLog.md
@@ -18,6 +18,9 @@
- Additional information about change #1
-->
## Upcoming Release
+* Supported accepting rotation policy in a JSON file
+* [Breaking Change] Changed parameter `ExpiresIn` in `Set-AzKeyVaultKeyRotationPolicy` from TimeSpan? to string. It must be an ISO 8601 duration like "P30D" for 30 days.
+* [Breaking Change] Changed output properties `ExpiresIn`, `TimeAfterCreate` and `TimeBeforeExpiry` of `Set-AzKeyVaultKeyRotationPolicy` and `Get-AzKeyVaultKeyRotationPolicy` from TimeSpan? to string.
* Supported creating/updating key with release policy in a Managed HSM
## Version 4.5.0
diff --git a/src/KeyVault/KeyVault/Commands/Key/KeyRotation/SetAzKeyVaultKeyRotationPolicy.cs b/src/KeyVault/KeyVault/Commands/Key/KeyRotation/SetAzKeyVaultKeyRotationPolicy.cs
index facfd191c7a4..ac13ea074bca 100644
--- a/src/KeyVault/KeyVault/Commands/Key/KeyRotation/SetAzKeyVaultKeyRotationPolicy.cs
+++ b/src/KeyVault/KeyVault/Commands/Key/KeyRotation/SetAzKeyVaultKeyRotationPolicy.cs
@@ -1,47 +1,113 @@
-using Microsoft.Azure.Commands.KeyVault.Models;
+using Microsoft.Azure.Commands.Common.Exceptions;
+using Microsoft.Azure.Commands.KeyVault.Models;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
+using Microsoft.WindowsAzure.Commands.Utilities.Common;
+
+using Newtonsoft.Json;
using System;
using System.Management.Automation;
+using Track2Sdk = Azure.Security.KeyVault.Keys;
+using System.IO;
+using Microsoft.WindowsAzure.Commands.Common;
+using Microsoft.Azure.Commands.KeyVault.Properties;
+using System.Collections.Generic;
namespace Microsoft.Azure.Commands.KeyVault.Commands.Key
{
///
/// Updates the KeyRotationPolicy for the specified key in Key Vault.
///
- [Cmdlet(VerbsCommon.Set, ResourceManager.Common.AzureRMConstants.AzurePrefix + "KeyVaultKeyRotationPolicy", SupportsShouldProcess = true, DefaultParameterSetName = ByVaultNameParameterSet)]
+ [Cmdlet(VerbsCommon.Set, ResourceManager.Common.AzureRMConstants.AzurePrefix + "KeyVaultKeyRotationPolicy", SupportsShouldProcess = true, DefaultParameterSetName = SetByExpandedPropertiesViaVaultName)]
[OutputType(typeof(PSKeyRotationPolicy))]
- public class SetAzKeyVaultKeyRotationPolicy: KeyVaultOnlyKeyCmdletBase
+ public class SetAzKeyVaultKeyRotationPolicy: KeyVaultCmdletBase
{
#region Parameter Set Names
- internal const string ByKeyRotationPolicyInputObjectParameterSet = "ByKeyRotationPolicyInputObject";
+ private const string SetByExpandedPropertiesViaVaultName = "ByVaultName";
+ private const string SetByRotationPolicyFileViaVaultName = "SetByRotationPolicyFileViaVaultName";
+
+ private const string SetByExpandedPropertiesViaKeyInputObject = "ByKeyInputObject";
+ private const string SetByRotationPolicyFileViaKeyInputObject = "SetByRotationPolicyFileViaKeyInputObject";
+
+ private const string ByKeyRotationPolicyInputObjectParameterSet = "ByKeyRotationPolicyInputObject";
#endregion
#region Input Parameter Definitions
- [Parameter(Mandatory = true,
- Position = 0,
- ParameterSetName = ByKeyRotationPolicyInputObjectParameterSet,
- ValueFromPipeline = true,
- HelpMessage = "PSKeyRotationPolicy object.")]
+ ///
+ /// Vault name
+ ///
+ [Parameter(Mandatory = true, Position = 0, ParameterSetName = SetByExpandedPropertiesViaVaultName, HelpMessage = "Vault name.")]
+ [Parameter(Mandatory = true, Position = 0, ParameterSetName = SetByRotationPolicyFileViaVaultName)]
+ [ResourceNameCompleter("Microsoft.KeyVault/vaults", "FakeResourceGroupName")]
+ [ValidateNotNullOrEmpty]
+ public string VaultName { get; set; }
+
+ ///
+ /// Key name.
+ ///
+ [Parameter(Mandatory = true, Position = 1, ParameterSetName = SetByExpandedPropertiesViaVaultName, HelpMessage = "Key name.")]
+ [Parameter(Mandatory = true, Position = 1, ParameterSetName = SetByRotationPolicyFileViaVaultName)]
+ [ValidateNotNullOrEmpty]
+ [Alias(Constants.KeyName)]
+ public string Name { get; set; }
+
+ ///
+ /// Key object
+ ///
+ [Parameter(Mandatory = true, Position = 0, ParameterSetName = SetByExpandedPropertiesViaKeyInputObject,
+ ValueFromPipeline = true, HelpMessage = "Key object")]
+ [Parameter(Mandatory = true, Position = 0, ParameterSetName = SetByRotationPolicyFileViaKeyInputObject,
+ ValueFromPipeline = true)]
+ [ValidateNotNullOrEmpty]
+ [Alias("Key")]
+ public PSKeyVaultKeyIdentityItem InputObject { get; set; }
+
+ [Parameter(Mandatory = true, Position = 0, ParameterSetName = ByKeyRotationPolicyInputObjectParameterSet,
+ ValueFromPipeline = true, HelpMessage = "PSKeyRotationPolicy object.")]
public PSKeyRotationPolicy KeyRotationPolicy { get; set; }
- [Parameter(ParameterSetName = ByVaultNameParameterSet,
- HelpMessage = "The time span when the key rotation policy will expire. It should be at least 28 days.")]
- [Parameter(ParameterSetName = ByKeyInputObjectParameterSet)]
- public TimeSpan ExpiresIn { get; set; }
+ [Parameter(ParameterSetName = SetByExpandedPropertiesViaVaultName,
+ HelpMessage = "The expiryTime will be applied on the new key version. It should be at least 28 days. It will be in ISO 8601 Format. Examples: 90 days: P90D, 3 months: P3M, 48 hours: PT48H, 1 year and 10 days: P1Y10D")]
+ [Parameter(ParameterSetName = SetByExpandedPropertiesViaKeyInputObject)]
+ public string ExpiresIn { get; set; }
- [Parameter(ParameterSetName = ByVaultNameParameterSet,
+ [Parameter(ParameterSetName = SetByExpandedPropertiesViaVaultName,
HelpMessage = "PSKeyRotationLifetimeAction object.")]
- [Parameter(ParameterSetName = ByKeyInputObjectParameterSet)]
+ [Parameter(ParameterSetName = SetByExpandedPropertiesViaKeyInputObject)]
public PSKeyRotationLifetimeAction[] KeyRotationLifetimeAction { get; set; }
+ [Parameter(Mandatory = true, ParameterSetName = SetByRotationPolicyFileViaVaultName,
+ HelpMessage = "A path to the rotation policy file that contains JSON policy definition.")]
+ [Parameter(Mandatory = true, ParameterSetName = SetByRotationPolicyFileViaKeyInputObject)]
+ public string PolicyPath { get; set; }
#endregion
- internal override void NormalizeParameterSets()
+ protected override void BeginProcessing()
+ {
+ PolicyPath = this.TryResolvePath(PolicyPath);
+ base.BeginProcessing();
+ }
+
+ internal void ValidateParameters()
+ {
+ if((this.ParameterSetName.Equals(SetByExpandedPropertiesViaVaultName) ||
+ this.ParameterSetName.Equals(SetByExpandedPropertiesViaKeyInputObject)) &&
+ null == ExpiresIn && null == KeyRotationLifetimeAction)
+ {
+ throw new ArgumentException(string.Format("Must specify ExpiresIn or KeyRotationLifetimeAction."));
+ }
+
+ if(this.IsParameterBound(c => c.PolicyPath) && !File.Exists(PolicyPath))
+ {
+ throw new AzPSFileNotFoundException(string.Format(Resources.FileNotFound, PolicyPath), nameof(PolicyPath));
+ }
+ }
+
+ internal void NormalizeParameterSets()
{
if (null != InputObject)
{
@@ -57,33 +123,84 @@ internal override void NormalizeParameterSets()
}
}
- if (!this.ParameterSetName.Equals(ByKeyRotationPolicyInputObjectParameterSet))
+ switch (this.ParameterSetName)
{
-
- // Only update specified parameter, others keep same
- KeyRotationPolicy = Track2DataClient.GetKeyRotationPolicy(VaultName, Name) ??
- new PSKeyRotationPolicy()
- {
+ case SetByRotationPolicyFileViaVaultName:
+ case SetByRotationPolicyFileViaKeyInputObject:
+ KeyRotationPolicy = ConstructKeyRotationPolicyFromFile(PolicyPath);
+ break;
+ case SetByExpandedPropertiesViaVaultName:
+ case SetByExpandedPropertiesViaKeyInputObject:
+ KeyRotationPolicy = new PSKeyRotationPolicy()
+ {
VaultName = VaultName,
KeyName = Name,
- ExpiresIn = null,
- LifetimeActions = null
+ ExpiresIn = ExpiresIn ?? Track2DataClient.GetKeyRotationPolicy(VaultName, Name).ExpiresIn,
+ LifetimeActions = KeyRotationLifetimeAction ?? Track2DataClient.GetKeyRotationPolicy(VaultName, Name).LifetimeActions
};
+ break;
+ default:
+ // do nothing
+ break;
+ }
- if (MyInvocation.BoundParameters.ContainsKey("ExpiresIn"))
- {
- KeyRotationPolicy.ExpiresIn = ExpiresIn;
- }
+ }
+
+ private PSKeyRotationPolicy ConstructKeyRotationPolicyFromFile(string policyPath)
+ {
+ try
+ {
+ string content = File.ReadAllText(policyPath);
+ // first-level dictionary
+ var dict = JsonUtilities.DeserializeJson(content, true);
- if (MyInvocation.BoundParameters.ContainsKey("KeyRotationLifetimeAction"))
+ // second-level dictionary
+ var attributes = JsonUtilities.DeserializeJson(JsonConvert.SerializeObject(dict["attributes"]), true);
+ var lifetimeActionsArray = JsonConvert.DeserializeObject