Skip to content

feat(terraform): 7 new policies #7056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4402b14
7 new policies
TomerSegev241 Mar 17, 2025
5c0fda1
Merge branch 'main' into feat(terraform)-medium-policies-from-CSPM
TomerSegev241 Mar 17, 2025
1b4fe7d
Merge branch 'main' into feat(terraform)-medium-policies-from-CSPM
tsmithv11 Mar 21, 2025
be6fb41
Update checkov/terraform/checks/resource/aws/AutoScalingGroupWithPubl…
TomerSegev241 Mar 23, 2025
2303bb7
Update checkov/terraform/checks/resource/aws/EMRPubliclyAccessible.py
TomerSegev241 Mar 23, 2025
ff53111
Update checkov/terraform/checks/resource/aws/RedshiftClusterWithCommo…
TomerSegev241 Mar 23, 2025
b0973cd
Update checkov/terraform/checks/resource/aws/S3BucketPubliclyReadable…
TomerSegev241 Mar 23, 2025
0f13976
Update checkov/terraform/checks/resource/aws/UnpatchedAuroraPostgresD…
TomerSegev241 Mar 23, 2025
18d55df
Update checkov/terraform/checks/resource/aws/WAFv2VulnerableForLog4j.py
TomerSegev241 Mar 23, 2025
22e7019
Update checkov/terraform/checks/resource/aws/S3AccessPointPubliclyAcc…
TomerSegev241 Mar 23, 2025
0ece751
changes due to @Taylor comments
TomerSegev241 Mar 23, 2025
f814203
Merge remote-tracking branch 'origin/feat(terraform)-medium-policies-…
TomerSegev241 Mar 23, 2025
3fe07ce
pre-commit warnings fixed
TomerSegev241 Mar 23, 2025
756672e
update due to Taylor comments
TomerSegev241 Apr 30, 2025
6748fe6
Merge remote-tracking branch 'origin/feat(terraform)-medium-policies-…
TomerSegev241 Apr 30, 2025
23f40a1
Merge branch 'main' into feat(terraform)-medium-policies-from-CSPM
TomerSegev241 Apr 30, 2025
27ea5bb
delete auto created init file
TomerSegev241 May 4, 2025
3ecba3a
Merge branch 'main' into feat(terraform)-medium-policies-from-CSPM
TomerSegev241 May 4, 2025
028ec9e
Merge remote-tracking branch 'origin/feat(terraform)-medium-policies-…
TomerSegev241 May 4, 2025
69691d5
delete auto created init file
TomerSegev241 May 4, 2025
39c9513
delete python test file
TomerSegev241 May 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added __init__.py
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class AutoScalingGroupWithPublicAccess(BaseResourceCheck):

def __init__(self):
name = "AWS Auto Scaling group launch configuration has public IP address assignment enabled"
id = "CKV_AWS_389"
supported_resources = ['aws_launch_configuration']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'associate_public_ip_address' in conf:
if str(conf['associate_public_ip_address'][0]).lower() == 'true':
return CheckResult.FAILED
return CheckResult.PASSED


check = AutoScalingGroupWithPublicAccess()
24 changes: 24 additions & 0 deletions checkov/terraform/checks/resource/aws/EMRPubliclyAccessible.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class EMRPubliclyAccessible(BaseResourceCheck):

def __init__(self):
name = "AWS EMR Block public access setting disabled"
id = "CKV_AWS_390"
supported_resources = ['aws_emr_block_public_access_configuration']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'block_public_access' in conf:
for arg in list(conf['block_public_access'][0].keys()):
if arg in ['block_public_acls', 'ignore_public_acls', 'restrict_public_buckets']:
if str(conf['block_public_access'][0][arg][0]).lower() == 'false':
return CheckResult.FAILED
return CheckResult.PASSED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These attributes don't exist. You want to check if block_public_security_group_rules is true (BaseResourceValueCheck)



check = EMRPubliclyAccessible()
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class RedshiftClusterWithCommonUsernameAndPublicAccess(BaseResourceCheck):

def __init__(self):
name = "AWS Redshift cluster with commonly used master username and public access setting enabled"
id = "CKV_AWS_391"
supported_resources = ['aws_redshift_cluster']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'master_username' in conf:
if conf['master_username'][0] in ['awsuser','administrator','admin']:
if 'publicly_accessible' in conf:
if str(conf['publicly_accessible'][0]).lower() == 'true':
return CheckResult.FAILED
Comment on lines +17 to +19
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default publicly_accessible is true, so also check for the absence of the attribute

return CheckResult.PASSED


check = RedshiftClusterWithCommonUsernameAndPublicAccess()
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class S3AccessPointPubliclyAccessible(BaseResourceCheck):

def __init__(self):
name = "AWS S3 access point Block public access setting disabled"
id = "CKV_AWS_392"
supported_resources = ['aws_s3_access_point']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'public_access_block_configuration' in conf:
for arg in list(conf['public_access_block_configuration'][0].keys()):
if arg == 'restrict_public_buckets':
if str(conf['public_access_block_configuration'][0][arg][0]).lower() == 'false':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a block. false is not a value for this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, I've changed the tested resource to be the block (aws_s3_account_public_access_block)

return CheckResult.FAILED
else:
return CheckResult.PASSED
return CheckResult.PASSED


check = S3AccessPointPubliclyAccessible()
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class S3BucketPubliclyReadableViaACL(BaseResourceCheck):

def __init__(self):
name = "AWS S3 buckets are accessible to public via ACL"
id = "CKV_AWS_393"
supported_resources = ['aws_s3_bucket_acl']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'acl' in conf:
if conf['acl'][0] == 'public-read':
return CheckResult.FAILED
return CheckResult.PASSED
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is like CKV_AWS_20 but less complete and different than what 630d3779-d932-4fbf-9cce-6e8d793c6916 is looking for

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean, do you think that this is more accurate? (setting block_public_policy to false)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to check that the S3 has the pbulic access block, and check if there is a aws_s3_account_public_access_block and check if there is a aws_s3_bucket_website_configuration attached. It would look closer to this: https://github.com/bridgecrewio/checkov/blob/66988745cf9b93c449e3693219c5679e3be19a32/checkov/terraform/checks/resource/aws/S3SecureDataTransport.py



check = S3BucketPubliclyReadableViaACL()
23 changes: 23 additions & 0 deletions checkov/terraform/checks/resource/aws/UnpatchedAuroraPostgresDB.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class UnpatchedAuroraPostgresDB(BaseResourceCheck):

def __init__(self):
name = "AWS Aurora PostgreSQL exposed to local file read vulnerability"
id = "CKV_AWS_388"
supported_resources = ['aws_db_instance']
categories = [CheckCategories.GENERAL_SECURITY]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
if 'engine' in conf and 'aurora-postgresql' in conf['engine']:
if 'engine_version' in conf and conf['engine_version'][0] in ['10.11','10.12','10.13','11.6','11.7','11.8']:
return CheckResult.FAILED
return CheckResult.PASSED



check = UnpatchedAuroraPostgresDB()
40 changes: 40 additions & 0 deletions checkov/terraform/checks/resource/aws/WAFv2VulnerableForLog4j.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.common.util.type_forcers import force_list
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck


class WAFv2VulnerableForLog4j(BaseResourceCheck):

def __init__(self):
name = "WAFv2 WebACL is not configured with AMR for Log4j Vulnerability"
id = "CKV_AWS_387"
supported_resources = ['aws_wafv2_web_acl']
categories = [CheckCategories.NETWORKING]
super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)

def scan_resource_conf(self, conf):
badInput = False
ipList = False
rules = conf.get("rule", [])
if not isinstance(rules, list):
rules = [rules]

for rule_block in rules:
if isinstance(rule_block, dict):
statements = rule_block.get("statement", [])
if not isinstance(statements, list):
statements = [statements]
for stmt in statements:
if isinstance(stmt, dict):
if 'managed_rule_group_statement' in stmt:
if stmt['managed_rule_group_statement'][0]['name']:
if stmt['managed_rule_group_statement'][0]['name'][0] == "AWSManagedRulesCommonRuleSet":
badInput = True
elif stmt['managed_rule_group_statement'][0]['name'][0] == "AWSManagedRulesAnonymousIpList":
ipList = True
if badInput and ipList:
return CheckResult.PASSED
return CheckResult.FAILED


check = WAFv2VulnerableForLog4j()
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
resource "aws_launch_configuration" "fail" {
name = "vulnerable-lc-${random_id.id.hex}"
image_id = "ami-0c55b24b055c14ff6" # Replace with a valid AMI ID for your region
instance_type = "t2.micro"
associate_public_ip_address = true # THIS IS THE VULNERABILITY
}

resource "aws_autoscaling_group" "vulnerable_asg" {
name = "vulnerable-asg-${random_id.id.hex}"
launch_configuration = aws_launch_configuration.vulnerable_launch_config.name
min_size = 1
max_size = 3
desired_capacity = 1
vpc_zone_identifier = ["subnet-0bb1c79de3EXAMPLE", "subnet-0bb1c79de4EXAMPLE"] # Replace with valid subnet IDs

tags = [
{
key = "Name"
value = "VulnerableAutoScalingGroup"
propagate_at_launch = true
},
]
}

resource "random_id" "id" {
byte_length = 8
}

resource "aws_launch_configuration" "pass" {
name = "safe-lc-${random_id.id.hex}"
image_id = "ami-0c55b24b055c14ff6" # Replace with a valid AMI ID for your region
instance_type = "t2.micro"
associate_public_ip_address = false # THIS IS THE SAFE CONFIGURATION
}

resource "aws_autoscaling_group" "safe_asg" {
name = "safe-asg-${random_id.id.hex}"
launch_configuration = aws_launch_configuration.safe_launch_config.name
min_size = 1
max_size = 3
desired_capacity = 1
vpc_zone_identifier = ["subnet-0bb1c79de3EXAMPLE", "subnet-0bb1c79de4EXAMPLE"] # Replace with valid subnet IDs


tags = [
{
key = "Name"
value = "SafeAutoScalingGroup"
propagate_at_launch = true
},
]
}

resource "random_id" "id" {
byte_length = 8
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

resource "aws_emr_block_public_access_configuration" "fail1" {
block_public_access {
block_public_acls = false
ignore_public_acls = false
restrict_public_buckets = false
}
}

resource "aws_emr_block_public_access_configuration" "pass" {
block_public_access {
block_public_acls = true
ignore_public_acls = true
restrict_public_buckets = true
}
}

resource "aws_emr_block_public_access_configuration" "fail2" {
block_public_access {
block_public_acls = false
ignore_public_acls = true
restrict_public_buckets = true
}
}

resource "aws_emr_block_public_access_configuration" "fail3" {
block_public_access {
block_public_acls = true
ignore_public_acls = false
restrict_public_buckets = true
}
}

resource "aws_emr_block_public_access_configuration" "fail4" {
block_public_access {
block_public_acls = true
ignore_public_acls = true
restrict_public_buckets = false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
provider "aws" {
region = "us-west-2"
}

resource "aws_redshift_cluster" "fail" {
cluster_identifier = "vulnerable-redshift-cluster"
database_name = "productiondb"
master_username = "administrator"
master_password = "Complex-P@ssw0rd789"
node_type = "dc2.large"
cluster_type = "single-node"

publicly_accessible = true

skip_final_snapshot = true

vpc_security_group_ids = [aws_security_group.redshift_sg.id]
}

resource "aws_security_group" "redshift_sg" {
name = "vulnerable-redshift-sg"
description = "Security group for vulnerable Redshift cluster"

ingress {
from_port = 5439
to_port = 5439
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}

provider "aws" {
region = "us-west-2"
}

resource "aws_redshift_cluster" "pass1" {
cluster_identifier = "safe-redshift-cluster"
database_name = "productiondb"
master_username = "custom_user_84629"
master_password = "vK#9mP$2nL@5qR8x"
node_type = "dc2.large"
cluster_type = "single-node"

publicly_accessible = false

skip_final_snapshot = true

vpc_security_group_ids = [aws_security_group.safe_redshift_sg.id]

encrypted = true
kms_key_id = aws_kms_key.redshift_key.arn
}

resource "aws_kms_key" "redshift_key" {
description = "KMS key for Redshift cluster encryption"
enable_key_rotation = true
}

resource "aws_security_group" "safe_redshift_sg" {
name = "safe-redshift-sg"
description = "Security group for safe Redshift cluster"

ingress {
from_port = 5439
to_port = 5439
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"] # Restricted to internal VPC CIDR
}
}

resource "aws_redshift_cluster" "pass2" {
cluster_identifier = "vulnerable-redshift-cluster"
database_name = "productiondb"
master_username = "administrator"
master_password = "Complex-P@ssw0rd789"
node_type = "dc2.large"
cluster_type = "single-node"

publicly_accessible = false

skip_final_snapshot = true

vpc_security_group_ids = [aws_security_group.redshift_sg.id]
}

resource "aws_redshift_cluster" "pass3" {
cluster_identifier = "vulnerable-redshift-cluster"
database_name = "productiondb"
master_username = "adm1n1str@t0r"
master_password = "Complex-P@ssw0rd789"
node_type = "dc2.large"
cluster_type = "single-node"

publicly_accessible = true

skip_final_snapshot = true

vpc_security_group_ids = [aws_security_group.redshift_sg.id]
}
Loading
Loading