diff --git a/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1 b/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1
index 7e28e1be08e6..300737836edb 100644
--- a/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1
+++ b/src/KeyVault/KeyVault.Test/PesterTests/Key.Tests.ps1
@@ -16,4 +16,15 @@ Describe "Update key" {
Get-AzKeyVaultKey -VaultName $vaultName -Name $keyName -IncludeVersions | Update-AzKeyVaultKey -Enable $true
Get-AzKeyVaultKey -VaultName $vaultName -Name $keyName -IncludeVersions | ForEach-Object { $_.Enabled | Should -BeTrue }
}
+}
+
+Describe "Add 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
+ } | Should -Throw "CurveName"
+ {
+ Add-AzKeyVaultKey -VaultName veakkine-kv -Name PSECImportedKey -KeyFilePath E:\targetBlob.byok -CurveName P-256 -ErrorAction Stop
+ } | Should -Throw "KeyType"
+ }
}
\ No newline at end of file
diff --git a/src/KeyVault/KeyVault/ChangeLog.md b/src/KeyVault/KeyVault/ChangeLog.md
index 414ccec27be2..e16a1798805f 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 specifying key type and curve name when importing keys via a BYOK file
## Version 3.3.1
* Fixed an issue in Secret Management module
diff --git a/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs b/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs
index cdf43c829af7..a9c1c576c3fe 100644
--- a/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs
+++ b/src/KeyVault/KeyVault/Commands/AddAzureKeyVaultKey.cs
@@ -12,6 +12,8 @@
// limitations under the License.
// ----------------------------------------------------------------------------------
+using Microsoft.Azure.Commands.Common.Exceptions;
+using Microsoft.Azure.Commands.KeyVault.Helpers;
using Microsoft.Azure.Commands.KeyVault.Models;
using Microsoft.Azure.Commands.KeyVault.Properties;
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
@@ -271,11 +273,17 @@ public class AddAzureKeyVaultKey : KeyVaultCmdletBase
[Parameter(Mandatory = true,
ParameterSetName = HsmInteractiveCreateParameterSet,
- HelpMessage = "Specifies the key type of this key.")]
+ HelpMessage = "Specifies the key type of this key. When importing BYOK keys, it defaults to 'RSA'.")]
[Parameter(Mandatory = true,
ParameterSetName = HsmInputObjectCreateParameterSet)]
[Parameter(Mandatory = true,
ParameterSetName = HsmResourceIdCreateParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = InteractiveImportParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = InputObjectImportParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ResourceIdImportParameterSet)]
[PSArgumentCompleter("RSA", "EC", "oct")]
public string KeyType { get; set; }
@@ -286,6 +294,12 @@ public class AddAzureKeyVaultKey : KeyVaultCmdletBase
ParameterSetName = HsmInputObjectCreateParameterSet)]
[Parameter(Mandatory = false,
ParameterSetName = HsmResourceIdCreateParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = InteractiveImportParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = InputObjectImportParameterSet)]
+ [Parameter(Mandatory = false,
+ ParameterSetName = ResourceIdImportParameterSet)]
[PSArgumentCompleter("P-256", "P-256K", "P-384", "P-521")]
public string CurveName { get; set; }
#endregion
@@ -405,6 +419,8 @@ internal PSKeyVaultKeyAttributes CreateKeyAttributes()
internal JsonWebKey CreateWebKeyFromFile()
{
+ ValidateEcParameters();
+
FileInfo keyFile = new FileInfo(this.GetUnresolvedProviderPathFromPSPath(this.KeyFilePath));
if (!keyFile.Exists)
{
@@ -412,7 +428,26 @@ internal JsonWebKey CreateWebKeyFromFile()
}
var converterChain = WebKeyConverterFactory.CreateConverterChain();
- return converterChain.ConvertKeyFromFile(keyFile, KeyFilePassword);
+ var converterExtraInfo = new WebKeyConverterExtraInfo()
+ {
+ KeyType = KeyType,
+ CurveName = CurveName
+ };
+
+ return converterChain.ConvertKeyFromFile(keyFile, KeyFilePassword, converterExtraInfo);
+ }
+
+ private void ValidateEcParameters()
+ {
+ if (JwkHelper.IsEC(KeyType) && string.IsNullOrEmpty(CurveName))
+ {
+ throw new AzPSArgumentException(Resources.EcButNoCurveName, nameof(CurveName));
+ }
+
+ if (!string.IsNullOrEmpty(CurveName) && !JwkHelper.IsEC(KeyType))
+ {
+ throw new AzPSArgumentException(Resources.CurveNameButNotEc, nameof(KeyType));
+ }
}
internal Track2Sdk.JsonWebKey CreateTrack2WebKeyFromFile()
diff --git a/src/KeyVault/KeyVault/Helpers/JwkHelper.cs b/src/KeyVault/KeyVault/Helpers/JwkHelper.cs
index 692c779f1b82..2b13f0c7d0e1 100644
--- a/src/KeyVault/KeyVault/Helpers/JwkHelper.cs
+++ b/src/KeyVault/KeyVault/Helpers/JwkHelper.cs
@@ -137,5 +137,9 @@ private static void EncodeIntegerBigEndian(BinaryWriter stream, byte[] value, bo
}
}
}
+
+ internal static bool IsEC(string keyType) =>
+ string.Equals(keyType, JsonWebKeyType.EllipticCurve, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(keyType, JsonWebKeyType.EllipticCurveHsm, StringComparison.OrdinalIgnoreCase);
}
}
diff --git a/src/KeyVault/KeyVault/Models/ByokWebKeyConverter.cs b/src/KeyVault/KeyVault/Models/ByokWebKeyConverter.cs
index 5994f62039a3..b36b600343dd 100644
--- a/src/KeyVault/KeyVault/Models/ByokWebKeyConverter.cs
+++ b/src/KeyVault/KeyVault/Models/ByokWebKeyConverter.cs
@@ -19,6 +19,8 @@
using Track2Sdk = Azure.Security.KeyVault.Keys;
using Track1Sdk = Microsoft.Azure.KeyVault.WebKey;
using System.Security.Cryptography;
+using Microsoft.Azure.KeyVault.WebKey;
+using Microsoft.Azure.Commands.KeyVault.Helpers;
namespace Microsoft.Azure.Commands.KeyVault.Models
{
@@ -32,12 +34,22 @@ public ByokWebKeyConverter(IWebKeyConverter next = null)
this.next = next;
}
- public Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password)
+ public Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password, WebKeyConverterExtraInfo extraInfo = null)
{
if (CanProcess(fileInfo))
- return Convert(fileInfo.FullName);
+ {
+ var jwk = Convert(fileInfo.FullName);
+
+ if (JwkHelper.IsEC(extraInfo?.KeyType))
+ {
+ jwk.Kty = JsonWebKeyType.EllipticCurveHsm; // byok -> hsm
+ jwk.CurveName = extraInfo.CurveName;
+ }
+
+ return jwk;
+ }
else if (next != null)
- return next.ConvertKeyFromFile(fileInfo, password);
+ return next.ConvertKeyFromFile(fileInfo, password, extraInfo);
else
throw new ArgumentException(string.Format(KeyVaultProperties.Resources.UnsupportedFileFormat, fileInfo.Name));
}
@@ -72,19 +84,19 @@ private Track1Sdk.JsonWebKey Convert(string byokFileName)
T = byokBlob,
};
}
-
+
private Track2Sdk.JsonWebKey ConvertToTrack2SdkJsonWebKey(string byokFileName)
{
byte[] byokBlob = File.ReadAllBytes(byokFileName);
- if (byokBlob == null || byokBlob.Length == 0)
- throw new ArgumentException(string.Format(KeyVaultProperties.Resources.InvalidKeyBlob, "BYOK"));
+ if (byokBlob == null || byokBlob.Length == 0)
+ throw new ArgumentException(string.Format(KeyVaultProperties.Resources.InvalidKeyBlob, "BYOK"));
- return new Track2Sdk.JsonWebKey(new RSACryptoServiceProvider())
- {
- KeyType = Track2Sdk.KeyType.RsaHsm,
- T = byokBlob,
- };
+ return new Track2Sdk.JsonWebKey(new RSACryptoServiceProvider())
+ {
+ KeyType = Track2Sdk.KeyType.RsaHsm,
+ T = byokBlob,
+ };
}
private IWebKeyConverter next;
diff --git a/src/KeyVault/KeyVault/Models/IWebKeyConverter.cs b/src/KeyVault/KeyVault/Models/IWebKeyConverter.cs
index 37abcd1c6b93..1c8d36661f23 100644
--- a/src/KeyVault/KeyVault/Models/IWebKeyConverter.cs
+++ b/src/KeyVault/KeyVault/Models/IWebKeyConverter.cs
@@ -21,10 +21,16 @@ namespace Microsoft.Azure.Commands.KeyVault.Models
{
internal interface IWebKeyConverter
{
- Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password);
+ Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password, WebKeyConverterExtraInfo extraInfo = null);
Track2Sdk.JsonWebKey ConvertToTrack2SdkKeyFromFile(FileInfo fileInfo, SecureString password);
}
-
+ ///
+ /// Extra information you may append to the converted JWK
+ ///
+ internal class WebKeyConverterExtraInfo {
+ public string KeyType;
+ public string CurveName;
+ }
}
diff --git a/src/KeyVault/KeyVault/Models/PfxWebKeyConverter.cs b/src/KeyVault/KeyVault/Models/PfxWebKeyConverter.cs
index d4514d52f961..5f73a7ac3699 100644
--- a/src/KeyVault/KeyVault/Models/PfxWebKeyConverter.cs
+++ b/src/KeyVault/KeyVault/Models/PfxWebKeyConverter.cs
@@ -20,7 +20,6 @@
using KeyVaultProperties = Microsoft.Azure.Commands.KeyVault.Properties;
using Track2Sdk = Azure.Security.KeyVault.Keys;
using Track1Sdk = Microsoft.Azure.KeyVault.WebKey;
-using Microsoft.Azure.KeyVault.WebKey;
namespace Microsoft.Azure.Commands.KeyVault.Models
{
@@ -31,12 +30,12 @@ public PfxWebKeyConverter(IWebKeyConverter next = null)
this.next = next;
}
- public Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password)
+ public Track1Sdk.JsonWebKey ConvertKeyFromFile(FileInfo fileInfo, SecureString password, WebKeyConverterExtraInfo extraInfo = null)
{
if (CanProcess(fileInfo))
return Convert(fileInfo.FullName, password);
if (next != null)
- return next.ConvertKeyFromFile(fileInfo, password);
+ return next.ConvertKeyFromFile(fileInfo, password, extraInfo);
throw new ArgumentException(string.Format(KeyVaultProperties.Resources.UnsupportedFileFormat, fileInfo.Name));
}
@@ -79,7 +78,7 @@ private Track1Sdk.JsonWebKey Convert(string pfxFileName, SecureString pfxPasswor
return CreateJWK(key);
}
-
+
private Track2Sdk.JsonWebKey ConvertToTrack2SdkJsonWebKey(string pfxFileName, SecureString pfxPassword)
{
X509Certificate2 certificate;
@@ -103,7 +102,7 @@ private Track2Sdk.JsonWebKey ConvertToTrack2SdkJsonWebKey(string pfxFileName, Se
// to do: support converting oct to jsonwebKey
throw new ArgumentException(string.Format(KeyVaultProperties.Resources.ImportNotSupported, "oct-HSM"));
-
+
}
private static Track1Sdk.JsonWebKey CreateJWK(RSA rsa)
@@ -151,7 +150,7 @@ private static Track2Sdk.JsonWebKey CreateTrack2SdkJWK(RSA rsa)
private static Track2Sdk.JsonWebKey CreateTrack2SdkJWK(ECDsa ecdSa)
{
- if (ecdSa == null)
+ if (ecdSa == null)
{
throw new ArgumentNullException("ecdSa");
}
diff --git a/src/KeyVault/KeyVault/Properties/Resources.Designer.cs b/src/KeyVault/KeyVault/Properties/Resources.Designer.cs
index 2e2e5ebed8c8..0b538ed84f7a 100644
--- a/src/KeyVault/KeyVault/Properties/Resources.Designer.cs
+++ b/src/KeyVault/KeyVault/Properties/Resources.Designer.cs
@@ -333,6 +333,15 @@ internal static string CreateKeyVault {
}
}
+ ///
+ /// Looks up a localized string similar to When '-CurveName' is specified, '-KeyType' must be 'EC'..
+ ///
+ internal static string CurveNameButNotEc {
+ get {
+ return ResourceManager.GetString("CurveNameButNotEc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Failed to decrypt security domain data. Please make sure the file is not modified and the keys / passwords are correct..
///
@@ -405,6 +414,15 @@ internal static string DownloadSecurityDomainKeyFail {
}
}
+ ///
+ /// Looks up a localized string similar to Please input a valid 'CurveName' when KeyType is 'EC'..
+ ///
+ internal static string EcButNoCurveName {
+ get {
+ return ResourceManager.GetString("EcButNoCurveName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Overwrite File ?.
///
diff --git a/src/KeyVault/KeyVault/Properties/Resources.resx b/src/KeyVault/KeyVault/Properties/Resources.resx
index 15f9cf62b0a5..40df75218fb9 100644
--- a/src/KeyVault/KeyVault/Properties/Resources.resx
+++ b/src/KeyVault/KeyVault/Properties/Resources.resx
@@ -585,4 +585,10 @@ You can find the object ID using Azure Active Directory Module for Windows Power
Failed to selective restore key {0} of managed HSM {1}.
+
+ Please input a valid 'CurveName' when KeyType is 'EC'.
+
+
+ When '-CurveName' is specified, '-KeyType' must be 'EC'.
+
\ No newline at end of file
diff --git a/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md b/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md
index 83d30e510e5b..dafaab931b67 100644
--- a/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md
+++ b/src/KeyVault/KeyVault/help/Add-AzKeyVaultKey.md
@@ -24,8 +24,8 @@ Add-AzKeyVaultKey [-VaultName] [-Name] -Destination [
```
Add-AzKeyVaultKey [-VaultName] [-Name] -KeyFilePath
[-KeyFilePassword ] [-Destination ] [-Disable] [-KeyOps ]
- [-Expires ] [-NotBefore ] [-Tag ] [-DefaultProfile ]
- [-WhatIf] [-Confirm] []
+ [-Expires ] [-NotBefore ] [-Tag ] [-KeyType ] [-CurveName ]
+ [-DefaultProfile ] [-WhatIf] [-Confirm] []
```
### HsmInteractiveCreate
@@ -53,8 +53,8 @@ Add-AzKeyVaultKey [-InputObject] [-Name] -Destination [-Name] -KeyFilePath
[-KeyFilePassword ] [-Destination ] [-Disable] [-KeyOps ]
- [-Expires ] [-NotBefore ] [-Tag ] [-DefaultProfile ]
- [-WhatIf] [-Confirm] []
+ [-Expires ] [-NotBefore ] [-Tag ] [-KeyType ] [-CurveName ]
+ [-DefaultProfile ] [-WhatIf] [-Confirm] []
```
### HsmInputObjectCreate
@@ -83,8 +83,8 @@ Add-AzKeyVaultKey [-ResourceId] [-Name] -Destination
```
Add-AzKeyVaultKey [-ResourceId] [-Name] -KeyFilePath
[-KeyFilePassword ] [-Destination ] [-Disable] [-KeyOps ]
- [-Expires ] [-NotBefore ] [-Tag ] [-DefaultProfile ]
- [-WhatIf] [-Confirm] []
+ [-Expires ] [-NotBefore ] [-Tag ] [-KeyType ] [-CurveName ]
+ [-DefaultProfile ] [-WhatIf] [-Confirm] []
```
### HsmResourceIdCreate
@@ -294,7 +294,7 @@ Specifies the curve name of elliptic curve cryptography, this value is valid whe
```yaml
Type: System.String
-Parameter Sets: HsmInteractiveCreate, HsmInputObjectCreate, HsmResourceIdCreate
+Parameter Sets: InteractiveImport, HsmInteractiveCreate, InputObjectImport, HsmInputObjectCreate, ResourceIdImport, HsmResourceIdCreate
Aliases:
Required: False
@@ -518,7 +518,19 @@ Accept wildcard characters: False
```
### -KeyType
-Specifies the key type of this key.
+Specifies the key type of this key. When importing BYOK keys, it defaults to 'RSA'.
+
+```yaml
+Type: System.String
+Parameter Sets: InteractiveImport, InputObjectImport, ResourceIdImport
+Aliases:
+
+Required: False
+Position: Named
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
```yaml
Type: System.String
diff --git a/src/KeyVault/KeyVault/help/Get-AzKeyVaultKey.md b/src/KeyVault/KeyVault/help/Get-AzKeyVaultKey.md
index 8625d293b9a8..b2088ecad244 100644
--- a/src/KeyVault/KeyVault/help/Get-AzKeyVaultKey.md
+++ b/src/KeyVault/KeyVault/help/Get-AzKeyVaultKey.md
@@ -87,19 +87,19 @@ Get-AzKeyVaultKey [-HsmObject] [-Name] [-IncludeVersions
### ByResourceIdVaultName
```
-Get-AzKeyVaultKey [-ResourceId] [[-Name] ] [-InRemovedState] [-OutFile ]
+Get-AzKeyVaultKey -ResourceId [[-Name] ] [-InRemovedState] [-OutFile ]
[-DefaultProfile ] []
```
### ByResourceIdKeyName
```
-Get-AzKeyVaultKey [-ResourceId] [-Name] [-Version] [-OutFile ]
+Get-AzKeyVaultKey -ResourceId [-Name] [-Version] [-OutFile ]
[-DefaultProfile ] []
```
### ByResourceIdKeyVersions
```
-Get-AzKeyVaultKey [-ResourceId] [-Name] [-IncludeVersions] [-OutFile ]
+Get-AzKeyVaultKey -ResourceId [-Name] [-IncludeVersions] [-OutFile ]
[-DefaultProfile ] []
```
@@ -471,7 +471,7 @@ Parameter Sets: ByResourceIdVaultName, ByResourceIdKeyName, ByResourceIdKeyVersi
Aliases:
Required: True
-Position: 0
+Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False