# CMP policy evaluations ======================================================= # Controls : CMP-001, CMP-002, CMP-003, CMP-004, CMP-005, CMP-006, CMP-007, # CMP-008, CMP-009, CMP-011 # # Co-emitted from ekm.rego: # CMP-010 → EKM-006 EBS Default Encryption (enabled flag check) package controls.aws.cmp import data.common.definitions as defs import data.common.exemptions as exemptions import data.common.network as network import data.common.outputs as outputs # CMP-001 — Require IMDSv2 on EC2 Instances ----------------------------------- deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-001", "ICP-TF-AWS-GAC-007"} some _, rc in input.resource_changes rc.type in {"aws_instance", "aws_launch_template"} rc.change.actions[_] in ["create", "update"] not _imdsv2_required(rc.change.after) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("'%s.%s' does not require IMDSv2 (http_tokens != required)", [rc.type, rc.name]), ) } _imdsv2_required(after) if { some opt in after.metadata_options opt.http_tokens == "required" } # CMP-002 — Restrict EC2 Metadata Hop Limit ----------------------------------- deny contains msg if { policy_id := "ICP-TF-AWS-CMP-002" some _, rc in input.resource_changes rc.type in {"aws_instance", "aws_launch_template"} rc.change.actions[_] in ["create", "update"] not _hop_limit_restricted(rc.change.after) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("'%s.%s' metadata hop limit is not set to 1", [rc.type, rc.name]), ) } _hop_limit_restricted(after) if { some opt in after.metadata_options opt.http_put_response_hop_limit == 1 } # CMP-003 — Prohibit Public IPv4 Addresses on EC2 Instances ------------------- deny contains msg if { policy_id := "ICP-TF-AWS-CMP-003" some _, rc in input.resource_changes rc.type == "aws_instance" rc.change.actions[_] in ["create", "update"] rc.change.after.associate_public_ip_address == true meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("EC2 instance '%s' has a public IPv4 address assigned", [rc.name]), ) } # CMP-004 — Prevent Auto-Assignment of Public IPs on Subnets ------------------ deny contains msg if { policy_id := "ICP-TF-AWS-CMP-004" some _, rc in input.resource_changes rc.type == "aws_subnet" rc.change.actions[_] in ["create", "update"] rc.change.after.map_public_ip_on_launch == true meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("Subnet '%s' auto-assigns public IPs on launch", [rc.name]), ) } # CMP-005 — Prohibit Unrestricted SSH Ingress --------------------------------- deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-005", "ICP-TF-AWS-NCD-001", "ICP-TF-AWS-GAC-017"} some _, rc in input.resource_changes rc.type in {"aws_security_group", "aws_vpc_security_group_ingress_rule"} rc.change.actions[_] in ["create", "update"] some rule in network.ingress_rules(rc) network.unrestricted_cidr(rule) network.port_in_range(22, rule) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("'%s.%s' allows unrestricted SSH ingress (port 22) from the internet", [rc.type, rc.name]), ) } # CMP-006 — Prohibit Unrestricted RDP Ingress --------------------------------- deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-006", "ICP-TF-AWS-NCD-002", "ICP-TF-AWS-GAC-018"} some _, rc in input.resource_changes rc.type in {"aws_security_group", "aws_vpc_security_group_ingress_rule"} rc.change.actions[_] in ["create", "update"] some rule in network.ingress_rules(rc) network.unrestricted_cidr(rule) network.port_in_range(3389, rule) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("'%s.%s' allows unrestricted RDP ingress (port 3389) from the internet", [rc.type, rc.name]), ) } # CMP-007 — Restrict Unrestricted Ingress to High-Risk Ports ------------------ deny contains msg if { policy_id := "ICP-TF-AWS-CMP-007" some _, rc in input.resource_changes rc.type in {"aws_security_group", "aws_vpc_security_group_ingress_rule"} rc.change.actions[_] in ["create", "update"] some rule in network.ingress_rules(rc) network.unrestricted_cidr(rule) some port in defs.common_use_ports network.port_in_range(port, rule) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("'%s.%s' allows unrestricted ingress to high-risk port %d from the internet", [rc.type, rc.name, port]), ) } # CMP-008 — Require Empty Default Security Group Rules ------------------------ deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-008", "ICP-TF-AWS-NCD-004", "ICP-TF-AWS-GAC-019"} some _, rc in input.resource_changes rc.type == "aws_default_security_group" rc.change.actions[_] in ["create", "update"] _has_rules(rc.change.after) meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("Default security group '%s' has ingress or egress rules defined", [rc.name]), ) } _has_rules(after) if count(after.ingress) > 0 _has_rules(after) if count(after.egress) > 0 # CMP-009 — Require Encryption on Attached EBS Volumes ------------------------ deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-009", "ICP-TF-AWS-GAC-005"} some _, rc in input.resource_changes rc.type == "aws_ebs_volume" rc.change.actions[_] in ["create", "update"] rc.change.after.encrypted != true meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("EBS volume '%s' is not encrypted", [rc.name]), ) } deny contains msg if { some policy_id in {"ICP-TF-AWS-CMP-009", "ICP-TF-AWS-GAC-005"} some _, rc in input.resource_changes rc.type == "aws_instance" rc.change.actions[_] in ["create", "update"] some dev in rc.change.after.ebs_block_device dev.encrypted != true meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("EBS block device on instance '%s' is not encrypted", [rc.name]), ) } # CMP-011 — Prohibit Privileged ECS Containers -------------------------------- deny contains msg if { policy_id := "ICP-TF-AWS-CMP-011" some _, rc in input.resource_changes rc.type == "aws_ecs_task_definition" rc.change.actions[_] in ["create", "update"] container_defs := json.unmarshal(rc.change.after.container_definitions) some container in container_defs container.privileged == true meta := data.policies[policy_id] meta.status == "active" not exemptions.policy_exemption(policy_id) not exemptions.severity_exemption(meta.severity) msg := outputs.violation( policy_id, meta, sprintf("ECS container '%s' in task '%s' runs in privileged mode", [container.name, rc.name]), ) }