diff --git a/src/KeyVault/KeyVault.Test/Models/PSKeyVaultCertificatePolicyTests.cs b/src/KeyVault/KeyVault.Test/Models/PSKeyVaultCertificatePolicyTests.cs new file mode 100644 index 000000000000..a94ebc1de7dd --- /dev/null +++ b/src/KeyVault/KeyVault.Test/Models/PSKeyVaultCertificatePolicyTests.cs @@ -0,0 +1,1660 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +using Microsoft.Azure.Commands.KeyVault.Models; +using Microsoft.Azure.ServiceManagement.Common.Models; +using Microsoft.WindowsAzure.Commands.ScenarioTest; +using System; +using System.Collections.Generic; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Azure.Commands.KeyVault.Test.Models +{ + public class PSKeyVaultCertificatePolicyTests + { + public PSKeyVaultCertificatePolicyTests(ITestOutputHelper output) + { + XunitTracingInterceptor.AddToContext(new XunitTracingInterceptor(output)); + } + + #region Create CertificatePolicy Tests + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithNoKeyTypeAndKeySize_SucceedsWithRsaKeyTypeAnd2048KeySize() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: string.Empty, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, Constants.RSA); + Assert.NotNull(policy.KeySize); + Assert.Equal(2048, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithRsaKeyTypeAndNoKeySize_SucceedsWith2048KeySize() + { + var keyType = Constants.RSAHSM; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.NotNull(policy.KeySize); + Assert.Equal(2048, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithRsaKeyTypeAndCurve_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEccKeyTypeAndNoCurve_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEcKeyTypeP256CurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P256; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEcKeyTypeP256KCurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P256K; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEcKeyTypeSECP256K1CurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.SECP256K1; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEcKeyTypeP384CurveAndNoKeySize_SucceedsWith384KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P384; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(384, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEcKeyTypeP521CurveAndNoKeySize_SucceedsWith521KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P521; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(521, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithRsaKeyTypeAnd256KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 256, + curve: string.Empty, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithRsaKeyTypeAnd384KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 384, + curve: string.Empty, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithRsaKeyTypeAnd521KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 521, + curve: string.Empty, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeAnd2048KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 2048, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeAnd3072KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 3072, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeAnd4096KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 4096, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeP256CurveAndNot256KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 1, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeP256KCurveAndNot256KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 1, + curve: Constants.P256K, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeSECP256K1CurveAndNot256KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 1, + curve: Constants.SECP256K1, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeP384CurveAndNot384KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 1, + curve: Constants.P384, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithECKeyTypeP521CurveAndNot521KeySize_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 1, + curve: Constants.P521, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithOneLifetimeAction_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: 1, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null); + + Assert.NotNull(policy.RenewAtNumberOfDaysBeforeExpiry); + Assert.Equal(1, policy.RenewAtNumberOfDaysBeforeExpiry.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithMoreThanOneLifetimeAction_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: 1, + renewAtPercentageLifetime: 1, + emailAtNumberOfDaysBeforeExpiry: 1, + emailAtPercentageLifetime: 1, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithNoEku_SucceedsWithNullEku() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: new List(), + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null); + + Assert.Null(policy.Ekus); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEmptyEku_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: new List() { string.Empty }, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithNoDnsName_SucceedsWithNullDnsName() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: new List(), + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null); + + Assert.Null(policy.Ekus); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithEmptyDnsName_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: new List() { string.Empty }, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void CreateCertificatePolicy_WithInValidSubjectName_ThrowsException() + { + Assert.Throws( + () => new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: "SubjectName", + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null)); + } + #endregion + + #region Validate CertificatePolicy Tests + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithNoKeyTypeAndKeySize_SucceedsWithRsaKeyTypeAnd2048KeySize() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: string.Empty, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, Constants.RSA); + Assert.NotNull(policy.KeySize); + Assert.Equal(2048, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithRsaKeyTypeAndNoKeySize_SucceedsWith2048KeySize() + { + var keyType = Constants.RSAHSM; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.NotNull(policy.KeySize); + Assert.Equal(2048, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithRsaKeyTypeAndCurve_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null) + { + Curve = Constants.P256, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEccKeyTypeAndNoCurve_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + Curve = string.Empty, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEcKeyTypeP256CurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P256; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEcKeyTypeP256KCurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P256K; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEcKeyTypeSECP256K1CurveAndNoKeySize_SucceedsWith256KeySize() + { + var keyType = Constants.EC; + var curve = Constants.SECP256K1; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(256, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEcKeyTypeP384CurveAndNoKeySize_SucceedsWith384KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P384; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(384, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEcKeyTypeP521CurveAndNoKeySize_SucceedsWith521KeySize() + { + var keyType = Constants.EC; + var curve = Constants.P521; + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: keyType, + keySize: 0, + curve: curve, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Equal(policy.Kty, keyType); + Assert.Equal(policy.Curve, curve); + Assert.NotNull(policy.KeySize); + Assert.Equal(521, policy.KeySize.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithRsaKeyTypeAnd256KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null) + { + KeySize= 256, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithRsaKeyTypeAnd384KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null) + { + KeySize = 384, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithRsaKeyTypeAnd521KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.RSA, + keySize: 0, + curve: string.Empty, + exportable: null, + certificateTransparency: null) + { + KeySize = 521, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeAnd2048KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + KeySize = 2048, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeAnd3072KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + KeySize = 3072, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeAnd4096KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + KeySize = 4096, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeP256CurveAndNot256KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + KeySize = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeP256KCurveAndNot256KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P256K, + exportable: null, + certificateTransparency: null) + { + KeySize = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeSECP256K1CurveAndNot256KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.SECP256K1, + exportable: null, + certificateTransparency: null) + { + KeySize = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeP384CurveAndNot384KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P384, + exportable: null, + certificateTransparency: null) + { + KeySize = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithECKeyTypeP521CurveAndNot521KeySize_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 0, + curve: Constants.P521, + exportable: null, + certificateTransparency: null) + { + KeySize = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithOneLifetimeAction_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + RenewAtNumberOfDaysBeforeExpiry = 1, + }; + policy.Validate(); + + Assert.NotNull(policy.RenewAtNumberOfDaysBeforeExpiry); + Assert.Equal(1, policy.RenewAtNumberOfDaysBeforeExpiry.Value); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithMoreThanOneLifetimeAction_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + RenewAtNumberOfDaysBeforeExpiry = 1, + RenewAtPercentageLifetime = 1, + EmailAtNumberOfDaysBeforeExpiry = 1, + EmailAtPercentageLifetime = 1, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithNoEku_SucceedsWithNullEku() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: new List(), + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null); + + policy.Validate(); + Assert.Null(policy.Ekus); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEmptyEku_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + Ekus = new List() { string.Empty }, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithNoDnsName_SucceedsWithNullDnsName() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: new List(), + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null); + policy.Validate(); + + Assert.Null(policy.Ekus); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithEmptyDnsName_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + DnsNames = new List() { string.Empty }, + }; + + Assert.Throws(() => policy.Validate()); + } + + [Fact] + [Trait(Category.AcceptanceType, Category.CheckIn)] + public void ValidateCertificatePolicy_WithInValidSubjectName_ThrowsException() + { + var policy = new PSKeyVaultCertificatePolicy( + dnsNames: null, + keyUsages: null, + ekus: null, + enabled: null, + issuerName: string.Empty, + certificateType: string.Empty, + renewAtNumberOfDaysBeforeExpiry: null, + renewAtPercentageLifetime: null, + emailAtNumberOfDaysBeforeExpiry: null, + emailAtPercentageLifetime: null, + reuseKeyOnRenewal: null, + secretContentType: string.Empty, + subjectName: string.Empty, + validityInMonths: null, + keyType: Constants.EC, + keySize: 256, + curve: Constants.P256, + exportable: null, + certificateTransparency: null) + { + SubjectName = "SubjectName", + }; + + Assert.Throws(() => policy.Validate()); + } + #endregion + } +} diff --git a/src/KeyVault/KeyVault/ChangeLog.md b/src/KeyVault/KeyVault/ChangeLog.md index c0c32d3211fb..e566d3e116b2 100644 --- a/src/KeyVault/KeyVault/ChangeLog.md +++ b/src/KeyVault/KeyVault/ChangeLog.md @@ -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 diff --git a/src/KeyVault/KeyVault/Commands/Constants.cs b/src/KeyVault/KeyVault/Commands/Constants.cs index 387a56cbaced..4607e655cf72 100644 --- a/src/KeyVault/KeyVault/Commands/Constants.cs +++ b/src/KeyVault/KeyVault/Commands/Constants.cs @@ -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 diff --git a/src/KeyVault/KeyVault/Commands/NewAzureKeyVaultCertificatePolicy.cs b/src/KeyVault/KeyVault/Commands/NewAzureKeyVaultCertificatePolicy.cs index 446d3c75699d..4fc2eb255fe2 100644 --- a/src/KeyVault/KeyVault/Commands/NewAzureKeyVaultCertificatePolicy.cs +++ b/src/KeyVault/KeyVault/Commands/NewAzureKeyVaultCertificatePolicy.cs @@ -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; @@ -167,124 +168,70 @@ public class NewAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase /// [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; } - /// - /// Key size - /// - [Parameter(Mandatory = false, - ValueFromPipelineByPropertyName = true, - HelpMessage = "Specifies the key size of the certificate.")] - [ValidateSet("2048", "3072", "4096")] - public int KeySize { get; set; } = 2048; + /// + /// Key size + /// + [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; } /// /// KeyNotExportable /// - [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; } + + /// + /// Elliptic Curve Name of the key + /// + [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 convertedKeyUsage = null; - if (KeyUsage != null) - { - convertedKeyUsage = new List(); - 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(), + 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); - } - } - } } } diff --git a/src/KeyVault/KeyVault/Commands/SetAzureKeyVaultCertificatePolicy.cs b/src/KeyVault/KeyVault/Commands/SetAzureKeyVaultCertificatePolicy.cs index e2520ab55f21..656263bd8a6e 100644 --- a/src/KeyVault/KeyVault/Commands/SetAzureKeyVaultCertificatePolicy.cs +++ b/src/KeyVault/KeyVault/Commands/SetAzureKeyVaultCertificatePolicy.cs @@ -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; @@ -222,8 +223,8 @@ public class SetAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase /// Key type /// [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; } /// @@ -231,9 +232,9 @@ public class SetAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase /// [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; } /// /// KeyNotExportable @@ -255,6 +256,15 @@ public class SetAzureKeyVaultCertificatePolicy : KeyVaultCmdletBase /// [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; } + + /// + /// Elliptic Curve Name of the key + /// + [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() @@ -267,51 +277,30 @@ public override void ExecuteCmdlet() { case ExpandedRenewNumberParameterSet: case ExpandedRenewPercentageParameterSet: - - // Validate input parameters - ValidateSubjectName(); - ValidateDnsNames(); - ValidateEkus(); - - List convertedKeyUsage = null; - if (KeyUsage != null) - { - convertedKeyUsage = new List(); - 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(), + 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; } @@ -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); - } - } - } } } diff --git a/src/KeyVault/KeyVault/Models/PSKeyVaultCertificatePolicy.cs b/src/KeyVault/KeyVault/Models/PSKeyVaultCertificatePolicy.cs index b578d59b7015..a778824eced7 100644 --- a/src/KeyVault/KeyVault/Models/PSKeyVaultCertificatePolicy.cs +++ b/src/KeyVault/KeyVault/Models/PSKeyVaultCertificatePolicy.cs @@ -16,6 +16,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; namespace Microsoft.Azure.Commands.KeyVault.Models { @@ -24,6 +26,7 @@ public class PSKeyVaultCertificatePolicy public string SecretContentType { get; set; } public string Kty { get; set; } public int? KeySize { get; set; } + public string Curve { get; set; } public bool? Exportable { get; set; } public bool? ReuseKeyOnRenewal { get; set; } public string SubjectName { get; set; } @@ -47,6 +50,63 @@ public PSKeyVaultCertificatePolicy() { } + public PSKeyVaultCertificatePolicy( + IList dnsNames, + IList keyUsages, + IList ekus, + bool? enabled, + string issuerName, + string certificateType, + int? renewAtNumberOfDaysBeforeExpiry, + int? renewAtPercentageLifetime, + int? emailAtNumberOfDaysBeforeExpiry, + int? emailAtPercentageLifetime, + bool? reuseKeyOnRenewal, + string secretContentType, + string subjectName, + int? validityInMonths, + string keyType, + int keySize, + string curve, + bool? exportable, + bool? certificateTransparency) + { + ValidateInternal( + dnsNames, + ekus, + renewAtNumberOfDaysBeforeExpiry, + renewAtPercentageLifetime, + emailAtNumberOfDaysBeforeExpiry, + emailAtPercentageLifetime, + subjectName, + keyType, + keySize, + curve); + + var keyTypeToUse = GetDefaultKeyTypeIfNotSpecified(keyType); + var keySizeToUse = GetDefaultKeySizeIfNotSpecified(keyTypeToUse, curve, keySize); + + DnsNames = (dnsNames == null || !dnsNames.Any()) ? null : dnsNames.ToList(); + KeyUsage = (keyUsages == null || !keyUsages.Any()) ? null : keyUsages.ToList(); + Ekus = (ekus == null || !ekus.Any()) ? null : ekus.ToList(); + Enabled = enabled; + IssuerName = issuerName; + CertificateType = certificateType; + RenewAtNumberOfDaysBeforeExpiry = renewAtNumberOfDaysBeforeExpiry; + RenewAtPercentageLifetime = renewAtPercentageLifetime; + EmailAtNumberOfDaysBeforeExpiry = emailAtNumberOfDaysBeforeExpiry; + EmailAtPercentageLifetime = emailAtPercentageLifetime; + ReuseKeyOnRenewal = reuseKeyOnRenewal; + SecretContentType = secretContentType; + SubjectName = subjectName; + ValidityInMonths = validityInMonths; + Kty = keyTypeToUse; + Curve = curve; + KeySize = keySizeToUse; + Exportable = exportable; + CertificateTransparency = certificateTransparency; + } + internal CertificatePolicy ToCertificatePolicy() { var certificatePolicy = new CertificatePolicy(); @@ -58,6 +118,7 @@ internal CertificatePolicy ToCertificatePolicy() if (!string.IsNullOrWhiteSpace(Kty) || KeySize.HasValue || + !string.IsNullOrWhiteSpace(Curve) || ReuseKeyOnRenewal.HasValue || Exportable.HasValue) { @@ -65,6 +126,7 @@ internal CertificatePolicy ToCertificatePolicy() { KeyType = Kty, KeySize = KeySize, + Curve = Curve, Exportable = Exportable, ReuseKey = ReuseKeyOnRenewal, }; @@ -219,6 +281,7 @@ internal static PSKeyVaultCertificatePolicy FromCertificatePolicy(CertificatePol SecretContentType = certificatePolicy.SecretProperties == null ? null : certificatePolicy.SecretProperties.ContentType, Kty = certificatePolicy.KeyProperties == null ? null : certificatePolicy.KeyProperties.KeyType, KeySize = certificatePolicy.KeyProperties == null ? null : certificatePolicy.KeyProperties.KeySize, + Curve = certificatePolicy.KeyProperties == null ? null : certificatePolicy.KeyProperties.Curve, Exportable = certificatePolicy.KeyProperties == null ? null : certificatePolicy.KeyProperties.Exportable, ReuseKeyOnRenewal = certificatePolicy.KeyProperties == null ? null : certificatePolicy.KeyProperties.ReuseKey, SubjectName = certificatePolicy.X509CertificateProperties == null ? null : certificatePolicy.X509CertificateProperties.Subject, @@ -263,5 +326,222 @@ internal static PSKeyVaultCertificatePolicy FromCertificatePolicy(CertificatePol return intValueGetter(lifetimeAction.Trigger); } + + private void ValidateInternal( + IList dnsNames, + IList ekus, + int? renewAtNumberOfDaysBeforeExpiry, + int? renewAtPercentageLifetime, + int? emailAtNumberOfDaysBeforeExpiry, + int? emailAtPercentageLifetime, + string subjectName, + string keyType, + int keySize, + string curve) + { + var keyTypeToUse = GetDefaultKeyTypeIfNotSpecified(keyType); + ValidateKeyTypeAndCurve(keyTypeToUse, curve); + + var keySizeToUse = GetDefaultKeySizeIfNotSpecified(keyTypeToUse, curve, keySize); + ValidateKeyTypeAndKeySize(keyTypeToUse, keySizeToUse); + ValidateCurveAndKeySize(curve, keySizeToUse); + + ValidatePercentageAndNumberOfDaysForEmailAndRenew(renewAtNumberOfDaysBeforeExpiry, renewAtPercentageLifetime, emailAtNumberOfDaysBeforeExpiry, emailAtPercentageLifetime); + ValidateEkus(ekus); + ValidateDnsNames(dnsNames); + ValidateSubjectName(subjectName); + } + + public void Validate() + { + ValidateInternal( + DnsNames, + Ekus, + RenewAtNumberOfDaysBeforeExpiry, + RenewAtPercentageLifetime, + EmailAtNumberOfDaysBeforeExpiry, + EmailAtPercentageLifetime, + SubjectName, + Kty, + KeySize ?? 0, + Curve); + } + + private string GetDefaultKeyTypeIfNotSpecified(string keyType) + { + return string.IsNullOrWhiteSpace(keyType) ? Constants.RSA : keyType; + } + + private void ValidateKeyTypeAndCurve(string keyType, string curve) + { + if (Constants.RSA.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.RSAHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + if (!string.IsNullOrWhiteSpace(curve)) + { + throw new ArgumentException($"Curve cannot be specified with {keyType} key type."); + } + } + + if (Constants.EC.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.ECHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + if (string.IsNullOrWhiteSpace(curve)) + { + throw new ArgumentException($"Curve must be specified with {keyType} key type."); + } + } + } + + private int GetDefaultKeySizeIfNotSpecified(string keyType, string curve, int keySize) + { + if (keySize == 0) + { + if (Constants.RSA.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.RSAHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + return 2048; + } + + if (Constants.EC.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.ECHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + if (Constants.P256.Equals(curve, StringComparison.OrdinalIgnoreCase) || + Constants.P256K.Equals(curve, StringComparison.OrdinalIgnoreCase) || + Constants.SECP256K1.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + return 256; + } + + if (Constants.P384.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + return 384; + } + + if (Constants.P521.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + return 521; + } + } + } + + return keySize; + } + + private void ValidateKeyTypeAndKeySize(string keyType, int keySize) + { + if (Constants.RSA.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.RSAHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + if (keySize == 256 || keySize == 384 || keySize == 521) + { + throw new ArgumentException($"{keySize} cannot be specified with {keyType} key type. Valid values for KeySize are: 2048, 3084, and 4096."); + } + } + + if (Constants.EC.Equals(keyType, StringComparison.OrdinalIgnoreCase) || + Constants.ECHSM.Equals(keyType, StringComparison.OrdinalIgnoreCase)) + { + if (keySize == 2048 || keySize == 3084 || keySize == 4096) + { + throw new ArgumentException($"{keySize} cannot be specified with {keyType} key type. Valid values for KeySize are: 256, 384, and 521."); + } + } + } + + private void ValidateCurveAndKeySize(string curve, int keySize) + { + if (string.IsNullOrWhiteSpace(curve)) + { + return; + } + + if (Constants.P256.Equals(curve, StringComparison.OrdinalIgnoreCase) || + Constants.P256K.Equals(curve, StringComparison.OrdinalIgnoreCase) || + Constants.SECP256K1.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + if (keySize != 256) + { + throw new ArgumentException($"Only key size of 256 is allowed with {curve}."); + } + } + + if (Constants.P384.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + if (keySize != 384) + { + throw new ArgumentException($"Only key size of 384 is allowed with {curve}."); + } + } + + if (Constants.P521.Equals(curve, StringComparison.OrdinalIgnoreCase)) + { + if (keySize != 521) + { + throw new ArgumentException($"Only key size of 521 is allowed with {curve}."); + } + } + } + + private void ValidatePercentageAndNumberOfDaysForEmailAndRenew( + int? renewAtNumberOfDaysBeforeExpiry, + int? renewAtPercentageLifetime, + int? emailAtNumberOfDaysBeforeExpiry, + int? emailAtPercentageLifetime) + { + if (renewAtNumberOfDaysBeforeExpiry.HasValue && renewAtPercentageLifetime.HasValue && emailAtNumberOfDaysBeforeExpiry.HasValue && emailAtPercentageLifetime.HasValue) + { + throw new ArgumentException("Only one of the values for RenewAtNumberOfDaysBeforeExpiry, RenewAtPercentageLifetime, EmailAtNumberOfDaysBeforeExpiry, EmailAtPercentageLifetime can be specified."); + } + } + + private void ValidateEkus(IList ekus) + { + if (ekus == null || !ekus.Any()) + { + return; + } + + foreach (var eku in ekus) + { + if (string.IsNullOrWhiteSpace(eku)) + { + throw new ArgumentException("One of the EKUs provided is empty."); + } + } + } + + private void ValidateDnsNames(IList dnsNames) + { + if (dnsNames == null || !dnsNames.Any()) + { + return; + } + + foreach (var dnsName in dnsNames) + { + if (string.IsNullOrWhiteSpace(dnsName)) + { + throw new ArgumentException("One of the DNS names provided is empty."); + } + } + } + + private void ValidateSubjectName(string subjectName) + { + if (string.IsNullOrWhiteSpace(subjectName)) + { + return; + } + + try + { + new X500DistinguishedName(subjectName); + } + catch (CryptographicException e) + { + throw new ArgumentException("The subject name provided is not a valid X500 name.", e); + } + } } } diff --git a/src/KeyVault/KeyVault/help/New-AzKeyVaultCertificatePolicy.md b/src/KeyVault/KeyVault/help/New-AzKeyVaultCertificatePolicy.md index c677c12c6857..a731d4c05a98 100644 --- a/src/KeyVault/KeyVault/help/New-AzKeyVaultCertificatePolicy.md +++ b/src/KeyVault/KeyVault/help/New-AzKeyVaultCertificatePolicy.md @@ -21,7 +21,7 @@ New-AzKeyVaultCertificatePolicy [-IssuerName] [-SubjectName] [-KeyUsage ] [-Ekus ] [-ValidityInMonths ] [-CertificateType ] [-EmailAtNumberOfDaysBeforeExpiry ] [-EmailAtPercentageLifetime ] - [-KeySize ] [-KeyType ] [-KeyNotExportable] [-DefaultProfile ] [-WhatIf] [-Confirm] + [-KeySize ] [-KeyType ] [-Curve ] [-KeyNotExportable] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` @@ -33,7 +33,7 @@ New-AzKeyVaultCertificatePolicy [-IssuerName] [[-SubjectName] ] [-KeyUsage ] [-Ekus ] [-ValidityInMonths ] [-CertificateType ] [-EmailAtNumberOfDaysBeforeExpiry ] [-EmailAtPercentageLifetime ] - [-KeySize ] [-KeyType ] [-KeyNotExportable] [-DefaultProfile ] [-WhatIf] [-Confirm] + [-KeySize ] [-KeyType ] [-Curve ] [-KeyNotExportable] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` @@ -49,6 +49,7 @@ PS C:\> New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12 SecretContentType : application/x-pkcs12 Kty : KeySize : 2048 +Curve : Exportable : ReuseKeyOnRenewal : True SubjectName : CN=contoso.com @@ -213,12 +214,15 @@ The acceptable values for this parameter are: - 2048 - 3072 - 4096 +- 256 +- 384 +- 521 ```yaml Type: System.Int32 Parameter Sets: (All) Aliases: -Accepted values: 2048, 3072, 4096 +Accepted values: 2048, 3072, 4096, 256, 384, 521 Required: False Position: Named @@ -232,12 +236,36 @@ Specifies the key type of the key that backs the certificate. The acceptable values for this parameter are: - RSA - RSA-HSM +- EC +- EC-HSM ```yaml Type: System.String Parameter Sets: (All) Aliases: -Accepted values: RSA, RSA-HSM +Accepted values: RSA, RSA-HSM, EC, EC-HSM + +Required: False +Position: Named +Default value: RSA +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + +### -Curve +Specifies the elliptic curve name of the key of the certificate. +The acceptable values for this parameter are: +- P-256 +- P-384 +- P-521 +- P-256K +- SECP256K1 + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: +Accepted values: P-256, P-384, P-521, P-256K, SECP256K1 Required: False Position: Named diff --git a/src/KeyVault/KeyVault/help/Set-AzKeyVaultCertificatePolicy.md b/src/KeyVault/KeyVault/help/Set-AzKeyVaultCertificatePolicy.md index 1b9d0a36597d..b927a4097d31 100644 --- a/src/KeyVault/KeyVault/help/Set-AzKeyVaultCertificatePolicy.md +++ b/src/KeyVault/KeyVault/help/Set-AzKeyVaultCertificatePolicy.md @@ -21,7 +21,7 @@ Set-AzKeyVaultCertificatePolicy [-VaultName] [-Name] [-RenewAt [-KeyUsage ] [-Ekus ] [-ValidityInMonths ] [-IssuerName ] [-CertificateType ] [-EmailAtNumberOfDaysBeforeExpiry ] [-EmailAtPercentageLifetime ] - [-KeySize ] [-KeyType ] [-KeyNotExportable] [-CertificateTransparency ] [-PassThru] + [-KeySize ] [-KeyType ] [-Curve ] [-KeyNotExportable] [-CertificateTransparency ] [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` @@ -29,7 +29,7 @@ Set-AzKeyVaultCertificatePolicy [-VaultName] [-Name] [-RenewAt ``` Set-AzKeyVaultCertificatePolicy [-VaultName] [-Name] [-InputObject] [-EmailAtNumberOfDaysBeforeExpiry ] - [-EmailAtPercentageLifetime ] [-KeySize ] [-KeyType ] [-CertificateTransparency ] [-PassThru] + [-EmailAtPercentageLifetime ] [-KeySize ] [-KeyType ] [-Curve ] [-CertificateTransparency ] [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` @@ -41,7 +41,7 @@ Set-AzKeyVaultCertificatePolicy [-VaultName] [-Name] -RenewAtN [-KeyUsage ] [-Ekus ] [-ValidityInMonths ] [-IssuerName ] [-CertificateType ] [-EmailAtNumberOfDaysBeforeExpiry ] [-EmailAtPercentageLifetime ] - [-KeySize ] [-KeyType ] [-KeyNotExportable] [-CertificateTransparency ] [-PassThru] + [-KeySize ] [-KeyType ] [-Curve ] [-KeyNotExportable] [-CertificateTransparency ] [-PassThru] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` @@ -57,6 +57,7 @@ PS C:\> Set-AzKeyVaultCertificatePolicy -VaultName "ContosoKV01" -Name "TestCert SecretContentType : application/x-pkcs12 Kty : KeySize : 2048 +Curve : Exportable : ReuseKeyOnRenewal : True SubjectName : CN=contoso.com @@ -251,16 +252,19 @@ The acceptable values for this parameter are: - 2048 - 3072 - 4096 +- 256 +- 384 +- 521 ```yaml Type: System.Int32 Parameter Sets: (All) Aliases: -Accepted values: 2048, 3072, 4096 +Accepted values: 2048, 3072, 4096, 256, 384, 521 Required: False Position: Named -Default value: None +Default value: 2048 Accept pipeline input: True (ByPropertyName) Accept wildcard characters: False ``` @@ -270,20 +274,44 @@ Specifies the key type of the key that backs the certificate. The acceptable values for this parameter are: - RSA - RSA-HSM +- EC +- EC-HSM ```yaml Type: System.String Parameter Sets: (All) Aliases: -Accepted values: RSA, RSA-HSM +Accepted values: RSA, RSA-HSM, EC, EC-HSM Required: False Position: Named -Default value: None +Default value: RSA Accept pipeline input: False Accept wildcard characters: False ``` +### -Curve +Specifies the elliptic curve name of the key of the certificate. +The acceptable values for this parameter are: +- P-256 +- P-384 +- P-521 +- P-256K +- SECP256K1 + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: +Accepted values: P-256, P-384, P-521, P-256K, SECP256K1 + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + ### -KeyUsage Specifies the key usages in the certificate.