Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from liamg/liamg-azure-support
Add azure support
- Loading branch information
Showing
11 changed files
with
439 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
/tfsec | ||
/bin | ||
/bin | ||
/.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
internal/app/tfsec/azurerm_open_network_security_rules_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package tfsec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/liamg/tfsec/internal/app/tfsec/checks" | ||
) | ||
|
||
func Test_AzureOpenNetworkSecurityGroupRule(t *testing.T) { | ||
|
||
var tests = []struct { | ||
name string | ||
source string | ||
expectedResultCode checks.Code | ||
}{ | ||
{ | ||
name: "check azurerm_network_security_rule inbound on 0.0.0.0/0", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Inbound" | ||
source_address_prefix = "0.0.0.0/0" | ||
}`, | ||
expectedResultCode: checks.AzureOpenInboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule inbound on *", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Inbound" | ||
source_address_prefix = "*" | ||
}`, | ||
expectedResultCode: checks.AzureOpenInboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule inbound on 0.0.0.0/0 in list", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Inbound" | ||
source_address_prefixes = ["0.0.0.0/0"] | ||
}`, | ||
expectedResultCode: checks.AzureOpenInboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule inbound on * in list", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Inbound" | ||
source_address_prefixes = ["*"] | ||
}`, | ||
expectedResultCode: checks.AzureOpenInboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule outbound on 0.0.0.0/0", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Outbound" | ||
destination_address_prefix = "0.0.0.0/0" | ||
}`, | ||
expectedResultCode: checks.AzureOpenOutboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule outbound on 0.0.0.0/0 in list", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Outbound" | ||
destination_address_prefixes = ["0.0.0.0/0"] | ||
}`, | ||
expectedResultCode: checks.AzureOpenOutboundNetworkSecurityGroupRule, | ||
}, | ||
{ | ||
name: "check azurerm_network_security_rule outbound on 10.0.0.0/16", | ||
source: ` | ||
resource "azurerm_network_security_rule" "my-rule" { | ||
direction = "Outbound" | ||
destination_address_prefix = "10.0.0.0/16" | ||
}`, | ||
expectedResultCode: checks.None, | ||
}, | ||
|
||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
results := scanSource(test.source) | ||
assertCheckCodeExists(t, test.expectedResultCode, results) | ||
}) | ||
} | ||
|
||
} |
50 changes: 50 additions & 0 deletions
50
internal/app/tfsec/azurerm_unencrypted_data_lake_store_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package tfsec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/liamg/tfsec/internal/app/tfsec/checks" | ||
) | ||
|
||
func Test_AzureUnencryptedDataLakeStore(t *testing.T) { | ||
|
||
var tests = []struct { | ||
name string | ||
source string | ||
expectedResultCode checks.Code | ||
}{ | ||
{ | ||
name: "check azurerm_data_lake_store with encryption disabled", | ||
source: ` | ||
resource "azurerm_data_lake_store" "my-lake-store" { | ||
encryption_state = "Disabled" | ||
}`, | ||
expectedResultCode: checks.AzureUnencryptedDataLakeStore, | ||
}, | ||
{ | ||
name: "check azurerm_data_lake_store with encryption enabled", | ||
source: ` | ||
resource "azurerm_data_lake_store" "my-lake-store" { | ||
encryption_state = "Enabled" | ||
}`, | ||
expectedResultCode: checks.None, | ||
}, | ||
{ | ||
name: "check azurerm_data_lake_store with encryption enabled by default", | ||
source: ` | ||
resource "azurerm_data_lake_store" "my-lake-store" { | ||
}`, | ||
expectedResultCode: checks.None, | ||
}, | ||
|
||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
results := scanSource(test.source) | ||
assertCheckCodeExists(t, test.expectedResultCode, results) | ||
}) | ||
} | ||
|
||
} |
53 changes: 53 additions & 0 deletions
53
internal/app/tfsec/azurerm_unencrypted_managed_disk_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package tfsec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/liamg/tfsec/internal/app/tfsec/checks" | ||
) | ||
|
||
func Test_AzureUnencryptedManagedDisk(t *testing.T) { | ||
|
||
var tests = []struct { | ||
name string | ||
source string | ||
expectedResultCode checks.Code | ||
}{ | ||
{ | ||
name: "check azurerm_managed_disk with no encryption_settings", | ||
source: ` | ||
resource "azurerm_managed_disk" "my-disk" { | ||
}`, | ||
expectedResultCode: checks.AzureUnencryptedManagedDisk, | ||
}, | ||
{ | ||
name: "check azurerm_managed_disk with encryption disabled", | ||
source: ` | ||
resource "azurerm_managed_disk" "my-disk" { | ||
encryption_settings = { | ||
enabled = false | ||
} | ||
}`, | ||
expectedResultCode: checks.AzureUnencryptedManagedDisk, | ||
}, | ||
{ | ||
name: "check azurerm_managed_disk with encryption enabled", | ||
source: ` | ||
resource "azurerm_managed_disk" "my-disk" { | ||
encryption_settings = { | ||
enabled = true | ||
} | ||
}`, | ||
expectedResultCode: checks.None, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
results := scanSource(test.source) | ||
assertCheckCodeExists(t, test.expectedResultCode, results) | ||
}) | ||
} | ||
|
||
} |
45 changes: 45 additions & 0 deletions
45
internal/app/tfsec/azurerm_virtual_machine_with_password_authentication_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package tfsec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/liamg/tfsec/internal/app/tfsec/checks" | ||
) | ||
|
||
func Test_AzureVMWithPasswordAuth(t *testing.T) { | ||
|
||
var tests = []struct { | ||
name string | ||
source string | ||
expectedResultCode checks.Code | ||
}{ | ||
{ | ||
name: "check azurerm_virtual_machine with password auth", | ||
source: ` | ||
resource "azurerm_virtual_machine" "my-disk" { | ||
os_profile_linux_config = { | ||
disable_password_authentication = false | ||
} | ||
}`, | ||
expectedResultCode: checks.AzureVMWithPasswordAuthentication, | ||
}, | ||
{ | ||
name: "check azurerm_virtual_machine without password auth", | ||
source: ` | ||
resource "azurerm_virtual_machine" "my-disk" { | ||
os_profile_linux_config = { | ||
disable_password_authentication = true | ||
} | ||
}`, | ||
expectedResultCode: checks.None, | ||
}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
results := scanSource(test.source) | ||
assertCheckCodeExists(t, test.expectedResultCode, results) | ||
}) | ||
} | ||
|
||
} |
68 changes: 68 additions & 0 deletions
68
internal/app/tfsec/checks/azurerm_open_network_security_rules.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package checks | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/hcl/v2" | ||
) | ||
|
||
const AzureOpenInboundNetworkSecurityGroupRule Code = "AZU001" | ||
const AzureOpenOutboundNetworkSecurityGroupRule Code = "AZU002" | ||
|
||
|
||
func init() { | ||
RegisterCheck(Check{ | ||
RequiredTypes: []string{"resource"}, | ||
RequiredLabels: []string{"azurerm_network_security_rule"}, | ||
CheckFunc: func(block *hcl.Block, ctx *hcl.EvalContext) []Result { | ||
|
||
directionVal, _, exists := getAttribute(block, ctx, "direction") | ||
if !exists { | ||
return nil | ||
} | ||
|
||
code := AzureOpenInboundNetworkSecurityGroupRule | ||
checkAttribute := "source_address_prefix" | ||
if directionVal.AsString() == "Outbound" { | ||
code = AzureOpenOutboundNetworkSecurityGroupRule | ||
checkAttribute = "destination_address_prefix" | ||
} | ||
|
||
if prefix, prefixRange, exists := getAttribute(block, ctx, checkAttribute); exists { | ||
if strings.HasSuffix(prefix.AsString(), "/0") || prefix.AsString() == "*" { | ||
return []Result{ | ||
NewResult( | ||
code, | ||
fmt.Sprintf( | ||
"Resource '%s' defines a fully open %s network security group rule.", | ||
getBlockName(block), | ||
strings.ToLower(directionVal.AsString()), | ||
), | ||
prefixRange, | ||
), | ||
} | ||
} | ||
} | ||
|
||
var results []Result | ||
|
||
if prefixesVal, prefixesRange, exists := getAttribute(block, ctx, checkAttribute+"es"); exists { | ||
for _, prefix := range prefixesVal.AsValueSlice() { | ||
if strings.HasSuffix(prefix.AsString(), "/0") || prefix.AsString() == "*"{ | ||
results = append(results, | ||
NewResult( | ||
code, | ||
fmt.Sprintf("Resource '%s' defines a fully open %s security group rule.", getBlockName(block), prefix.AsString()), | ||
prefixesRange, | ||
), | ||
) | ||
} | ||
} | ||
|
||
} | ||
|
||
return results | ||
}, | ||
}) | ||
} |
33 changes: 33 additions & 0 deletions
33
internal/app/tfsec/checks/azurerm_unencrypted_data_lake_store.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package checks | ||
|
||
import ( | ||
"fmt" | ||
"github.com/hashicorp/hcl/v2" | ||
"github.com/zclconf/go-cty/cty" | ||
) | ||
|
||
const AzureUnencryptedDataLakeStore Code = "AZU004" | ||
|
||
func init() { | ||
RegisterCheck(Check{ | ||
RequiredTypes: []string{"resource"}, | ||
RequiredLabels: []string{"azurerm_data_lake_store"}, | ||
CheckFunc: func(block *hcl.Block, ctx *hcl.EvalContext) []Result { | ||
|
||
if encryptionStateVal, encryptionStateRange, exists := getAttribute(block, ctx, "encryption_state"); exists && encryptionStateVal.Type() == cty.String && encryptionStateVal.AsString() == "Disabled" { | ||
return []Result{ | ||
NewResult( | ||
AzureUnencryptedDataLakeStore, | ||
fmt.Sprintf( | ||
"Resource '%s' defines an unencrypted data lake store.", | ||
getBlockName(block), | ||
), | ||
encryptionStateRange, | ||
), | ||
} | ||
} | ||
|
||
return nil | ||
}, | ||
}) | ||
} |
Oops, something went wrong.