-
Notifications
You must be signed in to change notification settings - Fork 4.1k
[Keyvault] ManagedHsm NetworkRuleSet Support #28602
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7df5a0b
52e9ef0
d1e741b
94009a1
a030538
cd3e37b
f63404a
fab4afe
548c04f
f347f61
c5c36e6
d35c833
27c58f6
9ce37ad
ee927a2
23a0875
b9d50f0
3883c7a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
// Code generated by Microsoft (R) AutoRest Code Generator. | ||
// Changes may cause incorrect behavior and will be lost if the code is regenerated. | ||
|
||
namespace Microsoft.Azure.Management.KeyVault.Models | ||
{ | ||
using System.Linq; | ||
|
||
/// <summary> | ||
/// A rule governing the accessibility of a managed hsm pool from a specific | ||
/// service tags. | ||
/// </summary> | ||
public partial class MhsmServiceTagRule | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the MhsmServiceTagRule class. | ||
/// </summary> | ||
public MhsmServiceTagRule() | ||
{ | ||
CustomInit(); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the MhsmServiceTagRule class. | ||
/// </summary> | ||
|
||
/// <param name="tag">Name of the service tag. | ||
/// </param> | ||
public MhsmServiceTagRule(string tag) | ||
|
||
{ | ||
this.Tag = tag; | ||
CustomInit(); | ||
} | ||
|
||
/// <summary> | ||
/// An initialization method that performs custom operations like setting defaults | ||
/// </summary> | ||
partial void CustomInit(); | ||
|
||
|
||
/// <summary> | ||
/// Gets or sets name of the service tag. | ||
/// </summary> | ||
[Newtonsoft.Json.JsonProperty(PropertyName = "tag")] | ||
public string Tag {get; set; } | ||
/// <summary> | ||
/// Validate the object. | ||
/// </summary> | ||
/// <exception cref="Microsoft.Rest.ValidationException"> | ||
/// Thrown if validation fails | ||
/// </exception> | ||
public virtual void Validate() | ||
{ | ||
if (this.Tag == null) | ||
{ | ||
throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.CannotBeNull, "Tag"); | ||
} | ||
|
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// ---------------------------------------------------------------------------------- | ||
// 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.WindowsAzure.Commands.ScenarioTest; | ||
using Xunit; | ||
|
||
namespace Microsoft.Azure.Commands.KeyVault.Test.ScenarioTests | ||
{ | ||
/// <summary> | ||
/// Four independent Facts for visibility/run selection. ONLY the New phase provisions the HSM. | ||
/// The other phases assume the same PowerShell global context (manual sequential run). When | ||
/// invoked individually via xUnit they will fail fast with a clear message if prerequisites are | ||
/// absent. This is intentional to avoid accidental reprovisioning of a long-lived Managed HSM. | ||
/// </summary> | ||
public class ManagedHsmNetworkRuleLifecycleTests : KeyVaultTestRunner | ||
{ | ||
public ManagedHsmNetworkRuleLifecycleTests(Xunit.Abstractions.ITestOutputHelper output) : base(output) | ||
{ | ||
} | ||
|
||
[Fact] | ||
[Trait(Category.AcceptanceType, Category.CheckIn)] | ||
public void TestManagedHsmNetworkRuleLifecycleFullSequence() | ||
{ | ||
TestRunner.RunTestScript( | ||
"Test-ManagedHsmNetworkRuleLifecycle-New", | ||
"Test-ManagedHsmNetworkRuleLifecycle-Add", | ||
"Test-ManagedHsmNetworkRuleLifecycle-Remove", | ||
"Test-ManagedHsmNetworkRuleLifecycle-Update" | ||
); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
# Shared state object to track HSM name, RG, IPs across test phases. | ||
# Each phase is a separate test, so no in-memory state is preserved. | ||
if (-not $Global:MhsmLifecycle) { $Global:MhsmLifecycle = @{} } | ||
|
||
|
||
function Test-ManagedHsmNetworkRuleLifecycle-New { | ||
if ($Global:MhsmLifecycle.HsmName) { | ||
Write-Host "[New] HSM already exists ($($Global:MhsmLifecycle.HsmName))" -ForegroundColor Yellow | ||
return | ||
} | ||
$rgName = getAssetName | ||
$rgLoc = Get-Location "Microsoft.Resources" "resourceGroups" "East US" | ||
$hsmName = getAssetName | ||
$hsmLoc = Get-Location "Microsoft.KeyVault" "managedHSMs" "East US" | ||
|
||
# Replace below with a valid admin object id for recording. | ||
# (Get-AzADUser -SignedIn).Id | ||
$adminId = "e1b70801-ae8d-4cb2-9d6a-12adffdc6856" | ||
|
||
New-AzResourceGroup -Name $rgName -Location $rgLoc | Out-Null | ||
$ip1 = "110.0.1.0/24" | ||
$nr = New-AzKeyVaultManagedHsmNetworkRuleSetObject -DefaultAction Deny -IpAddressRange $ip1 -Bypass AzureServices | ||
$hsm = New-AzKeyVaultManagedHsm -Name $hsmName -ResourceGroupName $rgName -Location $hsmLoc -Administrator $adminId -SoftDeleteRetentionInDays 7 -NetworkRuleSet $nr | ||
$acls = $hsm.OriginalManagedHsm.Properties.NetworkAcls | ||
Assert-AreEqual 1 $acls.IPRules.Count | ||
Assert-AreEqual $ip1 $acls.IPRules[0].Value | ||
Assert-AreEqual "Deny" $acls.DefaultAction | ||
|
||
$Global:MhsmLifecycle = @{ ResourceGroupName = $rgName; HsmName = $hsmName; Location = $hsmLoc; AdminId = $adminId; Ip1 = $ip1; Ip2 = $null } | ||
Write-Host "[New] Created HSM $hsmName in RG $rgName" -ForegroundColor Cyan | ||
} | ||
|
||
|
||
function Test-ManagedHsmNetworkRuleLifecycle-Add { | ||
if (-not $Global:MhsmLifecycle.HsmName) { throw "Run New first (no global context found)." } | ||
if ($Global:MhsmLifecycle.Ip2) { Write-Host "[Add] Ip2 already added ($($Global:MhsmLifecycle.Ip2))." -ForegroundColor Yellow; return } | ||
$ip2 = "110.0.3.0/24" | ||
Add-AzKeyVaultManagedHsmNetworkRule -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName -IpAddressRange $ip2 | Out-Null | ||
$hsm = Get-AzKeyVaultManagedHsm -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName | ||
$acls = $hsm.OriginalManagedHsm.Properties.NetworkAcls | ||
Assert-True { $acls.IPRules.Value -contains $Global:MhsmLifecycle.Ip1 } | ||
Assert-True { $acls.IPRules.Value -contains $ip2 } | ||
Assert-AreEqual "Deny" $acls.DefaultAction | ||
$Global:MhsmLifecycle.Ip2 = $ip2 | ||
Write-Host "[Add] Added IP2 $ip2" -ForegroundColor Cyan | ||
} | ||
|
||
|
||
function Test-ManagedHsmNetworkRuleLifecycle-Remove { | ||
if (-not $Global:MhsmLifecycle.HsmName) { throw "Run New first (no global context found)." } | ||
if (-not $Global:MhsmLifecycle.Ip2) { throw "Run Add first so two IPs exist before Remove." } | ||
Remove-AzKeyVaultManagedHsmNetworkRule -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName -IpAddressRange $Global:MhsmLifecycle.Ip1,$Global:MhsmLifecycle.Ip2 | Out-Null | ||
$acls = (Get-AzKeyVaultManagedHsm -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName).OriginalManagedHsm.Properties.NetworkAcls | ||
Assert-AreEqual 0 $acls.IPRules.Count | ||
Assert-AreEqual "Deny" $acls.DefaultAction | ||
Write-Host "[Remove] Both IP rules removed." -ForegroundColor Cyan | ||
} | ||
|
||
|
||
function Test-ManagedHsmNetworkRuleLifecycle-Update { | ||
if (-not $Global:MhsmLifecycle.HsmName) { throw "Run New first (no state file or global context)." } | ||
$acls = (Get-AzKeyVaultManagedHsm -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName).OriginalManagedHsm.Properties.NetworkAcls | ||
if ($acls.IPRules.Count -gt 0) { throw "Expected 0 IP rules before Update (run Remove)." } | ||
Update-AzKeyVaultManagedHsmNetworkRuleSet -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName -DefaultAction Allow | Out-Null | ||
$acls = (Get-AzKeyVaultManagedHsm -Name $Global:MhsmLifecycle.HsmName -ResourceGroupName $Global:MhsmLifecycle.ResourceGroupName).OriginalManagedHsm.Properties.NetworkAcls | ||
Assert-AreEqual 0 $acls.IPRules.Count | ||
Assert-AreEqual "Allow" $acls.DefaultAction | ||
Write-Host "[Update] DefaultAction switched to Allow." -ForegroundColor Cyan | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,5 @@ public void TestUpdateVaultWithNetworkRule() | |
TestRunner.RunTestScript("Test-UpdateVaultWithNetworkRule"); | ||
} | ||
|
||
|
||
} | ||
} |
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love that you covered both e2e and unit tests. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// ---------------------------------------------------------------------------------- | ||
// 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 System.Collections.Generic; | ||
using Microsoft.Azure.Commands.KeyVault.Models; | ||
using Microsoft.Azure.Management.KeyVault.Models; | ||
using Microsoft.WindowsAzure.Commands.ScenarioTest; | ||
using Xunit; | ||
using CmdModels = Microsoft.Azure.Commands.KeyVault.Models; | ||
|
||
namespace Microsoft.Azure.Commands.KeyVault.Test.UnitTests | ||
{ | ||
/// <summary> | ||
/// Unit tests for (legacy) management client network rule normalization. | ||
/// Updated semantics: client no longer silently flips DefaultAction; validation occurs in cmdlets. | ||
/// These tests ensure pass-through behavior (no auto mutation) is preserved. | ||
/// </summary> | ||
public class NetworkRuleEnforcementTests : KeyVaultUnitTestBase | ||
{ | ||
[Fact] | ||
[Trait(Category.AcceptanceType, Category.CheckIn)] | ||
public void Preserve_Allow_Even_When_IpRules_Present_No_AutoFlip() | ||
{ | ||
// Arrange | ||
var props = new ManagedHsmProperties | ||
{ | ||
NetworkAcls = new MhsmNetworkRuleSet | ||
{ | ||
DefaultAction = CmdModels.NetworkRuleAction.Allow.ToString(), | ||
IPRules = new List<MhsmipRule> { new MhsmipRule { Value = "1.2.3.4" } } | ||
} | ||
}; | ||
|
||
// Act | ||
VaultManagementClient.UpdateManagedHsmNetworkRuleSetProperties(props, props.NetworkAcls); | ||
|
||
// Assert | ||
Assert.Equal(CmdModels.NetworkRuleAction.Allow.ToString(), props.NetworkAcls.DefaultAction); | ||
} | ||
|
||
[Fact] | ||
[Trait(Category.AcceptanceType, Category.CheckIn)] | ||
public void Preserve_Allow_When_No_Rules_Present() | ||
{ | ||
// Arrange | ||
var props = new ManagedHsmProperties | ||
{ | ||
NetworkAcls = new MhsmNetworkRuleSet | ||
{ | ||
DefaultAction = CmdModels.NetworkRuleAction.Allow.ToString(), | ||
IPRules = new List<MhsmipRule>(), | ||
VirtualNetworkRules = new List<MhsmVirtualNetworkRule>() | ||
} | ||
}; | ||
|
||
// Act | ||
VaultManagementClient.UpdateManagedHsmNetworkRuleSetProperties(props, props.NetworkAcls); | ||
|
||
// Assert | ||
Assert.Equal(CmdModels.NetworkRuleAction.Allow.ToString(), props.NetworkAcls.DefaultAction); | ||
} | ||
|
||
[Fact] | ||
[Trait(Category.AcceptanceType, Category.CheckIn)] | ||
public void Preserve_Allow_With_VirtualNetworkRules_Present_No_AutoFlip() | ||
{ | ||
// Arrange (simulate future enablement of VNets; cmdlets would block today but client path must be passive) | ||
var props = new ManagedHsmProperties | ||
{ | ||
NetworkAcls = new MhsmNetworkRuleSet | ||
{ | ||
DefaultAction = CmdModels.NetworkRuleAction.Allow.ToString(), | ||
IPRules = new List<MhsmipRule>(), | ||
VirtualNetworkRules = new List<MhsmVirtualNetworkRule> { new MhsmVirtualNetworkRule { Id = "/subscriptions/xxx/resourceGroups/rg/providers/Microsoft.Network/virtualNetworks/vnet/subnets/sub" } } | ||
} | ||
}; | ||
|
||
// Act | ||
VaultManagementClient.UpdateManagedHsmNetworkRuleSetProperties(props, props.NetworkAcls); | ||
|
||
// Assert | ||
Assert.Equal(CmdModels.NetworkRuleAction.Allow.ToString(), props.NetworkAcls.DefaultAction); | ||
Assert.Single(props.NetworkAcls.VirtualNetworkRules); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually caused by a feature in the test framework to support recording test cases with user account instead of service account, in which case the command won't add default access policy, so the result is 0. So it's not that the test cases are incorrect, it's just an unfixed behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense! In that case should we leave this as 1? (Since from now on, it will use the user account)