Skip to content

Commit 5171cc0

Browse files
authored
support byte array in invoke-azkeyvaultkeyoperation (#23706)
1 parent ba60e00 commit 5171cc0

File tree

6 files changed

+215
-83
lines changed

6 files changed

+215
-83
lines changed

src/KeyVault/KeyVault/Az.KeyVault.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ TypesToProcess = @()
7272

7373
# Format files (.ps1xml) to be loaded when importing this module
7474
FormatsToProcess = 'KeyVault.Autorest/Az.KeyVault.format.ps1xml',
75-
'KeyVault.format.ps1xml'
75+
'KeyVault.format.ps1xml', 'keyvault.generated.format.ps1xml'
7676

7777
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
7878
NestedModules = @('./Az.KeyVault.Extension',

src/KeyVault/KeyVault/ChangeLog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
- Additional information about change #1
1919
-->
2020
## Upcoming Release
21+
* Added parameter `ByteArrayValue` in `Invoke-AzKeyVaultKeyOperation` to support operating byte array without conversion to secure string.
22+
* Added Property `RawResult` in the output type `PSKeyOperationResult` of `Invoke-AzKeyVaultKeyOperation`.
23+
* [Upcoming Breaking Change] Added breaking change warning message for parameter `Value` in `Invoke-AzKeyVaultKeyOperation`.
24+
- Parameter `Value` is expected to be removed in Az.KeyVault 6.0.0
25+
- `ByteArrayValue` is the alternative of parameter `Value` in byte array format
26+
* [Upcoming Breaking Change] Added breaking change warning message for the output type `PSKeyOperationResult` of `Invoke-AzKeyVaultKeyOperation`.
27+
- Property `Result` is expected to be removed in Az.KeyVault 6.0.0
28+
- Property `RawResult` is the alternative of parameter `Result` in byte array format
2129

2230
## Version 5.0.1
2331
* Removed redundant Microsoft Graph API calls for access policy in `Get-AzKeyVault`.

src/KeyVault/KeyVault/Commands/Key/InvokeAzureKeyVaultKeyOperation.cs

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
using Microsoft.Azure.Commands.Common.Exceptions;
2+
using Microsoft.Azure.Commands.KeyVault.Models;
23
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
4+
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
5+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
36

47
using System;
8+
using System.Collections;
59
using System.Management.Automation;
610
using System.Security;
711
using System.Text;
@@ -14,6 +18,7 @@ namespace Microsoft.Azure.Commands.KeyVault.Commands.Key
1418
/// 3. Wraps a symmetric key using a specified key.
1519
/// 4. Unwraps a symmetric key using the specified key that was initially used for wrapping that key.
1620
/// </summary>
21+
[CmdletOutputBreakingChangeWithVersion(typeof(PSKeyOperationResult), "12.0.0", "6.0.0", DeprecatedOutputProperties = new string[] { "Result" }, NewOutputProperties = new string[] { "RawResult" })]
1722
[Cmdlet(VerbsLifecycle.Invoke, ResourceManager.Common.AzureRMConstants.AzurePrefix + "KeyVaultKeyOperation", SupportsShouldProcess = true, DefaultParameterSetName = ByVaultNameParameterSet)]
1823
[OutputType(typeof(PSKeyOperationResult))]
1924
public class InvokeAzureKeyVaultKeyOperation : KeyVaultKeyCmdletBase
@@ -52,51 +57,89 @@ enum Operations
5257
[Alias("EncryptionAlgorithm", "WrapAlgorithm")]
5358
public string Algorithm { get; set; }
5459

55-
[Parameter(Mandatory = true,
56-
HelpMessage = "The value to be operated")]
60+
[Parameter(Mandatory = false, HelpMessage = "The value to be operated. This parameter will be converted to byte array in UTF-8 encoding way. If your value can't be encoded by UTF-8, please use parameter ByteArrayValue as its alternative.")]
5761
[ValidateNotNullOrEmpty]
62+
[CmdletParameterBreakingChangeWithVersion(nameof(Value), "12.0.0", "6.0.0", ReplaceMentCmdletParameterName = nameof(ByteArrayValue))]
5863
public SecureString Value { get; set; }
64+
65+
[Parameter(Mandatory = false, HelpMessage = "The value to be operated in byte array format.")]
66+
[ValidateNotNullOrEmpty]
67+
public byte[] ByteArrayValue { get; set; }
68+
5969
#endregion Input Parameter Definitions
6070

71+
private Operations opt = Operations.Unknown;
72+
73+
internal void ValidateParameters()
74+
{
75+
if (this.IsParameterBound(c => c.Value) && this.IsParameterBound(c => c.ByteArrayValue))
76+
{
77+
throw new AzPSArgumentException(string.Format("Please provide only one of parameter Value and ByteArrayValue"), nameof(ByteArrayValue));
78+
}
79+
else if (!this.IsParameterBound(c => c.Value) && !this.IsParameterBound(c => c.ByteArrayValue))
80+
{
81+
throw new AzPSArgumentException(string.Format("Must provide one of parameter Value and ByteArrayValue"), nameof(ByteArrayValue));
82+
}
83+
}
84+
6185
internal override void NormalizeParameterSets()
6286
{
87+
6388
if (InputObject != null)
6489
{
6590
Version = Version ?? InputObject.Version;
6691
}
92+
93+
Enum.TryParse(Operation, out opt);
94+
95+
if (this.IsParameterBound(c => c.Value))
96+
{
97+
switch (opt)
98+
{
99+
case Operations.Encrypt:
100+
ByteArrayValue = Encoding.UTF8.GetBytes(Value.ConvertToString());
101+
break;
102+
case Operations.Decrypt:
103+
ByteArrayValue = Convert.FromBase64String(Value.ConvertToString());
104+
break;
105+
case Operations.Wrap:
106+
ByteArrayValue = Encoding.UTF8.GetBytes(Value.ConvertToString());
107+
break;
108+
case Operations.Unwrap:
109+
ByteArrayValue = Convert.FromBase64String(Value.ConvertToString());
110+
break;
111+
default:
112+
throw new NotSupportedException("Not supported ${Operation} yet");
113+
}
114+
}
115+
67116
base.NormalizeParameterSets();
68117
}
69118

70119
public override void ExecuteCmdlet()
71120
{
121+
ValidateParameters();
72122
NormalizeParameterSets();
73123

74-
Operations opt = Operations.Unknown;
75-
Enum.TryParse(Operation, out opt);
76-
77124
if (string.IsNullOrEmpty(HsmName))
78125
{
79126
switch (opt)
80127
{
81128
case Operations.Encrypt:
82129
this.WriteObject(
83-
this.Track2DataClient.Encrypt(VaultName, Name, Version,
84-
Encoding.UTF8.GetBytes(Value.ConvertToString()), Algorithm));
130+
this.Track2DataClient.Encrypt(VaultName, Name, Version, ByteArrayValue, Algorithm));
85131
break;
86132
case Operations.Decrypt:
87133
this.WriteObject(
88-
this.Track2DataClient.Decrypt(VaultName, Name, Version,
89-
Convert.FromBase64String(Value.ConvertToString()), Algorithm));
134+
this.Track2DataClient.Decrypt(VaultName, Name, Version, ByteArrayValue, Algorithm));
90135
break;
91136
case Operations.Wrap:
92137
this.WriteObject(
93-
this.Track2DataClient.WrapKey(VaultName, Name, Version,
94-
Encoding.UTF8.GetBytes(Value.ConvertToString()), Algorithm));
138+
this.Track2DataClient.WrapKey(VaultName, Name, Version, ByteArrayValue, Algorithm));
95139
break;
96140
case Operations.Unwrap:
97141
this.WriteObject(
98-
this.Track2DataClient.UnwrapKey(VaultName, Name, Version,
99-
Convert.FromBase64String(Value.ConvertToString()), Algorithm));
142+
this.Track2DataClient.UnwrapKey(VaultName, Name, Version, ByteArrayValue, Algorithm));
100143
break;
101144
case Operations.Unknown:
102145
throw new NotSupportedException("Not supported ${Operation} yet");
@@ -108,23 +151,19 @@ public override void ExecuteCmdlet()
108151
{
109152
case Operations.Encrypt:
110153
this.WriteObject(
111-
this.Track2DataClient.ManagedHsmKeyEncrypt(HsmName, Name, Version,
112-
Encoding.UTF8.GetBytes(Value.ConvertToString()), Algorithm));
154+
this.Track2DataClient.ManagedHsmKeyEncrypt(HsmName, Name, Version, ByteArrayValue, Algorithm));
113155
break;
114156
case Operations.Decrypt:
115157
this.WriteObject(
116-
this.Track2DataClient.ManagedHsmKeyDecrypt(HsmName, Name, Version,
117-
Convert.FromBase64String(Value.ConvertToString()), Algorithm));
158+
this.Track2DataClient.ManagedHsmKeyDecrypt(HsmName, Name, Version, ByteArrayValue, Algorithm));
118159
break;
119160
case Operations.Wrap:
120161
this.WriteObject(
121-
this.Track2DataClient.ManagedHsmWrapKey(HsmName, Name, Version,
122-
Encoding.UTF8.GetBytes(Value.ConvertToString()), Algorithm));
162+
this.Track2DataClient.ManagedHsmWrapKey(HsmName, Name, Version, ByteArrayValue, Algorithm));
123163
break;
124164
case Operations.Unwrap:
125165
this.WriteObject(
126-
this.Track2DataClient.ManagedHsmUnwrapKey(HsmName, Name, Version,
127-
Convert.FromBase64String(Value.ConvertToString()), Algorithm));
166+
this.Track2DataClient.ManagedHsmUnwrapKey(HsmName, Name, Version, ByteArrayValue, Algorithm));
128167
break;
129168
case Operations.Unknown:
130169
throw new NotSupportedException("Not supported ${Operation} yet");

src/KeyVault/KeyVault/Models/Key/PSKeyOperationResult.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,63 @@
11
using Azure.Security.KeyVault.Keys.Cryptography;
22

3+
using Microsoft.WindowsAzure.Commands.Common.Attributes;
4+
35
namespace Microsoft.Azure.Commands.KeyVault.Models
46
{
57
/// <summary>
68
///
79
/// </summary>
810
public class PSKeyOperationResult
911
{
12+
1013
// Summary: Key identifier
14+
[Ps1Xml(Target = ViewControl.List, Label = nameof(KeyId), Position = 0)]
1115
public string KeyId { get; }
1216

17+
/// <summary>
18+
/// If operation is Wrap, the value is wrapped key
19+
/// If operation is Unwrap, the value is unwrapped key
20+
/// If operation is Encrypt, the value is encryted data
21+
/// If operation is Decrypt, the value is decrypted data
22+
/// </summary>
23+
[Ps1Xml(Target = ViewControl.List, Label = nameof(RawResult), Position = 1)]
24+
public byte[] RawResult { get; }
25+
1326
// Summary: encryted result or wraped result is base64 format. decryted result or unwraped result is plain text
1427
public string Result { get; }
1528

1629
// Summary: Algorithm used.
30+
[Ps1Xml(Target = ViewControl.List, Label = nameof(Algorithm), Position = 2)]
1731
public string Algorithm { get; }
1832

1933
public PSKeyOperationResult(WrapResult wrapResult)
2034
{
2135
this.KeyId = wrapResult.KeyId;
36+
this.RawResult = wrapResult.EncryptedKey;
2237
this.Result = System.Convert.ToBase64String(wrapResult.EncryptedKey);
2338
this.Algorithm = wrapResult.Algorithm.ToString();
2439
}
2540

2641
public PSKeyOperationResult(UnwrapResult unwrapResult)
2742
{
2843
this.KeyId = unwrapResult.KeyId;
44+
this.RawResult = unwrapResult.Key;
2945
this.Result = System.Text.Encoding.UTF8.GetString(unwrapResult.Key);
3046
this.Algorithm = unwrapResult.Algorithm.ToString();
3147
}
3248

3349
public PSKeyOperationResult(EncryptResult encryptResult)
3450
{
3551
this.KeyId = encryptResult.KeyId;
52+
this.RawResult = encryptResult.Ciphertext;
3653
this.Result = System.Convert.ToBase64String(encryptResult.Ciphertext);
3754
this.Algorithm = encryptResult.Algorithm.ToString();
3855
}
3956

4057
public PSKeyOperationResult(DecryptResult decryptResult)
4158
{
4259
this.KeyId = decryptResult.KeyId;
60+
this.RawResult = decryptResult.Plaintext;
4361
this.Result = System.Text.Encoding.UTF8.GetString(decryptResult.Plaintext);
4462
this.Algorithm = decryptResult.Algorithm.ToString();
4563
}

0 commit comments

Comments
 (0)