Skip to content
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
1,660 changes: 1,660 additions & 0 deletions src/KeyVault/KeyVault.Test/Models/PSKeyVaultCertificatePolicyTests.cs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/KeyVault/KeyVault/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
-->
## Upcoming Release
* Fixed error accessing value that is potentially not set
* Elliptic Curve Cryptography Certificate Managment
- Added support to specify the Curve for Certificate Policies

## Version 1.3.1
* Fixed miscellaneous typos across module
Expand Down
7 changes: 7 additions & 0 deletions src/KeyVault/KeyVault/Commands/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ public static class Constants
public const string StorageAccountName = "StorageAccountName";
public const string StorageAccountResourceId = "StorageAccountResourceId";
public const string TagsAlias = "Tags";
public const string EC = "EC";
public const string ECHSM = "EC-HSM";
public const string P256 = "P-256";
public const string P384 = "P-384";
public const string P521 = "P-521";
public const string P256K = "P-256K";
public const string SECP256K1 = "SECP256K1";
}

public static class CmdletNoun
Expand Down
145 changes: 46 additions & 99 deletions src/KeyVault/KeyVault/Commands/NewAzureKeyVaultCertificatePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Azure.Commands.KeyVault.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
Expand Down Expand Up @@ -167,124 +168,70 @@ public class NewAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the key type of the key backing the certificate.")]
[ValidateSet(Constants.RSA, Constants.RSAHSM)]
HelpMessage = "Specifies the key type of the key backing the certificate. Default is RSA.")]
[ValidateSet(Constants.RSA, Constants.RSAHSM, Constants.EC, Constants.ECHSM)]
public string KeyType { get; set; }

/// <summary>
/// Key size
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the key size of the certificate.")]
[ValidateSet("2048", "3072", "4096")]
public int KeySize { get; set; } = 2048;
/// <summary>
/// Key size
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the key size of the certificate. Default is 2048.")]
[ValidateSet("2048", "3072", "4096", "256", "384", "521")]
public int KeySize { get; set; }

/// <summary>
/// KeyNotExportable
/// </summary>
[Parameter(Mandatory = false,
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies whether the key is not exportable.")]
public SwitchParameter KeyNotExportable { get; set; }


[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Indicates whether certificate transparency is enabled for this certificate/issuer; if not specified, the default is 'true'")]
public bool? CertificateTransparency { get; set; }

/// <summary>
/// Elliptic Curve Name of the key
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the elliptic curve name of the key of the ECC certificate.")]
[ValidateSet(Constants.P256, Constants.P384, Constants.P521, Constants.P256K, Constants.SECP256K1)]
public string Curve { get; set; }
#endregion

public override void ExecuteCmdlet()
{
if (ShouldProcess(string.Empty, Properties.Resources.CreateCertificatePolicy))
{
// Validate input parameters
ValidateSubjectName();
ValidateDnsNames();
ValidateEkus();
ValidateBothPercentageAndNumberOfDaysAreNotPresent();

List<String> convertedKeyUsage = null;
if (KeyUsage != null)
{
convertedKeyUsage = new List<string>();
foreach (var key in KeyUsage)
{
convertedKeyUsage.Add(key.ToString());
}
}

var policy = new PSKeyVaultCertificatePolicy
{
DnsNames = DnsName,
KeyUsage = convertedKeyUsage,
Ekus = Ekus,
Enabled = !Disabled.IsPresent,
IssuerName = IssuerName,
CertificateType = CertificateType,
RenewAtNumberOfDaysBeforeExpiry = RenewAtNumberOfDaysBeforeExpiry,
RenewAtPercentageLifetime = RenewAtPercentageLifetime,
EmailAtNumberOfDaysBeforeExpiry = EmailAtNumberOfDaysBeforeExpiry,
EmailAtPercentageLifetime = EmailAtPercentageLifetime,
ReuseKeyOnRenewal = ReuseKeyOnRenewal.IsPresent,
SecretContentType = SecretContentType,
SubjectName = SubjectName,
ValidityInMonths = ValidityInMonths,
Kty = KeyType,
KeySize = KeySize,
Exportable = KeyNotExportable.IsPresent ? !KeyNotExportable.IsPresent : (bool?)null
};
var policy = new PSKeyVaultCertificatePolicy(
DnsName,
(KeyUsage == null || !KeyUsage.Any()) ? null : KeyUsage.Select(keyUsage => keyUsage.ToString()).ToList<string>(),
Ekus,
!Disabled.IsPresent,
IssuerName,
CertificateType,
RenewAtNumberOfDaysBeforeExpiry,
RenewAtPercentageLifetime,
EmailAtNumberOfDaysBeforeExpiry,
EmailAtPercentageLifetime,
ReuseKeyOnRenewal.IsPresent,
SecretContentType,
SubjectName,
ValidityInMonths,
KeyType,
KeySize,
Curve,
KeyNotExportable.IsPresent ? !KeyNotExportable.IsPresent : (bool?)null,
CertificateTransparency ?? (bool?)null);

this.WriteObject(policy);
}
}

private void ValidateBothPercentageAndNumberOfDaysAreNotPresent()
{
if (MyInvocation.BoundParameters.ContainsKey("RenewAtNumberOfDaysBeforeExpiry") &&
MyInvocation.BoundParameters.ContainsKey("RenewAtPercentageLifetime"))
{
throw new ArgumentException("Both RenewAtNumberOfDaysBeforeExpiry and RenewAtPercentageLifetime cannot be specified.");
}
}

private void ValidateEkus()
{
if (Ekus != null)
{
foreach (var eku in Ekus)
{
if (string.IsNullOrWhiteSpace(eku))
{
throw new ArgumentException("One of the EKUs provided is empty.");
}
}
}
}

private void ValidateDnsNames()
{
if (DnsName != null)
{
foreach (var dnsName in DnsName)
{
if (string.IsNullOrWhiteSpace(dnsName))
{
throw new ArgumentException("One of the DNS names provided is empty.");
}
}
}
}

private void ValidateSubjectName()
{
if (SubjectName != null)
{
try
{
new X500DistinguishedName(SubjectName);
}
catch (CryptographicException e)
{
throw new ArgumentException("The subject name provided is not a valid X500 name.", e);
}
}
}
}
}
126 changes: 36 additions & 90 deletions src/KeyVault/KeyVault/Commands/SetAzureKeyVaultCertificatePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
Expand Down Expand Up @@ -222,18 +223,18 @@ public class SetAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase
/// Key type
/// </summary>
[Parameter(Mandatory = false,
HelpMessage = "Specifies the key type of the key backing the certificate.")]
[ValidateSet(Constants.RSA, Constants.RSAHSM)]
HelpMessage = "Specifies the key type of the key backing the certificate. Default is RSA.")]
[ValidateSet(Constants.RSA, Constants.RSAHSM, Constants.EC, Constants.ECHSM)]
public string KeyType { get; set; }

/// <summary>
/// Key size
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the key size of the certificate.")]
[ValidateSet("2048", "3072", "4096")]
public int KeySize { get; set; } = 2048;
HelpMessage = "Specifies the key size of the certificate. Default is 2048.")]
[ValidateSet("2048", "3072", "4096", "256", "384", "521")]
public int KeySize { get; set; }

/// <summary>
/// KeyNotExportable
Expand All @@ -255,6 +256,15 @@ public class SetAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase
/// </summary>
[Parameter(HelpMessage = "This cmdlet does not return an object by default. If this switch is specified, it returns the policy object.")]
public SwitchParameter PassThru { get; set; }

/// <summary>
/// Elliptic Curve Name of the key
/// </summary>
[Parameter(Mandatory = false,
ValueFromPipelineByPropertyName = true,
HelpMessage = "Specifies the elliptic curve name of the key of the ECC certificate.")]
[ValidateSet(Constants.P256, Constants.P384, Constants.P521, Constants.P256K, Constants.SECP256K1)]
public string Curve { get; set; }
#endregion

public override void ExecuteCmdlet()
Expand All @@ -267,51 +277,30 @@ public override void ExecuteCmdlet()
{
case ExpandedRenewNumberParameterSet:
case ExpandedRenewPercentageParameterSet:

// Validate input parameters
ValidateSubjectName();
ValidateDnsNames();
ValidateEkus();

List<string> convertedKeyUsage = null;
if (KeyUsage != null)
{
convertedKeyUsage = new List<string>();
foreach (var key in KeyUsage)
{
convertedKeyUsage.Add(key.ToString());
}
}

policy = new PSKeyVaultCertificatePolicy
{
DnsNames = DnsName,
KeyUsage = convertedKeyUsage,
Ekus = Ekus,
Enabled = !Disabled.IsPresent,
IssuerName = IssuerName,
CertificateType = CertificateType,
RenewAtNumberOfDaysBeforeExpiry = RenewAtNumberOfDaysBeforeExpiry,
RenewAtPercentageLifetime = RenewAtPercentageLifetime,
EmailAtNumberOfDaysBeforeExpiry = EmailAtNumberOfDaysBeforeExpiry,
EmailAtPercentageLifetime = EmailAtPercentageLifetime,
SecretContentType = SecretContentType,
SubjectName = SubjectName,
ValidityInMonths = ValidityInMonths,
Kty = KeyType,
KeySize = KeySize,
Exportable = KeyNotExportable.IsPresent ? !KeyNotExportable.IsPresent : (bool?)null,
CertificateTransparency = CertificateTransparency ?? (bool?)null
};

if (MyInvocation.BoundParameters.ContainsKey("ReuseKeyOnRenewal"))
{
policy.ReuseKeyOnRenewal = ReuseKeyOnRenewal;
}

policy = new PSKeyVaultCertificatePolicy(
DnsName,
(KeyUsage == null || !KeyUsage.Any()) ? null : KeyUsage.Select(keyUsage => keyUsage.ToString()).ToList<string>(),
Ekus,
!Disabled.IsPresent,
IssuerName,
CertificateType,
RenewAtNumberOfDaysBeforeExpiry,
RenewAtPercentageLifetime,
EmailAtNumberOfDaysBeforeExpiry,
EmailAtPercentageLifetime,
ReuseKeyOnRenewal,
SecretContentType,
SubjectName,
ValidityInMonths,
KeyType,
KeySize,
Curve,
KeyNotExportable.IsPresent ? !KeyNotExportable.IsPresent : (bool?)null,
CertificateTransparency ?? (bool?)null);
break;

case ByValueParameterSet:
InputObject.Validate();
policy = InputObject;
break;
}
Expand All @@ -324,48 +313,5 @@ public override void ExecuteCmdlet()
}
}
}

private void ValidateEkus()
{
if (Ekus != null)
{
foreach (var eku in Ekus)
{
if (string.IsNullOrWhiteSpace(eku))
{
throw new ArgumentException("One of the EKUs provided is empty.");
}
}
}
}

private void ValidateDnsNames()
{
if (DnsName != null)
{
foreach (var dnsName in DnsName)
{
if (string.IsNullOrWhiteSpace(dnsName))
{
throw new ArgumentException("One of the DNS names provided is empty.");
}
}
}
}

private void ValidateSubjectName()
{
if (SubjectName != null)
{
try
{
new X500DistinguishedName(SubjectName);
}
catch (CryptographicException e)
{
throw new ArgumentException("The subject name provided is not a valid X500 name.", e);
}
}
}
}
}
Loading