diff --git a/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1 b/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1 index 300737836edb..5b8ba018a37e 100644 --- a/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1 +++ b/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1 @@ -1,8 +1,34 @@ -$vaultName = 'yemingkv27' +$vaultName = 'bez-kv0824' . "$PSScriptRoot\..\Scripts\Common.ps1" +Describe "Create key" { + It "should create RSA keys" { + $keyName = Get-KeyName + $key = Add-AzKeyVaultKey -VaultName $vaultName -Name $keyName -Destination Software + $key.KeyType | Should -Be "RSA" + $key.KeySize | Should -Be 2048 + + $keyName = Get-KeyName + $key = Add-AzKeyVaultKey -VaultName $vaultName -Name $keyName -Destination Software -Size 4096 + $key.KeyType | Should -Be "RSA" + $key.KeySize | Should -Be 4096 + } + + It "should create EC keys" { + $keyName = Get-KeyName + $key = Add-AzKeyVaultKey -VaultName $vaultName -Name $keyName -Destination Software -KeyType EC + $key.KeyType | Should -Be "EC" + $key.Key.CurveName | Should -Be "P-256" + + $keyName = Get-KeyName + $key = Add-AzKeyVaultKey -VaultName $vaultName -Name $keyName -Destination Software -KeyType EC -CurveName P-384 + $key.KeyType | Should -Be "EC" + $key.Key.CurveName | Should -Be "P-384" + } +} + Describe "Update key" { It "should update multiple versions" { $keyName = Get-KeyName @@ -18,7 +44,7 @@ Describe "Update key" { } } -Describe "Add key" { +Describe "Import key" { It "should throw when key type EC and curve name are not paired" { { Add-AzKeyVaultKey -VaultName veakkine-kv -Name PSECImportedKey -KeyFilePath E:\targetBlob.byok -KeyType EC -ErrorAction Stop diff --git a/src/KeyVault/KeyVault/ChangeLog.md b/src/KeyVault/KeyVault/ChangeLog.md index 3d4f0f9a7235..1fef91b8a7ad 100644 --- a/src/KeyVault/KeyVault/ChangeLog.md +++ b/src/KeyVault/KeyVault/ChangeLog.md @@ -18,6 +18,7 @@ - Additional information about change #1 --> ## Upcoming Release +* Supported adding EC keys in key vault [#15699] ## Version 3.4.5 * Removed duplicate list item in `Get-AzKeyVault` [#15164] diff --git a/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs b/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs index a9c1c576c3fe..8700f4b24882 100644 --- a/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs +++ b/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs @@ -278,6 +278,12 @@ public class AddAzureKeyVaultKey : KeyVaultCmdletBase ParameterSetName = HsmInputObjectCreateParameterSet)] [Parameter(Mandatory = true, ParameterSetName = HsmResourceIdCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = InteractiveCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = InputObjectCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = ResourceIdCreateParameterSet)] [Parameter(Mandatory = false, ParameterSetName = InteractiveImportParameterSet)] [Parameter(Mandatory = false, @@ -294,6 +300,12 @@ public class AddAzureKeyVaultKey : KeyVaultCmdletBase ParameterSetName = HsmInputObjectCreateParameterSet)] [Parameter(Mandatory = false, ParameterSetName = HsmResourceIdCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = InteractiveCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = InputObjectCreateParameterSet)] + [Parameter(Mandatory = false, + ParameterSetName = ResourceIdCreateParameterSet)] [Parameter(Mandatory = false, ParameterSetName = InteractiveImportParameterSet)] [Parameter(Mandatory = false, @@ -364,12 +376,12 @@ private PSKeyVaultKey CreateKeyVaultKey() { if (string.IsNullOrEmpty(KeyFilePath)) { - return this.DataServiceClient.CreateKey( + return this.Track2DataClient.CreateKey( VaultName, Name, CreateKeyAttributes(), Size, - null); + CurveName); } else { @@ -405,7 +417,17 @@ internal PSKeyVaultKeyAttributes CreateKeyAttributes() { if (!string.IsNullOrEmpty(VaultName) && !string.IsNullOrEmpty(Destination)) { - KeyType = (HsmDestination.Equals(Destination, StringComparison.OrdinalIgnoreCase)) ? JsonWebKeyType.RsaHsm : JsonWebKeyType.Rsa; + if (string.IsNullOrEmpty(KeyType)) + { + // Set default value as RSA + KeyType = JsonWebKeyType.Rsa; + } + if(HsmDestination.Equals(Destination, StringComparison.OrdinalIgnoreCase)) + { + if (KeyType == JsonWebKeyType.Rsa) KeyType = JsonWebKeyType.RsaHsm; + else if (KeyType == JsonWebKeyType.EllipticCurve) KeyType = JsonWebKeyType.EllipticCurveHsm; + // oct (AES) is only supported by managed HSM + } } return new Models.PSKeyVaultKeyAttributes( diff --git a/src/KeyVault/KeyVault/KeyVault.format.ps1xml b/src/KeyVault/KeyVault/KeyVault.format.ps1xml index 7380233c29e0..75bfa4f6af86 100644 --- a/src/KeyVault/KeyVault/KeyVault.format.ps1xml +++ b/src/KeyVault/KeyVault/KeyVault.format.ps1xml @@ -84,6 +84,10 @@ KeySize + + + CurveName + Version @@ -212,6 +216,10 @@ KeySize + + + CurveName + Id diff --git a/src/KeyVault/KeyVault/Models/KeyVaultDataServiceClient.cs b/src/KeyVault/KeyVault/Models/KeyVaultDataServiceClient.cs index 7bfca9ef47f3..0c7e1be7d3bb 100644 --- a/src/KeyVault/KeyVault/Models/KeyVaultDataServiceClient.cs +++ b/src/KeyVault/KeyVault/Models/KeyVaultDataServiceClient.cs @@ -80,7 +80,8 @@ public PSKeyVaultKey CreateKey(string vaultName, string keyName, PSKeyVaultKeyAt keySize: size, keyOps: keyAttributes.KeyOps == null ? null : new List(keyAttributes.KeyOps), keyAttributes: attributes, - tags: keyAttributes.TagsDirectionary).GetAwaiter().GetResult(); + tags: keyAttributes.TagsDirectionary, + curve: curveName).GetAwaiter().GetResult(); } catch (Exception ex) { diff --git a/src/KeyVault/KeyVault/Models/PSDeletedKeyVaultKey.cs b/src/KeyVault/KeyVault/Models/PSDeletedKeyVaultKey.cs index 69072ce94c04..8fbdd17f13e3 100644 --- a/src/KeyVault/KeyVault/Models/PSDeletedKeyVaultKey.cs +++ b/src/KeyVault/KeyVault/Models/PSDeletedKeyVaultKey.cs @@ -78,6 +78,7 @@ internal PSDeletedKeyVaultKey(DeletedKey deletedKey, VaultUriHelper vaultUriHelp SetObjectIdentifier(vaultUriHelper, new Microsoft.Azure.KeyVault.KeyIdentifier(deletedKey.Id.ToString())); Key = deletedKey.Key.ToTrack1JsonWebKey(); + KeySize = JwkHelper.ConvertToRSAKey(Key)?.KeySize; Attributes = new PSKeyVaultKeyAttributes( deletedKey.Properties.Enabled, /// see https://docs.microsoft.com/en-us/dotnet/standard/datetime/converting-between-datetime-and-offset#conversions-from-datetimeoffset-to-datetime @@ -112,6 +113,11 @@ public string KeyType get { return Key.Kty; } } + public string CurveName + { + get { return Key.CurveName; } + } + public int? KeySize; } } diff --git a/src/KeyVault/KeyVault/Models/PSKeyVaultKey.cs b/src/KeyVault/KeyVault/Models/PSKeyVaultKey.cs index b1b6f1f4550b..f9d4a1818fae 100644 --- a/src/KeyVault/KeyVault/Models/PSKeyVaultKey.cs +++ b/src/KeyVault/KeyVault/Models/PSKeyVaultKey.cs @@ -73,6 +73,7 @@ internal PSKeyVaultKey(Track2Sdk.KeyVaultKey key, VaultUriHelper vaultUriHelper, SetObjectIdentifier(vaultUriHelper, new Microsoft.Azure.KeyVault.KeyIdentifier(key.Id.ToString())); Key = key.Key.ToTrack1JsonWebKey(); + KeySize = JwkHelper.ConvertToRSAKey(Key)?.KeySize; Attributes = new PSKeyVaultKeyAttributes( key.Properties.Enabled, /// see https://docs.microsoft.com/en-us/dotnet/standard/datetime/converting-between-datetime-and-offset#conversions-from-datetimeoffset-to-datetime @@ -105,6 +106,11 @@ public string KeyType get { return Key.Kty; } } + public string CurveName + { + get { return Key.CurveName; } + } + public int? KeySize; } diff --git a/src/KeyVault/KeyVault/Track2Models/Track2VaultClient.cs b/src/KeyVault/KeyVault/Track2Models/Track2VaultClient.cs index 9b9b94fd2cd1..959972f08064 100644 --- a/src/KeyVault/KeyVault/Track2Models/Track2VaultClient.cs +++ b/src/KeyVault/KeyVault/Track2Models/Track2VaultClient.cs @@ -40,7 +40,7 @@ private PSKeyVaultKey CreateKey(KeyClient client, string keyName, PSKeyVaultKeyA } else if (keyAttributes.KeyType == KeyType.Ec || keyAttributes.KeyType == KeyType.EcHsm) { - options = new CreateEcKeyOptions(keyName, isHsm) { CurveName = string.IsNullOrEmpty(curveName) ? null : new KeyCurveName(curveName) }; + options = new CreateEcKeyOptions(keyName, isHsm) { CurveName = string.IsNullOrEmpty(curveName) ? (KeyCurveName?) null : new KeyCurveName(curveName) }; } else { diff --git a/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md b/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md index ae5661cc6a93..0c972e476613 100644 --- a/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md +++ b/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md @@ -16,8 +16,8 @@ Creates a key in a key vault or imports a key into a key vault. ### InteractiveCreate (Default) ``` Add-AzKeyVaultKey [-VaultName] [-Name] -Destination [-Disable] [-KeyOps ] - [-Expires ] [-NotBefore ] [-Tag ] [-Size ] - [-DefaultProfile ] [-WhatIf] [-Confirm] [] + [-Expires ] [-NotBefore ] [-Tag ] [-Size ] [-KeyType ] + [-CurveName ] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` ### InteractiveImport @@ -46,7 +46,8 @@ Add-AzKeyVaultKey -HsmName [-Name] -KeyFilePath [-Key ``` Add-AzKeyVaultKey [-InputObject] [-Name] -Destination [-Disable] [-KeyOps ] [-Expires ] [-NotBefore ] [-Tag ] [-Size ] - [-DefaultProfile ] [-WhatIf] [-Confirm] [] + [-KeyType ] [-CurveName ] [-DefaultProfile ] [-WhatIf] [-Confirm] + [] ``` ### InputObjectImport @@ -75,8 +76,8 @@ Add-AzKeyVaultKey [-HsmObject] [-Name] -KeyFilePath [-Name] -Destination [-Disable] [-KeyOps ] - [-Expires ] [-NotBefore ] [-Tag ] [-Size ] - [-DefaultProfile ] [-WhatIf] [-Confirm] [] + [-Expires ] [-NotBefore ] [-Tag ] [-Size ] [-KeyType ] + [-CurveName ] [-DefaultProfile ] [-WhatIf] [-Confirm] [] ``` ### ResourceIdImport @@ -135,6 +136,7 @@ Vault/HSM Name : contoso Name : ITSoftware Key Type : RSA Key Size : 2048 +Curve Name : Version : 67da57e9cadf48a2ad8d366b115843ab Id : https://contoso.vault.azure.net:443/keys/ITSoftware/67da57e9cadf48a2ad8d366b115843ab Enabled : True @@ -148,7 +150,29 @@ Tags : This command creates a software-protected key named ITSoftware in the key vault named Contoso. -### Example 2: Create an HSM-protected key +### Example 2: Create an EC key +```powershell +PS C:\> Add-AzKeyVaultKey -VaultName test-kv -Name test-key -Destination Software -KeyType EC + +Vault/HSM Name : test-kv +Name : test-key +Key Type : EC +Key Size : +Curve Name : P-256 +Version : 4da74af2b4fd47d6b1aa0b05c9a2ed13 +Id : https://test-kv.vault.azure.net:443/keys/test-key/4da74af2b4fd47d6b1aa0b05c9a2ed13 +Enabled : True +Expires : +Not Before : +Created : 8/24/2021 6:38:34 AM +Updated : 8/24/2021 6:38:34 AM +Recovery Level : Recoverable+Purgeable +Tags : +``` + +This command creates a software-protected EC key named test-key in the key vault named test-kv. Its curve name is P-256 by default. + +### Example 3: Create an HSM-protected key ```powershell PS C:\> Add-AzKeyVaultKey -VaultName 'contoso' -Name 'ITHsm' -Destination 'HSM' @@ -167,7 +191,7 @@ Tags : This command creates an HSM-protected key in the key vault named Contoso. -### Example 3: Create a key with non-default values +### Example 4: Create a key with non-default values ```powershell PS C:\> $KeyOperations = 'decrypt', 'verify' PS C:\> $Expires = (Get-Date).AddYears(2).ToUniversalTime() @@ -204,7 +228,7 @@ the *Expires* and *NotBefore* parameters created in the previous commands, and t severity and IT. The new key is disabled. You can enable it by using the **Set-AzKeyVaultKey** cmdlet. -### Example 4: Import an HSM-protected key +### Example 5: Import an HSM-protected key ```powershell PS C:\> Add-AzKeyVaultKey -VaultName 'contoso' -Name 'ITByok' -KeyFilePath 'C:\Contoso\ITByok.byok' -Destination 'HSM' @@ -227,7 +251,7 @@ To import a key from your own hardware security module, you must first generate For more information, see [How to Generate and Transfer HSM-Protected Keys for Azure Key Vault](http://go.microsoft.com/fwlink/?LinkId=522252). -### Example 5: Import a software-protected key +### Example 6: Import a software-protected key ```powershell PS C:\> $Password = ConvertTo-SecureString -String 'Password' -AsPlainText -Force PS C:\> Add-AzKeyVaultKey -VaultName 'contoso' -Name 'ITPfx' -KeyFilePath 'C:\Contoso\ITPfx.pfx' -KeyFilePassword $Password @@ -251,7 +275,7 @@ ConvertTo-SecureString`. The second command creates a software password in the Contoso key vault. The command specifies the location for the key and the password stored in $Password. -### Example 6: Import a key and assign attributes +### Example 7: Import a key and assign attributes ```powershell PS C:\> $Password = ConvertTo-SecureString -String 'password' -AsPlainText -Force PS C:\> $Expires = (Get-Date).AddYears(2).ToUniversalTime() @@ -282,7 +306,7 @@ The final command imports a key as an HSM key from the specified location. The c the expiration time stored in $Expires and password stored in $Password, and applies the tags stored in $tags. -### Example 7: Generate a Key Exchange Key (KEK) for "bring your own key" (BYOK) feature +### Example 8: Generate a Key Exchange Key (KEK) for "bring your own key" (BYOK) feature ```powershell PS C:\> $key = Add-AzKeyVaultKey -VaultName $vaultName -Name $keyName -Destination HSM -Size 2048 -KeyOps "import" @@ -298,7 +322,7 @@ Specifies the curve name of elliptic curve cryptography, this value is valid whe ```yaml Type: System.String -Parameter Sets: InteractiveImport, HsmInteractiveCreate, InputObjectImport, HsmInputObjectCreate, ResourceIdImport, HsmResourceIdCreate +Parameter Sets: InteractiveCreate, InteractiveImport, HsmInteractiveCreate, InputObjectCreate, InputObjectImport, HsmInputObjectCreate, ResourceIdCreate, ResourceIdImport, HsmResourceIdCreate Aliases: Required: False @@ -526,7 +550,7 @@ Specifies the key type of this key. When importing BYOK keys, it defaults to 'RS ```yaml Type: System.String -Parameter Sets: InteractiveImport, InputObjectImport, ResourceIdImport +Parameter Sets: InteractiveCreate, InteractiveImport, InputObjectCreate, InputObjectImport, ResourceIdCreate, ResourceIdImport Aliases: Required: False