Skip to content

Commit c017f1a

Browse files
authored
feat: Keyvault acls (#15)
* feat: Keyvault acls
1 parent 1833a81 commit c017f1a

File tree

5 files changed

+208
-2
lines changed

5 files changed

+208
-2
lines changed

docs/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
## azurerm_key_vault
1010
|Name|Description|Severity|Enabled|Link|
1111
| --- | --- | --- | --- | --- |
12-
|azurerm_key_vault_public_network_access_enabled|Consider disabling public network access on keyvaults. |NOTICE|||
12+
|azurerm_key_vault_public_network_access_enabled|Consider disabling public network access on keyvaults. |NOTICE|||
13+
|azurerm_key_vault_network_acls_default_deny|Deny network access to Keyvaults. You can add `bypass = "AzureServices"` to allow azure services to connect to keyvault or add `ip_rules`|WARNING|||
1314

1415
## azurerm_linux_function_app
1516
|Name|Description|Severity|Enabled|Link|

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ func createRuleSet() *tflint.BuiltinRuleSet {
1414
Rules: []tflint.Rule{
1515
rules.NewAzurermEventhubNamespacePublicNetworkAccessEnabled(),
1616
rules.NewAzurermEventhubNamespaceUnsecureTLS(),
17+
rules.NewAzurermKeyVaultNetworkACLsDefaultDeny(),
1718
rules.NewAzurermKeyVaultPublicNetworkAccessEnabled(),
1819
rules.NewAzurermLinuxFunctionAppFtpsState(),
1920
rules.NewAzurermLinuxFunctionAppHTTPSOnly(),
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package rules
2+
3+
import (
4+
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
5+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
6+
)
7+
8+
// AzurermKeyVaultNetworkACLsDefaultDeny checks that network_acls default_action is set to "Deny"
9+
type AzurermKeyVaultNetworkACLsDefaultDeny struct {
10+
tflint.DefaultRule
11+
12+
resourceType string
13+
blockName string
14+
}
15+
16+
// NewAzurermKeyVaultNetworkACLsDefaultDeny returns a new rule instance
17+
func NewAzurermKeyVaultNetworkACLsDefaultDeny() *AzurermKeyVaultNetworkACLsDefaultDeny {
18+
return &AzurermKeyVaultNetworkACLsDefaultDeny{
19+
resourceType: "azurerm_key_vault",
20+
blockName: "network_acls",
21+
}
22+
}
23+
24+
// Name returns the rule name
25+
func (r *AzurermKeyVaultNetworkACLsDefaultDeny) Name() string {
26+
return "azurerm_key_vault_network_acls_default_deny"
27+
}
28+
29+
// Enabled returns whether the rule is enabled by default
30+
func (r *AzurermKeyVaultNetworkACLsDefaultDeny) Enabled() bool {
31+
return true
32+
}
33+
34+
// Severity returns the rule severity
35+
func (r *AzurermKeyVaultNetworkACLsDefaultDeny) Severity() tflint.Severity {
36+
return tflint.WARNING
37+
}
38+
39+
// Link returns the rule reference link
40+
func (r *AzurermKeyVaultNetworkACLsDefaultDeny) Link() string {
41+
return ""
42+
}
43+
44+
// Check checks if network_acls default_action is set to "Deny"
45+
func (r *AzurermKeyVaultNetworkACLsDefaultDeny) Check(runner tflint.Runner) error {
46+
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
47+
Blocks: []hclext.BlockSchema{
48+
{
49+
Type: r.blockName,
50+
Body: &hclext.BodySchema{
51+
Attributes: []hclext.AttributeSchema{
52+
{Name: "default_action"},
53+
},
54+
},
55+
},
56+
},
57+
}, nil)
58+
if err != nil {
59+
return err
60+
}
61+
62+
for _, resource := range resources.Blocks {
63+
networkACLs := resource.Body.Blocks
64+
65+
if len(networkACLs) == 0 {
66+
runner.EmitIssue(
67+
r,
68+
"network_acls block is not defined, consider adding it with default_action = \"Deny\"",
69+
resource.DefRange,
70+
)
71+
continue
72+
}
73+
74+
for _, networkACL := range networkACLs {
75+
if networkACL.Type != r.blockName {
76+
continue
77+
}
78+
79+
attribute, exists := networkACL.Body.Attributes["default_action"]
80+
if !exists {
81+
runner.EmitIssue(
82+
r,
83+
"default_action is not defined in network_acls block",
84+
networkACL.DefRange,
85+
)
86+
continue
87+
}
88+
89+
err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
90+
if val != "Deny" {
91+
runner.EmitIssue(
92+
r,
93+
"network_acls default_action should be set to \"Deny\"",
94+
attribute.Expr.Range(),
95+
)
96+
}
97+
return nil
98+
}, nil)
99+
100+
if err != nil {
101+
return err
102+
}
103+
}
104+
}
105+
106+
return nil
107+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package rules
2+
3+
import (
4+
"testing"
5+
6+
hcl "github.com/hashicorp/hcl/v2"
7+
"github.com/terraform-linters/tflint-plugin-sdk/helper"
8+
)
9+
10+
func Test_AzurermKeyVaultNetworkACLsDefaultDeny(t *testing.T) {
11+
tests := []struct {
12+
Name string
13+
Content string
14+
Expected helper.Issues
15+
}{
16+
{
17+
Name: "no network_acls block",
18+
Content: `
19+
resource "azurerm_key_vault" "example" {
20+
}`,
21+
Expected: helper.Issues{
22+
{
23+
Rule: NewAzurermKeyVaultNetworkACLsDefaultDeny(),
24+
Message: "network_acls block is not defined, consider adding it with default_action = \"Deny\"",
25+
Range: hcl.Range{
26+
Filename: "resource.tf",
27+
Start: hcl.Pos{Line: 2, Column: 1},
28+
End: hcl.Pos{Line: 2, Column: 39},
29+
},
30+
},
31+
},
32+
},
33+
{
34+
Name: "network_acls without default_action",
35+
Content: `
36+
resource "azurerm_key_vault" "example" {
37+
network_acls {
38+
}
39+
}`,
40+
Expected: helper.Issues{
41+
{
42+
Rule: NewAzurermKeyVaultNetworkACLsDefaultDeny(),
43+
Message: "default_action is not defined in network_acls block",
44+
Range: hcl.Range{
45+
Filename: "resource.tf",
46+
Start: hcl.Pos{Line: 3, Column: 5},
47+
End: hcl.Pos{Line: 3, Column: 17},
48+
},
49+
},
50+
},
51+
},
52+
{
53+
Name: "network_acls with default_action Allow",
54+
Content: `
55+
resource "azurerm_key_vault" "example" {
56+
network_acls {
57+
default_action = "Allow"
58+
}
59+
}`,
60+
Expected: helper.Issues{
61+
{
62+
Rule: NewAzurermKeyVaultNetworkACLsDefaultDeny(),
63+
Message: "network_acls default_action should be set to \"Deny\"",
64+
Range: hcl.Range{
65+
Filename: "resource.tf",
66+
Start: hcl.Pos{Line: 4, Column: 26},
67+
End: hcl.Pos{Line: 4, Column: 33},
68+
},
69+
},
70+
},
71+
},
72+
{
73+
Name: "network_acls with default_action Deny",
74+
Content: `
75+
resource "azurerm_key_vault" "example" {
76+
network_acls {
77+
default_action = "Deny"
78+
}
79+
}`,
80+
Expected: helper.Issues{},
81+
},
82+
}
83+
84+
rule := NewAzurermKeyVaultNetworkACLsDefaultDeny()
85+
86+
for _, test := range tests {
87+
t.Run(test.Name, func(t *testing.T) {
88+
runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content})
89+
90+
if err := rule.Check(runner); err != nil {
91+
t.Fatalf("Unexpected error occurred: %s", err)
92+
}
93+
94+
helper.AssertIssues(t, test.Expected, runner.Issues)
95+
})
96+
}
97+
}

rules/azurerm_keyvault_public_network_access_enabled.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func (r *AzurermKeyVaultPublicNetworkAccessEnabled) Name() string {
2828

2929
// Enabled returns whether the rule is enabled by default
3030
func (r *AzurermKeyVaultPublicNetworkAccessEnabled) Enabled() bool {
31-
return true
31+
return false
3232
}
3333

3434
// Severity returns the rule severity

0 commit comments

Comments
 (0)