Skip to content

Commit

Permalink
feat: Keyvault acls
Browse files Browse the repository at this point in the history
  • Loading branch information
pregress committed Nov 11, 2024
1 parent 1833a81 commit eafac26
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 2 deletions.
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
## azurerm_key_vault
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_key_vault_public_network_access_enabled|Consider disabling public network access on keyvaults. |NOTICE|||
|azurerm_key_vault_public_network_access_enabled|Consider disabling public network access on keyvaults. |NOTICE|||
|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|||

## azurerm_linux_function_app
|Name|Description|Severity|Enabled|Link|
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func createRuleSet() *tflint.BuiltinRuleSet {
Rules: []tflint.Rule{
rules.NewAzurermEventhubNamespacePublicNetworkAccessEnabled(),
rules.NewAzurermEventhubNamespaceUnsecureTLS(),
rules.NewAzurermKeyVaultNetworkAclsDefaultDeny(),
rules.NewAzurermKeyVaultPublicNetworkAccessEnabled(),
rules.NewAzurermLinuxFunctionAppFtpsState(),
rules.NewAzurermLinuxFunctionAppHTTPSOnly(),
Expand Down
107 changes: 107 additions & 0 deletions rules/azurerm_keyvault_network_acls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package rules

import (
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
)

// AzurermKeyVaultNetworkAclsDefaultDeny checks that network_acls default_action is set to "Deny"
type AzurermKeyVaultNetworkAclsDefaultDeny struct {
tflint.DefaultRule

resourceType string
blockName string
}

// NewAzurermKeyVaultNetworkAclsDefaultDeny returns a new rule instance
func NewAzurermKeyVaultNetworkAclsDefaultDeny() *AzurermKeyVaultNetworkAclsDefaultDeny {
return &AzurermKeyVaultNetworkAclsDefaultDeny{
resourceType: "azurerm_key_vault",
blockName: "network_acls",
}
}

// Name returns the rule name
func (r *AzurermKeyVaultNetworkAclsDefaultDeny) Name() string {
return "azurerm_key_vault_network_acls_default_deny"
}

// Enabled returns whether the rule is enabled by default
func (r *AzurermKeyVaultNetworkAclsDefaultDeny) Enabled() bool {
return true
}

// Severity returns the rule severity
func (r *AzurermKeyVaultNetworkAclsDefaultDeny) Severity() tflint.Severity {
return tflint.WARNING
}

// Link returns the rule reference link
func (r *AzurermKeyVaultNetworkAclsDefaultDeny) Link() string {
return ""
}

// Check checks if network_acls default_action is set to "Deny"
func (r *AzurermKeyVaultNetworkAclsDefaultDeny) Check(runner tflint.Runner) error {
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: r.blockName,
Body: &hclext.BodySchema{
Attributes: []hclext.AttributeSchema{
{Name: "default_action"},
},
},
},
},
}, nil)
if err != nil {
return err
}

for _, resource := range resources.Blocks {
networkAcls := resource.Body.Blocks

if len(networkAcls) == 0 {
runner.EmitIssue(
r,
"network_acls block is not defined, consider adding it with default_action = \"Deny\"",
resource.DefRange,
)
continue
}

for _, networkAcl := range networkAcls {

Check failure on line 74 in rules/azurerm_keyvault_network_acls.go

View workflow job for this annotation

GitHub Actions / checks

range var networkAcl should be networkACL
if networkAcl.Type != r.blockName {
continue
}

attribute, exists := networkAcl.Body.Attributes["default_action"]
if !exists {
runner.EmitIssue(
r,
"default_action is not defined in network_acls block",
networkAcl.DefRange,
)
continue
}

err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
if val != "Deny" {
runner.EmitIssue(
r,
"network_acls default_action should be set to \"Deny\"",
attribute.Expr.Range(),
)
}
return nil
}, nil)

if err != nil {
return err
}
}
}

return nil
}
97 changes: 97 additions & 0 deletions rules/azurerm_keyvault_network_acls_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package rules

import (
"testing"

hcl "github.com/hashicorp/hcl/v2"
"github.com/terraform-linters/tflint-plugin-sdk/helper"
)

func Test_AzurermKeyVaultNetworkAclsDefaultDeny(t *testing.T) {
tests := []struct {
Name string
Content string
Expected helper.Issues
}{
{
Name: "no network_acls block",
Content: `
resource "azurerm_key_vault" "example" {
}`,
Expected: helper.Issues{
{
Rule: NewAzurermKeyVaultNetworkAclsDefaultDeny(),
Message: "network_acls block is not defined, consider adding it with default_action = \"Deny\"",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 2, Column: 1},
End: hcl.Pos{Line: 2, Column: 39},
},
},
},
},
{
Name: "network_acls without default_action",
Content: `
resource "azurerm_key_vault" "example" {
network_acls {
}
}`,
Expected: helper.Issues{
{
Rule: NewAzurermKeyVaultNetworkAclsDefaultDeny(),
Message: "default_action is not defined in network_acls block",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 3, Column: 5},
End: hcl.Pos{Line: 3, Column: 17},
},
},
},
},
{
Name: "network_acls with default_action Allow",
Content: `
resource "azurerm_key_vault" "example" {
network_acls {
default_action = "Allow"
}
}`,
Expected: helper.Issues{
{
Rule: NewAzurermKeyVaultNetworkAclsDefaultDeny(),
Message: "network_acls default_action should be set to \"Deny\"",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{Line: 4, Column: 26},
End: hcl.Pos{Line: 4, Column: 33},
},
},
},
},
{
Name: "network_acls with default_action Deny",
Content: `
resource "azurerm_key_vault" "example" {
network_acls {
default_action = "Deny"
}
}`,
Expected: helper.Issues{},
},
}

rule := NewAzurermKeyVaultNetworkAclsDefaultDeny()

for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content})

if err := rule.Check(runner); err != nil {
t.Fatalf("Unexpected error occurred: %s", err)
}

helper.AssertIssues(t, test.Expected, runner.Issues)
})
}
}
2 changes: 1 addition & 1 deletion rules/azurerm_keyvault_public_network_access_enabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func (r *AzurermKeyVaultPublicNetworkAccessEnabled) Name() string {

// Enabled returns whether the rule is enabled by default
func (r *AzurermKeyVaultPublicNetworkAccessEnabled) Enabled() bool {
return true
return false
}

// Severity returns the rule severity
Expand Down

0 comments on commit eafac26

Please sign in to comment.