Repository: tfsec/tfsec
Pull request #614 (2021-02-21 09:55:44)

Add some new checks and go back to update some
Update some checks to use attribute blocks in the result



Patch:
diff --git a/internal/app/tfsec/checks/aws038.go b/internal/app/tfsec/checks/aws038.go
index fa4b486cd..c5849d993 100644
--- a/internal/app/tfsec/checks/aws038.go
+++ b/internal/app/tfsec/checks/aws038.go
@@ -63,9 +63,10 @@ func init() {
 				value, _ := attr.Value().AsBigFloat().Float64()
 				if value > 90 {
 					return []scanner.Result{
-						check.NewResult(
-							fmt.Sprintf("Resource '%s' has a max age set which is greater than 90 days.", block.FullName()),
-							block.Range(),
+						check.NewResultWithValueAnnotation(
+							fmt.Sprintf("Resource '%s' has high password age.", block.FullName()),
+							attr.Range(),
+							attr,
 							scanner.SeverityWarning,
 						),
 					}
diff --git a/internal/app/tfsec/checks/aws050.go b/internal/app/tfsec/checks/aws050.go
index f8fc7c455..93ea7ed7d 100644
--- a/internal/app/tfsec/checks/aws050.go
+++ b/internal/app/tfsec/checks/aws050.go
@@ -70,9 +70,10 @@ func init() {
 				if isOpenCidr(cidrBlockAttr, check.Provider) {
 					if protoAttr.Value().AsString() == "all" || protoAttr.Value().AsString() == "-1" {
 						return []scanner.Result{
-							check.NewResult(
+							check.NewResultWithValueAnnotation(
 								fmt.Sprintf("Resource '%s' defines a fully open ingress Network ACL rule with ALL ports open.", block.FullName()),
 								cidrBlockAttr.Range(),
+								cidrBlockAttr,
 								scanner.SeverityError,
 							),
 						}
diff --git a/internal/app/tfsec/checks/aws052.go b/internal/app/tfsec/checks/aws052.go
index 7037dab4b..b2403d0b6 100644
--- a/internal/app/tfsec/checks/aws052.go
+++ b/internal/app/tfsec/checks/aws052.go
@@ -43,17 +43,27 @@ func init() {
 		RequiredLabels: []string{"aws_db_instance"},
 		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
 
-			storageEncryptedattr := block.GetAttribute("storage_encrypted")
-
-			if storageEncryptedattr == nil || storageEncryptedattr.IsFalse() {
+			if block.MissingChild("storage_encrypted") {
 				return []scanner.Result{
 					check.NewResult(
-						fmt.Sprintf("Resource '%s' defines a disabled RDS Instance Encryption.", block.FullName()),
+						fmt.Sprintf("Resource '%s' has no storage encryption defined.", block.FullName()),
 						block.Range(),
 						scanner.SeverityError,
 					),
 				}
 			}
+
+			storageEncrypted := block.GetAttribute("storage_encrypted")
+			if storageEncrypted.IsFalse() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has storage encrypted set to false", block.FullName()),
+						storageEncrypted.Range(),
+						storageEncrypted,
+						scanner.SeverityError,
+						),
+				}
+			}
 			return nil
 		},
 	})
diff --git a/internal/app/tfsec/checks/aws053.go b/internal/app/tfsec/checks/aws053.go
index e73dcf98e..095306d3f 100644
--- a/internal/app/tfsec/checks/aws053.go
+++ b/internal/app/tfsec/checks/aws053.go
@@ -49,7 +49,7 @@ func init() {
 		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
 
 			if block.HasChild("performance_insights_enabled") && block.GetAttribute("performance_insights_enabled").IsTrue() {
-				if block.MissingChild("performance_insights_kms_key_id") || block.GetAttribute("performance_insights_kms_key_id").IsEmpty() {
+				if block.MissingChild("performance_insights_kms_key_id")  {
 					return []scanner.Result{
 						check.NewResult(
 							fmt.Sprintf("Resource '%s' defines Performance Insights without encryption key specified.", block.FullName()),
@@ -57,6 +57,15 @@ func init() {
 							scanner.SeverityError,
 						),
 					}
+				} else if  block.GetAttribute("performance_insights_kms_key_id").IsEmpty() {
+					return []scanner.Result{
+						check.NewResultWithValueAnnotation(
+							fmt.Sprintf("Resource '%s' defines Performance Insights without encryption key specified.", block.FullName()),
+							block.GetAttribute("performance_insights_kms_key_id").Range(),
+							block.GetAttribute("performance_insights_kms_key_id"),
+							scanner.SeverityError,
+						),
+					}
 				}
 			}
 
diff --git a/internal/app/tfsec/checks/aws054.go b/internal/app/tfsec/checks/aws054.go
index daefebc96..7b4876bad 100644
--- a/internal/app/tfsec/checks/aws054.go
+++ b/internal/app/tfsec/checks/aws054.go
@@ -59,9 +59,10 @@ func init() {
 				enforceHttps := endpointOptions.GetAttribute("enforce_https")
 				if enforceHttps != nil && enforceHttps.IsFalse() {
 					return []scanner.Result{
-						check.NewResult(
+						check.NewResultWithValueAnnotation(
 							fmt.Sprintf("Resource '%s' explicitly turns off enforcing https on the ElasticSearch domain.", block.FullName()),
-							block.Range(),
+							enforceHttps.Range(),
+							enforceHttps,
 							scanner.SeverityError,
 						),
 					}
diff --git a/internal/app/tfsec/checks/aws055.go b/internal/app/tfsec/checks/aws055.go
index 5dbf73460..137b52b0b 100644
--- a/internal/app/tfsec/checks/aws055.go
+++ b/internal/app/tfsec/checks/aws055.go
@@ -85,9 +85,10 @@ func init() {
 
 			if enabled == nil || enabled.IsFalse() {
 				return []scanner.Result{
-					check.NewResult(
+					check.NewResultWithValueAnnotation(
 						fmt.Sprintf("Resource '%s' explicitly disables node to node encryption on the domain.", block.FullName()),
-						block.Range(),
+						enabled.Range(),
+						enabled,
 						scanner.SeverityError,
 					),
 				}
diff --git a/internal/app/tfsec/checks/aws057.go b/internal/app/tfsec/checks/aws057.go
index 46b649ab0..c9ee51c2c 100644
--- a/internal/app/tfsec/checks/aws057.go
+++ b/internal/app/tfsec/checks/aws057.go
@@ -92,9 +92,10 @@ func init() {
 
 			if enabled != nil && enabled.IsFalse() {
 				return []scanner.Result{
-					check.NewResult(
+					check.NewResultWithValueAnnotation(
 						fmt.Sprintf("Resource '%s' explicitly disables logging on the domain.", block.FullName()),
-						block.Range(),
+						enabled.Range(),
+						enabled,
 						scanner.SeverityError,
 					),
 				}
diff --git a/internal/app/tfsec/checks/aws058.go b/internal/app/tfsec/checks/aws058.go
index 81cab24a3..898d38756 100644
--- a/internal/app/tfsec/checks/aws058.go
+++ b/internal/app/tfsec/checks/aws058.go
@@ -54,7 +54,7 @@ func init() {
 					if block.MissingChild("source_arn") {
 						return []scanner.Result{
 							check.NewResult(
-								fmt.Sprintf("Resource '%s' .", block.FullName()),
+								fmt.Sprintf("Resource '%s' missing source ARN but has *.amazonaws.com Principal.", block.FullName()),
 								block.Range(),
 								scanner.SeverityError,
 							),
diff --git a/internal/app/tfsec/checks/aws059.go b/internal/app/tfsec/checks/aws059.go
index f6d310527..a81f45b14 100644
--- a/internal/app/tfsec/checks/aws059.go
+++ b/internal/app/tfsec/checks/aws059.go
@@ -96,7 +96,7 @@ func init() {
 			if block.MissingChild("encryption_configuration") {
 				return []scanner.Result{
 					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", blockName),
+						fmt.Sprintf("Resource '%s' missing encryption configuration block.", blockName),
 						block.Range(),
 						scanner.SeverityError,
 					),
diff --git a/internal/app/tfsec/checks/aws060.go b/internal/app/tfsec/checks/aws060.go
index 18a52435c..e2adb769f 100644
--- a/internal/app/tfsec/checks/aws060.go
+++ b/internal/app/tfsec/checks/aws060.go
@@ -77,7 +77,7 @@ func init() {
 			if block.MissingChild("configuration") {
 				return []scanner.Result{
 					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", block.FullName()),
+						fmt.Sprintf("Resource '%s' is missing the configuration block.", block.FullName()),
 						block.Range(),
 						scanner.SeverityError,
 					),
@@ -89,8 +89,8 @@ func init() {
 				configBlock.GetAttribute("enforce_workgroup_configuration").IsFalse() {
 				return []scanner.Result{
 					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", block.FullName()),
-						block.Range(),
+						fmt.Sprintf("Resource '%s' has enforce_workgroup_configuration set to false.", block.FullName()),
+						configBlock.Range(),
 						scanner.SeverityError,
 					),
 				}
diff --git a/internal/app/tfsec/checks/aws061.go b/internal/app/tfsec/checks/aws061.go
index fa69f48b0..676faa7ca 100644
--- a/internal/app/tfsec/checks/aws061.go
+++ b/internal/app/tfsec/checks/aws061.go
@@ -68,7 +68,7 @@ func init() {
 			if block.MissingChild("access_log_settings") {
 				return []scanner.Result{
 					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", block.FullName()),
+						fmt.Sprintf("Resource '%s' is missing access log settings block.", block.FullName()),
 						block.Range(),
 						scanner.SeverityError,
 					),
diff --git a/internal/app/tfsec/checks/aws062.go b/internal/app/tfsec/checks/aws062.go
index 567e7b434..0955768bf 100644
--- a/internal/app/tfsec/checks/aws062.go
+++ b/internal/app/tfsec/checks/aws062.go
@@ -68,9 +68,10 @@ func init() {
 			if userData.Contains("AWS_ACCESS_KEY_ID", parser.IgnoreCase) &&
 				userData.RegexMatches("(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}") {
 				return []scanner.Result{
-					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", block.FullName()),
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has userdata with access key id defined.", block.FullName()),
 						userData.Range(),
+						userData,
 						scanner.SeverityError,
 					),
 				}
@@ -79,9 +80,10 @@ func init() {
 			if userData.Contains("AWS_SECRET_ACCESS_KEY", parser.IgnoreCase) &&
 				userData.RegexMatches("(?i)aws_secre.+[=:]\\s{0,}[A-Za-z0-9\\/+=]{40}.?") {
 				return []scanner.Result{
-					check.NewResult(
-						fmt.Sprintf("Resource '%s' .", block.FullName()),
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has userdata with access secret key defined.", block.FullName()),
 						userData.Range(),
+						userData,
 						scanner.SeverityError,
 					),
 				}
diff --git a/internal/app/tfsec/checks/aws063.go b/internal/app/tfsec/checks/aws063.go
new file mode 100644
index 000000000..9bc256c3d
--- /dev/null
+++ b/internal/app/tfsec/checks/aws063.go
@@ -0,0 +1,84 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSCloudtrailEnabledInAllRegions scanner.RuleCode = "AWS063"
+const AWSCloudtrailEnabledInAllRegionsDescription scanner.RuleSummary = "Cloudtrail should be enabled in all regions regardless of where your AWS resources are generally homed"
+const AWSCloudtrailEnabledInAllRegionsExplanation = `
+When creating Cloudtrail in the AWS Management Console the trail is configured by default to be multi-region, this isn't the case with the Terraform resource. Cloudtrail should cover the full AWS account to ensure you can track changes in regions you are not actively operting in.
+`
+const AWSCloudtrailEnabledInAllRegionsBadExample = `
+resource "aws_cloudtrail" "bad_example" {
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+const AWSCloudtrailEnabledInAllRegionsGoodExample = `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSCloudtrailEnabledInAllRegions,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSCloudtrailEnabledInAllRegionsDescription,
+			Explanation: AWSCloudtrailEnabledInAllRegionsExplanation,
+			BadExample:  AWSCloudtrailEnabledInAllRegionsBadExample,
+			GoodExample: AWSCloudtrailEnabledInAllRegionsGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail#is_multi_region_trail",
+				"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/receive-cloudtrail-log-files-from-multiple-regions.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_cloudtrail"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+			if block.MissingChild("is_multi_region_trail")  {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' does not set multi region trail config.", block.FullName()),
+						block.Range(),
+						scanner.SeverityWarning,
+					),
+				}
+			}
+
+			multiRegion := block.GetAttribute("is_multi_region_trail")
+			if multiRegion.IsFalse() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' does not enable multi region trail.", block.FullName()),
+						multiRegion.Range(),
+						multiRegion,
+						scanner.SeverityWarning,
+						),
+				}
+			}/**/
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws064.go b/internal/app/tfsec/checks/aws064.go
new file mode 100644
index 000000000..b4ac27f3d
--- /dev/null
+++ b/internal/app/tfsec/checks/aws064.go
@@ -0,0 +1,87 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSCloudtrailLogValidationEnabled scanner.RuleCode = "AWS064"
+const AWSCloudtrailLogValidationEnabledDescription scanner.RuleSummary = "Cloudtrail log validation should be enabled to prevent tampering of log data"
+const AWSCloudtrailLogValidationEnabledExplanation = `
+Log validation should be activated on Cloudtrail logs to prevent the tampering of the underlying data in the S3 bucket. It is feasible that a rogue actor compromising an AWS account might want to modify the log data to remove trace of their actions.
+`
+const AWSCloudtrailLogValidationEnabledBadExample = `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+const AWSCloudtrailLogValidationEnabledGoodExample = `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSCloudtrailLogValidationEnabled,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSCloudtrailLogValidationEnabledDescription,
+			Explanation: AWSCloudtrailLogValidationEnabledExplanation,
+			BadExample:  AWSCloudtrailLogValidationEnabledBadExample,
+			GoodExample: AWSCloudtrailLogValidationEnabledGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail#enable_log_file_validation",
+				"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-validation-intro.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_cloudtrail"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+			if block.MissingChild("enable_log_file_validation")  {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' does not enable log file validation.", block.FullName()),
+						block.Range(),
+						scanner.SeverityWarning,
+					),
+				}
+			}
+
+			logFileValidation := block.GetAttribute("enable_log_file_validation")
+			if logFileValidation.IsFalse() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' does not enable log file validation.", block.FullName()),
+						logFileValidation.Range(),
+						logFileValidation,
+						scanner.SeverityWarning,
+					),
+				}
+			}/**/
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws065.go b/internal/app/tfsec/checks/aws065.go
new file mode 100644
index 000000000..a8cfe33e7
--- /dev/null
+++ b/internal/app/tfsec/checks/aws065.go
@@ -0,0 +1,90 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSCloudtrailEncryptedAtRest scanner.RuleCode = "AWS065"
+const AWSCloudtrailEncryptedAtRestDescription scanner.RuleSummary = "Cloudtrail should be encrypted at rest to secure access to sensitive trail data"
+const AWSCloudtrailEncryptedAtRestExplanation = `
+Cloudtrail logs should be encrypted at rest to secure the sensitive data. Cloudtrail logs record all activity that occurs in the the account through API calls and would be one of the first places to look when reacting to a breach.
+`
+const AWSCloudtrailEncryptedAtRestBadExample = `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+const AWSCloudtrailEncryptedAtRestGoodExample = `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+  kms_key_id = var.kms_id
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSCloudtrailEncryptedAtRest,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSCloudtrailEncryptedAtRestDescription,
+			Explanation: AWSCloudtrailEncryptedAtRestExplanation,
+			BadExample:  AWSCloudtrailEncryptedAtRestBadExample,
+			GoodExample: AWSCloudtrailEncryptedAtRestGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail#kms_key_id",
+				"https://docs.aws.amazon.com/awscloudtrail/latest/userguide/encrypting-cloudtrail-log-files-with-aws-kms.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_cloudtrail"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+				
+			if block.MissingChild("kms_key_id") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' does not have a kms_key_id set.", block.FullName()),
+						block.Range(),
+						scanner.SeverityError,
+						),
+				}
+			}
+
+			kmsKeyId := block.GetAttribute("kms_key_id")
+			if kmsKeyId.IsEmpty() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has a kms_key_id but it is not set.", block.FullName()),
+						kmsKeyId.Range(),
+						kmsKeyId,
+						scanner.SeverityError,
+						),
+				}
+			}
+
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws066.go b/internal/app/tfsec/checks/aws066.go
new file mode 100644
index 000000000..7414667a8
--- /dev/null
+++ b/internal/app/tfsec/checks/aws066.go
@@ -0,0 +1,128 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSEKSSecretsEncryptionEnabled scanner.RuleCode = "AWS066"
+const AWSEKSSecretsEncryptionEnabledDescription scanner.RuleSummary = "EKS should have the encryption of secrets enabled"
+const AWSEKSSecretsEncryptionEnabledExplanation = `
+EKS cluster resources should have the encryption_config block set with protection of the secrets resource.
+`
+const AWSEKSSecretsEncryptionEnabledBadExample = `
+resource "aws_eks_cluster" "bad_example" {
+    name = "bad_example_cluster"
+
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`
+const AWSEKSSecretsEncryptionEnabledGoodExample = `
+resource "aws_eks_cluster" "good_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSEKSSecretsEncryptionEnabled,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSEKSSecretsEncryptionEnabledDescription,
+			Explanation: AWSEKSSecretsEncryptionEnabledExplanation,
+			BadExample:  AWSEKSSecretsEncryptionEnabledBadExample,
+			GoodExample: AWSEKSSecretsEncryptionEnabledGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#encryption_config",
+				"https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-eks-adds-envelope-encryption-for-secrets-with-aws-kms/",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_eks_cluster"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+				
+			if block.MissingChild("encryption_config") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has no encryption_config block", block.FullName()),
+						block.Range(),
+						scanner.SeverityError,
+						),
+				}
+			}
+
+			encryption_config := block.GetBlock("encryption_config")
+			if encryption_config.MissingChild("resources") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has encryption_config block with no resources attribute specified", block.FullName()),
+						encryption_config.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			resources := encryption_config.GetAttribute("resources")
+			if !resources.Contains("secrets") {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' does not include secrets in encrypted resources", block.FullName()),
+						resources.Range(),
+						resources,
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			if encryption_config.MissingChild("provider") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has encryption_config block with no provider block specified", block.FullName()),
+						encryption_config.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			providerBlock := encryption_config.GetBlock("provider")
+			if providerBlock.MissingChild("key_arn"){
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has encryption_config block with provider block specified missing key arn", block.FullName()),
+						encryption_config.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			keyArn := providerBlock.GetAttribute("key_arn")
+			if keyArn.IsEmpty() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has encryption_config block with provider block specified but key_arn is empty", block.FullName()),
+						keyArn.Range(),
+						keyArn,
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws067.go b/internal/app/tfsec/checks/aws067.go
new file mode 100644
index 000000000..a33bbdbde
--- /dev/null
+++ b/internal/app/tfsec/checks/aws067.go
@@ -0,0 +1,95 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSEKSHasControlPlaneLoggingEnabled scanner.RuleCode = "AWS067"
+const AWSEKSHasControlPlaneLoggingEnabledDescription scanner.RuleSummary = "EKS Clusters should have cluster control plane logging turned on"
+const AWSEKSHasControlPlaneLoggingEnabledExplanation = `
+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.
+`
+const AWSEKSHasControlPlaneLoggingEnabledBadExample = `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`
+const AWSEKSHasControlPlaneLoggingEnabledGoodExample = `
+resource "aws_eks_cluster" "good_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+	enabled_cluster_log_types = ["api", "authenticator", "audit", "scheduler", "controllerManager"]
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSEKSHasControlPlaneLoggingEnabled,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSEKSHasControlPlaneLoggingEnabledDescription,
+			Explanation: AWSEKSHasControlPlaneLoggingEnabledExplanation,
+			BadExample:  AWSEKSHasControlPlaneLoggingEnabledBadExample,
+			GoodExample: AWSEKSHasControlPlaneLoggingEnabledGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#enabled_cluster_log_types",
+				"https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_eks_cluster"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+
+			controlPlaneLogging := []string{"api", "audit", "authenticator", "controllerManager", "scheduler"}
+
+			if block.MissingChild("enabled_cluster_log_types") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' missing the enabled_cluster_log_types attribute to enable control plane logging", block.FullName()),
+						block.Range(),
+						scanner.SeverityError,
+						),
+				}
+			}
+
+			configuredLogging := block.GetAttribute("enabled_cluster_log_types")
+			var logTypeResults []scanner.Result
+			for _, logType := range controlPlaneLogging {
+				if ! configuredLogging.Contains(logType) {
+					logTypeResults = append(logTypeResults, check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' is missing the control plane log type '%s'", block.FullName(), logType),
+						configuredLogging.Range(),
+						configuredLogging,
+						scanner.SeverityError,
+						))
+				}
+			}
+
+			return logTypeResults
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws068.go b/internal/app/tfsec/checks/aws068.go
new file mode 100644
index 000000000..f57eac088
--- /dev/null
+++ b/internal/app/tfsec/checks/aws068.go
@@ -0,0 +1,91 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSEKSClusterNotOpenPublicly scanner.RuleCode = "AWS068"
+const AWSEKSClusterNotOpenPubliclyDescription scanner.RuleSummary = "EKS cluster should not have open CIDR range for public access"
+const AWSEKSClusterNotOpenPubliclyExplanation = `
+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 CIDR range
+`
+const AWSEKSClusterNotOpenPubliclyBadExample = `
+resource "aws_eks_cluster" "bad_example" {
+    // other config 
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = true
+    }
+}
+`
+const AWSEKSClusterNotOpenPubliclyGoodExample = `
+resource "aws_eks_cluster" "good_example" {
+    // other config 
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = true
+        public_access_cidrs = ["10.2.0.0/8"]
+    }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSEKSClusterNotOpenPublicly,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSEKSClusterNotOpenPubliclyDescription,
+			Explanation: AWSEKSClusterNotOpenPubliclyExplanation,
+			BadExample:  AWSEKSClusterNotOpenPubliclyBadExample,
+			GoodExample: AWSEKSClusterNotOpenPubliclyGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#vpc_config",
+				"https://docs.aws.amazon.com/eks/latest/userguide/create-public-private-vpc.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_eks_cluster"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+
+			if block.MissingChild("vpc_config") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has no vpc_config block specified so default public access cidrs is set", block.FullName()),
+						block.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			vpcConfig := block.GetBlock("vpc_config")
+			if vpcConfig.MissingChild("public_access_cidrs") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' is using default public access cidrs in the vpc config", block.FullName()),
+						vpcConfig.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			publicAccessCidrs := vpcConfig.GetAttribute("public_access_cidrs")
+			if isOpenCidr(publicAccessCidrs, scanner.AWSProvider) {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has public access cidr explicitly set to wide open", block.FullName()),
+						publicAccessCidrs.Range(),
+						publicAccessCidrs,
+						scanner.SeverityError,
+					),
+				}
+			}
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/aws069.go b/internal/app/tfsec/checks/aws069.go
new file mode 100644
index 000000000..012781d96
--- /dev/null
+++ b/internal/app/tfsec/checks/aws069.go
@@ -0,0 +1,91 @@
+package checks
+
+import (
+	"fmt"
+	"github.com/tfsec/tfsec/internal/app/tfsec/parser"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+const AWSEKSClusterPublicAccessDisabled scanner.RuleCode = "AWS069"
+const AWSEKSClusterPublicAccessDisabledDescription scanner.RuleSummary = "EKS Clusters should have the public access disabled"
+const AWSEKSClusterPublicAccessDisabledExplanation = `
+EKS clusters are available publicly by default, this should be explicitly disabled in the vpc_config of the EKS cluster resource.
+`
+const AWSEKSClusterPublicAccessDisabledBadExample = `
+resource "aws_eks_cluster" "bad_example" {
+    // other config 
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = true
+    }
+}
+`
+const AWSEKSClusterPublicAccessDisabledGoodExample = `
+resource "aws_eks_cluster" "good_example" {
+    // other config 
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+        public_access_cidrs = ["10.2.0.0/8"]
+    }
+}
+`
+
+func init() {
+	scanner.RegisterCheck(scanner.Check{
+		Code: AWSEKSClusterPublicAccessDisabled,
+		Documentation: scanner.CheckDocumentation{
+			Summary:     AWSEKSClusterPublicAccessDisabledDescription,
+			Explanation: AWSEKSClusterPublicAccessDisabledExplanation,
+			BadExample:  AWSEKSClusterPublicAccessDisabledBadExample,
+			GoodExample: AWSEKSClusterPublicAccessDisabledGoodExample,
+			Links: []string{
+				"https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_cluster#endpoint_public_access",
+				"https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html",
+			},
+		},
+		Provider:       scanner.AWSProvider,
+		RequiredTypes:  []string{"resource"},
+		RequiredLabels: []string{"aws_eks_cluster"},
+		CheckFunc: func(check *scanner.Check, block *parser.Block, _ *scanner.Context) []scanner.Result {
+
+			if block.MissingChild("vpc_config") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' has no vpc_config block specified so default public access is enabled", block.FullName()),
+						block.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			vpcConfig := block.GetBlock("vpc_config")
+			if vpcConfig.MissingChild("endpoint_public_access") {
+				return []scanner.Result{
+					check.NewResult(
+						fmt.Sprintf("Resource '%s' is using default public access in the vpc config", block.FullName()),
+						vpcConfig.Range(),
+						scanner.SeverityError,
+					),
+				}
+			}
+
+			publicAccessEnabled := vpcConfig.GetAttribute("endpoint_public_access")
+			if publicAccessEnabled.IsTrue() {
+				return []scanner.Result{
+					check.NewResultWithValueAnnotation(
+						fmt.Sprintf("Resource '%s' has public access is explicitly set to enabled", block.FullName()),
+						publicAccessEnabled.Range(),
+						publicAccessEnabled,
+						scanner.SeverityError,
+					),
+				}
+			}
+			return nil
+		},
+	})
+}
diff --git a/internal/app/tfsec/checks/azu015.go b/internal/app/tfsec/checks/azu015.go
index b89514184..d557fbea1 100644
--- a/internal/app/tfsec/checks/azu015.go
+++ b/internal/app/tfsec/checks/azu015.go
@@ -59,7 +59,6 @@ func init() {
 					),
 				}
 			}
-
 			return nil
 		},
 	})


Test patch:
diff --git a/internal/app/tfsec/test/aws063_test.go b/internal/app/tfsec/test/aws063_test.go
new file mode 100644
index 000000000..f124acf02
--- /dev/null
+++ b/internal/app/tfsec/test/aws063_test.go
@@ -0,0 +1,82 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSCloudtrailEnabledInAllRegions(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test cloudtrail not configured for multi region use",
+			source: `
+resource "aws_cloudtrail" "bad_example" {
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustIncludeResultCode: checks.AWSCloudtrailEnabledInAllRegions,
+		},
+		{
+			name: "Test multiregion set to false fails",
+			source: `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = false
+  
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustIncludeResultCode: checks.AWSCloudtrailEnabledInAllRegions,
+		},
+		{
+			name: "Test multi region correctly configured",
+			source: `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustExcludeResultCode: checks.AWSCloudtrailEnabledInAllRegions,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws064_test.go b/internal/app/tfsec/test/aws064_test.go
new file mode 100644
index 000000000..f81c1885e
--- /dev/null
+++ b/internal/app/tfsec/test/aws064_test.go
@@ -0,0 +1,86 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSCloudtrailLogValidationEnabled(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test log file validation is not specified",
+			source: `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustIncludeResultCode: checks.AWSCloudtrailLogValidationEnabled,
+		},
+		{
+			name: "Test log file validation is specified but not true",
+			source: `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = false 
+  
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustIncludeResultCode: checks.AWSCloudtrailLogValidationEnabled,
+		},
+		{
+			name: "Test enable log validation is configured correctly",
+			source: `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustExcludeResultCode: checks.AWSCloudtrailLogValidationEnabled,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws065_test.go b/internal/app/tfsec/test/aws065_test.go
new file mode 100644
index 000000000..71edd37b0
--- /dev/null
+++ b/internal/app/tfsec/test/aws065_test.go
@@ -0,0 +1,88 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSCloudtrailEncryptedAtRest(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{		{
+		name: "Test check fails when missing kms id",
+		source: `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+		mustIncludeResultCode: checks.AWSCloudtrailEncryptedAtRest,
+	},
+		{
+			name: "Test check fails when kms_key_id present but empty",
+			source: `
+resource "aws_cloudtrail" "bad_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+  kms_key_id = ""
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustIncludeResultCode: checks.AWSCloudtrailEncryptedAtRest,
+		},
+		{
+			name: "Test check passes when kms_key_id present and populated",
+			source: `
+resource "aws_cloudtrail" "good_example" {
+  is_multi_region_trail = true
+  enable_log_file_validation = true
+  kms_key_id = var.kms_id
+
+  event_selector {
+    read_write_type           = "All"
+    include_management_events = true
+
+    data_resource {
+      type = "AWS::S3::Object"
+      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
+    }
+  }
+}
+`,
+			mustExcludeResultCode: checks.AWSCloudtrailEncryptedAtRest,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws066_test.go b/internal/app/tfsec/test/aws066_test.go
new file mode 100644
index 000000000..1b3721eb0
--- /dev/null
+++ b/internal/app/tfsec/test/aws066_test.go
@@ -0,0 +1,137 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSEKSSecretsEncryptionEnabled(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test eks cluster with no encryption block causes check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+		{
+			name: "Test eks cluster with encryption block causes check to fail when no resources",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+		{
+			name: "Test eks cluster with secrets no in the resources attribute causes check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [  ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+		{
+			name: "Test eks cluster with secrets in the resources attribute but no provider block causes check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+		{
+			name: "Test eks cluster with secrets in the resources and provider block but no key_arn set causes check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = ""
+        }
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+		{
+			name: "Test correctly configured eks cluster passes check",
+			source: `
+resource "aws_eks_cluster" "good_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustExcludeResultCode: checks.AWSEKSSecretsEncryptionEnabled,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws067_test.go b/internal/app/tfsec/test/aws067_test.go
new file mode 100644
index 000000000..3edc27eee
--- /dev/null
+++ b/internal/app/tfsec/test/aws067_test.go
@@ -0,0 +1,91 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSEKSHasControlPlaneLoggingEnabled(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test eks cluster with no logging configured fails check",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSHasControlPlaneLoggingEnabled,
+		},
+		{
+			name: "Test EKS cluster with only some cluster logging enabled fails check",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+	enabled_cluster_log_types = ["api", "authenticator", "scheduler", "controllerManager"]
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSHasControlPlaneLoggingEnabled,
+		},
+		{
+			name: "Test eks cluster with all logging enabled passes check",
+			source: `
+resource "aws_eks_cluster" "good_example" {
+    encryption_config {
+        resources = [ "secrets" ]
+        provider {
+            key_arn = var.kms_arn
+        }
+    }
+
+	enabled_cluster_log_types = ["api", "authenticator", "audit", "scheduler", "controllerManager"]
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustExcludeResultCode: checks.AWSEKSHasControlPlaneLoggingEnabled,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws068_test.go b/internal/app/tfsec/test/aws068_test.go
new file mode 100644
index 000000000..276112e48
--- /dev/null
+++ b/internal/app/tfsec/test/aws068_test.go
@@ -0,0 +1,71 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSEKSClusterNotOpenPublicly(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test public access cidrs left to default causes check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSClusterNotOpenPublicly,
+		},
+		{
+			name: "Test public access cidrs actively set to open check to fail",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+		public_access_cidrs = [ "0.0.0.0/0" ]
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSClusterNotOpenPublicly,
+		},
+		{
+			name: "Test public access cidrs correctly configured passess check",
+			source: `
+resource "aws_eks_cluster" "good_example" {
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+        public_access_cidrs = ["10.2.0.0/8"]
+    }
+}
+`,
+			mustExcludeResultCode: checks.AWSEKSClusterNotOpenPublicly,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}
diff --git a/internal/app/tfsec/test/aws069_test.go b/internal/app/tfsec/test/aws069_test.go
new file mode 100644
index 000000000..9e4a30c57
--- /dev/null
+++ b/internal/app/tfsec/test/aws069_test.go
@@ -0,0 +1,71 @@
+package test
+
+import (
+	"testing"
+
+	"github.com/tfsec/tfsec/internal/app/tfsec/checks"
+	"github.com/tfsec/tfsec/internal/app/tfsec/scanner"
+)
+
+func Test_AWSEKSClusterPublicAccessDisabled(t *testing.T) {
+
+	var tests = []struct {
+		name                  string
+		source                string
+		mustIncludeResultCode scanner.RuleCode
+		mustExcludeResultCode scanner.RuleCode
+	}{
+		{
+			name: "Test eks cluster without vpc_config defaults to public access fails check",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    // other config 
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSClusterPublicAccessDisabled,
+		},
+		{
+			name: "Test vpc config with public access fails check",
+			source: `
+resource "aws_eks_cluster" "bad_example" {
+    // other config 
+
+    name = "bad_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = true
+        public_access_cidrs = ["10.2.0.0/8"]
+    }
+}
+`,
+			mustIncludeResultCode: checks.AWSEKSClusterPublicAccessDisabled,
+		},
+		{
+			name: "Test eks cluster with the public access disabled passes check",
+			source: `
+resource "aws_eks_cluster" "good_example" {
+    // other config 
+
+    name = "good_example_cluster"
+    role_arn = var.cluster_arn
+    vpc_config {
+        endpoint_public_access = false
+        public_access_cidrs = ["10.2.0.0/8"]
+    }
+}
+`,
+			mustExcludeResultCode: checks.AWSEKSClusterPublicAccessDisabled,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			results := scanSource(test.source)
+			assertCheckCode(t, test.mustIncludeResultCode, test.mustExcludeResultCode, results)
+		})
+	}
+
+}