-
Notifications
You must be signed in to change notification settings - Fork 531
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added first kubernetes checks * fix example code * Add k8s to init Co-authored-by: Owen Rumney <owen.rumney@aquasec.com>
- Loading branch information
Showing
11 changed files
with
481 additions
and
6 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 |
---|---|---|
|
@@ -19,6 +19,7 @@ var providers = []string{ | |
"General", | ||
"GitHub", | ||
"Google", | ||
"Kubernetes", | ||
"OpenStack", | ||
"Oracle", | ||
} | ||
|
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
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
183 changes: 183 additions & 0 deletions
183
internal/app/tfsec/rules/kubernetes/network/no_public_egress_rule.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,183 @@ | ||
package network | ||
|
||
// ATTENTION! | ||
// This rule was autogenerated! | ||
// Before making changes, consider updating the generator. | ||
|
||
import ( | ||
"github.com/aquasecurity/tfsec/internal/app/tfsec/block" | ||
"github.com/aquasecurity/tfsec/internal/app/tfsec/cidr" | ||
"github.com/aquasecurity/tfsec/internal/app/tfsec/hclcontext" | ||
"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner" | ||
"github.com/aquasecurity/tfsec/pkg/provider" | ||
"github.com/aquasecurity/tfsec/pkg/result" | ||
"github.com/aquasecurity/tfsec/pkg/rule" | ||
"github.com/aquasecurity/tfsec/pkg/severity" | ||
) | ||
|
||
func init() { | ||
scanner.RegisterCheckRule(rule.Rule{ | ||
Provider: provider.KubernetesProvider, | ||
Service: "network", | ||
ShortCode: "no-public-egress", | ||
Documentation: rule.RuleDocumentation{ | ||
Summary: "Public egress should not be allowed via network policies", | ||
Explanation: `You should not expose infrastructure to the public internet except where explicitly required`, | ||
Impact: "Exfiltration of data to the public internet", | ||
Resolution: "Remove public access except where explicitly required", | ||
BadExample: []string{` | ||
resource "kubernetes_network_policy" "bad_example" { | ||
metadata { | ||
name = "terraform-example-network-policy" | ||
namespace = "default" | ||
} | ||
spec { | ||
pod_selector { | ||
match_expressions { | ||
key = "name" | ||
operator = "In" | ||
values = ["webfront", "api"] | ||
} | ||
} | ||
egress { | ||
ports { | ||
port = "http" | ||
protocol = "TCP" | ||
} | ||
ports { | ||
port = "8125" | ||
protocol = "UDP" | ||
} | ||
to { | ||
ip_block { | ||
cidr = "0.0.0.0/0" | ||
except = [ | ||
"10.0.0.0/24", | ||
"10.0.1.0/24", | ||
] | ||
} | ||
} | ||
} | ||
ingress { | ||
ports { | ||
port = "http" | ||
protocol = "TCP" | ||
} | ||
ports { | ||
port = "8125" | ||
protocol = "UDP" | ||
} | ||
from { | ||
ip_block { | ||
cidr = "10.0.0.0/16" | ||
except = [ | ||
"10.0.0.0/24", | ||
"10.0.1.0/24", | ||
] | ||
} | ||
} | ||
} | ||
policy_types = ["Ingress", "Egress"] | ||
} | ||
} | ||
`}, | ||
GoodExample: []string{` | ||
resource "kubernetes_network_policy" "good_example" { | ||
metadata { | ||
name = "terraform-example-network-policy" | ||
namespace = "default" | ||
} | ||
spec { | ||
pod_selector { | ||
match_expressions { | ||
key = "name" | ||
operator = "In" | ||
values = ["webfront", "api"] | ||
} | ||
} | ||
egress { | ||
ports { | ||
port = "http" | ||
protocol = "TCP" | ||
} | ||
ports { | ||
port = "8125" | ||
protocol = "UDP" | ||
} | ||
to { | ||
ip_block { | ||
cidr = "10.0.0.0/16" | ||
except = [ | ||
"10.0.0.0/24", | ||
"10.0.1.0/24", | ||
] | ||
} | ||
} | ||
} | ||
ingress { | ||
ports { | ||
port = "http" | ||
protocol = "TCP" | ||
} | ||
ports { | ||
port = "8125" | ||
protocol = "UDP" | ||
} | ||
from { | ||
ip_block { | ||
cidr = "10.0.0.0/16" | ||
except = [ | ||
"10.0.0.0/24", | ||
"10.0.1.0/24", | ||
] | ||
} | ||
} | ||
} | ||
policy_types = ["Ingress", "Egress"] | ||
} | ||
} | ||
`}, | ||
Links: []string{ | ||
"https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/network_policy#spec.ingress.from.ip_block.cidr", | ||
}, | ||
}, | ||
RequiredTypes: []string{ | ||
"resource", | ||
}, | ||
RequiredLabels: []string{ | ||
"kubernetes_network_policy", | ||
}, | ||
DefaultSeverity: severity.High, | ||
CheckFunc: func(set result.Set, resourceBlock block.Block, _ *hclcontext.Context) { | ||
|
||
egressBlock := resourceBlock.GetBlock("spec").GetBlock("egress") | ||
if egressBlock.IsNil() || len(egressBlock.GetBlocks("to")) == 0 { | ||
set.AddResult(). | ||
WithDescription("Resource '%s' allows all egress traffic by default", resourceBlock.FullName()) | ||
return | ||
} | ||
|
||
for _, to := range egressBlock.GetBlocks("to") { | ||
if cidrAttr := to.GetBlock("ip_block").GetAttribute("cidr"); cidrAttr.IsString() { | ||
if cidr.IsOpen(cidrAttr) { | ||
set.AddResult(). | ||
WithDescription("Resource '%s' allows egress traffic to the internet", resourceBlock.FullName()). | ||
WithAttribute(cidrAttr) | ||
} | ||
} | ||
} | ||
}, | ||
}) | ||
} |
53 changes: 53 additions & 0 deletions
53
internal/app/tfsec/rules/kubernetes/network/no_public_egress_rule_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 network | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/aquasecurity/tfsec/internal/app/tfsec/scanner" | ||
"github.com/aquasecurity/tfsec/internal/app/tfsec/testutil" | ||
) | ||
|
||
func Test_KubernetesNoPublicEgress_FailureExamples(t *testing.T) { | ||
expectedCode := "kubernetes-network-no-public-egress" | ||
|
||
rule, err := scanner.GetRuleById(expectedCode) | ||
if err != nil { | ||
t.Fatalf("Rule not found: %s", expectedCode) | ||
} | ||
for i, badExample := range rule.Documentation.BadExample { | ||
t.Logf("Running bad example for '%s' #%d", expectedCode, i+1) | ||
if strings.TrimSpace(badExample) == "" { | ||
t.Fatalf("bad example code not provided for %s", rule.ID()) | ||
} | ||
defer func() { | ||
if err := recover(); err != nil { | ||
t.Fatalf("Scan (bad) failed: %s", err) | ||
} | ||
}() | ||
results := testutil.ScanHCL(badExample, t) | ||
testutil.AssertCheckCode(t, rule.ID(), "", results) | ||
} | ||
} | ||
|
||
func Test_KubernetesNoPublicEgress_SuccessExamples(t *testing.T) { | ||
expectedCode := "kubernetes-network-no-public-egress" | ||
|
||
rule, err := scanner.GetRuleById(expectedCode) | ||
if err != nil { | ||
t.Fatalf("Rule not found: %s", expectedCode) | ||
} | ||
for i, example := range rule.Documentation.GoodExample { | ||
t.Logf("Running good example for '%s' #%d", expectedCode, i+1) | ||
if strings.TrimSpace(example) == "" { | ||
t.Fatalf("good example code not provided for %s", rule.ID()) | ||
} | ||
defer func() { | ||
if err := recover(); err != nil { | ||
t.Fatalf("Scan (good) failed: %s", err) | ||
} | ||
}() | ||
results := testutil.ScanHCL(example, t) | ||
testutil.AssertCheckCode(t, "", rule.ID(), results) | ||
} | ||
} |
Oops, something went wrong.