diff --git a/avd_docs/aws/ecr/AVD-AWS-0030/docs.md b/avd_docs/aws/ecr/AVD-AWS-0030/docs.md
index cacc98e8..ab63da31 100644
--- a/avd_docs/aws/ecr/AVD-AWS-0030/docs.md
+++ b/avd_docs/aws/ecr/AVD-AWS-0030/docs.md
@@ -1,8 +1,9 @@
Repository image scans should be enabled to ensure vulnerable software can be discovered and remediated as soon as possible.
+
### Impact
-The ability to scan images is not being used and vulnerabilities will not be highlighted
+
{{ remediationActions }}
diff --git a/avd_docs/aws/ecr/AVD-AWS-0031/docs.md b/avd_docs/aws/ecr/AVD-AWS-0031/docs.md
index f7d30790..e6251d5d 100644
--- a/avd_docs/aws/ecr/AVD-AWS-0031/docs.md
+++ b/avd_docs/aws/ecr/AVD-AWS-0031/docs.md
@@ -1,10 +1,10 @@
ECR images should be set to IMMUTABLE to prevent code injection through image mutation.
-
This can be done by setting image_tab_mutability
to IMMUTABLE
+
### Impact
-Image tags could be overwritten with compromised images
+
{{ remediationActions }}
diff --git a/avd_docs/aws/ecr/AVD-AWS-0032/docs.md b/avd_docs/aws/ecr/AVD-AWS-0032/docs.md
index b2078b0a..483f4b36 100644
--- a/avd_docs/aws/ecr/AVD-AWS-0032/docs.md
+++ b/avd_docs/aws/ecr/AVD-AWS-0032/docs.md
@@ -1,8 +1,9 @@
Allowing public access to the ECR repository risks leaking sensitive of abusable information
+
### Impact
-Risk of potential data leakage of sensitive artifacts
+
{{ remediationActions }}
diff --git a/avd_docs/aws/ecr/AVD-AWS-0033/docs.md b/avd_docs/aws/ecr/AVD-AWS-0033/docs.md
index a6e1af2c..25ca75f1 100644
--- a/avd_docs/aws/ecr/AVD-AWS-0033/docs.md
+++ b/avd_docs/aws/ecr/AVD-AWS-0033/docs.md
@@ -1,8 +1,9 @@
Images in the ECR repository are encrypted by default using AWS managed encryption keys. To increase control of the encryption and control the management of factors like key rotation, use a Customer Managed Key.
+
### Impact
-Using AWS managed keys does not allow for fine grained control
+
{{ remediationActions }}
diff --git a/avd_docs/aws/efs/AVD-AWS-0037/docs.md b/avd_docs/aws/efs/AVD-AWS-0037/docs.md
index c4667a47..5242c766 100644
--- a/avd_docs/aws/efs/AVD-AWS-0037/docs.md
+++ b/avd_docs/aws/efs/AVD-AWS-0037/docs.md
@@ -1,8 +1,9 @@
If your organization is subject to corporate or regulatory policies that require encryption of data and metadata at rest, we recommend creating a file system that is encrypted at rest, and mounting your file system using encryption of data in transit.
+
### Impact
-Data can be read from the EFS if compromised
+
{{ remediationActions }}
diff --git a/avd_docs/aws/eks/AVD-AWS-0038/docs.md b/avd_docs/aws/eks/AVD-AWS-0038/docs.md
index 79bc0e01..ae15d0ed 100644
--- a/avd_docs/aws/eks/AVD-AWS-0038/docs.md
+++ b/avd_docs/aws/eks/AVD-AWS-0038/docs.md
@@ -1,8 +1,9 @@
By default cluster control plane logging is not turned on. Logging is available for audit, api, authenticator, controllerManager and scheduler. All logging should be turned on for cluster control plane.
+
### Impact
-Logging provides valuable information about access and usage
+
{{ remediationActions }}
diff --git a/avd_docs/aws/eks/AVD-AWS-0039/docs.md b/avd_docs/aws/eks/AVD-AWS-0039/docs.md
index de61dab4..42437b50 100644
--- a/avd_docs/aws/eks/AVD-AWS-0039/docs.md
+++ b/avd_docs/aws/eks/AVD-AWS-0039/docs.md
@@ -1,8 +1,9 @@
EKS cluster resources should have the encryption_config block set with protection of the secrets resource.
+
### Impact
-EKS secrets could be read if compromised
+
{{ remediationActions }}
diff --git a/avd_docs/aws/eks/AVD-AWS-0040/docs.md b/avd_docs/aws/eks/AVD-AWS-0040/docs.md
index b4464df0..96743956 100644
--- a/avd_docs/aws/eks/AVD-AWS-0040/docs.md
+++ b/avd_docs/aws/eks/AVD-AWS-0040/docs.md
@@ -1,8 +1,9 @@
EKS clusters are available publicly by default, this should be explicitly disabled in the vpc_config of the EKS cluster resource.
+
### Impact
-EKS can be access from the internet
+
{{ remediationActions }}
diff --git a/avd_docs/aws/eks/AVD-AWS-0041/docs.md b/avd_docs/aws/eks/AVD-AWS-0041/docs.md
index 19a023a3..9e1ba77a 100644
--- a/avd_docs/aws/eks/AVD-AWS-0041/docs.md
+++ b/avd_docs/aws/eks/AVD-AWS-0041/docs.md
@@ -1,8 +1,9 @@
EKS Clusters have public access cidrs set to 0.0.0.0/0 by default which is wide open to the internet. This should be explicitly set to a more specific private CIDR range
+
### Impact
-EKS can be accessed from the internet
+
{{ remediationActions }}
diff --git a/checks/cloud/aws/ecr/enable_image_scans.go b/checks/cloud/aws/ecr/enable_image_scans.go
index 2cfb3e11..1eae943c 100755
--- a/checks/cloud/aws/ecr/enable_image_scans.go
+++ b/checks/cloud/aws/ecr/enable_image_scans.go
@@ -33,7 +33,8 @@ var CheckEnableImageScans = rules.Register(
Links: cloudFormationEnableImageScansLinks,
RemediationMarkdown: cloudFormationEnableImageScansRemediationMarkdown,
},
- Severity: severity.High,
+ Severity: severity.High,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, repo := range s.AWS.ECR.Repositories {
diff --git a/checks/cloud/aws/ecr/enable_image_scans.rego b/checks/cloud/aws/ecr/enable_image_scans.rego
new file mode 100644
index 00000000..c36535be
--- /dev/null
+++ b/checks/cloud/aws/ecr/enable_image_scans.rego
@@ -0,0 +1,41 @@
+# METADATA
+# title: ECR repository has image scans disabled.
+# description: |
+# Repository image scans should be enabled to ensure vulnerable software can be discovered and remediated as soon as possible.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning.html
+# custom:
+# id: AVD-AWS-0030
+# avd_id: AVD-AWS-0030
+# provider: aws
+# service: ecr
+# severity: HIGH
+# short_code: enable-image-scans
+# recommended_action: Enable ECR image scanning
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: ecr
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository#image_scanning_configuration
+# good_examples: checks/cloud/aws/ecr/enable_image_scans.tf.go
+# bad_examples: checks/cloud/aws/ecr/enable_image_scans.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/ecr/enable_image_scans.cf.go
+# bad_examples: checks/cloud/aws/ecr/enable_image_scans.cf.go
+package builtin.aws.ecr.aws0030
+
+import rego.v1
+
+deny contains res if {
+ some repo in input.aws.ecr.repositories
+ repo.imagescanning.scanonpush.value == false
+
+ res := result.new("Image scanning is not enabled", repo.imagescanning.scanonpush)
+}
diff --git a/checks/cloud/aws/ecr/enable_image_scans_test.go b/checks/cloud/aws/ecr/enable_image_scans_test.go
deleted file mode 100644
index 0cf5df66..00000000
--- a/checks/cloud/aws/ecr/enable_image_scans_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package ecr
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckEnableImageScans(t *testing.T) {
- tests := []struct {
- name string
- input ecr.ECR
- expected bool
- }{
- {
- name: "ECR repository with image scans disabled",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- ImageScanning: ecr.ImageScanning{
- Metadata: trivyTypes.NewTestMetadata(),
- ScanOnPush: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "ECR repository with image scans enabled",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- ImageScanning: ecr.ImageScanning{
- Metadata: trivyTypes.NewTestMetadata(),
- ScanOnPush: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.ECR = test.input
- results := CheckEnableImageScans.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckEnableImageScans.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/ecr/enable_image_scans_test.rego b/checks/cloud/aws/ecr/enable_image_scans_test.rego
new file mode 100644
index 00000000..ae0c46de
--- /dev/null
+++ b/checks/cloud/aws/ecr/enable_image_scans_test.rego
@@ -0,0 +1,18 @@
+package builtin.aws.ecr.aws0030_test
+
+import rego.v1
+
+import data.builtin.aws.ecr.aws0030 as check
+import data.lib.test
+
+test_allow_image_scanning_enabled if {
+ inp := {"aws": {"ecr": {"repositories": [{"imagescanning": {"scanonpush": {"value": true}}}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_image_scanning_disabled if {
+ inp := {"aws": {"ecr": {"repositories": [{"imagescanning": {"scanonpush": {"value": false}}}]}}}
+
+ test.assert_equal_message("Image scanning is not enabled", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/ecr/enforce_immutable_repository.go b/checks/cloud/aws/ecr/enforce_immutable_repository.go
index 6ebcfadc..dd9f2f41 100755
--- a/checks/cloud/aws/ecr/enforce_immutable_repository.go
+++ b/checks/cloud/aws/ecr/enforce_immutable_repository.go
@@ -35,7 +35,8 @@ This can be done by setting image_tab_mutability
to IMMUTABLE
Links: cloudFormationEnforceImmutableRepositoryLinks,
RemediationMarkdown: cloudFormationEnforceImmutableRepositoryRemediationMarkdown,
},
- Severity: severity.High,
+ Severity: severity.High,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, repo := range s.AWS.ECR.Repositories {
diff --git a/checks/cloud/aws/ecr/enforce_immutable_repository.rego b/checks/cloud/aws/ecr/enforce_immutable_repository.rego
new file mode 100644
index 00000000..1a89d859
--- /dev/null
+++ b/checks/cloud/aws/ecr/enforce_immutable_repository.rego
@@ -0,0 +1,42 @@
+# METADATA
+# title: ECR images tags shouldn't be mutable.
+# description: |
+# ECR images should be set to IMMUTABLE to prevent code injection through image mutation.
+# This can be done by setting image_tab_mutability
to IMMUTABLE
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://sysdig.com/blog/toctou-tag-mutability/
+# custom:
+# id: AVD-AWS-0031
+# avd_id: AVD-AWS-0031
+# provider: aws
+# service: ecr
+# severity: HIGH
+# short_code: enforce-immutable-repository
+# recommended_action: Only use immutable images in ECR
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: ecr
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository
+# good_examples: checks/cloud/aws/ecr/enforce_immutable_repository.tf.go
+# bad_examples: checks/cloud/aws/ecr/enforce_immutable_repository.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/ecr/enforce_immutable_repository.cf.go
+# bad_examples: checks/cloud/aws/ecr/enforce_immutable_repository.cf.go
+package builtin.aws.ecr.aws0031
+
+import rego.v1
+
+deny contains res if {
+ some repo in input.aws.ecr.repositories
+ repo.imagetagsimmutable.value == false
+
+ res := result.new("Repository tags are mutable.", repo.imagetagsimmutable)
+}
diff --git a/checks/cloud/aws/ecr/enforce_immutable_repository_test.go b/checks/cloud/aws/ecr/enforce_immutable_repository_test.go
deleted file mode 100644
index 8ced0b65..00000000
--- a/checks/cloud/aws/ecr/enforce_immutable_repository_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package ecr
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckEnforceImmutableRepository(t *testing.T) {
- tests := []struct {
- name string
- input ecr.ECR
- expected bool
- }{
- {
- name: "ECR mutable image tags",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- ImageTagsImmutable: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- },
- },
- },
- expected: true,
- },
- {
- name: "ECR immutable image tags",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- ImageTagsImmutable: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.ECR = test.input
- results := CheckEnforceImmutableRepository.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckEnforceImmutableRepository.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/ecr/enforce_immutable_repository_test.rego b/checks/cloud/aws/ecr/enforce_immutable_repository_test.rego
new file mode 100644
index 00000000..7068fa3d
--- /dev/null
+++ b/checks/cloud/aws/ecr/enforce_immutable_repository_test.rego
@@ -0,0 +1,18 @@
+package builtin.aws.ecr.aws0031_test
+
+import rego.v1
+
+import data.builtin.aws.ecr.aws0031 as check
+import data.lib.test
+
+test_allow_immutable_repository if {
+ inp := {"aws": {"ecr": {"repositories": [{"imagetagsimmutable": {"value": true}}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_immutable_repository if {
+ inp := {"aws": {"ecr": {"repositories": [{"imagetagsimmutable": {"value": false}}]}}}
+
+ test.assert_equal_message("Repository tags are mutable.", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/ecr/no_public_access.go b/checks/cloud/aws/ecr/no_public_access.go
index dbefbaa0..06139428 100755
--- a/checks/cloud/aws/ecr/no_public_access.go
+++ b/checks/cloud/aws/ecr/no_public_access.go
@@ -39,7 +39,8 @@ var CheckNoPublicAccess = rules.Register(
Links: cloudFormationNoPublicAccessLinks,
RemediationMarkdown: cloudFormationNoPublicAccessRemediationMarkdown,
},
- Severity: severity.High,
+ Severity: severity.High,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, repo := range s.AWS.ECR.Repositories {
diff --git a/checks/cloud/aws/ecr/no_public_access.rego b/checks/cloud/aws/ecr/no_public_access.rego
new file mode 100644
index 00000000..4dca26b3
--- /dev/null
+++ b/checks/cloud/aws/ecr/no_public_access.rego
@@ -0,0 +1,57 @@
+# METADATA
+# title: ECR repository policy must block public access
+# description: |
+# Allowing public access to the ECR repository risks leaking sensitive of abusable information
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/AmazonECR/latest/public/public-repository-policies.html
+# custom:
+# id: AVD-AWS-0032
+# avd_id: AVD-AWS-0032
+# provider: aws
+# service: ecr
+# severity: HIGH
+# short_code: no-public-access
+# recommended_action: Do not allow public access in the policy
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: ecr
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository_policy#policy
+# good_examples: checks/cloud/aws/ecr/no_public_access.tf.go
+# bad_examples: checks/cloud/aws/ecr/no_public_access.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/ecr/no_public_access.cf.go
+# bad_examples: checks/cloud/aws/ecr/no_public_access.cf.go
+package builtin.aws.ecr.aws0032
+
+import rego.v1
+
+deny contains res if {
+ some repo in input.aws.ecr.repositories
+ some policy in repo.policies
+ value := json.unmarshal(policy.document.value)
+ some statement in value.Statement
+ has_ecr_action(statement)
+ has_public_access(statement)
+ res := result.new("Policy provides public access to the ECR repository.", policy.document)
+}
+
+has_ecr_action(statement) if {
+ some action in statement.Action
+ startswith(action, "ecr:")
+}
+
+has_public_access(statement) if {
+ statement.Principal.All
+}
+
+has_public_access(statement) if {
+ "*" in statement.Principal.AWS
+}
diff --git a/checks/cloud/aws/ecr/no_public_access_test.go b/checks/cloud/aws/ecr/no_public_access_test.go
deleted file mode 100644
index f114083e..00000000
--- a/checks/cloud/aws/ecr/no_public_access_test.go
+++ /dev/null
@@ -1,138 +0,0 @@
-package ecr
-
-import (
- "testing"
-
- "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr"
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/iam"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/liamg/iamgo"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckNoPublicAccess(t *testing.T) {
- tests := []struct {
- name string
- input ecr.ECR
- expected bool
- }{
- {
- name: "ECR repository policy with wildcard principal",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: types.NewTestMetadata(),
- Policies: func() []iam.Policy {
-
- sb := iamgo.NewStatementBuilder()
- sb.WithSid("new policy")
- sb.WithEffect("Allow")
- sb.WithAllPrincipals(true)
- sb.WithActions([]string{
- "ecr:GetDownloadUrlForLayer",
- "ecr:BatchGetImage",
- "ecr:BatchCheckLayerAvailability",
- "ecr:PutImage",
- "ecr:InitiateLayerUpload",
- "ecr:UploadLayerPart",
- "ecr:CompleteLayerUpload",
- "ecr:DescribeRepositories",
- "ecr:GetRepositoryPolicy",
- "ecr:ListImages",
- "ecr:DeleteRepository",
- "ecr:BatchDeleteImage",
- "ecr:SetRepositoryPolicy",
- "ecr:DeleteRepositoryPolicy",
- })
-
- builder := iamgo.NewPolicyBuilder()
- builder.WithVersion("2021-10-07")
- builder.WithStatement(sb.Build())
-
- return []iam.Policy{
- {
- Document: iam.Document{
- Metadata: types.NewTestMetadata(),
- Parsed: builder.Build(),
- },
- },
- }
- }(),
- },
- },
- },
- expected: true,
- },
- {
- name: "ECR repository policy with specific principal",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: types.NewTestMetadata(),
- Policies: func() []iam.Policy {
-
- sb := iamgo.NewStatementBuilder()
- sb.WithSid("new policy")
- sb.WithEffect("Allow")
- sb.WithAWSPrincipals([]string{"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"})
- sb.WithActions([]string{
- "ecr:GetDownloadUrlForLayer",
- "ecr:BatchGetImage",
- "ecr:BatchCheckLayerAvailability",
- "ecr:PutImage",
- "ecr:InitiateLayerUpload",
- "ecr:UploadLayerPart",
- "ecr:CompleteLayerUpload",
- "ecr:DescribeRepositories",
- "ecr:GetRepositoryPolicy",
- "ecr:ListImages",
- "ecr:DeleteRepository",
- "ecr:BatchDeleteImage",
- "ecr:SetRepositoryPolicy",
- "ecr:DeleteRepositoryPolicy",
- })
-
- builder := iamgo.NewPolicyBuilder()
- builder.WithVersion("2021-10-07")
- builder.WithStatement(sb.Build())
-
- return []iam.Policy{
- {
- Document: iam.Document{
- Metadata: types.NewTestMetadata(),
- Parsed: builder.Build(),
- },
- },
- }
- }(),
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.ECR = test.input
- results := CheckNoPublicAccess.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckNoPublicAccess.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/ecr/no_public_access_test.rego b/checks/cloud/aws/ecr/no_public_access_test.rego
new file mode 100644
index 00000000..475943e6
--- /dev/null
+++ b/checks/cloud/aws/ecr/no_public_access_test.rego
@@ -0,0 +1,35 @@
+package builtin.aws.ecr.aws0032_test
+
+import rego.v1
+
+import data.builtin.aws.ecr.aws0032 as check
+import data.lib.test
+
+test_allow_without_public_access if {
+ inp := {"aws": {"ecr": {"repositories": [{"policies": [{"document": {"value": json.marshal({"Statement": [{
+ "Action": ["ecr:*"],
+ "Principal": {"AWS": "arn:aws:iam::123456789012:root"},
+ "Effect": "Allow",
+ }]})}}]}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_with_public_access_all if {
+ inp := {"aws": {"ecr": {"repositories": [{"policies": [{"document": {"value": json.marshal({"Statement": [{
+ "Action": ["ecr:*"],
+ "Principal": {"All": true},
+ }]})}}]}]}}}
+
+ test.assert_equal_message("Policy provides public access to the ECR repository", check.deny) with input as inp
+}
+
+test_deny_with_public_acces_any if {
+ inp := {"aws": {"ecr": {"repositories": [{"policies": [{"document": {"value": json.marshal({"Statement": [{
+ "Action": ["ecr:*"],
+ "Principal": {"AWS": ["*"]},
+ "Effect": "Allow",
+ }]})}}]}]}}}
+
+ test.assert_equal_message("Policy provides public access to the ECR repository", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/ecr/repository_customer_key.go b/checks/cloud/aws/ecr/repository_customer_key.go
index 59d33c95..56bf29de 100755
--- a/checks/cloud/aws/ecr/repository_customer_key.go
+++ b/checks/cloud/aws/ecr/repository_customer_key.go
@@ -34,7 +34,8 @@ var CheckRepositoryCustomerKey = rules.Register(
Links: cloudFormationRepositoryCustomerKeyLinks,
RemediationMarkdown: cloudFormationRepositoryCustomerKeyRemediationMarkdown,
},
- Severity: severity.Low,
+ Severity: severity.Low,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, repo := range s.AWS.ECR.Repositories {
diff --git a/checks/cloud/aws/ecr/repository_customer_key.rego b/checks/cloud/aws/ecr/repository_customer_key.rego
new file mode 100644
index 00000000..ece32597
--- /dev/null
+++ b/checks/cloud/aws/ecr/repository_customer_key.rego
@@ -0,0 +1,49 @@
+# METADATA
+# title: ECR Repository should use customer managed keys to allow more control
+# description: |
+# Images in the ECR repository are encrypted by default using AWS managed encryption keys. To increase control of the encryption and control the management of factors like key rotation, use a Customer Managed Key.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/AmazonECR/latest/userguide/encryption-at-rest.html
+# custom:
+# id: AVD-AWS-0033
+# avd_id: AVD-AWS-0033
+# provider: aws
+# service: ecr
+# severity: LOW
+# short_code: repository-customer-key
+# recommended_action: Use customer managed keys
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: ecr
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository#encryption_configuration
+# good_examples: checks/cloud/aws/ecr/repository_customer_key.tf.go
+# bad_examples: checks/cloud/aws/ecr/repository_customer_key.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/ecr/repository_customer_key.cf.go
+# bad_examples: checks/cloud/aws/ecr/repository_customer_key.cf.go
+package builtin.aws.ecr.aws0033
+
+import rego.v1
+
+deny contains res if {
+ some repo in input.aws.ecr.repositories
+ not is_encyption_type_kms(repo.encryption.type)
+ res := result.new("Repository is not encrypted using KMS.", repo.encryption.type)
+}
+
+deny contains res if {
+ some repo in input.aws.ecr.repositories
+ is_encyption_type_kms(repo.encryption.type)
+ repo.encryption.kmskeyid.value == ""
+ res := result.new("Repository encryption does not use a customer managed KMS key.", repo.encryption.kmskeyid)
+}
+
+is_encyption_type_kms(typ) if typ.value == "KMS"
diff --git a/checks/cloud/aws/ecr/repository_customer_key_test.go b/checks/cloud/aws/ecr/repository_customer_key_test.go
deleted file mode 100644
index 62168c80..00000000
--- a/checks/cloud/aws/ecr/repository_customer_key_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package ecr
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/ecr"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckRepositoryCustomerKey(t *testing.T) {
- tests := []struct {
- name string
- input ecr.ECR
- expected bool
- }{
- {
- name: "ECR repository not using KMS encryption",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: ecr.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Type: trivyTypes.String(ecr.EncryptionTypeAES256, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "ECR repository using KMS encryption but missing key",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: ecr.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Type: trivyTypes.String(ecr.EncryptionTypeKMS, trivyTypes.NewTestMetadata()),
- KMSKeyID: trivyTypes.String("", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "ECR repository encrypted with KMS key",
- input: ecr.ECR{
- Repositories: []ecr.Repository{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: ecr.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Type: trivyTypes.String(ecr.EncryptionTypeKMS, trivyTypes.NewTestMetadata()),
- KMSKeyID: trivyTypes.String("some-kms-key", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.ECR = test.input
- results := CheckRepositoryCustomerKey.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckRepositoryCustomerKey.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/ecr/repository_customer_key_test.rego b/checks/cloud/aws/ecr/repository_customer_key_test.rego
new file mode 100644
index 00000000..8c91a517
--- /dev/null
+++ b/checks/cloud/aws/ecr/repository_customer_key_test.rego
@@ -0,0 +1,30 @@
+package builtin.aws.ecr.aws0033_test
+
+import rego.v1
+
+import data.builtin.aws.ecr.aws0033 as check
+import data.lib.test
+
+test_allow_repo_with_kms if {
+ inp := {"aws": {"ecr": {"repositories": [{"encryption": {
+ "type": {"value": "KMS"},
+ "kmskeyid": {"value": "key"},
+ }}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_repo_without_kms_encryption if {
+ inp := {"aws": {"ecr": {"repositories": [{"encryption": {"type": {"value": "AES256"}}}]}}}
+
+ test.assert_equal_message("Repository is not encrypted using KMS.", check.deny) with input as inp
+}
+
+test_deny_repo_with_kms_encryption_without_key if {
+ inp := {"aws": {"ecr": {"repositories": [{"encryption": {
+ "type": {"value": "KMS"},
+ "kmskeyid": {"value": ""},
+ }}]}}}
+
+ test.assert_equal_message("Repository encryption does not use a customer managed KMS key.", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/efs/enable_at_rest_encryption.go b/checks/cloud/aws/efs/enable_at_rest_encryption.go
index d654348a..2a07bdd7 100755
--- a/checks/cloud/aws/efs/enable_at_rest_encryption.go
+++ b/checks/cloud/aws/efs/enable_at_rest_encryption.go
@@ -33,7 +33,8 @@ var CheckEnableAtRestEncryption = rules.Register(
Links: cloudFormationEnableAtRestEncryptionLinks,
RemediationMarkdown: cloudFormationEnableAtRestEncryptionRemediationMarkdown,
},
- Severity: severity.High,
+ Severity: severity.High,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, fs := range s.AWS.EFS.FileSystems {
diff --git a/checks/cloud/aws/efs/enable_at_rest_encryption.rego b/checks/cloud/aws/efs/enable_at_rest_encryption.rego
new file mode 100644
index 00000000..fd5b0365
--- /dev/null
+++ b/checks/cloud/aws/efs/enable_at_rest_encryption.rego
@@ -0,0 +1,40 @@
+# METADATA
+# title: EFS Encryption has not been enabled
+# description: |
+# If your organization is subject to corporate or regulatory policies that require encryption of data and metadata at rest, we recommend creating a file system that is encrypted at rest, and mounting your file system using encryption of data in transit.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/efs/latest/ug/encryption.html
+# custom:
+# id: AVD-AWS-0037
+# avd_id: AVD-AWS-0037
+# provider: aws
+# service: efs
+# severity: HIGH
+# short_code: enable-at-rest-encryption
+# recommended_action: Enable encryption for EFS
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: efs
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/efs_file_system
+# good_examples: checks/cloud/aws/efs/enable_at_rest_encryption.tf.go
+# bad_examples: checks/cloud/aws/efs/enable_at_rest_encryption.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/efs/enable_at_rest_encryption.cf.go
+# bad_examples: checks/cloud/aws/efs/enable_at_rest_encryption.cf.go
+package builtin.aws.efs.aws0037
+
+import rego.v1
+
+deny contains res if {
+ some fs in input.aws.efs.filesystems
+ fs.encrypted.value == false
+ res := result.new("File system is not encrypted.", fs.encrypted)
+}
diff --git a/checks/cloud/aws/efs/enable_at_rest_encryption_test.go b/checks/cloud/aws/efs/enable_at_rest_encryption_test.go
deleted file mode 100644
index e2f74dae..00000000
--- a/checks/cloud/aws/efs/enable_at_rest_encryption_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package efs
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/efs"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckEnableAtRestEncryption(t *testing.T) {
- tests := []struct {
- name string
- input efs.EFS
- expected bool
- }{
- {
- name: "positive result",
- input: efs.EFS{
- FileSystems: []efs.FileSystem{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encrypted: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- }},
- },
- expected: true,
- },
- {
- name: "negative result",
- input: efs.EFS{
- FileSystems: []efs.FileSystem{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encrypted: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- }},
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.EFS = test.input
- results := CheckEnableAtRestEncryption.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckEnableAtRestEncryption.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/efs/enable_at_rest_encryption_test.rego b/checks/cloud/aws/efs/enable_at_rest_encryption_test.rego
new file mode 100644
index 00000000..95e6627a
--- /dev/null
+++ b/checks/cloud/aws/efs/enable_at_rest_encryption_test.rego
@@ -0,0 +1,18 @@
+package builtin.aws.efs.aws0037_test
+
+import rego.v1
+
+import data.builtin.aws.efs.aws0037 as check
+import data.lib.test
+
+test_allow_fs_encrypted if {
+ inp := {"aws": {"efs": {"filesystems": [{"encrypted": {"value": true}}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_fs_unencrypted if {
+ inp := {"aws": {"efs": {"filesystems": [{"encrypted": {"value": false}}]}}}
+
+ test.assert_equal_message("File system is not encrypted.", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/eks/enable_control_plane_logging.go b/checks/cloud/aws/eks/enable_control_plane_logging.go
index 407f92bf..9589a8c1 100755
--- a/checks/cloud/aws/eks/enable_control_plane_logging.go
+++ b/checks/cloud/aws/eks/enable_control_plane_logging.go
@@ -27,7 +27,8 @@ var CheckEnableControlPlaneLogging = rules.Register(
Links: terraformEnableControlPlaneLoggingLinks,
RemediationMarkdown: terraformEnableControlPlaneLoggingRemediationMarkdown,
},
- Severity: severity.Medium,
+ Severity: severity.Medium,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, cluster := range s.AWS.EKS.Clusters {
diff --git a/checks/cloud/aws/eks/enable_control_plane_logging.rego b/checks/cloud/aws/eks/enable_control_plane_logging.rego
new file mode 100644
index 00000000..926bac94
--- /dev/null
+++ b/checks/cloud/aws/eks/enable_control_plane_logging.rego
@@ -0,0 +1,61 @@
+# METADATA
+# title: EKS Clusters should have cluster control plane logging turned on
+# description: |
+# By default cluster control plane logging is not turned on. Logging is available for audit, api, authenticator, controllerManager and scheduler. All logging should be turned on for cluster control plane.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html
+# custom:
+# id: AVD-AWS-0038
+# avd_id: AVD-AWS-0038
+# provider: aws
+# service: eks
+# severity: MEDIUM
+# short_code: enable-control-plane-logging
+# recommended_action: Enable logging for the EKS control plane
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: eks
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#enabled_cluster_log_types
+# good_examples: checks/cloud/aws/eks/enable_control_plane_logging.tf.go
+# bad_examples: checks/cloud/aws/eks/enable_control_plane_logging.tf.go
+package builtin.aws.eks.aws0038
+
+import rego.v1
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.logging.api.value == false
+ res := result.new("Control plane API logging is not enabled.", cluster.logging.api)
+}
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.logging.audit.value == false
+ res := result.new("Control plane audit logging is not enabled.", cluster.logging.audit)
+}
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.logging.authenticator.value == false
+ res := result.new("Control plane authenticator logging is not enabled.", cluster.logging.authenticator)
+}
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.logging.controllermanager.value == false
+ res := result.new("Control plane controller manager logging is not enabled.", cluster.logging.controllermanager)
+}
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.logging.scheduler.value == false
+ res := result.new("Control plane scheduler logging is not enabled.", cluster.logging.scheduler)
+}
diff --git a/checks/cloud/aws/eks/enable_control_plane_logging_test.go b/checks/cloud/aws/eks/enable_control_plane_logging_test.go
deleted file mode 100644
index 324735fc..00000000
--- a/checks/cloud/aws/eks/enable_control_plane_logging_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package eks
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/eks"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckEnableControlPlaneLogging(t *testing.T) {
- tests := []struct {
- name string
- input eks.EKS
- expected bool
- }{
- {
- name: "EKS cluster with all cluster logging disabled",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Logging: eks.Logging{
- API: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- Audit: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- Authenticator: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- ControllerManager: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- Scheduler: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS cluster with only some cluster logging enabled",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Logging: eks.Logging{
- API: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- Audit: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- Authenticator: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- ControllerManager: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- Scheduler: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS cluster with all cluster logging enabled",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Logging: eks.Logging{
- API: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- Audit: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- Authenticator: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- ControllerManager: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- Scheduler: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.EKS = test.input
- results := CheckEnableControlPlaneLogging.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckEnableControlPlaneLogging.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/eks/enable_control_plane_logging_test.rego b/checks/cloud/aws/eks/enable_control_plane_logging_test.rego
new file mode 100644
index 00000000..fb3a7996
--- /dev/null
+++ b/checks/cloud/aws/eks/enable_control_plane_logging_test.rego
@@ -0,0 +1,39 @@
+package builtin.aws.eks.aws0038_test
+
+import rego.v1
+
+import data.builtin.aws.eks.aws0038 as check
+import data.lib.test
+
+test_allow_all_logging_enabled if {
+ inp := {"aws": {"eks": {"clusters": [{"logging": {
+ "audit": {"value": true},
+ "authenticator": {"value": true},
+ "controllermanager": {"value": true},
+ "scheduler": {"value": true},
+ }}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
+
+test_deny_all_logging_disabled if {
+ inp := {"aws": {"eks": {"clusters": [{"logging": {
+ "audit": {"value": false},
+ "authenticator": {"value": false},
+ "controllermanager": {"value": false},
+ "scheduler": {"value": false},
+ }}]}}}
+
+ test.assert_count(check.deny, 4) with input as inp
+}
+
+test_deny_one_logging_disabled if {
+ inp := {"aws": {"eks": {"clusters": [{"logging": {
+ "audit": {"value": false},
+ "authenticator": {"value": true},
+ "controllermanager": {"value": true},
+ "scheduler": {"value": true},
+ }}]}}}
+
+ test.assert_equal_message("Control plane audit logging is not enabled.", check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/eks/encrypt_secrets.go b/checks/cloud/aws/eks/encrypt_secrets.go
index 809090bd..d70739ed 100755
--- a/checks/cloud/aws/eks/encrypt_secrets.go
+++ b/checks/cloud/aws/eks/encrypt_secrets.go
@@ -33,7 +33,8 @@ var CheckEncryptSecrets = rules.Register(
Links: cloudFormationEncryptSecretsLinks,
RemediationMarkdown: cloudFormationEncryptSecretsRemediationMarkdown,
},
- Severity: severity.High,
+ Severity: severity.High,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, cluster := range s.AWS.EKS.Clusters {
diff --git a/checks/cloud/aws/eks/encrypt_secrets.rego b/checks/cloud/aws/eks/encrypt_secrets.rego
new file mode 100644
index 00000000..11a2a56f
--- /dev/null
+++ b/checks/cloud/aws/eks/encrypt_secrets.rego
@@ -0,0 +1,47 @@
+# METADATA
+# title: EKS should have the encryption of secrets enabled
+# description: |
+# EKS cluster resources should have the encryption_config block set with protection of the secrets resource.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-eks-adds-envelope-encryption-for-secrets-with-aws-kms/
+# custom:
+# id: AVD-AWS-0039
+# avd_id: AVD-AWS-0039
+# provider: aws
+# service: eks
+# severity: HIGH
+# short_code: encrypt-secrets
+# recommended_action: Enable encryption of EKS secrets
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: eks
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#encryption_config
+# good_examples: checks/cloud/aws/eks/encrypt_secrets.tf.go
+# bad_examples: checks/cloud/aws/eks/encrypt_secrets.tf.go
+# cloudformation:
+# good_examples: checks/cloud/aws/eks/encrypt_secrets.cf.go
+# bad_examples: checks/cloud/aws/eks/encrypt_secrets.cf.go
+package builtin.aws.eks.aws0039
+
+import rego.v1
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.encryption.secrets.value == false
+ res := result.new("Cluster does not have secret encryption enabled.", cluster.encryption.secrets)
+}
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.encryption.secrets.value == true
+ cluster.encryption.kmskeyid.value == ""
+ res := result.new("Cluster encryption requires a KMS key ID, which is missing", cluster.encryption.kmskeyid)
+}
diff --git a/checks/cloud/aws/eks/encrypt_secrets_test.go b/checks/cloud/aws/eks/encrypt_secrets_test.go
deleted file mode 100644
index 38534f85..00000000
--- a/checks/cloud/aws/eks/encrypt_secrets_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package eks
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/eks"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckEncryptSecrets(t *testing.T) {
- tests := []struct {
- name string
- input eks.EKS
- expected bool
- }{
- {
- name: "EKS Cluster with no secrets in the resources attribute",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: eks.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Secrets: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- KMSKeyID: trivyTypes.String("", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS Cluster with secrets in the resources attribute but no KMS key",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: eks.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Secrets: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- KMSKeyID: trivyTypes.String("", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS Cluster with secrets in the resources attribute and a KMS key",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- Metadata: trivyTypes.NewTestMetadata(),
- Encryption: eks.Encryption{
- Metadata: trivyTypes.NewTestMetadata(),
- Secrets: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- KMSKeyID: trivyTypes.String("some-arn", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.EKS = test.input
- results := CheckEncryptSecrets.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckEncryptSecrets.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/eks/encrypt_secrets_test.rego b/checks/cloud/aws/eks/encrypt_secrets_test.rego
new file mode 100644
index 00000000..53b8bc74
--- /dev/null
+++ b/checks/cloud/aws/eks/encrypt_secrets_test.rego
@@ -0,0 +1,33 @@
+package builtin.aws.eks.aws0039_test
+
+import rego.v1
+
+import data.builtin.aws.eks.aws0039 as check
+import data.lib.test
+
+test_deny_without_secrets_and_kms if {
+ inp := {"aws": {"eks": {"clusters": [{"encryption": {
+ "kmskeyid": {"value": ""},
+ "secrets": {"value": false},
+ }}]}}}
+
+ test.assert_equal_message("Cluster does not have secret encryption enabled.", check.deny) with input as inp
+}
+
+test_deny_with_secrets_but_no_kms if {
+ inp := {"aws": {"eks": {"clusters": [{"encryption": {
+ "kmskeyid": {"value": ""},
+ "secrets": {"value": true},
+ }}]}}}
+
+ test.assert_equal_message("Cluster encryption requires a KMS key ID, which is missing", check.deny) with input as inp
+}
+
+test_allow_with_secrets_and_kms if {
+ inp := {"aws": {"eks": {"clusters": [{"encryption": {
+ "kmskeyid": {"value": "test"},
+ "secrets": {"value": true},
+ }}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/eks/no_public_cluster_access.go b/checks/cloud/aws/eks/no_public_cluster_access.go
index 6c406503..8c79c344 100755
--- a/checks/cloud/aws/eks/no_public_cluster_access.go
+++ b/checks/cloud/aws/eks/no_public_cluster_access.go
@@ -27,7 +27,8 @@ var CheckNoPublicClusterAccess = rules.Register(
Links: terraformNoPublicClusterAccessLinks,
RemediationMarkdown: terraformNoPublicClusterAccessRemediationMarkdown,
},
- Severity: severity.Critical,
+ Severity: severity.Critical,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, cluster := range s.AWS.EKS.Clusters {
diff --git a/checks/cloud/aws/eks/no_public_cluster_access.rego b/checks/cloud/aws/eks/no_public_cluster_access.rego
new file mode 100644
index 00000000..3d8c284c
--- /dev/null
+++ b/checks/cloud/aws/eks/no_public_cluster_access.rego
@@ -0,0 +1,37 @@
+# METADATA
+# title: EKS Clusters should have the public access disabled
+# description: |
+# EKS clusters are available publicly by default, this should be explicitly disabled in the vpc_config of the EKS cluster resource.
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html
+# custom:
+# id: AVD-AWS-0040
+# avd_id: AVD-AWS-0040
+# provider: aws
+# service: eks
+# severity: CRITICAL
+# short_code: no-public-cluster-access
+# recommended_action: Don't enable public access to EKS Clusters
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: eks
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#endpoint_public_access
+# good_examples: checks/cloud/aws/eks/no_public_cluster_access.tf.go
+# bad_examples: checks/cloud/aws/eks/no_public_cluster_access.tf.go
+package builtin.aws.eks.aws0040
+
+import rego.v1
+
+deny contains res if {
+ some cluster in input.aws.eks.clusters
+ cluster.publicaccessenabled.value == true
+ res := result.new("Public cluster access is enabled.", cluster.publicaccessenabled)
+}
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_test.go b/checks/cloud/aws/eks/no_public_cluster_access_test.go
deleted file mode 100644
index 5d5c8f9d..00000000
--- a/checks/cloud/aws/eks/no_public_cluster_access_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package eks
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/eks"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckNoPublicClusterAccess(t *testing.T) {
- tests := []struct {
- name string
- input eks.EKS
- expected bool
- }{
- {
- name: "EKS Cluster with public access enabled",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- PublicAccessEnabled: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS Cluster with public access disabled",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- PublicAccessEnabled: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.EKS = test.input
- results := CheckNoPublicClusterAccess.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckNoPublicClusterAccess.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_test.rego b/checks/cloud/aws/eks/no_public_cluster_access_test.rego
new file mode 100644
index 00000000..5b910e62
--- /dev/null
+++ b/checks/cloud/aws/eks/no_public_cluster_access_test.rego
@@ -0,0 +1,18 @@
+package builtin.aws.eks.aws0040_test
+
+import rego.v1
+
+import data.builtin.aws.eks.aws0040 as check
+import data.lib.test
+
+test_deny_public_access_enabled if {
+ inp := {"aws": {"eks": {"clusters": [{"publicaccessenabled": {"value": true}}]}}}
+
+ test.assert_equal_message("public access should be enabled", check.deny) with input as inp
+}
+
+test_allow_public_access_disabled if {
+ inp := {"aws": {"eks": {"clusters": [{"publicaccessenabled": {"value": false}}]}}}
+
+ test.assert_empty(check.deny) with input as inp
+}
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.go b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.go
index 8f478094..8e1f6a20 100755
--- a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.go
+++ b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.go
@@ -35,7 +35,8 @@ var CheckNoPublicClusterAccessToCidr = rules.Register(
Links: terraformNoPublicClusterAccessToCidrLinks,
RemediationMarkdown: terraformNoPublicClusterAccessToCidrRemediationMarkdown,
},
- Severity: severity.Critical,
+ Severity: severity.Critical,
+ Deprecated: true,
},
func(s *state.State) (results scan.Results) {
for _, cluster := range s.AWS.EKS.Clusters {
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.rego b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.rego
new file mode 100644
index 00000000..2dd138b3
--- /dev/null
+++ b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr.rego
@@ -0,0 +1,38 @@
+# METADATA
+# title: EKS cluster should not have open CIDR range for public access
+# description: |
+# EKS Clusters have public access cidrs set to 0.0.0.0/0 by default which is wide open to the internet. This should be explicitly set to a more specific private CIDR range
+# scope: package
+# schemas:
+# - input: schema["cloud"]
+# related_resources:
+# - https://docs.aws.amazon.com/eks/latest/userguide/create-public-private-vpc.html
+# custom:
+# id: AVD-AWS-0041
+# avd_id: AVD-AWS-0041
+# provider: aws
+# service: eks
+# severity: CRITICAL
+# short_code: no-public-cluster-access-to-cidr
+# recommended_action: Don't enable public access to EKS Clusters
+# input:
+# selector:
+# - type: cloud
+# subtypes:
+# - service: eks
+# provider: aws
+# terraform:
+# links:
+# - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#vpc_config
+# good_examples: checks/cloud/aws/eks/no_public_cluster_access_to_cidr.tf.go
+# bad_examples: checks/cloud/aws/eks/no_public_cluster_access_to_cidr.tf.go
+package builtin.aws.eks.aws0041
+
+import rego.v1
+
+# TODO: add support for "github.com/aquasecurity/trivy-checks/internal/cidr"
+# deny contains res if {
+# some cluster in input.aws.eks.clusters
+# cluster.publicaccesenabled.value == true
+# some cidr in cluster.publicaccescidrs
+# }
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.go b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.go
deleted file mode 100644
index 390a0952..00000000
--- a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package eks
-
-import (
- "testing"
-
- trivyTypes "github.com/aquasecurity/trivy/pkg/iac/types"
-
- "github.com/aquasecurity/trivy/pkg/iac/state"
-
- "github.com/aquasecurity/trivy/pkg/iac/providers/aws/eks"
- "github.com/aquasecurity/trivy/pkg/iac/scan"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckNoPublicClusterAccessToCidr(t *testing.T) {
- tests := []struct {
- name string
- input eks.EKS
- expected bool
- }{
- {
- name: "EKS Cluster with public access CIDRs actively set to open",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- PublicAccessEnabled: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- PublicAccessCIDRs: []trivyTypes.StringValue{
- trivyTypes.String("0.0.0.0/0", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: true,
- },
- {
- name: "EKS Cluster with public access enabled but private CIDRs",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- PublicAccessEnabled: trivyTypes.Bool(true, trivyTypes.NewTestMetadata()),
- PublicAccessCIDRs: []trivyTypes.StringValue{
- trivyTypes.String("10.2.0.0/8", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- {
- name: "EKS Cluster with public access disabled and private CIDRs",
- input: eks.EKS{
- Clusters: []eks.Cluster{
- {
- PublicAccessEnabled: trivyTypes.Bool(false, trivyTypes.NewTestMetadata()),
- PublicAccessCIDRs: []trivyTypes.StringValue{
- trivyTypes.String("10.2.0.0/8", trivyTypes.NewTestMetadata()),
- },
- },
- },
- },
- expected: false,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- var testState state.State
- testState.AWS.EKS = test.input
- results := CheckNoPublicClusterAccessToCidr.Evaluate(&testState)
- var found bool
- for _, result := range results {
- if result.Status() == scan.StatusFailed && result.Rule().LongID() == CheckNoPublicClusterAccessToCidr.LongID() {
- found = true
- }
- }
- if test.expected {
- assert.True(t, found, "Rule should have been found")
- } else {
- assert.False(t, found, "Rule should not have been found")
- }
- })
- }
-}
diff --git a/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.rego b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.rego
new file mode 100644
index 00000000..8d1d5388
--- /dev/null
+++ b/checks/cloud/aws/eks/no_public_cluster_access_to_cidr_test.rego
@@ -0,0 +1,6 @@
+package builtin.aws.eks.aws0041_test
+
+import rego.v1
+
+import data.builtin.aws.eks.aws0041 as check
+import data.lib.test