Skip to content

Commit 9cb4be7

Browse files
feat(new): Added Azure.EventHub.Firewall (Azure#2872)
* feat(new): Added Azure.EventHub.Firewall * doc: Update changelog * refactor: Updated Azure.EventHub.Firewall * Update for AnyOf function --------- Co-authored-by: Bernie White <[email protected]>
1 parent 00e1ca9 commit 9cb4be7

File tree

5 files changed

+468
-15
lines changed

5 files changed

+468
-15
lines changed

docs/CHANGELOG-v1.md

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
3939
[#2846](https://github.com/Azure/PSRule.Rules.Azure/issues/2846)
4040
- Check that database accounts have public network access disabled by @BenjaminEngeset.
4141
[#2702](https://github.com/Azure/PSRule.Rules.Azure/issues/2702)
42+
- Event Hub:
43+
- Check that access to the namespace endpoints is restricted to only allowed sources by @BenjaminEngeset.
44+
[#2701](https://github.com/Azure/PSRule.Rules.Azure/issues/2701)
4245
- Updated rules:
4346
- API Management:
4447
- **Important change**: Updated `Azure.APIM.AvailabilityZone` to improve accuracy with non-premium SKUs by @BenjaminEngeset.
@@ -49,6 +52,7 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers
4952
- Updated rule doc.
5053
- Bumped rule set to `2024_06`.
5154

55+
5256
## v1.37.0-B0009 (pre-release)
5357

5458
What's changed since v1.36.0:
+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
severity: Critical
3+
pillar: Security
4+
category: SE:06 Network controls
5+
resource: Event Hub
6+
online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.EventHub.Firewall/
7+
---
8+
9+
# Access to the namespace endpoints should be restricted to only allowed sources
10+
11+
## SYNOPSIS
12+
13+
Access to the namespace endpoints should be restricted to only allowed sources.
14+
15+
## DESCRIPTION
16+
17+
By default, Event Hub namespaces are accessible from public internet.
18+
19+
With the firewall feature, it is possible to either fully disabling public network access by ensuring that the namespace endpoints isn't exposed on the public internet or configure rules to only accept traffic from specific addresses.
20+
21+
## RECOMMENDATION
22+
23+
Consider restricting network access to the Event Hub namespace by requiring private endpoints or by limiting access to permitted client addresses with the service firewall.
24+
25+
## EXAMPLES
26+
27+
### Configure with Azure template
28+
29+
To deploy Event Hub namespaces that pass this rule:
30+
31+
- Set the `properties.publicNetworkAccess` property to `Disabled` to require private endpoints. OR
32+
- Alternatively, you can configure the `Microsoft.EventHub/namespaces/networkRuleSets` sub-resource by:
33+
- Setting the `properties.publicNetworkAccess` property to `Disabled` to require private endpoints. OR
34+
- Setting the `properties.defaultAction` property to `Deny` to restrict network access to the service by default.
35+
36+
For example:
37+
38+
```json
39+
{
40+
"type": "Microsoft.EventHub/namespaces",
41+
"apiVersion": "2024-01-01",
42+
"name": "[parameters('name')]",
43+
"location": "[parameters('location')]",
44+
"identity": {
45+
"type": "SystemAssigned"
46+
},
47+
"sku": {
48+
"name": "Standard"
49+
},
50+
"properties": {
51+
"disableLocalAuth": true,
52+
"minimumTlsVersion": "1.2",
53+
"publicNetworkAccess": "Disabled",
54+
"zoneRedundant": true
55+
}
56+
}
57+
```
58+
59+
### Configure with Bicep
60+
61+
To deploy Event Hub namespaces that pass this rule:
62+
63+
- Set the `properties.publicNetworkAccess` property to `Disabled` to require private endpoints. OR
64+
- Alternatively, you can configure the `Microsoft.EventHub/namespaces/networkRuleSets` sub-resource by:
65+
- Setting the `properties.publicNetworkAccess` property to `Disabled` to require private endpoints. OR
66+
- Setting the `properties.defaultAction` property to `Deny` to restrict network access to the service by default.
67+
68+
For example:
69+
70+
```bicep
71+
resource ns 'Microsoft.EventHub/namespaces@2024-01-01' = {
72+
name: name
73+
location: location
74+
identity: {
75+
type: 'SystemAssigned'
76+
}
77+
sku: {
78+
name: 'Standard'
79+
}
80+
properties: {
81+
disableLocalAuth: true
82+
minimumTlsVersion: '1.2'
83+
publicNetworkAccess: 'Disabled'
84+
zoneRedundant: true
85+
}
86+
}
87+
```
88+
89+
## NOTES
90+
91+
If there are no IP and virtual network rules, all the traffic flows into the namespace even if you set the defaultAction to `deny` on the firewall. The namespace can be accessed over the public internet. Specify at least one IP rule or virtual network rule for the namespace to activate the default action on the firewall.
92+
93+
The firewall feature isn't supported in the `basic` tier.
94+
95+
## LINKS
96+
97+
- [SE:06 Network controls](https://learn.microsoft.com/azure/well-architected/security/networking)
98+
- [Azure security baseline for Event Hub](https://learn.microsoft.com/security/benchmark/azure/baselines/event-hubs-security-baseline)
99+
- [NS-1: Establish network segmentation boundaries](https://learn.microsoft.com/security/benchmark/azure/baselines/event-hubs-security-baseline#ns-1-establish-network-segmentation-boundaries)
100+
- [NS-2: Secure cloud services with network controls](https://learn.microsoft.com/security/benchmark/azure/baselines/event-hubs-security-baseline#ns-1-establish-network-segmentation-boundaries)
101+
- [Allow access to Azure Event Hub namespaces from specific IP addresses or ranges](https://learn.microsoft.com/azure/event-hubs/event-hubs-ip-filtering)
102+
- [Allow access to Azure Event Hub namespaces from specific virtual networks](https://learn.microsoft.com/azure/event-hubs/event-hubs-service-endpoints)
103+
- [Allow access to Azure Event Hub namespaces via private endpoints](https://learn.microsoft.com/azure/event-hubs/private-link-service)
104+
- [Azure resource deployment](https://learn.microsoft.com/azure/templates/microsoft.eventhub/namespaces/eventhubs)
105+
- [Azure resource deployment](https://learn.microsoft.com/azure/templates/microsoft.eventhub/namespaces/networkrulesets)

src/PSRule.Rules.Azure/rules/Azure.EventHub.Rule.ps1

+33
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,37 @@ Rule 'Azure.EventHub.Usage' -Ref 'AZR-000101' -Type 'Microsoft.EventHub/namespac
1313
$Assert.GreaterOrEqual($items, '.', 1);
1414
}
1515

16+
# Synopsis: Access to the namespace endpoints should be restricted to only allowed sources.
17+
Rule 'Azure.EventHub.Firewall' -Ref 'AZR-000422' -Type 'Microsoft.EventHub/namespaces', 'Microsoft.EventHub/namespaces/networkRuleSets' -If { Test-IsNoBasicTier } -Tag @{ release = 'GA'; ruleSet = '2024_06'; 'Azure.WAF/pillar' = 'Security'; } -Labels @{ 'Azure.MCSB.v1/control' = 'NS-1', 'NS-2' } {
18+
# NB: Microsoft.EventHub/namespaces/networkRuleSets overrides properties.publicNetworkAccess and properties.defaultAction property.
19+
20+
$firewalls = @($TargetObject)
21+
if ($PSRule.TargetType -eq 'Microsoft.EventHub/namespaces') {
22+
$firewalls = @(GetSubResources -ResourceType 'Microsoft.EventHub/namespaces/networkRuleSets')
23+
}
24+
25+
if ($firewalls.Count -eq 0 -and $PSRule.TargetType -eq 'Microsoft.EventHub/namespaces') {
26+
$Assert.HasFieldValue($TargetObject, 'properties.publicNetworkAccess', 'Disabled')
27+
}
28+
29+
else {
30+
foreach ($firewall in $firewalls) {
31+
AnyOf {
32+
$Assert.HasFieldValue($firewall, 'properties.publicNetworkAccess', 'Disabled')
33+
$Assert.HasFieldValue($firewall, 'properties.defaultAction', 'Deny')
34+
}
35+
}
36+
}
37+
}
38+
1639
#endregion Rules
40+
41+
#region Helper functions
42+
43+
function global:Test-IsNoBasicTier {
44+
[CmdletBinding()]
45+
param ()
46+
-not $Assert.HasFieldValue($TargetObject, 'sku.tier', 'Basic').Result
47+
}
48+
49+
#endregion Helper functions

tests/PSRule.Rules.Azure.Tests/Azure.EventHub.Tests.ps1

+31-12
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ Describe 'Azure.EventHub' -Tag 'EventHub' {
2727
Context 'Conditions' {
2828
BeforeAll {
2929
$invokeParams = @{
30-
Baseline = 'Azure.All'
31-
Module = 'PSRule.Rules.Azure'
30+
Baseline = 'Azure.All'
31+
Module = 'PSRule.Rules.Azure'
3232
WarningAction = 'Ignore'
33-
ErrorAction = 'Stop'
33+
ErrorAction = 'Stop'
3434
}
3535
$dataPath = Join-Path -Path $here -ChildPath 'Resources.EventHub.json';
3636
$result = Invoke-PSRule @invokeParams -InputPath $dataPath;
@@ -42,8 +42,8 @@ Describe 'Azure.EventHub' -Tag 'EventHub' {
4242
# Fail
4343
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
4444
$ruleResult | Should -Not -BeNullOrEmpty;
45-
$ruleResult.Length | Should -Be 2;
46-
$ruleResult.TargetName | Should -BeIn 'hubns-B', 'hubns-C';
45+
$ruleResult.Length | Should -Be 5;
46+
$ruleResult.TargetName | Should -BeIn 'hubns-B', 'hubns-C', 'hubns-D', 'hubns-E', 'hubns-F';
4747

4848
# Pass
4949
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
@@ -58,8 +58,8 @@ Describe 'Azure.EventHub' -Tag 'EventHub' {
5858
# Fail
5959
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
6060
$ruleResult | Should -Not -BeNullOrEmpty;
61-
$ruleResult.Length | Should -Be 2;
62-
$ruleResult.TargetName | Should -BeIn 'hubns-B', 'hubns-C';
61+
$ruleResult.Length | Should -Be 5;
62+
$ruleResult.TargetName | Should -BeIn 'hubns-B', 'hubns-C', 'hubns-D', 'hubns-E', 'hubns-F';
6363

6464
# Pass
6565
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
@@ -82,8 +82,27 @@ Describe 'Azure.EventHub' -Tag 'EventHub' {
8282
# Pass
8383
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
8484
$ruleResult | Should -Not -BeNullOrEmpty;
85-
$ruleResult.Length | Should -Be 1;
86-
$ruleResult.TargetName | Should -BeIn 'hubns-C';
85+
$ruleResult.Length | Should -Be 4;
86+
$ruleResult.TargetName | Should -BeIn 'hubns-C', 'hubns-D', 'hubns-E', 'hubns-F';
87+
}
88+
89+
It 'Azure.EventHub.Firewall' {
90+
$filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.EventHub.Firewall' };
91+
92+
# Fail
93+
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' });
94+
$ruleResult.Length | Should -Be 4;
95+
$ruleResult.TargetName | Should -BeIn 'hubns-B', 'hubns-C', 'hubns-D', 'default-A';
96+
97+
$ruleResult[0].Reason | Should -BeExactly "Path properties.publicNetworkAccess: Does not exist."
98+
$ruleResult[1].Reason | Should -BeExactly "Path properties.publicNetworkAccess: Is set to 'Enabled'."
99+
$ruleResult[2].Reason | Should -BeIn "Path properties.publicNetworkAccess: Is set to 'Enabled'.", "Path properties.defaultAction: Is set to 'Allow'."
100+
$ruleResult[3].Reason | Should -BeIn "Path properties.publicNetworkAccess: Is set to 'Enabled'.", "Path properties.defaultAction: Is set to 'Allow'."
101+
102+
# Pass
103+
$ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' });
104+
$ruleResult.Length | Should -Be 5;
105+
$ruleResult.TargetName | Should -BeIn 'hubns-E', 'hubns-F', 'default-B', 'default-C', 'default-D';
87106
}
88107
}
89108

@@ -92,10 +111,10 @@ Describe 'Azure.EventHub' -Tag 'EventHub' {
92111
$outputFile = Join-Path -Path $rootPath -ChildPath out/tests/Resources.EventHub.json;
93112
Export-AzRuleTemplateData -TemplateFile (Join-Path -Path $here -ChildPath 'Resources.EventHub.Template.json') -OutputPath $outputFile;
94113
$invokeParams = @{
95-
Baseline = 'Azure.All'
96-
Module = 'PSRule.Rules.Azure'
114+
Baseline = 'Azure.All'
115+
Module = 'PSRule.Rules.Azure'
97116
WarningAction = 'Ignore'
98-
ErrorAction = 'Stop'
117+
ErrorAction = 'Stop'
99118
}
100119
$result = Invoke-PSRule @invokeParams -InputPath $outputFile -Outcome All;
101120
}

0 commit comments

Comments
 (0)