Skip to content

Commit 2e8fe0a

Browse files
authored
[KeyVault] Supports creating custom role definitions (#15953)
* [KeyVault] Supports creating custom role definitions * Add ShouldProcess to New-RoleDefinition
1 parent 33040c6 commit 2e8fe0a

33 files changed

+918
-83
lines changed

src/KeyVault/KeyVault.Test/PesterTests/ManagedHsmDataPlaneTests.Tests.ps1

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path) -replace '\.Tests\.', '.'
44

55
. $PSScriptRoot/ManagedHsmDataPlaneTests.ps1
66
# ImportModules
7-
$hsmName = 'bezmhsm'
7+
$hsmName = 'yeminghsm'
88
$signInName = '[email protected]'
99
$storageAccount = 'bezstorageaccount'
1010
$containerName = 'backup'
@@ -171,19 +171,19 @@ Describe "BackupAndRestoreAzManagedHsmKey" {
171171
Describe "BackupAndRestoreAzManagedHsm" {
172172
$script:backupUri = ''
173173
$containerUri = "https://$storageAccount.blob.core.windows.net/$containerName"
174-
It "Backup then restore a managed HSM" {
174+
It "Backup a managed HSM" {
175175
$script:backupUri = Backup-AzKeyVault -HsmName $hsmName -StorageContainerUri $containerUri -SasToken $sasToken
176176
$script:backupUri | Should -Not -Be $null
177177
}
178178

179-
It "Selective restore a managed HSM"{
179+
It "Selective restore a key to managed HSM"{
180180
$script:backupUri = [System.Uri]::new($script:backupUri)
181181
$backupFolder = $script:backupUri.Segments[$script:backupUri.Segments.Length - 1]
182182
$restoreResult = Restore-AzKeyVault -HsmName $hsmName -KeyName $keyName -StorageContainerUri $containerUri -BackupFolder $backupFolder -SasToken $sasToken -PassThru
183183
$restoreResult | Should -Be $True
184184
}
185185

186-
It "Restore a managed HSM" {
186+
It "Restore whole managed HSM" {
187187
$script:backupUri = [System.Uri]::new($script:backupUri)
188188
$backupFolder = $script:backupUri.Segments[$script:backupUri.Segments.Length - 1]
189189
# Clean hsm
@@ -276,4 +276,34 @@ Describe 'Export Import Security domain' {
276276

277277
# Cannot test importing because it needs another HSM
278278
# Import-AzKeyVaultSecurityDomain -Name $hsmName -Keys $certsKeys -SecurityDomainPath $sd.FullName
279+
}
280+
281+
Describe 'Custom Role Definition' {
282+
$roleName = "my custom role"
283+
$roleDesc = "description for my role"
284+
$roleAction = @("Microsoft.KeyVault/managedHsm/roleAssignments/write/action", "Microsoft.KeyVault/managedHsm/roleAssignments/delete/action")
285+
It 'Can create' {
286+
# 0 custom role
287+
Get-AzKeyVaultRoleDefinition -HsmName $hsmName -Custom | Should -BeNullOrEmpty
288+
289+
# create by object
290+
$role = Get-AzKeyVaultRoleDefinition -HsmName $hsmName -RoleDefinitionName 'Managed HSM Crypto User'
291+
$role.Name = $null
292+
$role.RoleName = $roleName
293+
$role.Description = $roleDesc
294+
$role.Permissions[0].AllowedDataActions = $roleAction
295+
New-AzKeyVaultRoleDefinition -HsmName $hsmName -Role $role
296+
297+
# 1 custom role
298+
$actual = Get-AzKeyVaultRoleDefinition -HsmName $hsmName -Custom
299+
$actual | Should -Not -BeNullOrEmpty
300+
$actual.RoleName | Should -Be $roleName
301+
$actual.Description | Should -Be $roleDesc
302+
$actual.Permissions[0].AllowedDataActions | Should -Be $roleAction
303+
}
304+
305+
It 'Can remove' {
306+
Remove-AzKeyVaultRoleDefinition -HsmName $hsmName -RoleName $roleName -Force
307+
Get-AzKeyVaultRoleDefinition -HsmName $hsmName -Custom | Should -BeNullOrEmpty
308+
}
279309
}

src/KeyVault/KeyVault/Az.KeyVault.psd1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ CmdletsToExport = 'Add-AzKeyVaultCertificate', 'Update-AzKeyVaultCertificate',
9696
'Update-AzKeyVaultManagedHsm', 'Get-AzKeyVault', 'New-AzKeyVault',
9797
'Remove-AzKeyVault', 'Undo-AzKeyVaultRemoval', 'Backup-AzKeyVault',
9898
'Restore-AzKeyVault', 'Get-AzKeyVaultRoleDefinition',
99-
'Get-AzKeyVaultRoleAssignment', 'New-AzKeyVaultRoleAssignment',
100-
'Remove-AzKeyVaultRoleAssignment', 'Remove-AzKeyVaultAccessPolicy',
99+
'Get-AzKeyVaultRoleAssignment', 'New-AzKeyVaultRoleAssignment', 'New-AzKeyVaultRoleDefinition',
100+
'Remove-AzKeyVaultRoleDefinition', 'Remove-AzKeyVaultRoleAssignment', 'Remove-AzKeyVaultAccessPolicy',
101101
'Set-AzKeyVaultAccessPolicy', 'Backup-AzKeyVaultKey',
102102
'Get-AzKeyVaultKey', 'Get-AzKeyVaultSecret',
103103
'Undo-AzKeyVaultKeyRemoval', 'Undo-AzKeyVaultSecretRemoval',
@@ -132,7 +132,7 @@ CmdletsToExport = 'Add-AzKeyVaultCertificate', 'Update-AzKeyVaultCertificate',
132132
# VariablesToExport = @()
133133

134134
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
135-
AliasesToExport = 'Set-AzKeyVaultKey', 'Set-AzKeyVaultSecretAttribute',
135+
AliasesToExport = 'Set-AzKeyVaultKey', 'Set-AzKeyVaultRoleDefinition', 'Set-AzKeyVaultSecretAttribute',
136136
'Set-AzKeyVaultKeyAttribute', 'Set-AzKeyVaultCertificateAttribute'
137137

138138
# DSC resources to export from this module

src/KeyVault/KeyVault/ChangeLog.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
- Additional information about change #1
1919
-->
2020
## Upcoming Release
21-
* Supports Encrypt/Decrypt/Wrap/Unwrap using keys [#15679]
21+
* Supported custom role definitions on managed HSM:
22+
- Create via `New-AzKeyVaultRoleDefinition`,
23+
- Delete via `Remove-AzKeyVaultRoleDefinition`,
24+
- Filter all custom roles via `Get-AzKeyVaultRoleDefinition -Custom`.
25+
* Supported Encrypt/Decrypt/Wrap/Unwrap using keys [#15679]
2226
* Enabled managing resources in other subscriptions without switching the context by adding `-Subscription <String>`.
2327

2428
## Version 3.5.0

src/KeyVault/KeyVault/Commands/Constants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static class CmdletNoun
5656
public const string AzureKeyVaultManagedStorageShareSasParameters = "AzureKeyVaultManagedStorageShareSasParameters";
5757
public const string AzureKeyVaultManagedStorageTableSasParameters = "AzureKeyVaultManagedStorageTableSasParameters";
5858
public const string KeyVault = "KeyVault";
59-
public const string KeyVaultHsmRoleDefinition = KeyVault + "RoleDefinition";
59+
public const string KeyVaultRoleDefinition = KeyVault + "RoleDefinition";
6060
public const string KeyVaultRoleAssignment = KeyVault + "RoleAssignment";
6161
}
6262

src/KeyVault/KeyVault/Commands/RBAC/GetAzureManagedHsmRoleAssignment.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.KeyVault.Models;
216
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
317
using Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory;
418
using Microsoft.Azure.Graph.RBAC.Version1_6.Models;

src/KeyVault/KeyVault/Commands/RBAC/GetAzureManagedHsmRoleDefinition.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.KeyVault.Models;
216
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
317
using System;
418
using System.Linq;
519
using System.Management.Automation;
620

721
namespace Microsoft.Azure.Commands.KeyVault.Commands
822
{
9-
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzurePrefix + CmdletNoun.KeyVaultHsmRoleDefinition, DefaultParameterSetName = InteractiveCreateParameterSet)]
23+
[Cmdlet("Get", ResourceManager.Common.AzureRMConstants.AzurePrefix + CmdletNoun.KeyVaultRoleDefinition, DefaultParameterSetName = InteractiveParameterSet)]
1024
[OutputType(typeof(PSKeyVaultRoleDefinition))]
1125
public class GetAzureManagedHsmRoleDefinition : RbacCmdletBase
1226
{
13-
private const string InteractiveCreateParameterSet = "Interactive";
27+
private const string InteractiveParameterSet = "Interactive";
1428
private const string ByNameParameterSet = "ByName";
29+
private const string CustomOnlyParameterSet = "CustomOnly";
1530

1631
[Parameter(Mandatory = true, Position = 1,
1732
HelpMessage = "Name of the HSM.")]
@@ -21,6 +36,10 @@ public class GetAzureManagedHsmRoleDefinition : RbacCmdletBase
2136
[Parameter(Mandatory = false, HelpMessage = "Scope at which the role assignment or definition applies to, e.g., '/' or '/keys' or '/keys/{keyName}'.")]
2237
public string Scope { get; set; } = string.Empty;
2338

39+
[Parameter(Mandatory = true, ParameterSetName = CustomOnlyParameterSet,
40+
HelpMessage = "If specified, only displays the custom created roles in the directory.")]
41+
public SwitchParameter Custom { get; set; }
42+
2443
[Parameter(ParameterSetName = ByNameParameterSet, Mandatory = true,
2544
HelpMessage = "Name of the role definition to get.")]
2645
[Alias("RoleName")]
@@ -31,12 +50,15 @@ public override void ExecuteCmdlet()
3150
var roleDefinitions = Track2DataClient.GetHsmRoleDefinitions(HsmName, Scope);
3251
switch (ParameterSetName)
3352
{
34-
case InteractiveCreateParameterSet:
53+
case InteractiveParameterSet:
3554
WriteObject(roleDefinitions, enumerateCollection: true);
3655
break;
3756
case ByNameParameterSet:
3857
WriteObject(roleDefinitions.FirstOrDefault(def => string.Equals(RoleDefinitionName, def.RoleName, StringComparison.OrdinalIgnoreCase)));
3958
break;
59+
case CustomOnlyParameterSet:
60+
WriteObject(roleDefinitions.Where(def => def.RoleType == PSKeyVaultRoleDefinition.CustomRoleType), enumerateCollection: true);
61+
break;
4062
}
4163
}
4264
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.Common.Exceptions;
16+
using Microsoft.Azure.Commands.KeyVault.Models;
17+
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
18+
using Microsoft.WindowsAzure.Commands.Utilities.Common;
19+
using Newtonsoft.Json;
20+
using System;
21+
using System.IO;
22+
using System.Management.Automation;
23+
24+
namespace Microsoft.Azure.Commands.KeyVault.Commands
25+
{
26+
[Cmdlet("New", ResourceManager.Common.AzureRMConstants.AzurePrefix + CmdletNoun.KeyVaultRoleDefinition, DefaultParameterSetName = InputObjectParameterSet, SupportsShouldProcess = true)]
27+
[Alias("Set-" + ResourceManager.Common.AzureRMConstants.AzurePrefix + CmdletNoun.KeyVaultRoleDefinition)]
28+
[OutputType(typeof(PSKeyVaultRoleDefinition))]
29+
public class NewAzureKeyVaultRoleDefinition : RbacCmdletBase
30+
{
31+
private const string InputObjectParameterSet = "InputObject";
32+
private const string InputFileParameterSet = "InputFile";
33+
34+
[Parameter(Mandatory = true, Position = 1, HelpMessage = "Name of the HSM.")]
35+
[ResourceNameCompleter(ResourceType.ManagedHsm, "IntentionalFakeParameterName")]
36+
public string HsmName { get; set; }
37+
38+
[Parameter(Mandatory = false, HelpMessage = "Scope at which the role assignment or definition applies to, e.g., '/' or '/keys' or '/keys/{keyName}'. '/' is used when omitted.")]
39+
public string Scope { get; set; } = "/";
40+
41+
[ValidateNotNullOrEmpty]
42+
[Parameter(ParameterSetName = InputObjectParameterSet, Mandatory = true, Position = 2, HelpMessage = "A role definition object.")]
43+
public PSKeyVaultRoleDefinition Role { get; set; }
44+
45+
[ValidateNotNullOrEmpty]
46+
[Parameter(ParameterSetName = InputFileParameterSet, Mandatory = true, Position = 2, HelpMessage = "File name containing a single role definition.")]
47+
public string InputFile { get; set; }
48+
49+
public override void ExecuteCmdlet()
50+
{
51+
if (ParameterSetName == InputFileParameterSet)
52+
{
53+
string fileName = this.TryResolvePath(InputFile);
54+
if (!(new FileInfo(fileName)).Exists)
55+
{
56+
throw new AzPSArgumentException(string.Format("File {0} does not exist", fileName), nameof(InputFile));
57+
}
58+
59+
try
60+
{
61+
Role = JsonConvert.DeserializeObject<PSKeyVaultRoleDefinition>(File.ReadAllText(fileName));
62+
}
63+
catch (JsonException)
64+
{
65+
WriteVerbose("Failed to deserialize the input role definition file.");
66+
throw;
67+
}
68+
}
69+
base.ConfirmAction(
70+
"Creating custom role",
71+
HsmName, () =>
72+
{
73+
WriteObject(Track2DataClient.CreateOrUpdateHsmRoleDefinition(HsmName, Scope, Role));
74+
});
75+
}
76+
}
77+
}

src/KeyVault/KeyVault/Commands/RBAC/NewAzureManagedHsmRoleAssignment.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.KeyVault.Models;
216
using Microsoft.Azure.Commands.KeyVault.Properties;
317
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
418
using Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory;

src/KeyVault/KeyVault/Commands/RBAC/RbacCmdletBase.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.KeyVault.Models;
216
using Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory;
317
using System;
418
using System.Linq;
519

620
namespace Microsoft.Azure.Commands.KeyVault.Commands
721
{
8-
public class RbacCmdletBase: KeyVaultCmdletBase
22+
public class RbacCmdletBase : KeyVaultCmdletBase
923
{
1024
private ActiveDirectoryClient _activeDirectoryClient;
1125

src/KeyVault/KeyVault/Commands/RBAC/RemoveAzureManagedHsmRoleAssignment.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
using Microsoft.Azure.Commands.KeyVault.Models;
1+
// ----------------------------------------------------------------------------------
2+
//
3+
// Copyright Microsoft Corporation
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
// ----------------------------------------------------------------------------------
14+
15+
using Microsoft.Azure.Commands.KeyVault.Models;
216
using Microsoft.Azure.Commands.KeyVault.Properties;
317
using Microsoft.Azure.Commands.ResourceManager.Common.ArgumentCompleters;
418
using Microsoft.Azure.Graph.RBAC.Version1_6.ActiveDirectory;

0 commit comments

Comments
 (0)