Skip to content

Commit 02f0cac

Browse files
committed
Feat: storage network rules
1 parent 4fa72b1 commit 02f0cac

5 files changed

+98
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ You can install the plugin with `tflint --init`. Declare a config in `.tflint.hc
1717
plugin "azurerm-security" {
1818
enabled = true
1919
20-
version = "0.1.9"
20+
version = "0.1.10"
2121
source = "github.com/pregress/tflint-ruleset-azurerm-security"
2222
}
2323
```

docs/rules/azurerm_storage_account_public_network_access_enabled.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,32 @@ resource "azurerm_storage_account" "example" {
1313

1414
## Why
1515

16-
Disabling public_network_access_enabled ensures the Storage Account is not accessible from the public internet, reducing exposure to potential security threats and limiting access to trusted, private networks only.
16+
Storage accounts with unrestricted public network access expose your data to potential security threats. By either disabling public network access altogether or implementing network rules with "Deny" as the default action, you can significantly reduce your storage account's attack surface.
1717

1818
## How to Fix
1919

20+
Option 1: Disable public network access completely:
21+
2022
```hcl
2123
resource "azurerm_storage_account" "example" {
2224
public_network_access_enabled = false
2325
}
2426
```
2527

28+
Option 2: Implement network rules with default action set to "Deny":
29+
30+
```hcl
31+
resource "azurerm_storage_account" "example" {
32+
network_rules {
33+
default_action = "Deny"
34+
bypass = ["AzureServices"]
35+
# Add specific IP rules or virtual network subnet IDs as needed
36+
ip_rules = ["203.0.113.0/24"]
37+
}
38+
}
39+
```
40+
41+
This configuration enables fine-grained access control, allowing connectivity only from specified IP addresses or virtual networks while blocking all other traffic.
2642

2743
## How to disable
2844

project/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package project
33
import "fmt"
44

55
// Version is ruleset version
6-
const Version string = "0.1.9"
6+
const Version string = "0.1.10"
77

88
// ReferenceLink returns the rule reference link
99
func ReferenceLink(name string) string {

rules/azurerm_storage_account_public_network_access_enabled .go renamed to rules/azurerm_storage_account_public_network_access_enabled.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package rules
33
import (
44
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
55
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
6-
6+
77
"github.com/terraform-linters/tflint-ruleset-azurerm-security/project"
88
)
99

@@ -49,18 +49,51 @@ func (r *AzurermStorageAccountPublicNetworkAccessEnabled) Check(runner tflint.Ru
4949
Attributes: []hclext.AttributeSchema{
5050
{Name: r.attributeName},
5151
},
52+
Blocks: []hclext.BlockSchema{
53+
{
54+
Type: "network_rules",
55+
Body: &hclext.BodySchema{
56+
Attributes: []hclext.AttributeSchema{
57+
{Name: "default_action"},
58+
},
59+
},
60+
},
61+
},
5262
}, nil)
5363
if err != nil {
5464
return err
5565
}
5666

5767
for _, resource := range resources.Blocks {
68+
// Check for network_rules block with default_action = "Deny"
69+
hasSecureNetworkRulesWithDeny := false
70+
hasSecureNetworkRules := false
71+
for _, block := range resource.Body.Blocks {
72+
if block.Type == "network_rules" {
73+
hasSecureNetworkRules = true
74+
if defaultActionAttr, exists := block.Body.Attributes["default_action"]; exists {
75+
var defaultAction string
76+
if err := runner.EvaluateExpr(defaultActionAttr.Expr, &defaultAction, nil); err == nil {
77+
if defaultAction == "Deny" {
78+
hasSecureNetworkRulesWithDeny = true
79+
break
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
// If network rules with default_action = "Deny" exist, the configuration is secure
87+
if hasSecureNetworkRulesWithDeny {
88+
continue
89+
}
90+
5891
attribute, exists := resource.Body.Attributes[r.attributeName]
59-
if !exists {
60-
// Emit an issue if the attribute does not exist
92+
if !exists && !hasSecureNetworkRules {
93+
// If the attribute does not exist and there are no secure network rules, emit an issue
6194
runner.EmitIssue(
6295
r,
63-
"public_network_access_enabled is not defined and defaults to true, consider disabling it",
96+
"public_network_access_enabled is not defined and defaults to true, consider disabling it or adding network_rules with default_action = \"Deny\"",
6497
resource.DefRange,
6598
)
6699
continue
@@ -70,7 +103,7 @@ func (r *AzurermStorageAccountPublicNetworkAccessEnabled) Check(runner tflint.Ru
70103
if val {
71104
runner.EmitIssue(
72105
r,
73-
"Consider changing public_network_access_enabled to false",
106+
"Consider changing public_network_access_enabled to false or add network_rules with default_action = \"Deny\"",
74107
attribute.Expr.Range(),
75108
)
76109
}

rules/azurerm_storage_account_public_network_access_enabled_test.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ func Test_AzurermStorageAccountPublicNetworkAccessEnabled(t *testing.T) {
1414
Expected helper.Issues
1515
}{
1616
{
17-
Name: "public network access disabled",
17+
Name: "public network access enabled",
1818
Content: `
1919
resource "azurerm_storage_account" "example" {
2020
public_network_access_enabled = true
2121
}`,
2222
Expected: helper.Issues{
2323
{
2424
Rule: NewAzurermStorageAccountPublicNetworkAccessEnabled(),
25-
Message: "Consider changing public_network_access_enabled to false",
25+
Message: "Consider changing public_network_access_enabled to false or add network_rules with default_action = \"Deny\"",
2626
Range: hcl.Range{
2727
Filename: "resource.tf",
2828
Start: hcl.Pos{Line: 3, Column: 37},
@@ -39,7 +39,7 @@ resource "azurerm_storage_account" "example" {
3939
Expected: helper.Issues{
4040
{
4141
Rule: NewAzurermStorageAccountPublicNetworkAccessEnabled(),
42-
Message: "public_network_access_enabled is not defined and defaults to true, consider disabling it",
42+
Message: "public_network_access_enabled is not defined and defaults to true, consider disabling it or adding network_rules with default_action = \"Deny\"",
4343
Range: hcl.Range{
4444
Filename: "resource.tf",
4545
Start: hcl.Pos{Line: 2, Column: 1},
@@ -56,6 +56,44 @@ resource "azurerm_storage_account" "example" {
5656
}`,
5757
Expected: helper.Issues{},
5858
},
59+
{
60+
Name: "public network access enabled netork rules with default_action = Deny",
61+
Content: `
62+
resource "azurerm_storage_account" "example" {
63+
public_network_access_enabled = true
64+
65+
network_rules {
66+
default_action = "Deny"
67+
bypass = ["AzureServices"]
68+
ip_rules = ["1.1.1.1"]
69+
}
70+
}`,
71+
Expected: helper.Issues{},
72+
},
73+
{
74+
Name: "public network access enbled network rules with default_action = Allow",
75+
Content: `
76+
resource "azurerm_storage_account" "example" {
77+
public_network_access_enabled = true
78+
79+
network_rules {
80+
default_action = "Allow"
81+
bypass = ["AzureServices"]
82+
ip_rules = ["1.1.1.1"]
83+
}
84+
}`,
85+
Expected: helper.Issues{
86+
{
87+
Rule: NewAzurermStorageAccountPublicNetworkAccessEnabled(),
88+
Message: "Consider changing public_network_access_enabled to false or add network_rules with default_action = \"Deny\"",
89+
Range: hcl.Range{
90+
Filename: "resource.tf",
91+
Start: hcl.Pos{Line: 3, Column: 37},
92+
End: hcl.Pos{Line: 3, Column: 41},
93+
},
94+
},
95+
},
96+
},
5997
}
6098

6199
rule := NewAzurermStorageAccountPublicNetworkAccessEnabled()

0 commit comments

Comments
 (0)