Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 38 additions & 0 deletions conftest-policies/dynamodb_encryption_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import rego.v1

test_dynamodb_unencrypted_denied if {
result := deny_dynamodb_unencrypted with input as {"resource": {"aws_dynamodb_table": {"unencrypted": [{"server_side_encryption": false}]}}}
count(result) == 1
}

test_dynamodb_encrypted_allowed if {
result := deny_dynamodb_unencrypted with input as {"resource": {"aws_dynamodb_table": {"encrypted": [{"server_side_encryption": true}]}}}
count(result) == 0
}

test_dynamodb_pitr_disabled_denied if {
result := deny_dynamodb_pitr_disabled with input as {"resource": {"aws_dynamodb_table": {"no_pitr": [{"point_in_time_recovery": false}]}}}
count(result) == 1
}

test_dynamodb_pitr_enabled_allowed if {
result := deny_dynamodb_pitr_disabled with input as {"resource": {"aws_dynamodb_table": {"with_pitr": [{"point_in_time_recovery": true}]}}}
count(result) == 0
}

test_dynamodb_replica_missing_warning if {
result := deny_dynamodb_replica_missing with input as {"resource": {"aws_dynamodb_table": {"single_region": [{"billing_mode": "PAY_PER_REQUEST"}]}}}
count(result) == 1
}

test_dynamodb_with_replica_allowed if {
result := deny_dynamodb_replica_missing with input as {"resource": {"aws_dynamodb_table": {"multi_region": [{"billing_mode": "PAY_PER_REQUEST", "replica": [{"region_name": "us-east-1"}]}]}}}
count(result) == 0
}

test_dynamodb_provisioned_without_replica_allowed if {
result := deny_dynamodb_replica_missing with input as {"resource": {"aws_dynamodb_table": {"provisioned": [{"billing_mode": "PROVISIONED"}]}}}
count(result) == 0
}
58 changes: 58 additions & 0 deletions conftest-policies/rds_encryption_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import rego.v1

test_rds_instance_unencrypted_denied if {
result := deny_rds_unencrypted with input as {"resource": {"aws_db_instance": {"unencrypted": [{"storage_encrypted": false}]}}}
count(result) == 1
}

test_rds_instance_encrypted_allowed if {
result := deny_rds_unencrypted with input as {"resource": {"aws_db_instance": {"encrypted": [{"storage_encrypted": true}]}}}
count(result) == 0
}

test_rds_instance_default_encrypted_allowed if {
result := deny_rds_unencrypted with input as {"resource": {"aws_db_instance": {"default": [{}]}}}
count(result) == 0
}

test_rds_cluster_unencrypted_denied if {
result := deny_rds_unencrypted with input as {"resource": {"aws_rds_cluster": {"unencrypted": [{"storage_encrypted": false}]}}}
count(result) == 1
}

test_rds_cluster_encrypted_allowed if {
result := deny_rds_unencrypted with input as {"resource": {"aws_rds_cluster": {"encrypted": [{"storage_encrypted": true}]}}}
count(result) == 0
}

test_rds_cluster_instance_unencrypted_denied if {
result := deny_rds_unencrypted with input as {"resource": {"aws_rds_cluster_instance": {"unencrypted": [{"storage_encrypted": false}]}}}
count(result) == 1
}

test_rds_cluster_instance_encrypted_allowed if {
result := deny_rds_unencrypted with input as {"resource": {"aws_rds_cluster_instance": {"encrypted": [{"storage_encrypted": true}]}}}
count(result) == 0
}

test_rds_skip_final_snapshot_denied if {
result := deny_rds_skip_final_snapshot with input as {"resource": {"aws_db_instance": {"no_snapshot": [{"skip_final_snapshot": true}]}}}
count(result) == 1
}

test_rds_skip_final_snapshot_allowed if {
result := deny_rds_skip_final_snapshot with input as {"resource": {"aws_db_instance": {"with_snapshot": [{"skip_final_snapshot": false}]}}}
count(result) == 0
}

test_rds_cluster_skip_final_snapshot_denied if {
result := deny_rds_skip_final_snapshot with input as {"resource": {"aws_rds_cluster": {"no_snapshot": [{"skip_final_snapshot": true}]}}}
count(result) == 1
}

test_rds_cluster_skip_final_snapshot_allowed if {
result := deny_rds_skip_final_snapshot with input as {"resource": {"aws_rds_cluster": {"with_snapshot": [{"skip_final_snapshot": false}]}}}
count(result) == 0
}
33 changes: 33 additions & 0 deletions conftest-policies/s3_public_access_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

import rego.v1

test_s3_bucket_public_acl_denied if {
result := deny_s3_public_access with input as {"resource": {"aws_s3_bucket": {"public": [{"acl": "public-read"}]}}}
count(result) == 1
}

test_s3_bucket_private_acl_allowed if {
result := deny_s3_public_access with input as {"resource": {"aws_s3_bucket": {"private": [{"acl": "private"}]}}}
count(result) == 0
}

test_s3_bucket_log_delivery_acl_allowed if {
result := deny_s3_public_access with input as {"resource": {"aws_s3_bucket": {"logs": [{"acl": "log_delivery_write"}]}}}
count(result) == 0
}

test_s3_public_access_block_disabled_denied if {
result := deny_s3_public_access_block_disabled with input as {"resource": {"aws_s3_bucket_public_access_block": {"bad": [{"block_public_acls": false}]}}}
count(result) == 1
}

test_s3_public_access_block_enabled_allowed if {
result := deny_s3_public_access_block_disabled with input as {"resource": {"aws_s3_bucket_public_access_block": {"good": [{"block_public_acls": true, "block_public_policy": true, "ignore_public_acls": true, "restrict_public_buckets": true}]}}}
count(result) == 0
}

test_s3_public_access_block_partial_allowed if {
result := deny_s3_public_access_block_disabled with input as {"resource": {"aws_s3_bucket_public_access_block": {"partial": [{"block_public_acls": true, "block_public_policy": false}]}}}
count(result) == 1
}
41 changes: 22 additions & 19 deletions conftest-policies/security_group_rules.rego
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package main
import rego.v1

deny_insecure_security_group_ingress contains msg if {
some name, block in input.resource.aws_security_group
some rule in block.ingress
rule.cidr_blocks
some cidr in rule.cidr_blocks
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "ingress", [])
some cidr in object.get(rule, "cidr_blocks", [])
cidr == "0.0.0.0/0"
msg := sprintf(
"aws_security_group.%s: ingress rule allows 0.0.0.0/0 - restrict to specific IPs",
Expand All @@ -15,10 +15,10 @@ deny_insecure_security_group_ingress contains msg if {
}

deny_insecure_security_group_ingress contains msg if {
some name, block in input.resource.aws_security_group
some rule in block.ingress
rule.ipv6_cidr_blocks
some cidr in rule.ipv6_cidr_blocks
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "ingress", [])
some cidr in object.get(rule, "ipv6_cidr_blocks", [])
cidr == "::/0"
msg := sprintf(
"aws_security_group.%s: ingress rule allows ::/0 - restrict to specific IPv6 ranges",
Expand All @@ -27,10 +27,10 @@ deny_insecure_security_group_ingress contains msg if {
}

deny_insecure_security_group_egress contains msg if {
some name, block in input.resource.aws_security_group
some rule in block.egress
rule.cidr_blocks
some cidr in rule.cidr_blocks
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "egress", [])
some cidr in object.get(rule, "cidr_blocks", [])
cidr == "0.0.0.0/0"
msg := sprintf(
"aws_security_group.%s: egress rule allows 0.0.0.0/0 - restrict to specific IPs",
Expand All @@ -39,10 +39,10 @@ deny_insecure_security_group_egress contains msg if {
}

deny_insecure_security_group_egress contains msg if {
some name, block in input.resource.aws_security_group
some rule in block.egress
rule.ipv6_cidr_blocks
some cidr in rule.ipv6_cidr_blocks
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "egress", [])
some cidr in object.get(rule, "ipv6_cidr_blocks", [])
cidr == "::/0"
msg := sprintf(
"aws_security_group.%s: egress rule allows ::/0 - restrict to specific IPv6 ranges",
Expand All @@ -51,7 +51,8 @@ deny_insecure_security_group_egress contains msg if {
}

deny_security_group_without_description contains msg if {
some name, block in input.resource.aws_security_group
some name, blocks in input.resource.aws_security_group
some block in blocks
object.get(block, "description", "") == ""
msg := sprintf(
"aws_security_group.%s: security group must have a description",
Expand All @@ -60,7 +61,8 @@ deny_security_group_without_description contains msg if {
}

deny_security_group_rule_without_description contains msg if {
some name, block in input.resource.aws_security_group
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "ingress", [])
object.get(rule, "description", "") == ""
msg := sprintf(
Expand All @@ -70,7 +72,8 @@ deny_security_group_rule_without_description contains msg if {
}

deny_security_group_rule_without_description contains msg if {
some name, block in input.resource.aws_security_group
some name, blocks in input.resource.aws_security_group
some block in blocks
some rule in object.get(block, "egress", [])
object.get(rule, "description", "") == ""
msg := sprintf(
Expand Down
48 changes: 48 additions & 0 deletions conftest-policies/security_group_rules_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import rego.v1

test_sg_ingress_0_0_0_0_denied if {
result := deny_insecure_security_group_ingress with input as {"resource": {"aws_security_group": {"bad": [{"ingress": [{"cidr_blocks": ["0.0.0.0/0"]}]}]}}}
count(result) == 1
}

test_sg_ingress_specific_ip_allowed if {
result := deny_insecure_security_group_ingress with input as {"resource": {"aws_security_group": {"good": [{"ingress": [{"cidr_blocks": ["10.0.0.0/8"]}]}]}}}
count(result) == 0
}

test_sg_ingress_ipv6_all_denied if {
result := deny_insecure_security_group_ingress with input as {"resource": {"aws_security_group": {"bad_ipv6": [{"ingress": [{"ipv6_cidr_blocks": ["::/0"]}]}]}}}
count(result) == 1
}

test_sg_egress_0_0_0_0_denied if {
result := deny_insecure_security_group_egress with input as {"resource": {"aws_security_group": {"bad": [{"egress": [{"cidr_blocks": ["0.0.0.0/0"]}]}]}}}
count(result) == 1
}

test_sg_egress_specific_ip_allowed if {
result := deny_insecure_security_group_egress with input as {"resource": {"aws_security_group": {"good": [{"egress": [{"cidr_blocks": ["10.0.0.0/8"]}]}]}}}
count(result) == 0
}

test_sg_without_description_denied if {
result := deny_security_group_without_description with input as {"resource": {"aws_security_group": {"no_desc": [{}]}}}
count(result) == 1
}

test_sg_with_description_allowed if {
result := deny_security_group_without_description with input as {"resource": {"aws_security_group": {"with_desc": [{"description": "Security group"}]}}}
count(result) == 0
}

test_sg_rule_without_description_denied if {
result := deny_security_group_rule_without_description with input as {"resource": {"aws_security_group": {"bad": [{"ingress": [{"description": ""}]}]}}}
count(result) == 1
}

test_sg_rule_with_description_allowed if {
result := deny_security_group_rule_without_description with input as {"resource": {"aws_security_group": {"good": [{"ingress": [{"description": "Allow HTTP"}]}]}}}
count(result) == 0
}