Skip to content

Commit 457f309

Browse files
authored
New rules (#6)
* linux web app * new rules --------- Co-authored-by: Preben Huybrechts <[email protected]>
1 parent 907277f commit 457f309

10 files changed

+657
-1
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ plugin "template" {
3333

3434
|Name|Description|Severity|Enabled|Link|
3535
| --- | --- | --- | --- | --- |
36-
|azurerm_storage_account_tls_version.go|Enforce TLS 1.2 on storage accounts |ERROR|||
36+
|azurerm_linux_web_app_ftps_state|Disable sftp to a linux web app |ERROR|||
37+
|azurerm_linux_web_app_minimum_tls_version|Enforce TLS 1.2 on linux web apps |ERROR|||
38+
|azurerm_mssql_database_transparent_data_encryption_enabled|Enforce transparant data encryption|ERROR|||
39+
|azurerm_storage_account_tls_version|Enforce TLS 1.2 on storage accounts |ERROR|||
40+
|azurerm_windows_web_app_ftps_state|Disable sftp to a windows web app |ERROR|||
41+
|azurerm_windows_web_app_minimum_tls_version|Enforce TLS 1.2 on windows web apps |ERROR|||
3742

3843
## Building the plugin
3944

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ func main() {
1212
Name: "azurerm-security",
1313
Version: "0.1.0",
1414
Rules: []tflint.Rule{
15+
rules.NewAzurermLinuxWebAppFtpsState(),
16+
rules.NewAzurermLinuxWebAppMinimumTlsVersion(),
17+
rules.NewAzurermMssqlDatabaseEncryption(),
1518
rules.NewAzurermStorageAccountUnsecureTls(),
19+
rules.NewAzurermWindowsWebAppFtpsState(),
20+
rules.NewAzurermWindowsWebAppMinimumTlsVersion(),
1621
},
1722
},
1823
})
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package rules
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
7+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
8+
)
9+
10+
// AzurermLinuxWebAppFtpsState checks if ftps_state is disabled
11+
type AzurermLinuxWebAppFtpsState struct {
12+
tflint.DefaultRule
13+
14+
resourceType string
15+
attributeName string
16+
expectedValue string
17+
}
18+
19+
// NewAzurermLinuxWebAppFtpsState creates a new rule instance
20+
func NewAzurermLinuxWebAppFtpsState() *AzurermLinuxWebAppFtpsState {
21+
return &AzurermLinuxWebAppFtpsState{
22+
resourceType: "azurerm_linux_web_app",
23+
attributeName: "ftps_state",
24+
expectedValue: "Disabled",
25+
}
26+
}
27+
28+
// Name returns the rule name
29+
func (r *AzurermLinuxWebAppFtpsState) Name() string {
30+
return "azurerm_linux_web_app_ftps_state"
31+
}
32+
33+
// Enabled returns whether the rule is enabled by default
34+
func (r *AzurermLinuxWebAppFtpsState) Enabled() bool {
35+
return true
36+
}
37+
38+
// Severity returns the rule severity
39+
func (r *AzurermLinuxWebAppFtpsState) Severity() tflint.Severity {
40+
return tflint.ERROR
41+
}
42+
43+
// Link returns the rule reference link
44+
func (r *AzurermLinuxWebAppFtpsState) Link() string {
45+
return ""
46+
}
47+
48+
// Check verifies that ftps_state is set to "Disabled"
49+
func (r *AzurermLinuxWebAppFtpsState) Check(runner tflint.Runner) error {
50+
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
51+
Attributes: []hclext.AttributeSchema{
52+
{Name: r.attributeName},
53+
},
54+
}, nil)
55+
if err != nil {
56+
return err
57+
}
58+
59+
for _, resource := range resources.Blocks {
60+
attribute, exists := resource.Body.Attributes[r.attributeName]
61+
if !exists {
62+
runner.EmitIssue(
63+
r,
64+
"ftps_state should be set to Disabled",
65+
resource.DefRange,
66+
)
67+
continue
68+
}
69+
70+
err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
71+
if val != r.expectedValue {
72+
runner.EmitIssue(
73+
r,
74+
fmt.Sprintf("ftps_state is set to %q, should be Disabled", val),
75+
attribute.Expr.Range(),
76+
)
77+
}
78+
return nil
79+
}, nil)
80+
81+
if err != nil {
82+
return err
83+
}
84+
}
85+
86+
return nil
87+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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_AzurermLinuxWebAppFtpsState(t *testing.T) {
11+
tests := []struct {
12+
Name string
13+
Content string
14+
Expected helper.Issues
15+
}{
16+
{
17+
Name: "FTPS enabled",
18+
Content: `
19+
resource "azurerm_linux_web_app" "example" {
20+
ftps_state = "Enabled"
21+
}`,
22+
Expected: helper.Issues{
23+
{
24+
Rule: NewAzurermLinuxWebAppFtpsState(),
25+
Message: `ftps_state is set to "Enabled", should be Disabled`,
26+
Range: hcl.Range{
27+
Filename: "resource.tf",
28+
Start: hcl.Pos{Line: 3, Column: 18},
29+
End: hcl.Pos{Line: 3, Column: 27},
30+
},
31+
},
32+
},
33+
},
34+
{
35+
Name: "FTPS state missing",
36+
Content: `
37+
resource "azurerm_linux_web_app" "example" {
38+
}`,
39+
Expected: helper.Issues{
40+
{
41+
Rule: NewAzurermLinuxWebAppFtpsState(),
42+
Message: `ftps_state should be set to Disabled`,
43+
Range: hcl.Range{
44+
Filename: "resource.tf",
45+
Start: hcl.Pos{Line: 2, Column: 1},
46+
End: hcl.Pos{Line: 2, Column: 43},
47+
},
48+
},
49+
},
50+
},
51+
{
52+
Name: "FTPS disabled",
53+
Content: `
54+
resource "azurerm_linux_web_app" "example" {
55+
ftps_state = "Disabled"
56+
}`,
57+
Expected: helper.Issues{},
58+
},
59+
}
60+
61+
rule := NewAzurermLinuxWebAppFtpsState()
62+
63+
for _, test := range tests {
64+
t.Run(test.Name, func(t *testing.T) {
65+
runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content})
66+
67+
if err := rule.Check(runner); err != nil {
68+
t.Fatalf("Unexpected error occurred: %s", err)
69+
}
70+
71+
helper.AssertIssues(t, test.Expected, runner.Issues)
72+
})
73+
}
74+
}
75+
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package rules
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/terraform-linters/tflint-plugin-sdk/hclext"
7+
"github.com/terraform-linters/tflint-plugin-sdk/tflint"
8+
)
9+
10+
// AzurermLinuxWebAppMinimumTlsVersion checks that minimum_tls_version is set to at least "1.2"
11+
type AzurermLinuxWebAppMinimumTlsVersion struct {
12+
tflint.DefaultRule
13+
14+
resourceType string
15+
attributeName string
16+
version string
17+
}
18+
19+
// NewAzurermLinuxWebAppMinimumTlsVersion returns a new rule instance
20+
func NewAzurermLinuxWebAppMinimumTlsVersion() *AzurermLinuxWebAppMinimumTlsVersion {
21+
return &AzurermLinuxWebAppMinimumTlsVersion{
22+
resourceType: "azurerm_linux_web_app",
23+
attributeName: "minimum_tls_version",
24+
version: "1.2",
25+
}
26+
}
27+
28+
// Name returns the rule name
29+
func (r *AzurermLinuxWebAppMinimumTlsVersion) Name() string {
30+
return "azurerm_linux_web_app_minimum_tls_version"
31+
}
32+
33+
// Enabled returns whether the rule is enabled by default
34+
func (r *AzurermLinuxWebAppMinimumTlsVersion) Enabled() bool {
35+
return true
36+
}
37+
38+
// Severity returns the rule severity
39+
func (r *AzurermLinuxWebAppMinimumTlsVersion) Severity() tflint.Severity {
40+
return tflint.ERROR
41+
}
42+
43+
// Link returns the rule reference link
44+
func (r *AzurermLinuxWebAppMinimumTlsVersion) Link() string {
45+
return ""
46+
}
47+
48+
// Check verifies that minimum_tls_version is at least "1.2"
49+
func (r *AzurermLinuxWebAppMinimumTlsVersion) Check(runner tflint.Runner) error {
50+
resources, err := runner.GetResourceContent(r.resourceType, &hclext.BodySchema{
51+
Attributes: []hclext.AttributeSchema{
52+
{Name: r.attributeName},
53+
},
54+
}, nil)
55+
if err != nil {
56+
return err
57+
}
58+
59+
for _, resource := range resources.Blocks {
60+
attribute, exists := resource.Body.Attributes[r.attributeName]
61+
if !exists {
62+
// Emit issue if minimum_tls_version attribute is missing
63+
runner.EmitIssue(
64+
r,
65+
fmt.Sprintf("%s is missing, should be set to %s or higher", r.attributeName, r.version),
66+
resource.DefRange,
67+
)
68+
continue
69+
}
70+
71+
err := runner.EvaluateExpr(attribute.Expr, func(val string) error {
72+
if val != r.version {
73+
runner.EmitIssue(
74+
r,
75+
fmt.Sprintf("%s is set to %s, should be %s or higher", r.attributeName, val, r.version),
76+
attribute.Expr.Range(),
77+
)
78+
}
79+
return nil
80+
}, nil)
81+
if err != nil {
82+
return err
83+
}
84+
}
85+
86+
return nil
87+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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_AzurermLinuxWebAppMinimumTlsVersion(t *testing.T) {
11+
tests := []struct {
12+
Name string
13+
Content string
14+
Expected helper.Issues
15+
}{
16+
{
17+
Name: "minimum_tls_version below 1.2",
18+
Content: `
19+
resource "azurerm_linux_web_app" "example" {
20+
minimum_tls_version = "1.0"
21+
}`,
22+
Expected: helper.Issues{
23+
{
24+
Rule: NewAzurermLinuxWebAppMinimumTlsVersion(),
25+
Message: "minimum_tls_version is set to 1.0, should be 1.2 or higher",
26+
Range: hcl.Range{
27+
Filename: "resource.tf",
28+
Start: hcl.Pos{Line: 3, Column: 27},
29+
End: hcl.Pos{Line: 3, Column: 32},
30+
},
31+
},
32+
},
33+
},
34+
{
35+
Name: "minimum_tls_version set to 1.2",
36+
Content: `
37+
resource "azurerm_linux_web_app" "example" {
38+
minimum_tls_version = "1.2"
39+
}`,
40+
Expected: helper.Issues{},
41+
},
42+
{
43+
Name: "minimum_tls_version attribute missing",
44+
Content: `
45+
resource "azurerm_linux_web_app" "example" {
46+
}`,
47+
Expected: helper.Issues{
48+
{
49+
Rule: NewAzurermLinuxWebAppMinimumTlsVersion(),
50+
Message: "minimum_tls_version is missing, should be set to 1.2 or higher",
51+
Range: hcl.Range{
52+
Filename: "resource.tf",
53+
Start: hcl.Pos{Line: 2, Column: 1},
54+
End: hcl.Pos{Line: 2, Column: 43},
55+
},
56+
},
57+
},
58+
},
59+
}
60+
61+
rule := NewAzurermLinuxWebAppMinimumTlsVersion()
62+
63+
for _, test := range tests {
64+
t.Run(test.Name, func(t *testing.T) {
65+
runner := helper.TestRunner(t, map[string]string{"resource.tf": test.Content})
66+
67+
if err := rule.Check(runner); err != nil {
68+
t.Fatalf("Unexpected error occurred: %s", err)
69+
}
70+
71+
helper.AssertIssues(t, test.Expected, runner.Issues)
72+
})
73+
}
74+
}

0 commit comments

Comments
 (0)