Skip to content

Commit

Permalink
feat: function rules (#11)
Browse files Browse the repository at this point in the history
* feat: function rules

* main branch for linter

* Add lint to makefile

* Format makefile

* lint

---------
  • Loading branch information
pregress authored Nov 4, 2024
1 parent 5c79115 commit 3cc330a
Show file tree
Hide file tree
Showing 28 changed files with 1,397 additions and 86 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: lint
on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main

jobs:
checks:
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ build:
install: build
mkdir -p ~/.tflint.d/plugins
mv ./tflint-ruleset-azurerm-security ~/.tflint.d/plugins

lint:
golint --set_exit_status $$(go list ./...)
go vet ./...

tools:
go install golang.org/x/lint/golint@latest
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ You can install the plugin with `tflint --init`. Declare a config in `.tflint.hc
plugin "azurerm-security" {
enabled = true
version = "0.1.2"
version = "0.1.3"
source = "github.com/pregress/tflint-ruleset-azurerm-security"
}
```
Expand Down
34 changes: 33 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,46 @@
# Rules

## azurerm_key_vault
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_key_vault_public_network_access_enabled|Consider disabling public network access on keyvaults. |NOTICE|||

## azurerm_linux_function_app
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_linux_function_app_ftps_state|Disable sftp to a linux function app |WARNING|||
|azurerm_linux_function_app_https_only|Force all traffic over https |WARNING|||
|azurerm_linux_function_app_minimum_tls_version|Enforce TLS 1.2 on linux function apps |WARNING|||

## azurerm_linux_web_app
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_linux_web_app_ftps_state|Disable sftp to a linux web app |WARNING|||
|azurerm_linux_web_app_https_only|Force all traffic over https |WARNING|||
|azurerm_linux_web_app_minimum_tls_version|Enforce TLS 1.2 on linux web apps |WARNING|||

## azurerm_mssql_database
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_mssql_database_transparent_data_encryption_enabled|Enforce transparant data encryption|WARNING|||

## azurerm_storage_account
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_storage_account_public_network_access_enabled|Consider disabling public network access on storage accounts. |NOTICE|||
|azurerm_storage_account_tls_version|Enforce TLS 1.2 on storage accounts |WARNING|||

## azurerm_windows_function_app
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_windows_function_app_ftps_state|Disable sftp to a windows function app |WARNING|||
|azurerm_windows_function_app_https_only|Force all traffic over https |WARNING|||
|azurerm_windows_function_app_minimum_tls_version|Enforce TLS 1.2 on windows function apps |WARNING|||


## azurerm_windows_web_app
|Name|Description|Severity|Enabled|Link|
| --- | --- | --- | --- | --- |
|azurerm_windows_web_app_ftps_state|Disable sftp to a windows web app |WARNING|||
|azurerm_windows_web_app_https_only|Force all traffic over https |WARNING|||
|azurerm_windows_web_app_minimum_tls_version|Enforce TLS 1.2 on windows web apps |WARNING|||
|azurerm_windows_web_app_minimum_tls_version|Enforce TLS 1.2 on windows web apps |WARNING|||
22 changes: 14 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,33 @@ import (
"github.com/terraform-linters/tflint-ruleset-azurerm-security/rules"
)

func CreateRuleSet() *tflint.BuiltinRuleSet {
func createRuleSet() *tflint.BuiltinRuleSet {
return &tflint.BuiltinRuleSet{
Name: "azurerm-security",
Version: "0.1.2",
Version: "0.1.3",
Rules: []tflint.Rule{
rules.NewAzurermKeyVaultPublicNetworkAccessEnabled(),
rules.NewAzurermLinuxFunctionAppFtpsState(),
rules.NewAzurermLinuxFunctionAppHTTPSOnly(),
rules.NewAzurermLinuxFunctionAppMinimumTLSVersion(),
rules.NewAzurermLinuxWebAppFtpsState(),
rules.NewAzurermLinuxWebAppHttpsOnly(),
rules.NewAzurermLinuxWebAppMinimumTlsVersion(),
rules.NewAzurermLinuxWebAppHTTPSOnly(),
rules.NewAzurermLinuxWebAppMinimumTLSVersion(),
rules.NewAzurermMssqlDatabaseEncryption(),
rules.NewAzurermStorageAccountPublicNetworkAccessEnabled(),
rules.NewAzurermStorageAccountUnsecureTls(),
rules.NewAzurermStorageAccountUnsecureTLS(),
rules.NewAzurermWindowsFunctionAppFtpsState(),
rules.NewAzurermWindowsFunctionAppHTTPSOnly(),
rules.NewAzurermWindowsFunctionAppMinimumTLSVersion(),
rules.NewAzurermWindowsWebAppFtpsState(),
rules.NewAzurermWindowsWebAppHttpsOnly(),
rules.NewAzurermWindowsWebAppMinimumTlsVersion(),
rules.NewAzurermWindowsWebAppHTTPSOnly(),
rules.NewAzurermWindowsWebAppMinimumTLSVersion(),
},
}
}

func main() {
plugin.Serve(&plugin.ServeOpts{
RuleSet: CreateRuleSet(),
RuleSet: createRuleSet(),
})
}
2 changes: 1 addition & 1 deletion main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestRulesLength(t *testing.T) {
ruleSet := CreateRuleSet()
ruleSet := createRuleSet()
actualRules := len(ruleSet.Rules)

// Count .go files in rules directory that don't end with _test.go
Expand Down
105 changes: 105 additions & 0 deletions rules/azurerm_linux_function_app_ftps_state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package rules

import (
"fmt"
"strings"

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

// AzurermLinuxFunctionAppFtpsState checks that ftps_state is set to "Disabled"
type AzurermLinuxFunctionAppFtpsState struct {
tflint.DefaultRule

resourceType string
attributePath []string
expectedValue string
}

// NewAzurermLinuxFunctionAppFtpsState returns a new rule instance
func NewAzurermLinuxFunctionAppFtpsState() *AzurermLinuxFunctionAppFtpsState {
return &AzurermLinuxFunctionAppFtpsState{
resourceType: "azurerm_linux_function_app",
attributePath: []string{"site_config", "ftps_state"},
expectedValue: "Disabled",
}
}

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

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

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

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

// Check verifies that ftps_state is set to "Disabled"
func (r *AzurermLinuxFunctionAppFtpsState) Check(runner tflint.Runner) error {
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
Blocks: []hclext.BlockSchema{
{
Type: "site_config",
Body: &hclext.BodySchema{
Attributes: []hclext.AttributeSchema{
{Name: "ftps_state"},
},
},
},
},
}, nil)
if err != nil {
return err
}

for _, resource := range resources.Blocks {
siteConfigBlocks := resource.Body.Blocks.OfType("site_config")
if len(siteConfigBlocks) == 0 {
runner.EmitIssue(
r,
"site_config block is missing, ftps_state should be set to Disabled",
resource.DefRange,
)
continue
}

siteConfig := siteConfigBlocks[0]
attribute, exists := siteConfig.Body.Attributes["ftps_state"]
if !exists {
runner.EmitIssue(
r,
"ftps_state is missing in site_config, should be set to Disabled",
siteConfig.DefRange,
)
continue
}

err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
if !strings.EqualFold(val, r.expectedValue) {
runner.EmitIssue(
r,
fmt.Sprintf("ftps_state is set to %s, should be set to Disabled", val),
attribute.Expr.Range(),
)
}
return nil
}, nil)
if err != nil {
return err
}
}

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

import (
"testing"

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

func Test_AzurermLinuxFunctionAppFtpsState(t *testing.T) {
tests := []struct {
Name string
Content string
Expected helper.Issues
}{
{
Name: "ftps_state not set to Disabled",
Content: `
resource "azurerm_linux_function_app" "example" {
site_config {
ftps_state = "FtpsOnly"
}
}`,
Expected: helper.Issues{
{
Rule: NewAzurermLinuxFunctionAppFtpsState(),
Message: "ftps_state is set to FtpsOnly, should be set to Disabled",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{
Line: 4,
Column: 22,
},
End: hcl.Pos{
Line: 4,
Column: 32,
},
},
},
},
},
{
Name: "ftps_state set to disabled (lowercase)",
Content: `
resource "azurerm_linux_function_app" "example" {
site_config {
ftps_state = "disabled"
}
}`,
Expected: helper.Issues{},
},
{
Name: "ftps_state set to DISABLED (uppercase)",
Content: `
resource "azurerm_linux_function_app" "example" {
site_config {
ftps_state = "DISABLED"
}
}`,
Expected: helper.Issues{},
},
{
Name: "ftps_state attribute missing",
Content: `
resource "azurerm_linux_function_app" "example" {
site_config {
}
}`,
Expected: helper.Issues{
{
Rule: NewAzurermLinuxFunctionAppFtpsState(),
Message: "ftps_state is missing in site_config, should be set to Disabled",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{
Line: 3,
Column: 5,
},
End: hcl.Pos{
Line: 3,
Column: 16,
},
},
},
},
},
{
Name: "site_config block missing",
Content: `
resource "azurerm_linux_function_app" "example" {
}`,
Expected: helper.Issues{
{
Rule: NewAzurermLinuxFunctionAppFtpsState(),
Message: "site_config block is missing, ftps_state should be set to Disabled",
Range: hcl.Range{
Filename: "resource.tf",
Start: hcl.Pos{
Line: 2,
Column: 1,
},
End: hcl.Pos{
Line: 2,
Column: 48,
},
},
},
},
},
}

rule := NewAzurermLinuxFunctionAppFtpsState()

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)
})
}
}
Loading

0 comments on commit 3cc330a

Please sign in to comment.