diff --git a/assets/libraries/cloudformation.rego b/assets/libraries/cloudformation.rego index 3cc318f1551..287e5b5444a 100644 --- a/assets/libraries/cloudformation.rego +++ b/assets/libraries/cloudformation.rego @@ -51,23 +51,37 @@ checkAction(currentAction, actionToCompare) { contains(lower(action), actionToCompare) } -# Dictionary of UDP ports -udpPortsMap = { - 53: "DNS", - 137: "NetBIOS Name Service", - 138: "NetBIOS Datagram Service", - 139: "NetBIOS Session Service", - 161: "SNMP", - 389: "LDAP", - 1434: "MSSQL Browser", - 2483: "Oracle DB SSL", - 2484: "Oracle DB SSL", - 5432: "PostgreSQL", - 11211: "Memcached", - 11214: "Memcached SSL", - 11215: "Memcached SSL", +get_ingress_list(resource) = result { + ingress_array_types := ["AWS::EC2::SecurityGroup","AWS::RDS::DBSecurityGroup"] + resource.Type == ingress_array_types[_] + result := resource.Properties[get_field(resource.Type)] +} else = result { + # assumes it is a "AWS::EC2::SecurityGroupIngress" or "AWS::EC2::SecurityGroupEgress" resource + result := [resource.Properties] +} + +get_field("AWS::EC2::SecurityGroup") = "SecurityGroupIngress" +get_field("AWS::RDS::DBSecurityGroup") = "DBSecurityGroupIngress" #legacy + +containsPort(from_port, to_port, port) { + from_port <= port + to_port >= port } +entireNetwork(rule) { + rule.CidrIp == "0.0.0.0/0" +} else { + rule.CidrIpv6 == common_lib.unrestricted_ipv6[_] +} + +getProtocolList(protocol) = list { + protocol == "-1" + list = ["TCP", "UDP"] +} else = list { + common_lib.inArray(["TCP", "UDP"],upper(protocol)) + list = [upper(protocol)] +} else = [] + # Get content of the resource(s) based on the type getResourcesByType(resources, type) = list { list = [resource | resources[i].Type == type; resource := resources[i]] diff --git a/assets/libraries/common.rego b/assets/libraries/common.rego index efcef660dba..3468766a215 100644 --- a/assets/libraries/common.rego +++ b/assets/libraries/common.rego @@ -75,6 +75,9 @@ emptyOrNull("") = true emptyOrNull(null) = true +# List of valid forms for the "::/0" ipv6 address +unrestricted_ipv6 := ["::/0","0000:0000:0000:0000:0000:0000:0000:0000/0","0:0:0:0:0:0:0:0/0"] + # Checks if an IP is private isPrivateIP(ipVal) { private_ips := ["10.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "fc00::/8", "fd00::/8"] diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/query.rego b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/query.rego index 5c676ab3281..14aeff5d676 100644 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/query.rego +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/query.rego @@ -3,68 +3,95 @@ package Cx import data.generic.common as common_lib import data.generic.cloudformation as cf_lib -isAccessibleFromEntireNetwork(ingress) { - endswith(ingress.CidrIp, "/0") -} - -getProtocolList(protocol) = list { - sprintf("%v", [protocol]) == "-1" - list = ["TCP", "UDP"] -} else = list { - upper(protocol) == "TCP" - list = ["TCP"] -} else = list { - upper(protocol) == "UDP" - list = ["UDP"] -} - CxPolicy[result] { - ############# document and resource - resources := input.document[i].Resources + doc := input.document[i] + resources := doc.Resources + + ec2Instance = resources[ec2_instance_name] + ec2Instance.Type == "AWS::EC2::Instance" - ec2InstanceList = [{"name": key, "properties": ec2Instance} | - ec2Instance := resources[key] - ec2Instance.Type == "AWS::EC2::Instance" - ] + sec_group := resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" - ec2Instance := ec2InstanceList[_] + cf_lib.get_name(ec2Instance.Properties.SecurityGroupIds[_]) == sec_group_name + ingresses_with_names := search_for_standalone_ingress(sec_group_name, doc) - securityGroupList = [{"name": key, "properties": secGroup} | - secGroup := resources[key] - secGroup.Type == "AWS::EC2::SecurityGroup" - ] + ingress_list := array.concat(ingresses_with_names.ingress_list, get_inline_ingress_list(sec_group)) + ingress := ingress_list[ing_index] - secGroup := securityGroupList[_] + # check that it is exposed + cidr_fields := {"CidrIp", "CidrIpv6"} + endswith(ingress[cidr_fields[c]], "/0") - ec2Instance.properties.Properties.SecurityGroups[_] == secGroup.name + #check which sensitive port numbers are included + ports := get_sensitive_ports(ingress) - ingress := secGroup.properties.Properties.SecurityGroupIngress[l] + results := get_search_values(ing_index, sec_group_name, ingresses_with_names.names) - protocols := getProtocolList(ingress.IpProtocol) - protocol := protocols[m] - portsMap := { - "TCP": common_lib.tcpPortsMap, - "UDP": cf_lib.udpPortsMap, + result := { + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, + "searchValue": ports[x].searchValue, + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("%s should not be allowed in EC2 security group for instance '%s'", [ports[x].value, ec2_instance_name]), + "keyActualValue": sprintf("%s is allowed in EC2 security group for instance '%s'", [ports[x].value, ec2_instance_name]), + "searchLine": results.searchLine, } +} + +get_sensitive_ports(ingress) = ports { + ingress.IpProtocol == "-1" + ports := [{ + "value" : "ALL PORTS (ALL PROTOCOLS:0-65535)", + "searchValue" : "ALL PROTOCOLS,0-65535" + }] +} else = ports { + portName := common_lib.tcpPortsMap[portNumber] + protocol := upper(ingress.IpProtocol) + protocol == ["TCP", "UDP"][_] + cf_lib.containsPort(ingress.FromPort, ingress.ToPort, portNumber) - ############# Checks - isAccessibleFromEntireNetwork(ingress) + ports := [x | x := { + "value" : sprintf("%s (%s:%d)", [portName, protocol, portNumber]), + "searchValue" : sprintf("%s,%d", [protocol, portNumber]), + }] +} - # is in ports range - portRange := numbers.range(ingress.FromPort, ingress.ToPort) - portNumber := portRange[idx] - portName := portsMap[protocol][portNumber] +search_for_standalone_ingress(sec_group_name, doc) = ingresses_with_names { + resources := doc.Resources - ############# Result - result := { - "documentId": input.document[i].id, - "resourceType": "AWS::EC2::SecurityGroup", - "resourceName": cf_lib.get_resource_name(secGroup.properties, secGroup.name), - "searchKey": sprintf("Resources.%s.SecurityGroupIngress", [secGroup.name]), - "searchValue": sprintf("%s/%s:%d", [ec2Instance.name, protocol, portNumber]), - "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("%s (%s:%d) should not be allowed in EC2 security group for instance %s", [portName, protocol, portNumber, ec2Instance.name]), - "keyActualValue": sprintf("%s (%s:%d) is allowed in EC2 security group for instance %s", [portName, protocol, portNumber, ec2Instance.name]), - "searchLine": common_lib.build_search_line(["Resources", secGroup.name, "Properties", "SecurityGroupIngress", l], []), + names := [name | + ingress := resources[name] + ingress.Type == "AWS::EC2::SecurityGroupIngress" + cf_lib.get_name(ingress.Properties.GroupId) == sec_group_name + ] + + ingresses_with_names := { + "ingress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = { "ingress_list": [], "names": []} + + +get_search_values(ing_index, sec_group_name, names_list) = results { + ing_index < count(names_list) # if ingress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[ing_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[ing_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupIngress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupIngress[%d]", [sec_group_name, ing_index-count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupIngress", ing_index-count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" } } + +get_inline_ingress_list(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupIngress") +} else = group.Properties.SecurityGroupIngress \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative1.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative1.yaml index e31bcae543a..5c0b72dadf0 100644 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative1.yaml @@ -1,29 +1,50 @@ -AWSTemplateFormatVersion: 2010-09-09T00:00:00Z Resources: - SafeSecGroup: + EC2Instance01: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-79fd7eee + InstanceType: t3.medium + SecurityGroupIds: + - !Ref Negative1IPv4_1 + - !Ref Negative1IPv4_2 + - !Ref Negative1ArrayTestIPv4 + KeyName: my-new-rsa-key + + Negative1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: - SecurityGroupEgress: - - IpProtocol: tcp + GroupDescription: "Incorrect protocol: ICMP" + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: "icmp" FromPort: 22 ToPort: 22 - CidrIp: 127.0.0.1/32 - GroupDescription: Allow http and ssh - VpcId: my-vpc + CidrIp: "10.0.0.0/0" + + Negative1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Unknown port: port 5000" + VpcId: !Ref MyVPC SecurityGroupIngress: - - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/32 - IpProtocol: tcp - - ToPort: 77 - CidrIp: 127.0.0.1/32 - IpProtocol: all - FromPort: 77 - MyNegativeEC2Instance: - Type: AWS::EC2::Instance + - IpProtocol: "tcp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "192.168.0.0/0" + + Negative1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup Properties: - SecurityGroups: - - SafeSecGroup - KeyName: my-new-rsa-key - ImageId: ami-79fd7eee - InstanceType: t3.medium + GroupDescription: "Mixed incorrect CIDRs and protocols" + VpcId: !Ref MyVPC + SecurityGroupIngress: + # incorrect cidr (not exposed) + - IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "8.8.0.0/16" + # all fields "incorrect" + - IpProtocol: "icmp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "10.68.0.0/14" diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.json deleted file mode 100644 index 1f235ddbceb..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Resources": { - "SafeSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "FromPort": 80, - "ToPort": 80, - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp" - }, - { - "ToPort": 77, - "CidrIp": "127.0.0.1/32", - "IpProtocol": "all", - "FromPort": 77 - } - ], - "SecurityGroupEgress": [ - { - "FromPort": 22, - "ToPort": 22, - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp" - } - ] - } - }, - "MyNegativeEC2Instance": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "SafeSecGroup" - ], - "KeyName": "my-new-rsa-key", - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.medium" - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.yaml new file mode 100644 index 00000000000..b7da44dfdca --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative2.yaml @@ -0,0 +1,89 @@ +Resources: + EC2Instance01: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-79fd7eee + InstanceType: t3.medium + SecurityGroupIds: + - !Ref Negative2SecurityGroup + KeyName: my-new-rsa-key + + Negative2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for negative test cases" + VpcId: !Ref MyVPC + +# IPv4 Rules + Negative2IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "icmp" # incorrect protocol + FromPort: 22 + ToPort: 22 + CidrIp: "10.0.0.0/0" + + Negative2IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # unknown port + ToPort: 5000 + CidrIp: "192.168.0.0/0" + + Negative2IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "8.8.0.0/16" # incorrect cidr (not exposed) + + Negative2IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "icmp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "8.8.0.0/16" + +# IPv6 Rules + Negative2IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "58" # protocol number 58 is "icmpv6" = incorrect protocol + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00::/0" + + Negative2IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # unknown port + ToPort: 5000 + CidrIpv6: "fd12:3456:789a::1/0" + + Negative2IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "2400:cb00::/32" # incorrect cidr (not exposed) + + Negative2IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "58" # ICMPv6 + FromPort: 5000 + ToPort: 5000 + CidrIpv6: "2400:cb00::/32" diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative3.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative3.json new file mode 100644 index 00000000000..710bf5bd410 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative3.json @@ -0,0 +1,69 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "EC2Instance01": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "ami-79fd7eee", + "InstanceType": "t3.medium", + "SecurityGroupIds": [ + { "Ref": "Negative1IPv4_1" }, + { "Ref": "Negative1IPv4_2" }, + { "Ref": "Negative1ArrayTestIPv4" } + ], + "KeyName": "my-new-rsa-key" + } + }, + "Negative1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Incorrect protocol: ICMP", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "icmp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + ] + } + }, + "Negative1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Unknown port: port 5000", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "192.168.0.0/0" + } + ] + } + }, + "Negative1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Mixed incorrect CIDRs and protocols", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "8.8.0.0/16" + }, + { + "IpProtocol": "icmp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "10.68.0.0/14" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative4.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative4.json new file mode 100644 index 00000000000..a821e4e5b95 --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/negative4.json @@ -0,0 +1,103 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "EC2Instance01": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "ami-79fd7eee", + "InstanceType": "t3.medium", + "SecurityGroupIds": [ + { "Ref": "Negative2SecurityGroup" } + ], + "KeyName": "my-new-rsa-key" + } + }, + "Negative2SecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for negative test cases", + "VpcId": { "Ref": "MyVPC" } + } + }, + "Negative2IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "icmp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + }, + "Negative2IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "192.168.0.0/0" + } + }, + "Negative2IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "icmp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "58", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00::/0" + } + }, + "Negative2IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "fd12:3456:789a::1/0" + } + }, + "Negative2IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "2400:cb00::/32" + } + }, + "Negative2IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "58", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "2400:cb00::/32" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive1.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive1.yaml index 55d7868218f..11efef4b2de 100644 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive1.yaml @@ -1,29 +1,49 @@ -AWSTemplateFormatVersion: 2010-09-09T00:00:00Z Resources: - UnsafeSecGroup01: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http and redis - VpcId: my-vpc - SecurityGroupIngress: - - FromPort: 8080 - ToPort: 8080 - CidrIp: 127.0.0.1/32 - IpProtocol: tcp - - IpProtocol: tcp - FromPort: 6379 - ToPort: 6379 - CidrIp: 10.0.0.1/0 - SecurityGroupEgress: - - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - IpProtocol: tcp EC2Instance01: Type: AWS::EC2::Instance Properties: ImageId: ami-79fd7eee InstanceType: t3.medium - SecurityGroups: - - UnsafeSecGroup01 + SecurityGroupIds: + - !Ref Positive1IPv4_1 + - !Ref Positive1IPv4_2 + - !Ref Positive1ArrayTestIPv4 KeyName: my-new-rsa-key + + Positive1IPv4_1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Allow all protocols on port 22 from 10.0.0.0/0" + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 22 + ToPort: 22 + CidrIp: "10.0.0.0/0" + + Positive1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Allow TCP on port 22 from 192.168.0.0/0" + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIp: "192.168.0.0/0" + + Positive1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Allow UDP on ports 22 and 110 from multiple CIDRs" + SecurityGroupIngress: + - IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "172.16.0.0/0" + - IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "10.68.0.0" + - IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "172.16.0.0/0" diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive2.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive2.yaml index 22978904fd5..256d1f5c96d 100644 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive2.yaml +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive2.yaml @@ -1,33 +1,89 @@ -AWSTemplateFormatVersion: 2010-09-09T00:00:00Z Resources: - UnsafeSecGroup02: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http and mysql - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/32 - - ToPort: 1434 - CidrIp: 10.0.0.1/0 - IpProtocol: tcp - FromPort: 1433 - - IpProtocol: tcp - FromPort: 150 - ToPort: 180 - CidrIp: 10.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EC2Instance02: + EC2Instance01: Type: AWS::EC2::Instance Properties: + ImageId: ami-79fd7eee InstanceType: t3.medium - SecurityGroups: - - UnsafeSecGroup02 + SecurityGroupIds: + - !Ref DualStackSecurityGroup KeyName: my-new-rsa-key - ImageId: ami-79fd7eee + + DualStackSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for IPv4 and IPv6 ingress rules" + VpcId: !Ref MyVPC + +# IPv4 Rules + IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 22 + ToPort: 22 + CidrIp: "10.0.0.0/0" + + IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIp: "192.168.0.0/0" + + IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "172.16.0.0/0" + + IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "172.16.0.0/0" + +# IPv6 Rules + IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00::/0" + + IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd12:3456:789a::1/0" + + IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00:abcd:1234::42/0" + + IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIpv6: "fd00:abcd:1234::42/0" diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.json new file mode 100644 index 00000000000..2e2045085ce --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.json @@ -0,0 +1,72 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "EC2Instance01": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "ami-79fd7eee", + "InstanceType": "t3.medium", + "SecurityGroupIds": [ + { "Ref": "Positive1IPv4_1" }, + { "Ref": "Positive1IPv4_2" }, + { "Ref": "Positive1ArrayTestIPv4" } + ], + "KeyName": "my-new-rsa-key" + } + }, + "Positive1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow all protocols on port 22 from 10.0.0.0/0", + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + ] + } + }, + "Positive1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow TCP on port 22 from 192.168.0.0/0", + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "192.168.0.0/0" + } + ] + } + }, + "Positive1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow UDP on ports 22 and 110 from multiple CIDRs", + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "172.16.0.0/0" + }, + { + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "10.68.0.0/16" + }, + { + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "172.16.0.0/0" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.yaml deleted file mode 100644 index e9febf914e4..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive3.yaml +++ /dev/null @@ -1,29 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09T00:00:00Z -Resources: - UnsafeSecGroup03: - Type: AWS::EC2::SecurityGroup - Properties: - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - GroupDescription: Allow http and hadoop - VpcId: my-vpc - SecurityGroupIngress: - - ToPort: 80 - CidrIp: 0.0.0.0/0 - IpProtocol: tcp - FromPort: 80 - - ToPort: 9000 - CidrIp: 10.0.0.1/0 - IpProtocol: tcp - FromPort: 9000 - EC2Instance03: - Type: AWS::EC2::Instance - Properties: - SecurityGroups: - - UnsafeSecGroup03 - KeyName: my-new-rsa-key - ImageId: ami-79fd7eee - InstanceType: t3.medium diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.json new file mode 100644 index 00000000000..24f9680390f --- /dev/null +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.json @@ -0,0 +1,103 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "EC2Instance01": { + "Type": "AWS::EC2::Instance", + "Properties": { + "ImageId": "ami-79fd7eee", + "InstanceType": "t3.medium", + "SecurityGroupIds": [ + { "Ref": "DualStackSecurityGroup" } + ], + "KeyName": "my-new-rsa-key" + } + }, + "DualStackSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for IPv4 and IPv6 ingress rules", + "VpcId": { "Ref": "MyVPC" } + } + }, + "IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + }, + "IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "192.168.0.0/0" + } + }, + "IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "172.16.0.0/0" + } + }, + "IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "172.16.0.0/0" + } + }, + "IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00::/0" + } + }, + "IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd12:3456:789a::1/0" + } + }, + "IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00:abcd:1234::42/0" + } + }, + "IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIpv6": "fd00:abcd:1234::42/0" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.yaml b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.yaml deleted file mode 100644 index ec4114cc01a..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive4.yaml +++ /dev/null @@ -1,33 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09T00:00:00Z -Resources: - UnsafeSecGroup04: - Type: AWS::EC2::SecurityGroup - Properties: - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - GroupDescription: Allow LDAP and SNMP - VpcId: my-vpc - SecurityGroupIngress: - - ToPort: 389 - FromPort: 389 - IpProtocol: "-1" - CidrIp: 10.0.0.0/0 - - ToPort: 150 - FromPort: 180 - IpProtocol: udp - CidrIp: 10.0.0.1/0 - - ToPort: 53 - FromPort: 53 - IpProtocol: "-1" - CidrIp: 10.0.0.1/0 - EC2Instance03: - Type: AWS::EC2::Instance - Properties: - SecurityGroups: - - UnsafeSecGroup04 - KeyName: my-new-rsa-key - ImageId: ami-79fd7eee - InstanceType: t3.medium diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive5.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive5.json deleted file mode 100644 index ea745d55676..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive5.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Resources": { - "UnsafeSecGroup01": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "SecurityGroupEgress": [ - { - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp" - } - ], - "GroupDescription": "Allow http and redis", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "FromPort": 8080, - "ToPort": 8080, - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp" - }, - { - "IpProtocol": "tcp", - "FromPort": 6379, - "ToPort": 6379, - "CidrIp": "10.0.0.1/0" - } - ] - } - }, - "EC2Instance01": { - "Type": "AWS::EC2::Instance", - "Properties": { - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.medium", - "SecurityGroups": [ - "UnsafeSecGroup01" - ], - "KeyName": "my-new-rsa-key" - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive6.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive6.json deleted file mode 100644 index 5301f4e773f..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive6.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Resources": { - "UnsafeSecGroup02": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and mysql", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "127.0.0.1/32" - }, - { - "CidrIp": "10.0.0.1/0", - "IpProtocol": "tcp", - "FromPort": 1433, - "ToPort": 1434 - }, - { - "IpProtocol": "tcp", - "FromPort": 150, - "ToPort": 180, - "CidrIp": "10.0.0.1/0" - } - ], - "SecurityGroupEgress": [ - { - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp" - } - ] - } - }, - "EC2Instance02": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "UnsafeSecGroup02" - ], - "KeyName": "my-new-rsa-key", - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.medium" - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive7.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive7.json deleted file mode 100644 index 575b1b41eb3..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive7.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "Resources": { - "UnsafeSecGroup03": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - } - ], - "GroupDescription": "Allow http and hadoop", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "FromPort": 80, - "ToPort": 80, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp" - }, - { - "ToPort": 9000, - "CidrIp": "10.0.0.1/0", - "IpProtocol": "tcp", - "FromPort": 9000 - } - ] - } - }, - "EC2Instance03": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "UnsafeSecGroup03" - ], - "KeyName": "my-new-rsa-key", - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.medium" - } - } - }, - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z" -} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive8.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive8.json deleted file mode 100644 index 783ebb64e31..00000000000 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive8.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "Resources": { - "UnsafeSecGroup04": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - } - ], - "GroupDescription": "Allow LDAP and SNMP", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "CidrIp": "10.0.0.0/0", - "ToPort": 389, - "FromPort": 389, - "IpProtocol": "-1" - }, - { - "FromPort": 180, - "IpProtocol": "udp", - "CidrIp": "10.0.0.1/0", - "ToPort": 150 - }, - { - "IpProtocol": "-1", - "CidrIp": "10.0.0.1/0", - "ToPort": 53, - "FromPort": 53 - } - ] - } - }, - "EC2Instance03": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "UnsafeSecGroup04" - ], - "KeyName": "my-new-rsa-key", - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.medium" - } - } - }, - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z" -} diff --git a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive_expected_result.json index e1393e7868a..d3faf52b8e8 100644 --- a/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/ec2_sensitive_port_is_publicly_exposed/test/positive_expected_result.json @@ -2,133 +2,145 @@ { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 13, + "line": 18, "fileName": "positive1.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 13, - "fileName": "positive2.yaml" + "line": 28, + "fileName": "positive1.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 13, + "line": 38, + "fileName": "positive1.yaml" + }, + { + "queryName": "EC2 Sensitive Port Is Publicly Exposed", + "severity": "HIGH", + "line": 46, + "fileName": "positive1.yaml" + }, + { + "queryName": "EC2 Sensitive Port Is Publicly Exposed", + "severity": "HIGH", + "line": 20, "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 17, + "line": 29, "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 14, - "fileName": "positive3.yaml" + "line": 38, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 18, - "fileName": "positive3.yaml" + "line": 47, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 14, - "fileName": "positive4.yaml" + "line": 57, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 14, - "fileName": "positive4.yaml" + "line": 66, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 18, - "fileName": "positive4.yaml" + "line": 75, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 22, - "fileName": "positive4.yaml" + "line": 84, + "fileName": "positive2.yaml" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 22, - "fileName": "positive4.yaml" + "line": 23, + "fileName": "positive3.json" }, { - "line": 25, - "fileName": "positive5.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", - "severity": "HIGH" + "severity": "HIGH", + "line": 37, + "fileName": "positive3.json" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 17, - "fileName": "positive6.json" + "line": 51, + "fileName": "positive3.json" }, { - "line": 17, - "fileName": "positive6.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", - "severity": "HIGH" + "severity": "HIGH", + "line": 63, + "fileName": "positive3.json" }, { - "line": 23, - "fileName": "positive6.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", - "severity": "HIGH" + "severity": "HIGH", + "line": 24, + "fileName": "positive4.json" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 18, - "fileName": "positive7.json" + "line": 34, + "fileName": "positive4.json" }, { "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 24, - "fileName": "positive7.json" + "line": 44, + "fileName": "positive4.json" }, { + "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 18, - "fileName": "positive8.json", - "queryName": "EC2 Sensitive Port Is Publicly Exposed" + "line": 54, + "fileName": "positive4.json" }, { - "fileName": "positive8.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 18 + "line": 64, + "fileName": "positive4.json" }, { + "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 24, - "fileName": "positive8.json", - "queryName": "EC2 Sensitive Port Is Publicly Exposed" + "line": 74, + "fileName": "positive4.json" }, { - "fileName": "positive8.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", "severity": "HIGH", - "line": 30 + "line": 84, + "fileName": "positive4.json" }, { - "line": 30, - "fileName": "positive8.json", "queryName": "EC2 Sensitive Port Is Publicly Exposed", - "severity": "HIGH" + "severity": "HIGH", + "line": 94, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/query.rego b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/query.rego index 370078c9508..fd20a3027c7 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/query.rego +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/query.rego @@ -3,96 +3,97 @@ package Cx import data.generic.cloudformation as cf_lib import data.generic.common as common_lib -isAccessibleFromEntireNetwork(ingress) { - endswith(ingress.CidrIp, "/0") -} +CxPolicy[result] { + doc := input.document[i] + resources := doc.Resources -getProtocolList(protocol) = list { - upper(protocol) == ["-1", "ALL"][_] - list = ["TCP", "UDP"] -} else = list { - upper(protocol) == "TCP" - list = ["TCP"] -} else = list { - upper(protocol) == "UDP" - list = ["UDP"] -} + elbInstance = resources[elb_instance_name] + elbType := getELBType(elbInstance.Type) -getProtocolPorts(protocols, tcpPortsMap, udpPortsMap) = portsMap { - protocols[_] == ["-1", "ALL"][_] - portsMap = object.union(tcpPortsMap, udpPortsMap) -} else = portsMap { - protocols[_] == "UDP" - portsMap = udpPortsMap -} else = portsMap { - protocols[_] == "TCP" - portsMap = tcpPortsMap -} + sec_group := resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" -getELBType(elb) = type { - common_lib.valid_key(elb.Properties, "Type") - type = elb.Properties.Type -} else = type { - elb.Type == "AWS::ElasticLoadBalancing::LoadBalancer" - type = "classic" -} else = type { - elb.Type == "AWS::ElasticLoadBalancingV2::LoadBalancer" - type = "application" -} + cf_lib.get_name(elbInstance.Properties.SecurityGroups[_]) == sec_group_name + ingresses_with_names := search_for_standalone_ingress(sec_group_name, doc) -getLinkedSecGroupList(elb, resources) = elbSecGroupName { - common_lib.valid_key(elb.Properties, "SecurityGroups") - elbSecGroupName = elb.Properties.SecurityGroups -} else = ec2SecGroup { - ec2InstanceList := [ec2 | ec2 := resources[name]; contains(upper(ec2.Type), "INSTANCE")] - ec2Instance := ec2InstanceList[i] - common_lib.valid_key(ec2Instance.Properties, "SecurityGroups") - ec2SecGroup = ec2Instance.Properties.SecurityGroups -} + ingress_list := array.concat(ingresses_with_names.ingress_list, get_inline_ingress_list(sec_group)) + ingress := ingress_list[ing_index] + + # check that it is exposed + cidr_fields := {"CidrIp", "CidrIpv6"} + endswith(ingress[cidr_fields[c]], "/0") + + #check which sensitive port numbers are included + ports := get_sensitive_ports(ingress) + + results := get_search_values(ing_index, sec_group_name, ingresses_with_names.names) -CxPolicy[result] { - ############# document and resource - resources := input.document[i].Resources - loadBalancerList := [{"name": key, "properties": loadBalancer} | - loadBalancer := resources[key] - contains(loadBalancer.Type, "ElasticLoadBalancing") - ] - - elb := loadBalancerList[j] - elbType := getELBType(elb.properties) - elbSecGroupList := getLinkedSecGroupList(elb.properties, resources) - - securityGroupList = [{"name": key, "properties": secGroup} | - secGroup := resources[key] - contains(secGroup.Type, "SecurityGroup") - ] - - secGroup := securityGroupList[k] - secGroup.name == elbSecGroupList[l] - ingress := secGroup.properties.Properties.SecurityGroupIngress[m] - - protocols := getProtocolList(ingress.IpProtocol) - protocol := protocols[n] - portsMap = getProtocolPorts(protocols, common_lib.tcpPortsMap, cf_lib.udpPortsMap) - - ############# Checks - isAccessibleFromEntireNetwork(ingress) - - # is in ports range - portRange := numbers.range(ingress.FromPort, ingress.ToPort) - portsMap[portRange[idx]] - portNumber = portRange[idx] - portName := portsMap[portNumber] - - ############## Result result := { - "documentId": input.document[i].id, - "resourceType": secGroup.properties.Type, - "resourceName": cf_lib.get_resource_name(secGroup.properties, secGroup.name), - "searchKey": sprintf("Resources.%s.SecurityGroupIngress", [secGroup.name]), - "searchValue": sprintf("%s,%d", [protocol, portNumber]), + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, + "searchValue": ports[x].searchValue, "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("%s (%s:%d) should not be allowed in %s load balancer %s", [portName, protocol, portNumber, elbType, elb.name]), - "keyActualValue": sprintf("%s (%s:%d) is allowed in %v load balancer %s", [portName, protocol, portNumber, elbType, elb.name]), + "keyExpectedValue": sprintf("%s should not be allowed in %s load balancer '%s'", [ports[x].value, elbType, elb_instance_name]), + "keyActualValue": sprintf("%s is allowed in %v load balancer '%s'", [ports[x].value, elbType, elb_instance_name]), + "searchLine": results.searchLine, } } + +get_sensitive_ports(ingress) = ports { + ingress.IpProtocol == "-1" + ports := [{ + "value" : "ALL PORTS (ALL PROTOCOLS:0-65535)", + "searchValue" : "ALL PROTOCOLS,0-65535" + }] +} else = ports { + portName := common_lib.tcpPortsMap[portNumber] + protocol := upper(ingress.IpProtocol) + protocol == ["TCP", "UDP"][_] + cf_lib.containsPort(ingress.FromPort, ingress.ToPort, portNumber) + + ports := [x | x := { + "value" : sprintf("%s (%s:%d)", [portName, protocol, portNumber]), + "searchValue" : sprintf("%s,%d", [protocol, portNumber]), + }] +} + +search_for_standalone_ingress(sec_group_name, doc) = ingresses_with_names { + resources := doc.Resources + + names := [name | + ingress := resources[name] + ingress.Type == "AWS::EC2::SecurityGroupIngress" + cf_lib.get_name(ingress.Properties.GroupId) == sec_group_name + ] + + ingresses_with_names := { + "ingress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = { "ingress_list": [], "names": []} + +get_search_values(ing_index, sec_group_name, names_list) = results { + ing_index < count(names_list) # if ingress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[ing_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[ing_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupIngress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupIngress[%d]", [sec_group_name, ing_index-count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupIngress", ing_index-count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" + } +} + +getELBType("AWS::ElasticLoadBalancing::LoadBalancer") = "classic" +getELBType("AWS::ElasticLoadBalancingV2::LoadBalancer") = "application" + +get_inline_ingress_list(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupIngress") +} else = group.Properties.SecurityGroupIngress diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative1.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative1.yaml index cf023a77e3a..c782207ff0f 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative1.yaml @@ -1,50 +1,51 @@ -AWSTemplateFormatVersion: 2010-09-09 Resources: - MyLoadBalancer: - Type: AWS::ElasticLoadBalancing::LoadBalancer - Properties: - AvailabilityZones: - - "us-east-2a" - CrossZone: true - Scheme: internet-facing - Listeners: - - InstancePort: '80' - InstanceProtocol: HTTP - LoadBalancerPort: '443' - Protocol: HTTPS - PolicyNames: - - My-SSLNegotiation-Policy - SSLCertificateId: arn:aws:iam::123456789012:server-certificate/my-server-certificate - HealthCheck: - Target: HTTP:80/ - HealthyThreshold: '2' - UnhealthyThreshold: '3' - Interval: '10' - Timeout: '5' - SecurityGroups: - [ !Ref LBNegativeSecGroup01 ] - Policies: - - PolicyName: My-SSLNegotiation-Policy - PolicyType: SSLNegotiationPolicyType - Attributes: - - Name: Reference-Security-Policy - Value: ELBSecurityPolicy-TLS-1-2-2017-01 - LBNegativeSecGroup01: + LoadBalancer01: + Type: AWS::ElasticLoadBalancing::LoadBalancer + Properties: + Listeners: + - LoadBalancerPort: 80 + InstancePort: 80 + Protocol: HTTP + SecurityGroups: + - !Ref Negative1IPv4_1 + - !Ref Negative1IPv4_2 + - !Ref Negative1ArrayTestIPv4 + + Negative1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp + GroupDescription: "Incorrect protocol: ICMP" + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: "icmp" FromPort: 22 ToPort: 22 - CidrIp: 127.0.0.1/32 - SecurityGroupEgress: - - IpProtocol: tcp + CidrIp: "10.0.0.0/0" + + Negative1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Unknown port: port 5000" + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "192.168.0.0/0" + + Negative1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Mixed incorrect CIDRs and protocols" + VpcId: !Ref MyVPC + SecurityGroupIngress: + # incorrect cidr (not exposed) + - IpProtocol: "udp" FromPort: 22 ToPort: 22 - CidrIp: 0.0.0.0/0 + CidrIp: "8.8.0.0/16" + # all fields "incorrect" + - IpProtocol: "icmp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "10.68.0.0/14" diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative2.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative2.yaml index 795c67a2739..0e02b7e5a4e 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative2.yaml +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative2.yaml @@ -1,78 +1,90 @@ -AWSTemplateFormatVersion: 2010-09-09 -Parameters: - MySubnets: - Description: "My subnet" - Type: List Resources: - ApplicationLoadBalancer: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer + LoadBalancer01: + Type: AWS::ElasticLoadBalancing::LoadBalancer Properties: - Name: ip-target-alb - Subnets: !Ref MySubnets + Listeners: + - LoadBalancerPort: 80 + InstancePort: 80 + Protocol: HTTP SecurityGroups: - - !Ref ALBNegativeSecGroup - Tags: - - Key: Name - Value: ip-target-alb - ALBNegativeSecGroup: + - !Ref Negative2SecurityGroup + + Negative2SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp - FromPort: 77 - ToPort: 77 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - HTTPALBListener: - Type: AWS::ElasticLoadBalancingV2::Listener + GroupDescription: "Security group for negative test cases" + VpcId: !Ref MyVPC + +# IPv4 Rules + Negative2IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress Properties: - LoadBalancerArn: !Ref ApplicationLoadBalancer - Port: 80 - Protocol: HTTP - DefaultActions: - - Type: forward - TargetGroupArn: !Ref IPTargetGroup - IPTargetGroup: - Type: AWS::ElasticLoadBalancingV2::TargetGroup + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "icmp" # incorrect protocol + FromPort: 22 + ToPort: 22 + CidrIp: "10.0.0.0/0" + + Negative2IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress Properties: - VpcId: my-vpc - Port: 80 - Protocol: HTTP - TargetType: ip - Matcher: - HttpCode: '200' - HealthCheckIntervalSeconds: 10 - HealthCheckPath: /health/check - HealthCheckProtocol: HTTP - HealthCheckTimeoutSeconds: 5 - HealthyThresholdCount: 2 - UnhealthyThresholdCount: 2 - TestListenerRule1: - Type: "AWS::ElasticLoadBalancingV2::ListenerRule" + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # unknown port + ToPort: 5000 + CidrIp: "192.168.0.0/0" + + Negative2IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress Properties: - Priority: 1 - ListenerArn: !Ref HTTPALBListener - Conditions: - - Field: "host-header" - Values: - - "test1.checkmarx.com" - Actions: - - Type: "forward" - TargetGroupArn: !Ref IPTargetGroup - Order: 1 - ForwardConfig: - TargetGroups: - - TargetGroupArn: !Ref IPTargetGroup - Weight: 1 - TargetGroupStickinessConfig: - Enabled: false + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "8.8.0.0/16" # incorrect cidr (not exposed) + + Negative2IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "icmp" + FromPort: 5000 + ToPort: 5000 + CidrIp: "8.8.0.0/16" + +# IPv6 Rules + Negative2IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "58" # protocol number 58 is "icmpv6" = incorrect protocol + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00::/0" + + Negative2IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # unknown port + ToPort: 5000 + CidrIpv6: "fd12:3456:789a::1/0" + + Negative2IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "2400:cb00::/32" # incorrect cidr (not exposed) + + Negative2IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "58" # ICMPv6 + FromPort: 5000 + ToPort: 5000 + CidrIpv6: "2400:cb00::/32" diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.json new file mode 100644 index 00000000000..0fe763a03cf --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.json @@ -0,0 +1,73 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "LoadBalancer01": { + "Type": "AWS::ElasticLoadBalancing::LoadBalancer", + "Properties": { + "Listeners": [ + { + "LoadBalancerPort": 80, + "InstancePort": 80, + "Protocol": "HTTP" + } + ], + "SecurityGroups": [ + { "Ref": "Negative1IPv4_1" }, + { "Ref": "Negative1IPv4_2" }, + { "Ref": "Negative1ArrayTestIPv4" } + ] + } + }, + "Negative1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Incorrect protocol: ICMP", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "icmp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + ] + } + }, + "Negative1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Unknown port: port 5000", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "192.168.0.0/0" + } + ] + } + }, + "Negative1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Mixed incorrect CIDRs and protocols", + "VpcId": { "Ref": "MyVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "8.8.0.0/16" + }, + { + "IpProtocol": "icmp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "10.68.0.0/14" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.yaml deleted file mode 100644 index 425f2e71eef..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative3.yaml +++ /dev/null @@ -1,82 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Parameters: - MySubnet: - Description: "My subnet" - Type: List -Resources: - NetworkLoadBalancer: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: t10-networkloadbalancer - Scheme: internet-facing - Subnets: !Ref MySubnet - Type: network - Tags: - - Key: Name - Value: t10-networklb - InstancesNegativeSecGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp - FromPort: 77 - ToPort: 77 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EC2Instance01: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: [!Ref 'InstancesNegativeSecGroup'] - KeyName: my-rsa-key - ImageId: ami-79fd7eee - EC2Instance02: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: [!Ref 'InstancesNegativeSecGroup'] - KeyName: my-rsa-key - ImageId: ami-79fd7eee - NetworkLoadBalancerTargetGroup: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - Name: t10-networklb-target - Port: 443 - Protocol: TCP - VpcId: t10-vpc-id - TargetGroupAttributes: - - Key: deregistration_delay.timeout_seconds - Value: 60 - Targets: - - Id: !Ref EC2Instance01 - Port: 443 - - Id: !Ref EC2Instance02 - Port: 443 - Tags: - - Key: Name - Value: t10-networklb-target - NetworkLoadBalancerListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup - LoadBalancerArn: !Ref NetworkLoadBalancer - Port: 443 - Protocol: TCP - NetworkLoadBalancerListenerCert: - Type: AWS::ElasticLoadBalancingV2::ListenerCertificate - Properties: - Certificates: - - CertificateArn: arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456.... - ListenerArn: !Ref NetworkLoadBalancerListener diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative4.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative4.json index 72f46f46621..b6c701658d2 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative4.json +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative4.json @@ -1,78 +1,107 @@ { - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "AWSTemplateFormatVersion": "2010-09-09", "Resources": { - "MyLoadBalancer": { + "LoadBalancer01": { "Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": { - "HealthCheck": { - "UnhealthyThreshold": "3", - "Interval": "10", - "Timeout": "5", - "Target": "HTTP:80/", - "HealthyThreshold": "2" - }, - "SecurityGroups": [ - "LBNegativeSecGroup01" - ], - "Policies": [ - { - "PolicyType": "SSLNegotiationPolicyType", - "Attributes": [ - { - "Name": "Reference-Security-Policy", - "Value": "ELBSecurityPolicy-TLS-1-2-2017-01" - } - ], - "PolicyName": "My-SSLNegotiation-Policy" - } - ], - "AvailabilityZones": [ - "us-east-2a" - ], - "CrossZone": true, - "Scheme": "internet-facing", "Listeners": [ { - "LoadBalancerPort": "443", - "Protocol": "HTTPS", - "PolicyNames": [ - "My-SSLNegotiation-Policy" - ], - "SSLCertificateId": "arn:aws:iam::123456789012:server-certificate/my-server-certificate", - "InstancePort": "80", - "InstanceProtocol": "HTTP" + "LoadBalancerPort": 80, + "InstancePort": 80, + "Protocol": "HTTP" } + ], + "SecurityGroups": [ + { "Ref": "Negative2SecurityGroup" } ] } }, - "LBNegativeSecGroup01": { + "Negative2SecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "127.0.0.1/32" - }, - { - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "127.0.0.1/32" - } - ], - "SecurityGroupEgress": [ - { - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0" - } - ] - }, - "Type": "AWS::EC2::SecurityGroup" + "GroupDescription": "Security group for negative test cases", + "VpcId": { "Ref": "MyVPC" } + } + }, + "Negative2IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "icmp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + }, + "Negative2IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "192.168.0.0/0" + } + }, + "Negative2IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "icmp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "58", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00::/0" + } + }, + "Negative2IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "fd12:3456:789a::1/0" + } + }, + "Negative2IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "2400:cb00::/32" + } + }, + "Negative2IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "Negative2SecurityGroup" }, + "IpProtocol": "58", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "2400:cb00::/32" + } } } } diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative5.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative5.json deleted file mode 100644 index 4127161ee8e..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative5.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Parameters": { - "MySubnets": { - "Description": "My subnet", - "Type": "List\u003cString\u003e" - } - }, - "Resources": { - "IPTargetGroup": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "VpcId": "my-vpc", - "Protocol": "HTTP", - "HealthCheckIntervalSeconds": 10, - "UnhealthyThresholdCount": 2, - "Port": 80, - "TargetType": "ip", - "Matcher": { - "HttpCode": "200" - }, - "HealthCheckPath": "/health/check", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 2 - } - }, - "TestListenerRule1": { - "Properties": { - "Priority": 1, - "ListenerArn": "HTTPALBListener", - "Conditions": [ - { - "Field": "host-header", - "Values": [ - "test1.checkmarx.com" - ] - } - ], - "Actions": [ - { - "TargetGroupArn": "IPTargetGroup", - "Order": 1, - "ForwardConfig": { - "TargetGroups": [ - { - "TargetGroupArn": "IPTargetGroup", - "Weight": 1 - } - ], - "TargetGroupStickinessConfig": { - "Enabled": false - } - }, - "Type": "forward" - } - ] - }, - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule" - }, - "ApplicationLoadBalancer": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "Name": "ip-target-alb", - "Subnets": "MySubnets", - "SecurityGroups": [ - "ALBNegativeSecGroup" - ], - "Tags": [ - { - "Key": "Name", - "Value": "ip-target-alb" - } - ] - } - }, - "ALBNegativeSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "127.0.0.1/32" - }, - { - "IpProtocol": "tcp", - "FromPort": 77, - "ToPort": 77, - "CidrIp": "127.0.0.1/0" - } - ], - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - } - ] - } - }, - "HTTPALBListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "LoadBalancerArn": "ApplicationLoadBalancer", - "Port": 80, - "Protocol": "HTTP", - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "IPTargetGroup" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative6.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative6.json deleted file mode 100644 index e9538989f51..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/negative6.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Parameters": { - "MySubnet": { - "Type": "List\u003cString\u003e", - "Description": "My subnet" - } - }, - "Resources": { - "InstancesNegativeSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - }, - { - "IpProtocol": "tcp", - "FromPort": 77, - "ToPort": 77, - "CidrIp": "127.0.0.1/0" - } - ], - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - } - ] - } - }, - "EC2Instance01": { - "Type": "AWS::EC2::Instance", - "Properties": { - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "InstancesNegativeSecGroup" - ], - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee" - } - }, - "EC2Instance02": { - "Type": "AWS::EC2::Instance", - "Properties": { - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "InstancesNegativeSecGroup" - ], - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee" - } - }, - "NetworkLoadBalancerTargetGroup": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "Name": "t10-networklb-target", - "Port": 443, - "Protocol": "TCP", - "VpcId": "t10-vpc-id", - "TargetGroupAttributes": [ - { - "Value": 60, - "Key": "deregistration_delay.timeout_seconds" - } - ], - "Targets": [ - { - "Id": "EC2Instance01", - "Port": 443 - }, - { - "Id": "EC2Instance02", - "Port": 443 - } - ], - "Tags": [ - { - "Key": "Name", - "Value": "t10-networklb-target" - } - ] - } - }, - "NetworkLoadBalancerListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "NetworkLoadBalancerTargetGroup" - } - ], - "LoadBalancerArn": "NetworkLoadBalancer", - "Port": 443, - "Protocol": "TCP" - } - }, - "NetworkLoadBalancerListenerCert": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate", - "Properties": { - "Certificates": [ - { - "CertificateArn": "arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456...." - } - ], - "ListenerArn": "NetworkLoadBalancerListener" - } - }, - "NetworkLoadBalancer": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "Name": "t10-networkloadbalancer", - "Scheme": "internet-facing", - "Subnets": "MySubnet", - "Type": "network", - "Tags": [ - { - "Key": "Name", - "Value": "t10-networklb" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive1.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive1.yaml index 02e1078ac69..ff9e5f6d7fd 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive1.yaml @@ -1,50 +1,50 @@ -AWSTemplateFormatVersion: 2010-09-09 Resources: - MyLoadBalancer: - Type: AWS::ElasticLoadBalancing::LoadBalancer - Properties: - AvailabilityZones: - - "us-east-2a" - CrossZone: true - Scheme: internet-facing - Listeners: - - InstancePort: '80' - InstanceProtocol: HTTP - LoadBalancerPort: '443' - Protocol: HTTPS - PolicyNames: - - My-SSLNegotiation-Policy - SSLCertificateId: arn:aws:iam::123456789012:server-certificate/my-server-certificate - HealthCheck: - Target: HTTP:80/ - HealthyThreshold: '2' - UnhealthyThreshold: '3' - Interval: '10' - Timeout: '5' - SecurityGroups: - - !Ref LBSecGroup - Policies: - - PolicyName: My-SSLNegotiation-Policy - PolicyType: SSLNegotiationPolicyType - Attributes: - - Name: Reference-Security-Policy - Value: ELBSecurityPolicy-TLS-1-2-2017-01 - LBSecGroup: + LoadBalancer01: + Type: AWS::ElasticLoadBalancing::LoadBalancer + Properties: + Listeners: + - LoadBalancerPort: 80 + InstancePort: 80 + Protocol: HTTP + SecurityGroups: + - !Ref Positive1IPv4_1 + - !Ref Positive1IPv4_2 + - !Ref Positive1ArrayTestIPv4 + + Positive1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 50 - ToPort: 80 - CidrIp: 127.0.0.1/0 - - IpProtocol: tcp + GroupDescription: "Allow all protocols on port 22 from 10.0.0.0/0" + SecurityGroupIngress: + - IpProtocol: "-1" FromPort: 22 ToPort: 22 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp + CidrIp: "10.0.0.0/0" + + Positive1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Allow TCP on port 22 from 192.168.0.0/0" + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIp: "192.168.0.0/0" + + Positive1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Allow UDP on ports 22 and 110 from multiple CIDRs" + SecurityGroupIngress: + - IpProtocol: "udp" FromPort: 22 ToPort: 22 - CidrIp: 0.0.0.0/0 + CidrIp: "172.16.0.0/0" + - IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "10.68.0.0" + - IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "172.16.0.0/0" diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive2.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive2.yaml index b035470845a..a5ae0f4dd6f 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive2.yaml +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive2.yaml @@ -1,78 +1,90 @@ -AWSTemplateFormatVersion: 2010-09-09 -Parameters: - MySubnets: - Description: "My subnet" - Type: List Resources: - ApplicationLoadBalancer: + LoadBalancer01: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: - Name: ip-target-alb - Subnets: !Ref MySubnets + Listeners: + - LoadBalancerPort: 80 + InstancePort: 80 + Protocol: HTTP SecurityGroups: - - !Ref ALBSecGroup - Tags: - - Key: Name - Value: ip-target-alb - ALBSecGroup: + - !Ref DualStackSecurityGroup + + DualStackSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp - FromPort: 6379 - ToPort: 6379 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - HTTPALBListener: - Type: AWS::ElasticLoadBalancingV2::Listener + GroupDescription: "Security group for IPv4 and IPv6 ingress rules" + VpcId: !Ref MyVPC + +# IPv4 Rules + IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress Properties: - LoadBalancerArn: !Ref ApplicationLoadBalancer - Port: 80 - Protocol: HTTP - DefaultActions: - - Type: forward - TargetGroupArn: !Ref IPTargetGroup - IPTargetGroup: - Type: AWS::ElasticLoadBalancingV2::TargetGroup + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 22 + ToPort: 22 + CidrIp: "10.0.0.0/0" + + IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress Properties: - VpcId: my-vpc - Port: 80 - Protocol: HTTP - TargetType: ip - Matcher: - HttpCode: '200' - HealthCheckIntervalSeconds: 10 - HealthCheckPath: /health/check - HealthCheckProtocol: HTTP - HealthCheckTimeoutSeconds: 5 - HealthyThresholdCount: 2 - UnhealthyThresholdCount: 2 - TestListenerRule1: - Type: "AWS::ElasticLoadBalancingV2::ListenerRule" + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIp: "192.168.0.0/0" + + IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress Properties: - Priority: 1 - ListenerArn: !Ref HTTPALBListener - Conditions: - - Field: "host-header" - Values: - - "test1.checkmarx.com" - Actions: - - Type: "forward" - TargetGroupArn: !Ref IPTargetGroup - Order: 1 - ForwardConfig: - TargetGroups: - - TargetGroupArn: !Ref IPTargetGroup - Weight: 1 - TargetGroupStickinessConfig: - Enabled: false + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIp: "172.16.0.0/0" + + IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIp: "172.16.0.0/0" + +# IPv6 Rules + IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00::/0" + + IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd12:3456:789a::1/0" + + IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 22 + ToPort: 22 + CidrIpv6: "fd00:abcd:1234::42/0" + + IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "udp" + FromPort: 110 + ToPort: 110 + CidrIpv6: "fd00:abcd:1234::42/0" diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.json new file mode 100644 index 00000000000..f27832f242b --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.json @@ -0,0 +1,76 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "LoadBalancer01": { + "Type": "AWS::ElasticLoadBalancing::LoadBalancer", + "Properties": { + "Listeners": [ + { + "LoadBalancerPort": 80, + "InstancePort": 80, + "Protocol": "HTTP" + } + ], + "SecurityGroups": [ + { "Ref": "Positive1IPv4_1" }, + { "Ref": "Positive1IPv4_2" }, + { "Ref": "Positive1ArrayTestIPv4" } + ] + } + }, + "Positive1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow all protocols on port 22 from 10.0.0.0/0", + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + ] + } + }, + "Positive1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow TCP on port 22 from 192.168.0.0/0", + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "192.168.0.0/0" + } + ] + } + }, + "Positive1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow UDP on ports 22 and 110 from multiple CIDRs", + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "172.16.0.0/0" + }, + { + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "10.68.0.0" + }, + { + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "172.16.0.0/0" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.yaml deleted file mode 100644 index e2f5f459da1..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive3.yaml +++ /dev/null @@ -1,81 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Parameters: - MySubnet: - Description: "My subnet" - Type: List -Resources: - GatewayLoadBalancer: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: my-gateway-load-balancer - Scheme: internet-facing - Type: gateway - Subnets: !Ref MySubnet - InstancesSecGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp - FromPort: 636 - ToPort: 636 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EC2Instance01: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: - - !Ref 'InstancesSecGroup' - KeyName: my-rsa-key - ImageId: ami-79fd7eee - EC2Instance02: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: - - !Ref 'InstancesSecGroup' - KeyName: my-rsa-key - ImageId: ami-79fd7eee - GatewayLoadBalancerTargetGroup: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - Name: t10-networklb-target - Port: 443 - Protocol: TCP - VpcId: t10-vpc-id - TargetGroupAttributes: - - Key: deregistration_delay.timeout_seconds - Value: '60' - Targets: - - Id: !Ref EC2Instance01 - Port: 443 - - Id: !Ref EC2Instance02 - Port: 443 - Tags: - - Key: Name - Value: t10-networklb-target - GatewayLoadBalancerListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref GatewayLoadBalancerTargetGroup - LoadBalancerArn: !Ref GatewayLoadBalancer - Port: 443 - Protocol: TCP - GatewayLoadBalancerListenerCert: - Type: AWS::ElasticLoadBalancingV2::ListenerCertificate - Properties: - Certificates: - - CertificateArn: arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456.... - ListenerArn: !Ref GatewayLoadBalancerListener diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.json new file mode 100644 index 00000000000..53fdf3eaa87 --- /dev/null +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.json @@ -0,0 +1,107 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "LoadBalancer01": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "Listeners": [ + { + "LoadBalancerPort": 80, + "InstancePort": 80, + "Protocol": "HTTP" + } + ], + "SecurityGroups": [ + { "Ref": "DualStackSecurityGroup" } + ] + } + }, + "DualStackSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for IPv4 and IPv6 ingress rules", + "VpcId": { "Ref": "MyVPC" } + } + }, + "IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "10.0.0.0/0" + } + }, + "IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "192.168.0.0/0" + } + }, + "IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIp": "172.16.0.0/0" + } + }, + "IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIp": "172.16.0.0/0" + } + }, + "IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00::/0" + } + }, + "IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "tcp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd12:3456:789a::1/0" + } + }, + "IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "fd00:abcd:1234::42/0" + } + }, + "IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { "Ref": "DualStackSecurityGroup" }, + "IpProtocol": "udp", + "FromPort": 110, + "ToPort": 110, + "CidrIpv6": "fd00:abcd:1234::42/0" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.yaml b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.yaml deleted file mode 100644 index ec23d335026..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive4.yaml +++ /dev/null @@ -1,84 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Parameters: - MySubnet: - Description: "My subnet" - Type: List -Resources: - NetworkLoadBalancer: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: t10-networkloadbalancer - Scheme: internet-facing - Subnets: !Ref MySubnet - Type: network - Tags: - - Key: Name - Value: t10-networklb - ELBInstanceSecGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http and ssh - VpcId: my-vpc - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 81 - ToPort: 80 - CidrIp: 127.0.0.1/32 - - IpProtocol: tcp - FromPort: 27017 - ToPort: 27018 - CidrIp: 127.0.0.1/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EC2Instance01: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: - - !Ref 'ELBInstanceSecGroup' - KeyName: my-rsa-key - ImageId: ami-79fd7eee - EC2Instance02: - Type: AWS::EC2::Instance - Properties: - InstanceType: t3.2xlarge - SecurityGroups: - - !Ref 'ELBInstanceSecGroup' - KeyName: my-rsa-key - ImageId: ami-79fd7eee - NetworkLoadBalancerTargetGroup: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - Name: t10-networklb-target - Port: 443 - Protocol: TCP - VpcId: t10-vpc-id - TargetGroupAttributes: - - Key: deregistration_delay.timeout_seconds - Value: '60' - Targets: - - Id: !Ref EC2Instance01 - Port: 443 - - Id: !Ref EC2Instance02 - Port: 443 - Tags: - - Key: Name - Value: t10-networklb-target - NetworkLoadBalancerListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref NetworkLoadBalancerTargetGroup - LoadBalancerArn: !Ref NetworkLoadBalancer - Port: 443 - Protocol: TCP - NetworkLoadBalancerListenerCert: - Type: AWS::ElasticLoadBalancingV2::ListenerCertificate - Properties: - Certificates: - - CertificateArn: arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456.... - ListenerArn: !Ref NetworkLoadBalancerListener diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive5.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive5.json deleted file mode 100644 index 378d200bfd8..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive5.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "Resources": { - "MyLoadBalancer": { - "Properties": { - "Scheme": "internet-facing", - "Listeners": [ - { - "SSLCertificateId": "arn:aws:iam::123456789012:server-certificate/my-server-certificate", - "InstancePort": "80", - "InstanceProtocol": "HTTP", - "LoadBalancerPort": "443", - "Protocol": "HTTPS", - "PolicyNames": [ - "My-SSLNegotiation-Policy" - ] - } - ], - "HealthCheck": { - "HealthyThreshold": "2", - "UnhealthyThreshold": "3", - "Interval": "10", - "Timeout": "5", - "Target": "HTTP:80/" - }, - "SecurityGroups": [ - "LBSecGroup" - ], - "Policies": [ - { - "Attributes": [ - { - "Name": "Reference-Security-Policy", - "Value": "ELBSecurityPolicy-TLS-1-2-2017-01" - } - ], - "PolicyName": "My-SSLNegotiation-Policy", - "PolicyType": "SSLNegotiationPolicyType" - } - ], - "AvailabilityZones": [ - "us-east-2a" - ], - "CrossZone": true - }, - "Type": "AWS::ElasticLoadBalancing::LoadBalancer" - }, - "LBSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 50, - "ToPort": 80, - "CidrIp": "127.0.0.1/0" - }, - { - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "127.0.0.1/0" - } - ], - "SecurityGroupEgress": [ - { - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp" - } - ] - } - } - }, - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z" -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive6.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive6.json deleted file mode 100644 index d888e378a38..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive6.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Parameters": { - "MySubnets": { - "Description": "My subnet", - "Type": "List\u003cString\u003e" - } - }, - "Resources": { - "ApplicationLoadBalancer": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "SecurityGroups": [ - "ALBSecGroup" - ], - "Tags": [ - { - "Key": "Name", - "Value": "ip-target-alb" - } - ], - "Name": "ip-target-alb", - "Subnets": "MySubnets" - } - }, - "ALBSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "FromPort": 80, - "ToPort": 80, - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp" - }, - { - "IpProtocol": "tcp", - "FromPort": 6379, - "ToPort": 6379, - "CidrIp": "127.0.0.1/0" - } - ], - "SecurityGroupEgress": [ - { - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22 - } - ] - } - }, - "HTTPALBListener": { - "Properties": { - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "IPTargetGroup" - } - ], - "LoadBalancerArn": "ApplicationLoadBalancer", - "Port": 80, - "Protocol": "HTTP" - }, - "Type": "AWS::ElasticLoadBalancingV2::Listener" - }, - "IPTargetGroup": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/health/check", - "HealthCheckProtocol": "HTTP", - "HealthyThresholdCount": 2, - "VpcId": "my-vpc", - "TargetType": "ip", - "Matcher": { - "HttpCode": "200" - }, - "UnhealthyThresholdCount": 2, - "Port": 80, - "Protocol": "HTTP", - "HealthCheckTimeoutSeconds": 5 - } - }, - "TestListenerRule1": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - "Properties": { - "Priority": 1, - "ListenerArn": "HTTPALBListener", - "Conditions": [ - { - "Values": [ - "test1.checkmarx.com" - ], - "Field": "host-header" - } - ], - "Actions": [ - { - "Type": "forward", - "TargetGroupArn": "IPTargetGroup", - "Order": 1, - "ForwardConfig": { - "TargetGroups": [ - { - "TargetGroupArn": "IPTargetGroup", - "Weight": 1 - } - ], - "TargetGroupStickinessConfig": { - "Enabled": false - } - } - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive7.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive7.json deleted file mode 100644 index b15bb8bd3ea..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive7.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "Resources": { - "GatewayLoadBalancerListenerCert": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate", - "Properties": { - "Certificates": [ - { - "CertificateArn": "arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456...." - } - ], - "ListenerArn": "GatewayLoadBalancerListener" - } - }, - "GatewayLoadBalancer": { - "Properties": { - "Name": "my-gateway-load-balancer", - "Scheme": "internet-facing", - "Type": "gateway", - "Subnets": "MySubnet" - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer" - }, - "InstancesSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "127.0.0.1/32" - }, - { - "ToPort": 636, - "CidrIp": "127.0.0.1/0", - "IpProtocol": "tcp", - "FromPort": 636 - } - ], - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22 - } - ] - } - }, - "EC2Instance01": { - "Type": "AWS::EC2::Instance", - "Properties": { - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "InstancesSecGroup" - ], - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee" - } - }, - "EC2Instance02": { - "Type": "AWS::EC2::Instance", - "Properties": { - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "InstancesSecGroup" - ], - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee" - } - }, - "GatewayLoadBalancerTargetGroup": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "60" - } - ], - "Targets": [ - { - "Id": "EC2Instance01", - "Port": 443 - }, - { - "Id": "EC2Instance02", - "Port": 443 - } - ], - "Tags": [ - { - "Key": "Name", - "Value": "t10-networklb-target" - } - ], - "Name": "t10-networklb-target", - "Port": 443, - "Protocol": "TCP", - "VpcId": "t10-vpc-id" - } - }, - "GatewayLoadBalancerListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "GatewayLoadBalancerTargetGroup" - } - ], - "LoadBalancerArn": "GatewayLoadBalancer", - "Port": 443, - "Protocol": "TCP" - } - } - }, - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Parameters": { - "MySubnet": { - "Description": "My subnet", - "Type": "List\u003cString\u003e" - } - } -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive8.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive8.json deleted file mode 100644 index 1082e38b9d1..00000000000 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive8.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", - "Parameters": { - "MySubnet": { - "Description": "My subnet", - "Type": "List\u003cString\u003e" - } - }, - "Resources": { - "EC2Instance02": { - "Type": "AWS::EC2::Instance", - "Properties": { - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee", - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "ELBInstanceSecGroup" - ] - } - }, - "NetworkLoadBalancerTargetGroup": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "Targets": [ - { - "Id": "EC2Instance01", - "Port": 443 - }, - { - "Id": "EC2Instance02", - "Port": 443 - } - ], - "Tags": [ - { - "Key": "Name", - "Value": "t10-networklb-target" - } - ], - "Name": "t10-networklb-target", - "Port": 443, - "Protocol": "TCP", - "VpcId": "t10-vpc-id", - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "60" - } - ] - } - }, - "NetworkLoadBalancerListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "Port": 443, - "Protocol": "TCP", - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "NetworkLoadBalancerTargetGroup" - } - ], - "LoadBalancerArn": "NetworkLoadBalancer" - } - }, - "NetworkLoadBalancerListenerCert": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerCertificate", - "Properties": { - "Certificates": [ - { - "CertificateArn": "arn:aws:acm:eu-west-1:xxxaccountxxx:certificate/123456...." - } - ], - "ListenerArn": "NetworkLoadBalancerListener" - } - }, - "NetworkLoadBalancer": { - "Properties": { - "Tags": [ - { - "Value": "t10-networklb", - "Key": "Name" - } - ], - "Name": "t10-networkloadbalancer", - "Scheme": "internet-facing", - "Subnets": "MySubnet", - "Type": "network" - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer" - }, - "ELBInstanceSecGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http and ssh", - "VpcId": "my-vpc", - "SecurityGroupIngress": [ - { - "CidrIp": "127.0.0.1/32", - "IpProtocol": "tcp", - "FromPort": 81, - "ToPort": 80 - }, - { - "FromPort": 27017, - "ToPort": 27018, - "CidrIp": "127.0.0.1/0", - "IpProtocol": "tcp" - } - ], - "SecurityGroupEgress": [ - { - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp" - } - ] - } - }, - "EC2Instance01": { - "Type": "AWS::EC2::Instance", - "Properties": { - "InstanceType": "t3.2xlarge", - "SecurityGroups": [ - "ELBInstanceSecGroup" - ], - "KeyName": "my-rsa-key", - "ImageId": "ami-79fd7eee" - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive_expected_result.json index 90389869786..2088a4bfba3 100644 --- a/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/elb_sensitive_port_is_exposed_to_entire_network/test/positive_expected_result.json @@ -1,86 +1,146 @@ [ { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 37, - "fileName": "positive1.yaml", - "queryName": "ELB Sensitive Port Is Exposed To Entire Network" + "line": 19, + "fileName": "positive1.yaml" }, { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 37, - "fileName": "positive1.yaml", - "queryName": "ELB Sensitive Port Is Exposed To Entire Network" + "line": 29, + "fileName": "positive1.yaml" }, { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 37, - "fileName": "positive1.yaml", - "queryName": "ELB Sensitive Port Is Exposed To Entire Network" + "line": 39, + "fileName": "positive1.yaml" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 22, + "line": 47, + "fileName": "positive1.yaml" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 21, "fileName": "positive2.yaml" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 19, - "fileName": "positive3.yaml" + "line": 30, + "fileName": "positive2.yaml" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 39, + "fileName": "positive2.yaml" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 48, + "fileName": "positive2.yaml" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 58, + "fileName": "positive2.yaml" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 67, + "fileName": "positive2.yaml" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 22, - "fileName": "positive4.yaml" + "line": 76, + "fileName": "positive2.yaml" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 22, - "fileName": "positive4.yaml" + "line": 85, + "fileName": "positive2.yaml" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 52, - "fileName": "positive5.json" + "line": 27, + "fileName": "positive3.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 52, - "fileName": "positive5.json" + "line": 41, + "fileName": "positive3.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 52, - "fileName": "positive5.json" + "line": 55, + "fileName": "positive3.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 31, - "fileName": "positive6.json" + "line": 67, + "fileName": "positive3.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", "line": 28, - "fileName": "positive7.json" + "fileName": "positive4.json" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 38, + "fileName": "positive4.json" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 48, + "fileName": "positive4.json" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 58, + "fileName": "positive4.json" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 68, + "fileName": "positive4.json" + }, + { + "queryName": "ELB Sensitive Port Is Exposed To Entire Network", + "severity": "HIGH", + "line": 78, + "fileName": "positive4.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 97, - "fileName": "positive8.json" + "line": 88, + "fileName": "positive4.json" }, { "queryName": "ELB Sensitive Port Is Exposed To Entire Network", "severity": "HIGH", - "line": 97, - "fileName": "positive8.json" + "line": 98, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/metadata.json b/assets/queries/cloudFormation/aws/fully_open_ingress/metadata.json index b4e1bb785a4..5223ccadbc9 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/metadata.json +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/metadata.json @@ -3,7 +3,7 @@ "queryName": "Fully Open Ingress", "severity": "HIGH", "category": "Networking and Firewall", - "descriptionText": "ECS Service's security group should not allow unrestricted access to all ports from all IPv4 addresses", + "descriptionText": "ECS Service's security group should not allow unrestricted access to all ports from all IPv4 or IPv6 addresses", "descriptionUrl": "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html#create-a-base-security-group", "platform": "CloudFormation", "descriptionID": "747f49ac", diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/query.rego b/assets/queries/cloudFormation/aws/fully_open_ingress/query.rego index 638771e3ac6..265b4e9e677 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/query.rego +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/query.rego @@ -1,46 +1,67 @@ package Cx -import data.generic.common as commonLib +import data.generic.common as common_lib import data.generic.cloudformation as cf_lib +unrestricted_ips := array.concat(common_lib.unrestricted_ipv6, ["0.0.0.0/0"]) +cidr_fields := ["CidrIp","CidrIpv6"] + CxPolicy[result] { doc := input.document[i] + + cf_lib.getResourcesByType(doc.Resources, "AWS::ECS::Service") != [] + cf_lib.getResourcesByType(doc.Resources, "AWS::ECS::Cluster") != [] + + types := ["AWS::EC2::SecurityGroup","AWS::EC2::SecurityGroupIngress"] + resource := doc.Resources[name] - resource.Type == "AWS::ECS::Service" + resource.Type == types[_] - clusterList := [cluster | - doc.Resources[j].Type == "AWS::ECS::Cluster" - cluster := j - ] + ingress_list := cf_lib.get_ingress_list(resource) + results := exposed_inline_or_standalone_ingress(ingress_list[ing_index], ing_index, resource.Type, name) + results != "" + + result := { + "documentId": doc.id, + "resourceType": resource.Type, + "resourceName": cf_lib.get_resource_name(resource, name), + "searchKey": results.searchKey, + "issueType": "IncorrectValue", + "keyExpectedValue": results.keyExpectedValue, + "keyActualValue": results.keyActualValue, + "searchLine" : results.searchLine, + } +} - count(clusterList) > 0 +exposed_inline_or_standalone_ingress(resource, ing_index, type, resource_index) = results { # inline ingress + type == "AWS::EC2::SecurityGroup" - securityGroupList := [secGroup | - doc.Resources[j].Type == "AWS::EC2::SecurityGroup" - secGroup := j - ] + resource[cidr_fields[c]] == unrestricted_ips[_] + affects_all_ports(resource) - count(securityGroupList) > 0 + results := { + "searchKey": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d].%s", [resource_index, ing_index, cidr_fields[c]]), + "keyExpectedValue": sprintf("Resource '%s' of type '%s' should not accept ingress connections from all addresses to all available ports", [resource_index, type]), + "keyActualValue": sprintf("Resource '%s' of type '%s' is accepting ingress connections from all addresses to all available ports", [resource_index, type]), + "searchLine" : common_lib.build_search_line(["Resources", resource_index, "Properties", "SecurityGroupIngress", ing_index, cidr_fields[c]],[]) + } +} else = results { # standalone ingress resource + type == "AWS::EC2::SecurityGroupIngress" - doc.Resources[k].Type == "AWS::EC2::SecurityGroupIngress" - doc.Resources[k].Properties.CidrIp == "0.0.0.0/0" - doc.Resources[k].Properties.ToPort == 0 - commonLib.inArray(securityGroupList, doc.Resources[k].Properties.GroupId) + resource[cidr_fields[c]] == unrestricted_ips[_] + affects_all_ports(resource) - result := { - "documentId": input.document[i].id, - "resourceType": doc.Resources[k].Type, - "resourceName": cf_lib.get_resource_name(doc.Resources[k], k), - "searchKey": sprintf("Resources.%s.Properties.CidrIp", [k]), - "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resource name '%s' of type '%s' should not accept ingress connections from all IPv4 adresses and to all available ports", [ - k, - doc.Resources[k].Type, - ]), - "keyActualValue": sprintf("Resource name '%s' of type '%s' should not accept ingress connections from CIDR %s to all available ports", [ - k, - doc.Resources[k].Type, - doc.Resources[k].Properties.CidrIp, - ]), + results := { + "searchKey": sprintf("Resources.%s.Properties.%s", [resource_index, cidr_fields[c]]), + "keyExpectedValue": sprintf("Resource '%s' of type '%s' should not accept ingress connections from all addresses to all available ports", [resource_index, type]), + "keyActualValue": sprintf("Resource '%s' of type '%s' is accepting ingress connections from all addresses to all available ports", [resource_index, type]), + "searchLine" : common_lib.build_search_line(["Resources", resource_index, "Properties", cidr_fields[c]],[]) } -} +} else = "" + +affects_all_ports(resource) { + resource.IpProtocol == "-1" +} else { + resource.FromPort == 0 + resource.ToPort == 65535 +} \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative1.yaml b/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative1.yaml index bc057b78c50..3458ec5ff0c 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative1.yaml @@ -1,267 +1,58 @@ -AWSTemplateFormatVersion: '2010-09-09' -Parameters: - VpcId: - Type: AWS::EC2::VPC::Id - Description: Select a VPC that allows instances access to the Internet. - SubnetId: - Type: List - Description: Select at two subnets in your selected VPC. Resources: - ECSCluster: + Sample_Service: + Type: AWS::ECS::Service + Properties: + Cluster: !Ref 'ECSCluster' + Sample_Cluster: Type: AWS::ECS::Cluster - EcsSecurityGroup: + + # EC2 Security Group with inline IPv4 and IPv6 rules + DBEC2SecurityGroupInline: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: ECS Security Group - VpcId: !Ref 'VpcId' - EcsSecurityGroupHTTPinbound: - Type: AWS::EC2::SecurityGroupIngress + GroupDescription: "Inline IPv4 and IPv6 ingress" + VpcId: !Ref VPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 0 + ToPort: 65534 #does not expose all ports + CidrIp: 0.0.0.0/0 + - IpProtocol: "udp" + FromPort: 0 + ToPort: 65535 + CidrIpv6: 2607:f0d0:1002:51::4/56 #cidr not exposed + + # EC2 Security Group with standalone ingress rules + DBEC2SecurityGroupStandalone: + Type: AWS::EC2::SecurityGroup Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 0.0.0.0/0 - EcsSecurityGroupSSHinbound: + GroupDescription: "Standalone IPv4 and IPv6 ingress" + VpcId: !Ref VPC + + DBEC2SecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EcsSecurityGroupALBports: + GroupId: !Ref DBEC2SecurityGroupStandalone + IpProtocol: "-1" + CidrIp: 192.162.0.0/16 #cidr not exposed + + DBEC2SecurityGroupIngressIPv6: Type: AWS::EC2::SecurityGroupIngress Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 31000 - ToPort: 61000 - SourceSecurityGroupId: !Ref 'EcsSecurityGroup' - CloudwatchLogsGroup: - Type: AWS::Logs::LogGroup - Properties: - LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']] - RetentionInDays: 14 - TaskDefinition: - Type: AWS::ECS::TaskDefinition - Properties: - Family: !Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]] - ContainerDefinitions: - - Name: simple-app - Cpu: 10 - Essential: true - Image: httpd:2.4 - Memory: 300 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - MountPoints: - - ContainerPath: /usr/local/apache2/htdocs - SourceVolume: my-vol - PortMappings: - - ContainerPort: 80 - - Name: busybox - Cpu: 10 - Command: ['/bin/sh -c "while true; do echo '' Amazon ECS - Sample App'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html - ; sleep 1; done"'] - EntryPoint: [sh, -c] - Essential: false - Image: busybox - Memory: 200 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - VolumesFrom: - - SourceContainer: simple-app - Volumes: - - Name: my-vol - ECSALB: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: ECSALB - Scheme: internet-facing - LoadBalancerAttributes: - - Key: idle_timeout.timeout_seconds - Value: '30' - Subnets: !Ref 'SubnetId' - SecurityGroups: [!Ref 'EcsSecurityGroup'] - ALBListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - LoadBalancerArn: !Ref 'ECSALB' - Port: 80 - Protocol: HTTP - ECSALBListenerRule: - Type: AWS::ElasticLoadBalancingV2::ListenerRule - Properties: - Actions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - Conditions: - - Field: path-pattern - Values: [/] - ListenerArn: !Ref 'ALBListener' - Priority: 1 - ECSTG: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - HealthCheckIntervalSeconds: 10 - HealthCheckPath: / - HealthCheckProtocol: HTTP - HealthCheckTimeoutSeconds: 5 - HealthyThresholdCount: 2 - Name: ECSTG - Port: 80 - Protocol: HTTP - UnhealthyThresholdCount: 2 - VpcId: !Ref 'VpcId' - ECSAutoScalingGroup: - Type: AWS::AutoScaling::AutoScalingGroup - Properties: - VPCZoneIdentifier: !Ref 'SubnetId' - LaunchConfigurationName: !Ref 'ContainerInstances' - MinSize: '1' - MaxSize: 4 - DesiredCapacity: 2 - CreationPolicy: - ResourceSignal: - Timeout: PT15M - UpdatePolicy: - AutoScalingReplacingUpdate: - WillReplace: true - ContainerInstances: - Type: AWS::AutoScaling::LaunchConfiguration - Properties: - ImageId: ami-09bee01cc997a78a6 - SecurityGroups: [!Ref 'EcsSecurityGroup'] - InstanceType: t2.small - IamInstanceProfile: !Ref 'EC2InstanceProfile' - KeyName: my-ssh-key - UserData: - Fn::Base64: !Sub | - #!/bin/bash -xe - echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config - yum install -y aws-cfn-bootstrap - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region} - service: - Type: AWS::ECS::Service - Properties: - Cluster: !Ref 'ECSCluster' - DesiredCount: 1 - LoadBalancers: - - ContainerName: simple-app - ContainerPort: 80 - TargetGroupArn: !Ref 'ECSTG' - Role: !Ref 'ECSServiceRole' - TaskDefinition: !Ref 'taskdefinition' - ECSServiceRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ecs.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets', - 'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer', - 'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress'] - Resource: '*' - ServiceScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - MaxCapacity: 2 - MinCapacity: 1 - ResourceId: !Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]] - RoleARN: !GetAtt [AutoscalingRole, Arn] - ScalableDimension: ecs:service:DesiredCount - ServiceNamespace: ecs - ServiceScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: AStepPolicy - PolicyType: StepScaling - ScalingTargetId: !Ref 'ServiceScalingTarget' - StepScalingPolicyConfiguration: - AdjustmentType: PercentChangeInCapacity - Cooldown: 60 - MetricAggregationType: Average - StepAdjustments: - - MetricIntervalLowerBound: 0 - ScalingAdjustment: 200 - ALB500sAlarmScaleUp: - Type: AWS::CloudWatch::Alarm - Properties: - EvaluationPeriods: 1 - Statistic: Average - Threshold: 10 - AlarmDescription: Alarm if our ALB generates too many HTTP 500s. - Period: 60 - AlarmActions: [!Ref 'ServiceScalingPolicy'] - Namespace: AWS/ApplicationELB - Dimensions: - - Name: LoadBalancer - Value: !GetAtt - - ECSALB - - LoadBalancerFullName - ComparisonOperator: GreaterThanThreshold - MetricName: HTTPCode_ELB_5XX_Count - EC2Role: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ec2.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['ecs:CreateCluster', 'ecs:DeregisterContainerInstance', 'ecs:DiscoverPollEndpoint', - 'ecs:Poll', 'ecs:RegisterContainerInstance', 'ecs:StartTelemetrySession', - 'ecs:Submit*', 'logs:CreateLogStream', 'logs:PutLogEvents'] - Resource: '*' - AutoscalingRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [application-autoscaling.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: service-autoscaling - PolicyDocument: - Statement: - - Effect: Allow - Action: ['application-autoscaling:*', 'cloudwatch:DescribeAlarms', 'cloudwatch:PutMetricAlarm', - 'ecs:DescribeServices', 'ecs:UpdateService'] - Resource: '*' - EC2InstanceProfile: - Type: AWS::IAM::InstanceProfile - Properties: - Path: / - Roles: [!Ref 'EC2Role'] + GroupId: !Ref DBEC2SecurityGroupStandalone + IpProtocol: "tcp" + FromPort: 0 + ToPort: 34000 #does not expose all ports + CidrIpv6: ::/0 + + # RDS Instance referencing all security groups + DBInstance: + Type: AWS::RDS::DBInstance + Properties: + PubliclyAccessible: true + DBName: !Ref DBName + Engine: MySQL + VPCSecurityGroups: + - !Ref DBEC2SecurityGroupInline + - !Ref DBEC2SecurityGroupStandalone + diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative2.json b/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative2.json index ca3c105b5ce..787de2fb4df 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative2.json +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/test/negative2.json @@ -1,464 +1,86 @@ { - "AWSTemplateFormatVersion": "2010-09-09", - "Parameters": { - "VpcId": { - "Type": "AWS::EC2::VPC::Id", - "Description": "Select a VPC that allows instances access to the Internet." - }, - "SubnetId": { - "Description": "Select at two subnets in your selected VPC.", - "Type": "List\u003cAWS::EC2::Subnet::Id\u003e" - } - }, "Resources": { - "EcsSecurityGroupHTTPinbound": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "CidrIp": "0.0.0.0/0", - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80 - } - }, - "EcsSecurityGroupALBports": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 31000, - "ToPort": 61000, - "SourceSecurityGroupId": "EcsSecurityGroup" - } - }, - "CloudwatchLogsGroup": { - "Type": "AWS::Logs::LogGroup", - "Properties": { - "LogGroupName": [ - "-", - [ - "ECSLogGroup", - "AWS::StackName" - ] - ], - "RetentionInDays": 14 - } - }, - "ALBListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "ECSTG" - } - ], - "LoadBalancerArn": "ECSALB", - "Port": 80, - "Protocol": "HTTP" - } - }, - "ECSALBListenerRule": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - "Properties": { - "Actions": [ - { - "TargetGroupArn": "ECSTG", - "Type": "forward" - } - ], - "Conditions": [ - { - "Field": "path-pattern", - "Values": [ - "/" - ] - } - ], - "ListenerArn": "ALBListener", - "Priority": 1 - } - }, - "ALB500sAlarmScaleUp": { - "Properties": { - "Dimensions": [ - { - "Name": "LoadBalancer", - "Value": [ - "ECSALB", - "LoadBalancerFullName" - ] - } - ], - "ComparisonOperator": "GreaterThanThreshold", - "MetricName": "HTTPCode_ELB_5XX_Count", - "Statistic": "Average", - "Threshold": 10, - "AlarmDescription": "Alarm if our ALB generates too many HTTP 500s.", - "Period": 60, - "EvaluationPeriods": 1, - "AlarmActions": [ - "ServiceScalingPolicy" - ], - "Namespace": "AWS/ApplicationELB" - }, - "Type": "AWS::CloudWatch::Alarm" - }, - "AutoscalingRole": { - "Type": "AWS::IAM::Role", + "Sample_Service": { + "Type": "AWS::ECS::Service", "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "application-autoscaling.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "service-autoscaling", - "PolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "application-autoscaling:*", - "cloudwatch:DescribeAlarms", - "cloudwatch:PutMetricAlarm", - "ecs:DescribeServices", - "ecs:UpdateService" - ], - "Resource": "*" - } - ] - } - } - ] + "Cluster": { + "Ref": "ECSCluster" + } } }, - "ECSCluster": { + "Sample_Cluster": { "Type": "AWS::ECS::Cluster" }, - "ECSServiceRole": { - "Type": "AWS::IAM::Role", + "DBEC2SecurityGroupInline": { + "Type": "AWS::EC2::SecurityGroup", "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "ecs.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] + "GroupDescription": "Inline IPv4 and IPv6 ingress", + "VpcId": { + "Ref": "VPC" }, - "Path": "/", - "Policies": [ + "SecurityGroupIngress": [ { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:DeregisterTargets", - "elasticloadbalancing:Describe*", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:RegisterTargets", - "ec2:Describe*", - "ec2:AuthorizeSecurityGroupIngress" - ], - "Resource": "*" - } - ] - } + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 65534, + "CidrIp": "0.0.0.0/0" + }, + { + "IpProtocol": "udp", + "FromPort": 0, + "ToPort": 65535, + "CidrIpv6": "2607:f0d0:1002:51::4/56" } ] } }, - "ServiceScalingPolicy": { - "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", - "Properties": { - "PolicyName": "AStepPolicy", - "PolicyType": "StepScaling", - "ScalingTargetId": "ServiceScalingTarget", - "StepScalingPolicyConfiguration": { - "Cooldown": 60, - "MetricAggregationType": "Average", - "StepAdjustments": [ - { - "MetricIntervalLowerBound": 0, - "ScalingAdjustment": 200 - } - ], - "AdjustmentType": "PercentChangeInCapacity" - } - } - }, - "EC2InstanceProfile": { - "Type": "AWS::IAM::InstanceProfile", - "Properties": { - "Path": "/", - "Roles": [ - "EC2Role" - ] - } - }, - "ECSAutoScalingGroup": { - "Type": "AWS::AutoScaling::AutoScalingGroup", + "DBEC2SecurityGroupStandalone": { + "Type": "AWS::EC2::SecurityGroup", "Properties": { - "VPCZoneIdentifier": "SubnetId", - "LaunchConfigurationName": "ContainerInstances", - "MinSize": "1", - "MaxSize": 4, - "DesiredCapacity": 2 - }, - "CreationPolicy": { - "ResourceSignal": { - "Timeout": "PT15M" - } - }, - "UpdatePolicy": { - "AutoScalingReplacingUpdate": { - "WillReplace": true + "GroupDescription": "Standalone IPv4 and IPv6 ingress", + "VpcId": { + "Ref": "VPC" } } }, - "ECSALB": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "Scheme": "internet-facing", - "LoadBalancerAttributes": [ - { - "Key": "idle_timeout.timeout_seconds", - "Value": "30" - } - ], - "Subnets": "SubnetId", - "SecurityGroups": [ - "EcsSecurityGroup" - ], - "Name": "ECSALB" - } - }, - "ECSTG": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", + "DBEC2SecurityGroupIngress": { + "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "Name": "ECSTG", - "Protocol": "HTTP", - "HealthCheckPath": "/", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 2, - "UnhealthyThresholdCount": 2, - "VpcId": "VpcId", - "HealthCheckIntervalSeconds": 10, - "HealthCheckProtocol": "HTTP", - "Port": 80 + "GroupId": { + "Ref": "DBEC2SecurityGroupStandalone" + }, + "IpProtocol": "-1", + "CidrIp": "192.162.0.0/16" } }, - "EC2Role": { - "Type": "AWS::IAM::Role", + "DBEC2SecurityGroupIngressIPv6": { + "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "ec2.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] + "GroupId": { + "Ref": "DBEC2SecurityGroupStandalone" }, - "Path": "/", - "Policies": [ - { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Resource": "*", - "Effect": "Allow", - "Action": [ - "ecs:CreateCluster", - "ecs:DeregisterContainerInstance", - "ecs:DiscoverPollEndpoint", - "ecs:Poll", - "ecs:RegisterContainerInstance", - "ecs:StartTelemetrySession", - "ecs:Submit*", - "logs:CreateLogStream", - "logs:PutLogEvents" - ] - } - ] - } - } - ] + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 34000, + "CidrIpv6": "::/0" } }, - "TaskDefinition": { + "DBInstance": { + "Type": "AWS::RDS::DBInstance", "Properties": { - "Volumes": [ - { - "Name": "my-vol" - } - ], - "Family": [ - "", - [ - "AWS::StackName", - "-ecs-demo-app" - ] - ], - "ContainerDefinitions": [ + "PubliclyAccessible": true, + "DBName": { + "Ref": "DBName" + }, + "Engine": "MySQL", + "VPCSecurityGroups": [ { - "Image": "httpd:2.4", - "Memory": 300, - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region", - "awslogs-stream-prefix": "ecs-demo-app" - } - }, - "MountPoints": [ - { - "ContainerPath": "/usr/local/apache2/htdocs", - "SourceVolume": "my-vol" - } - ], - "PortMappings": [ - { - "ContainerPort": 80 - } - ], - "Name": "simple-app", - "Cpu": 10, - "Essential": true + "Ref": "DBEC2SecurityGroupInline" }, { - "VolumesFrom": [ - { - "SourceContainer": "simple-app" - } - ], - "Cpu": 10, - "EntryPoint": [ - "sh", - "-c" - ], - "Essential": false, - "Image": "busybox", - "Memory": 200, - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-stream-prefix": "ecs-demo-app", - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region" - } - }, - "Name": "busybox", - "Command": [ - "/bin/sh -c \"while true; do echo '\u003chtml\u003e \u003chead\u003e \u003ctitle\u003eAmazon ECS Sample App\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003c/body\u003e\u003c/html\u003e' \u003e bottom; cat top date bottom \u003e /usr/local/apache2/htdocs/index.html ; sleep 1; done\"" - ] + "Ref": "DBEC2SecurityGroupStandalone" } ] - }, - "Type": "AWS::ECS::TaskDefinition" - }, - "EcsSecurityGroupSSHinbound": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "ToPort": 22, - "CidrIp": "0.0.0.0/0", - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 22 - } - }, - "ContainerInstances": { - "Type": "AWS::AutoScaling::LaunchConfiguration", - "Properties": { - "ImageId": "ami-09bee01cc997a78a6", - "SecurityGroups": [ - "EcsSecurityGroup" - ], - "InstanceType": "t2.small", - "IamInstanceProfile": "EC2InstanceProfile", - "KeyName": "my-ssh-key", - "UserData": { - "Fn::Base64": "#!/bin/bash -xe\necho ECS_CLUSTER=${ECSCluster} \u003e\u003e /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}\n" - } - } - }, - "service": { - "Type": "AWS::ECS::Service", - "Properties": { - "Cluster": "ECSCluster", - "DesiredCount": 1, - "LoadBalancers": [ - { - "ContainerPort": 80, - "TargetGroupArn": "ECSTG", - "ContainerName": "simple-app" - } - ], - "Role": "ECSServiceRole", - "TaskDefinition": "taskdefinition" - } - }, - "ServiceScalingTarget": { - "Properties": { - "MinCapacity": 1, - "ResourceId": [ - "", - [ - "service/", - "ECSCluster", - "/", - [ - "service", - "Name" - ] - ] - ], - "RoleARN": [ - "AutoscalingRole", - "Arn" - ], - "ScalableDimension": "ecs:service:DesiredCount", - "ServiceNamespace": "ecs", - "MaxCapacity": 2 - }, - "Type": "AWS::ApplicationAutoScaling::ScalableTarget" - }, - "EcsSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "ECS Security Group", - "VpcId": "VpcId" } } } diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive1.yaml b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive1.yaml index 81d6210817c..41647277a20 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive1.yaml @@ -1,277 +1,58 @@ -AWSTemplateFormatVersion: '2010-09-09' -Parameters: - VpcId: - Type: AWS::EC2::VPC::Id - Description: Select a VPC that allows instances access to the Internet. - SubnetId: - Type: List - Description: Select at two subnets in your selected VPC. Resources: - ECSCluster: + Sample_Service: + Type: AWS::ECS::Service + Properties: + Cluster: !Ref 'ECSCluster' + Sample_Cluster: Type: AWS::ECS::Cluster - EcsSecurityGroup: + + # EC2 Security Group with inline IPv4 and IPv6 rules + DBEC2SecurityGroupInline: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: ECS Security Group - VpcId: !Ref 'VpcId' - EcsSecurityGroupHTTPinbound02: - Type: AWS::EC2::SecurityGroupIngress + GroupDescription: "Inline IPv4 and IPv6 ingress" + VpcId: !Ref VPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 0 + ToPort: 65535 + CidrIp: 0.0.0.0/0 + - IpProtocol: "udp" + FromPort: 0 + ToPort: 65535 + CidrIpv6: ::/0 + + # EC2 Security Group with standalone ingress rules + DBEC2SecurityGroupStandalone: + Type: AWS::EC2::SecurityGroup Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 80 - ToPort: 0 - CidrIp: 0.0.0.0/0 - EcsSecurityGroupSSHinbound: + GroupDescription: "Standalone IPv4 and IPv6 ingress" + VpcId: !Ref VPC + + DBEC2SecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 22 - ToPort: 0 + GroupId: !Ref DBEC2SecurityGroupStandalone + IpProtocol: "-1" CidrIp: 0.0.0.0/0 - EcsSecurityGroupALBports: + + DBEC2SecurityGroupIngressIPv6: Type: AWS::EC2::SecurityGroupIngress Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 31000 - ToPort: 61000 - SourceSecurityGroupId: !Ref 'EcsSecurityGroup' - CloudwatchLogsGroup: - Type: AWS::Logs::LogGroup - Properties: - LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']] - RetentionInDays: 14 - TaskDefinition: - Type: AWS::ECS::TaskDefinition - Properties: - Family: !Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]] - ContainerDefinitions: - - Name: simple-app - Cpu: 10 - Essential: true - Image: httpd:2.4 - Memory: 300 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - MountPoints: - - ContainerPath: /usr/local/apache2/htdocs - SourceVolume: my-vol - PortMappings: - - ContainerPort: 80 - - Name: busybox - Cpu: 10 - Command: ['/bin/sh -c "while true; do echo '' Amazon ECS - Sample App'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html - ; sleep 1; done"'] - EntryPoint: [sh, -c] - Essential: false - Image: busybox - Memory: 200 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - VolumesFrom: - - SourceContainer: simple-app - Volumes: - - Name: my-vol - ECSALB: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: ECSALB - Scheme: internet-facing - LoadBalancerAttributes: - - Key: idle_timeout.timeout_seconds - Value: '30' - Subnets: !Ref 'SubnetId' - SecurityGroups: [!Ref 'EcsSecurityGroup'] - ALBListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - LoadBalancerArn: !Ref 'ECSALB' - Port: 80 - Protocol: HTTP - ECSALBListenerRule: - Type: AWS::ElasticLoadBalancingV2::ListenerRule - Properties: - Actions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - Conditions: - - Field: path-pattern - Values: [/] - ListenerArn: !Ref 'ALBListener' - Priority: 1 - ECSTG: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - HealthCheckIntervalSeconds: 10 - HealthCheckPath: / - HealthCheckProtocol: HTTP - HealthCheckTimeoutSeconds: 5 - HealthyThresholdCount: 2 - Name: ECSTG - Port: 80 - Protocol: HTTP - UnhealthyThresholdCount: 2 - VpcId: !Ref 'VpcId' - ECSAutoScalingGroup: - Type: AWS::AutoScaling::AutoScalingGroup - Properties: - VPCZoneIdentifier: !Ref 'SubnetId' - LaunchConfigurationName: !Ref 'ContainerInstances' - MinSize: '1' - MaxSize: 4 - DesiredCapacity: 2 - CreationPolicy: - ResourceSignal: - Timeout: PT15M - UpdatePolicy: - AutoScalingReplacingUpdate: - WillReplace: true - ContainerInstances: - Type: AWS::AutoScaling::LaunchConfiguration - Properties: - ImageId: ami-128731982dhash - SecurityGroups: [!Ref 'EcsSecurityGroup'] - InstanceType: t2.small - IamInstanceProfile: !Ref 'EC2InstanceProfile' - KeyName: my-ssh-key - UserData: - Fn::Base64: !Sub | - #!/bin/bash -xe - echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config - yum install -y aws-cfn-bootstrap - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region} - service: - Type: AWS::ECS::Service - Properties: - Cluster: !Ref 'ECSCluster' - DesiredCount: 1 - LoadBalancers: - - ContainerName: simple-app - ContainerPort: 80 - TargetGroupArn: !Ref 'ECSTG' - Role: !Ref 'ECSServiceRole' - TaskDefinition: !Ref 'TaskDefinition' - ECSServiceRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ecs.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets', - 'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer', - 'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress'] - Resource: '*' - ServiceScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - MaxCapacity: 2 - MinCapacity: 1 - ResourceId: !Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]] - RoleARN: !GetAtt [AutoscalingRole, Arn] - ScalableDimension: ecs:service:DesiredCount - ServiceNamespace: ecs - ServiceScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: AStepPolicy - PolicyType: StepScaling - ScalingTargetId: !Ref 'ServiceScalingTarget' - StepScalingPolicyConfiguration: - AdjustmentType: PercentChangeInCapacity - Cooldown: 60 - MetricAggregationType: Average - StepAdjustments: - - MetricIntervalLowerBound: 0 - ScalingAdjustment: 200 - ALB500sAlarmScaleUp: - Type: AWS::CloudWatch::Alarm - Properties: - EvaluationPeriods: 1 - Statistic: Average - Threshold: 10 - AlarmDescription: Alarm if our ALB generates too many HTTP 500s. - Period: 60 - AlarmActions: [!Ref 'ServiceScalingPolicy'] - Namespace: AWS/ApplicationELB - Dimensions: - - Name: LoadBalancer - Value: !GetAtt - - ECSALB - - LoadBalancerFullName - ComparisonOperator: GreaterThanThreshold - MetricName: HTTPCode_ELB_5XX_Count - EC2Role: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ec2.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['ecs:CreateCluster', 'ecs:DeregisterContainerInstance', 'ecs:DiscoverPollEndpoint', - 'ecs:Poll', 'ecs:RegisterContainerInstance', 'ecs:StartTelemetrySession', - 'ecs:Submit*', 'logs:CreateLogStream', 'logs:PutLogEvents'] - Resource: '*' - AutoscalingRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [application-autoscaling.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: service-autoscaling - PolicyDocument: - Statement: - - Effect: Allow - Action: ['application-autoscaling:*', 'cloudwatch:DescribeAlarms', 'cloudwatch:PutMetricAlarm', - 'ecs:DescribeServices', 'ecs:UpdateService'] - Resource: '*' - EC2InstanceProfile: - Type: AWS::IAM::InstanceProfile - Properties: - Path: / - Roles: [!Ref 'EC2Role'] -Outputs: - ecsservice: - Value: !Ref 'service' - ecscluster: - Value: !Ref 'ECSCluster' - ECSALB: - Description: Your ALB DNS URL - Value: !Join ['', [!GetAtt [ECSALB, DNSName]]] - taskdef: - Value: !Ref 'TaskDefinition' + GroupId: !Ref DBEC2SecurityGroupStandalone + IpProtocol: "tcp" + FromPort: 0 + ToPort: 65535 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" + + # RDS Instance referencing all security groups + DBInstance: + Type: AWS::RDS::DBInstance + Properties: + PubliclyAccessible: true + DBName: !Ref DBName + Engine: MySQL + VPCSecurityGroups: + - !Ref DBEC2SecurityGroupInline + - !Ref DBEC2SecurityGroupStandalone + diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.json b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.json new file mode 100644 index 00000000000..477923289ad --- /dev/null +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.json @@ -0,0 +1,87 @@ +{ + "Resources": { + "Sample_Service": { + "Type": "AWS::ECS::Service", + "Properties": { + "Cluster": { + "Ref": "ECSCluster" + } + } + }, + "Sample_Cluster": { + "Type": "AWS::ECS::Cluster" + }, + "DBEC2SecurityGroupInline": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Inline IPv4 and IPv6 ingress", + "VpcId": { + "Ref": "VPC" + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 65535, + "CidrIp": "0.0.0.0/0" + }, + { + "IpProtocol": "udp", + "FromPort": 0, + "ToPort": 65535, + "CidrIpv6": "::/0" + } + ] + } + }, + "DBEC2SecurityGroupStandalone": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Standalone IPv4 and IPv6 ingress", + "VpcId": { + "Ref": "VPC" + } + } + }, + "DBEC2SecurityGroupIngress": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DBEC2SecurityGroupStandalone" + }, + "IpProtocol": "-1", + "CidrIp": "0.0.0.0/0" + } + }, + "DBEC2SecurityGroupIngressIPv6": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DBEC2SecurityGroupStandalone" + }, + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 65535, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + }, + "DBInstance": { + "Type": "AWS::RDS::DBInstance", + "Properties": { + "PubliclyAccessible": true, + "DBName": { + "Ref": "DBName" + }, + "Engine": "MySQL", + "VPCSecurityGroups": [ + { + "Ref": "DBEC2SecurityGroupInline" + }, + { + "Ref": "DBEC2SecurityGroupStandalone" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.yaml b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.yaml deleted file mode 100644 index 11edb784160..00000000000 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive2.yaml +++ /dev/null @@ -1,268 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Parameters: - VpcId: - Type: AWS::EC2::VPC::Id - Description: Select a VPC that allows instances access to the Internet. - SubnetId: - Type: List - Description: Select at two subnets in your selected VPC. -Resources: - ECSCluster: - Type: AWS::ECS::Cluster - EcsSecurityGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: ECS Security Group - VpcId: !Ref 'VpcId' - EcsSecurityGroupHTTPinbound: - Type: AWS::EC2::SecurityGroupIngress - Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 80 - ToPort: 0 - CidrIp: 0.0.0.0/0 - EcsSecurityGroupSSHinbound: - Type: AWS::EC2::SecurityGroupIngress - Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 0.0.0.0/0 - EcsSecurityGroupALBports: - Type: AWS::EC2::SecurityGroupIngress - Properties: - GroupId: !Ref 'EcsSecurityGroup' - IpProtocol: tcp - FromPort: 31000 - ToPort: 61000 - SourceSecurityGroupId: !Ref 'EcsSecurityGroup' - CloudwatchLogsGroup: - Type: AWS::Logs::LogGroup - Properties: - LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']] - RetentionInDays: 14 - TaskDefinition: - Type: AWS::ECS::TaskDefinition - Properties: - Family: !Join ['', [!Ref 'AWS::StackName', -ecs-demo-app]] - ContainerDefinitions: - - Name: simple-app - Cpu: 10 - Essential: true - Image: httpd:2.4 - Memory: 300 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - MountPoints: - - ContainerPath: /usr/local/apache2/htdocs - SourceVolume: my-vol - PortMappings: - - ContainerPort: 80 - - Name: busybox - Cpu: 10 - Command: ['/bin/sh -c "while true; do echo '' Amazon ECS - Sample App'' > bottom; cat top date bottom > /usr/local/apache2/htdocs/index.html - ; sleep 1; done"'] - EntryPoint: [sh, -c] - Essential: false - Image: busybox - Memory: 200 - LogConfiguration: - LogDriver: awslogs - Options: - awslogs-group: !Ref 'CloudwatchLogsGroup' - awslogs-region: !Ref 'AWS::Region' - awslogs-stream-prefix: ecs-demo-app - VolumesFrom: - - SourceContainer: simple-app - Volumes: - - Name: my-vol - ECSALB: - Type: AWS::ElasticLoadBalancingV2::LoadBalancer - Properties: - Name: ECSALB - Scheme: internet-facing - LoadBalancerAttributes: - - Key: idle_timeout.timeout_seconds - Value: '30' - Subnets: !Ref 'SubnetId' - SecurityGroups: [!Ref 'EcsSecurityGroup'] - ALBListener: - Type: AWS::ElasticLoadBalancingV2::Listener - Properties: - DefaultActions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - LoadBalancerArn: !Ref 'ECSALB' - Port: 80 - Protocol: HTTP - ECSALBListenerRule: - Type: AWS::ElasticLoadBalancingV2::ListenerRule - Properties: - Actions: - - Type: forward - TargetGroupArn: !Ref 'ECSTG' - Conditions: - - Field: path-pattern - Values: [/] - ListenerArn: !Ref 'ALBListener' - Priority: 1 - ECSTG: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - HealthCheckIntervalSeconds: 10 - HealthCheckPath: / - HealthCheckProtocol: HTTP - HealthCheckTimeoutSeconds: 5 - HealthyThresholdCount: 2 - Name: ECSTG - Port: 80 - Protocol: HTTP - UnhealthyThresholdCount: 2 - VpcId: !Ref 'VpcId' - ECSAutoScalingGroup: - Type: AWS::AutoScaling::AutoScalingGroup - Properties: - VPCZoneIdentifier: !Ref 'SubnetId' - LaunchConfigurationName: !Ref 'ContainerInstances' - MinSize: '1' - MaxSize: 4 - DesiredCapacity: 2 - CreationPolicy: - ResourceSignal: - Timeout: PT15M - UpdatePolicy: - AutoScalingReplacingUpdate: - WillReplace: true - ContainerInstances: - Type: AWS::AutoScaling::LaunchConfiguration - Properties: - ImageId: ami-09bee01cc997a78a6 - SecurityGroups: [!Ref 'EcsSecurityGroup'] - InstanceType: t2.small - IamInstanceProfile: !Ref 'EC2InstanceProfile' - KeyName: my-ssh-key - UserData: - Fn::Base64: !Sub | - #!/bin/bash -xe - echo ECS_CLUSTER=${ECSCluster} >> /etc/ecs/ecs.config - yum install -y aws-cfn-bootstrap - /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region} - service: - Type: AWS::ECS::Service - Properties: - Cluster: !Ref 'ECSCluster' - DesiredCount: 1 - LoadBalancers: - - ContainerName: simple-app - ContainerPort: 80 - TargetGroupArn: !Ref 'ECSTG' - Role: !Ref 'ECSServiceRole' - TaskDefinition: !Ref 'TaskDefinition' - ECSServiceRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ecs.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets', - 'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer', - 'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress'] - Resource: '*' - ServiceScalingTarget: - Type: AWS::ApplicationAutoScaling::ScalableTarget - Properties: - MaxCapacity: 2 - MinCapacity: 1 - ResourceId: !Join ['', [service/, !Ref 'ECSCluster', /, !GetAtt [service, Name]]] - RoleARN: !GetAtt [AutoscalingRole, Arn] - ScalableDimension: ecs:service:DesiredCount - ServiceNamespace: ecs - ServiceScalingPolicy: - Type: AWS::ApplicationAutoScaling::ScalingPolicy - Properties: - PolicyName: AStepPolicy - PolicyType: StepScaling - ScalingTargetId: !Ref 'ServiceScalingTarget' - StepScalingPolicyConfiguration: - AdjustmentType: PercentChangeInCapacity - Cooldown: 60 - MetricAggregationType: Average - StepAdjustments: - - MetricIntervalLowerBound: 0 - ScalingAdjustment: 200 - ALB500sAlarmScaleUp: - Type: AWS::CloudWatch::Alarm - Properties: - EvaluationPeriods: 1 - Statistic: Average - Threshold: 10 - AlarmDescription: Alarm if our ALB generates too many HTTP 500s. - Period: 60 - AlarmActions: [!Ref 'ServiceScalingPolicy'] - Namespace: AWS/ApplicationELB - Dimensions: - - Name: LoadBalancer - Value: !GetAtt - - ECSALB - - LoadBalancerFullName - ComparisonOperator: GreaterThanThreshold - MetricName: HTTPCode_ELB_5XX_Count - EC2Role: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [ec2.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: ecs-service - PolicyDocument: - Statement: - - Effect: Allow - Action: ['ecs:CreateCluster', 'ecs:DeregisterContainerInstance', 'ecs:DiscoverPollEndpoint', - 'ecs:Poll', 'ecs:RegisterContainerInstance', 'ecs:StartTelemetrySession', - 'ecs:Submit*', 'logs:CreateLogStream', 'logs:PutLogEvents'] - Resource: '*' - AutoscalingRole: - Type: AWS::IAM::Role - Properties: - AssumeRolePolicyDocument: - Statement: - - Effect: Allow - Principal: - Service: [application-autoscaling.amazonaws.com] - Action: ['sts:AssumeRole'] - Path: / - Policies: - - PolicyName: service-autoscaling - PolicyDocument: - Statement: - - Effect: Allow - Action: ['application-autoscaling:*', 'cloudwatch:DescribeAlarms', 'cloudwatch:PutMetricAlarm', - 'ecs:DescribeServices', 'ecs:UpdateService'] - Resource: '*' - EC2InstanceProfile: - Type: AWS::IAM::InstanceProfile - Properties: - Path: / - Roles: [!Ref 'EC2Role'] - diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive3.json b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive3.json deleted file mode 100644 index ad510cda6ee..00000000000 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive3.json +++ /dev/null @@ -1,488 +0,0 @@ -{ - "AWSTemplateFormatVersion": "2010-09-09", - "Parameters": { - "VpcId": { - "Type": "AWS::EC2::VPC::Id", - "Description": "Select a VPC that allows instances access to the Internet." - }, - "SubnetId": { - "Type": "List\u003cAWS::EC2::Subnet::Id\u003e", - "Description": "Select at two subnets in your selected VPC." - } - }, - "Resources": { - "ECSCluster": { - "Type": "AWS::ECS::Cluster" - }, - "EcsSecurityGroupALBports": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "IpProtocol": "tcp", - "FromPort": 31000, - "ToPort": 61000, - "SourceSecurityGroupId": "EcsSecurityGroup", - "GroupId": "EcsSecurityGroup" - } - }, - "ECSServiceRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "ecs.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:DeregisterTargets", - "elasticloadbalancing:Describe*", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:RegisterTargets", - "ec2:Describe*", - "ec2:AuthorizeSecurityGroupIngress" - ], - "Resource": "*", - "Effect": "Allow" - } - ] - } - } - ] - } - }, - "AutoscalingRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "application-autoscaling.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "service-autoscaling", - "PolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "application-autoscaling:*", - "cloudwatch:DescribeAlarms", - "cloudwatch:PutMetricAlarm", - "ecs:DescribeServices", - "ecs:UpdateService" - ], - "Resource": "*" - } - ] - } - } - ] - } - }, - "EcsSecurityGroupSSHinbound": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "ToPort": 0, - "CidrIp": "0.0.0.0/0", - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 22 - } - }, - "ECSALB": { - "Properties": { - "Name": "ECSALB", - "Scheme": "internet-facing", - "LoadBalancerAttributes": [ - { - "Key": "idle_timeout.timeout_seconds", - "Value": "30" - } - ], - "Subnets": "SubnetId", - "SecurityGroups": [ - "EcsSecurityGroup" - ] - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer" - }, - "ECSAutoScalingGroup": { - "Type": "AWS::AutoScaling::AutoScalingGroup", - "Properties": { - "VPCZoneIdentifier": "SubnetId", - "LaunchConfigurationName": "ContainerInstances", - "MinSize": "1", - "MaxSize": 4, - "DesiredCapacity": 2 - }, - "CreationPolicy": { - "ResourceSignal": { - "Timeout": "PT15M" - } - }, - "UpdatePolicy": { - "AutoScalingReplacingUpdate": { - "WillReplace": true - } - } - }, - "ServiceScalingTarget": { - "Type": "AWS::ApplicationAutoScaling::ScalableTarget", - "Properties": { - "MaxCapacity": 2, - "MinCapacity": 1, - "ResourceId": [ - "", - [ - "service/", - "ECSCluster", - "/", - [ - "service", - "Name" - ] - ] - ], - "RoleARN": [ - "AutoscalingRole", - "Arn" - ], - "ScalableDimension": "ecs:service:DesiredCount", - "ServiceNamespace": "ecs" - } - }, - "ServiceScalingPolicy": { - "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", - "Properties": { - "PolicyType": "StepScaling", - "ScalingTargetId": "ServiceScalingTarget", - "StepScalingPolicyConfiguration": { - "StepAdjustments": [ - { - "MetricIntervalLowerBound": 0, - "ScalingAdjustment": 200 - } - ], - "AdjustmentType": "PercentChangeInCapacity", - "Cooldown": 60, - "MetricAggregationType": "Average" - }, - "PolicyName": "AStepPolicy" - } - }, - "EC2Role": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "ec2.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ecs:CreateCluster", - "ecs:DeregisterContainerInstance", - "ecs:DiscoverPollEndpoint", - "ecs:Poll", - "ecs:RegisterContainerInstance", - "ecs:StartTelemetrySession", - "ecs:Submit*", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Resource": "*", - "Effect": "Allow" - } - ] - } - } - ] - } - }, - "ECSTG": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "Name": "ECSTG", - "Port": 80, - "Protocol": "HTTP", - "HealthCheckPath": "/", - "HealthyThresholdCount": 2, - "UnhealthyThresholdCount": 2, - "VpcId": "VpcId" - } - }, - "service": { - "Type": "AWS::ECS::Service", - "Properties": { - "Cluster": "ECSCluster", - "DesiredCount": 1, - "LoadBalancers": [ - { - "ContainerName": "simple-app", - "ContainerPort": 80, - "TargetGroupArn": "ECSTG" - } - ], - "Role": "ECSServiceRole", - "TaskDefinition": "TaskDefinition" - } - }, - "ALB500sAlarmScaleUp": { - "Properties": { - "Threshold": 10, - "Dimensions": [ - { - "Name": "LoadBalancer", - "Value": [ - "ECSALB", - "LoadBalancerFullName" - ] - } - ], - "ComparisonOperator": "GreaterThanThreshold", - "MetricName": "HTTPCode_ELB_5XX_Count", - "EvaluationPeriods": 1, - "AlarmDescription": "Alarm if our ALB generates too many HTTP 500s.", - "Period": 60, - "AlarmActions": [ - "ServiceScalingPolicy" - ], - "Namespace": "AWS/ApplicationELB", - "Statistic": "Average" - }, - "Type": "AWS::CloudWatch::Alarm" - }, - "EC2InstanceProfile": { - "Type": "AWS::IAM::InstanceProfile", - "Properties": { - "Path": "/", - "Roles": [ - "EC2Role" - ] - } - }, - "EcsSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "VpcId": "VpcId", - "GroupDescription": "ECS Security Group" - } - }, - "EcsSecurityGroupHTTPinbound02": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 0, - "CidrIp": "0.0.0.0/0" - } - }, - "CloudwatchLogsGroup": { - "Type": "AWS::Logs::LogGroup", - "Properties": { - "LogGroupName": [ - "-", - [ - "ECSLogGroup", - "AWS::StackName" - ] - ], - "RetentionInDays": 14 - } - }, - "TaskDefinition": { - "Type": "AWS::ECS::TaskDefinition", - "Properties": { - "Family": [ - "", - [ - "AWS::StackName", - "-ecs-demo-app" - ] - ], - "ContainerDefinitions": [ - { - "Name": "simple-app", - "Cpu": 10, - "Essential": true, - "Image": "httpd:2.4", - "Memory": 300, - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region", - "awslogs-stream-prefix": "ecs-demo-app" - } - }, - "MountPoints": [ - { - "ContainerPath": "/usr/local/apache2/htdocs", - "SourceVolume": "my-vol" - } - ], - "PortMappings": [ - { - "ContainerPort": 80 - } - ] - }, - { - "VolumesFrom": [ - { - "SourceContainer": "simple-app" - } - ], - "Name": "busybox", - "Cpu": 10, - "Command": [ - "/bin/sh -c \"while true; do echo '\u003chtml\u003e \u003chead\u003e \u003ctitle\u003eAmazon ECS Sample App\u003c/title\u003e\u003c/head\u003e\u003c/html\u003e' \u003e bottom; cat top date bottom \u003e /usr/local/apache2/htdocs/index.html ; sleep 1; done\"" - ], - "Image": "busybox", - "Memory": 200, - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-stream-prefix": "ecs-demo-app", - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region" - } - }, - "EntryPoint": [ - "sh", - "-c" - ], - "Essential": false - } - ], - "Volumes": [ - { - "Name": "my-vol" - } - ] - } - }, - "ALBListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "LoadBalancerArn": "ECSALB", - "Port": 80, - "Protocol": "HTTP", - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "ECSTG" - } - ] - } - }, - "ECSALBListenerRule": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - "Properties": { - "Actions": [ - { - "Type": "forward", - "TargetGroupArn": "ECSTG" - } - ], - "Conditions": [ - { - "Values": [ - "/" - ], - "Field": "path-pattern" - } - ], - "ListenerArn": "ALBListener", - "Priority": 1 - } - }, - "ContainerInstances": { - "Type": "AWS::AutoScaling::LaunchConfiguration", - "Properties": { - "ImageId": "ami-128731982dhash", - "SecurityGroups": [ - "EcsSecurityGroup" - ], - "InstanceType": "t2.small", - "IamInstanceProfile": "EC2InstanceProfile", - "KeyName": "my-ssh-key", - "UserData": { - "Fn::Base64": "#!/bin/bash -xe\necho ECS_CLUSTER=${ECSCluster} \u003e\u003e /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}\n" - } - } - } - }, - "Outputs": { - "ecscluster": { - "Value": "ECSCluster" - }, - "ECSALB": { - "Description": "Your ALB DNS URL", - "Value": [ - "", - [ - [ - "ECSALB", - "DNSName" - ] - ] - ] - }, - "taskdef": { - "Value": "TaskDefinition" - }, - "ecsservice": { - "Value": "service" - } - } -} diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive4.json b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive4.json deleted file mode 100644 index 80a3785dccf..00000000000 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive4.json +++ /dev/null @@ -1,465 +0,0 @@ -{ - "Resources": { - "TaskDefinition": { - "Type": "AWS::ECS::TaskDefinition", - "Properties": { - "Family": [ - "", - [ - "AWS::StackName", - "-ecs-demo-app" - ] - ], - "ContainerDefinitions": [ - { - "Essential": true, - "Image": "httpd:2.4", - "Memory": 300, - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region", - "awslogs-stream-prefix": "ecs-demo-app" - } - }, - "MountPoints": [ - { - "SourceVolume": "my-vol", - "ContainerPath": "/usr/local/apache2/htdocs" - } - ], - "PortMappings": [ - { - "ContainerPort": 80 - } - ], - "Name": "simple-app", - "Cpu": 10 - }, - { - "EntryPoint": [ - "sh", - "-c" - ], - "Essential": false, - "Memory": 200, - "Command": [ - "/bin/sh -c \"while true; do echo '\u003chtml\u003e \u003chead\u003e \u003ctitle\u003eAmazon ECS Sample App\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003c/body\u003e\u003c/html\u003e' \u003e bottom; cat top date bottom \u003e /usr/local/apache2/htdocs/index.html ; sleep 1; done\"" - ], - "Cpu": 10, - "Image": "busybox", - "LogConfiguration": { - "LogDriver": "awslogs", - "Options": { - "awslogs-stream-prefix": "ecs-demo-app", - "awslogs-group": "CloudwatchLogsGroup", - "awslogs-region": "AWS::Region" - } - }, - "VolumesFrom": [ - { - "SourceContainer": "simple-app" - } - ], - "Name": "busybox" - } - ], - "Volumes": [ - { - "Name": "my-vol" - } - ] - } - }, - "ALBListener": { - "Type": "AWS::ElasticLoadBalancingV2::Listener", - "Properties": { - "DefaultActions": [ - { - "Type": "forward", - "TargetGroupArn": "ECSTG" - } - ], - "LoadBalancerArn": "ECSALB", - "Port": 80, - "Protocol": "HTTP" - } - }, - "ECSServiceRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "ecs.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", - "elasticloadbalancing:DeregisterTargets", - "elasticloadbalancing:Describe*", - "elasticloadbalancing:RegisterInstancesWithLoadBalancer", - "elasticloadbalancing:RegisterTargets", - "ec2:Describe*", - "ec2:AuthorizeSecurityGroupIngress" - ], - "Resource": "*", - "Effect": "Allow" - } - ] - } - } - ] - } - }, - "ALB500sAlarmScaleUp": { - "Type": "AWS::CloudWatch::Alarm", - "Properties": { - "Period": 60, - "Dimensions": [ - { - "Name": "LoadBalancer", - "Value": [ - "ECSALB", - "LoadBalancerFullName" - ] - } - ], - "ComparisonOperator": "GreaterThanThreshold", - "AlarmDescription": "Alarm if our ALB generates too many HTTP 500s.", - "Statistic": "Average", - "Threshold": 10, - "AlarmActions": [ - "ServiceScalingPolicy" - ], - "Namespace": "AWS/ApplicationELB", - "MetricName": "HTTPCode_ELB_5XX_Count", - "EvaluationPeriods": 1 - } - }, - "service": { - "Type": "AWS::ECS::Service", - "Properties": { - "TaskDefinition": "TaskDefinition", - "Cluster": "ECSCluster", - "DesiredCount": 1, - "LoadBalancers": [ - { - "ContainerName": "simple-app", - "ContainerPort": 80, - "TargetGroupArn": "ECSTG" - } - ], - "Role": "ECSServiceRole" - } - }, - "EcsSecurityGroupSSHinbound": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 22, - "ToPort": 22, - "CidrIp": "0.0.0.0/0" - } - }, - "EcsSecurityGroupALBports": { - "Type": "AWS::EC2::SecurityGroupIngress", - "Properties": { - "FromPort": 31000, - "ToPort": 61000, - "SourceSecurityGroupId": "EcsSecurityGroup", - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp" - } - }, - "CloudwatchLogsGroup": { - "Type": "AWS::Logs::LogGroup", - "Properties": { - "RetentionInDays": 14, - "LogGroupName": [ - "-", - [ - "ECSLogGroup", - "AWS::StackName" - ] - ] - } - }, - "ECSALB": { - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - "Properties": { - "Scheme": "internet-facing", - "LoadBalancerAttributes": [ - { - "Key": "idle_timeout.timeout_seconds", - "Value": "30" - } - ], - "Subnets": "SubnetId", - "SecurityGroups": [ - "EcsSecurityGroup" - ], - "Name": "ECSALB" - } - }, - "ECSALBListenerRule": { - "Type": "AWS::ElasticLoadBalancingV2::ListenerRule", - "Properties": { - "Actions": [ - { - "Type": "forward", - "TargetGroupArn": "ECSTG" - } - ], - "Conditions": [ - { - "Field": "path-pattern", - "Values": [ - "/" - ] - } - ], - "ListenerArn": "ALBListener", - "Priority": 1 - } - }, - "ContainerInstances": { - "Type": "AWS::AutoScaling::LaunchConfiguration", - "Properties": { - "IamInstanceProfile": "EC2InstanceProfile", - "KeyName": "my-ssh-key", - "UserData": { - "Fn::Base64": "#!/bin/bash -xe\necho ECS_CLUSTER=${ECSCluster} \u003e\u003e /etc/ecs/ecs.config\nyum install -y aws-cfn-bootstrap\n/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ECSAutoScalingGroup --region ${AWS::Region}\n" - }, - "ImageId": "ami-09bee01cc997a78a6", - "SecurityGroups": [ - "EcsSecurityGroup" - ], - "InstanceType": "t2.small" - } - }, - "ECSCluster": { - "Type": "AWS::ECS::Cluster" - }, - "EcsSecurityGroupHTTPinbound": { - "Properties": { - "GroupId": "EcsSecurityGroup", - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 0, - "CidrIp": "0.0.0.0/0" - }, - "Type": "AWS::EC2::SecurityGroupIngress" - }, - "ECSTG": { - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - "Properties": { - "Name": "ECSTG", - "Port": 80, - "VpcId": "VpcId", - "HealthCheckPath": "/", - "HealthCheckProtocol": "HTTP", - "HealthyThresholdCount": 2, - "Protocol": "HTTP", - "UnhealthyThresholdCount": 2, - "HealthCheckIntervalSeconds": 10, - "HealthCheckTimeoutSeconds": 5 - } - }, - "ServiceScalingTarget": { - "Type": "AWS::ApplicationAutoScaling::ScalableTarget", - "Properties": { - "MaxCapacity": 2, - "MinCapacity": 1, - "ResourceId": [ - "", - [ - "service/", - "ECSCluster", - "/", - [ - "service", - "Name" - ] - ] - ], - "RoleARN": [ - "AutoscalingRole", - "Arn" - ], - "ScalableDimension": "ecs:service:DesiredCount", - "ServiceNamespace": "ecs" - } - }, - "AutoscalingRole": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Service": [ - "application-autoscaling.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ] - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "service-autoscaling", - "PolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "application-autoscaling:*", - "cloudwatch:DescribeAlarms", - "cloudwatch:PutMetricAlarm", - "ecs:DescribeServices", - "ecs:UpdateService" - ], - "Resource": "*" - } - ] - } - } - ] - } - }, - "EcsSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "ECS Security Group", - "VpcId": "VpcId" - } - }, - "ECSAutoScalingGroup": { - "CreationPolicy": { - "ResourceSignal": { - "Timeout": "PT15M" - } - }, - "UpdatePolicy": { - "AutoScalingReplacingUpdate": { - "WillReplace": true - } - }, - "Type": "AWS::AutoScaling::AutoScalingGroup", - "Properties": { - "VPCZoneIdentifier": "SubnetId", - "LaunchConfigurationName": "ContainerInstances", - "MinSize": "1", - "MaxSize": 4, - "DesiredCapacity": 2 - } - }, - "ServiceScalingPolicy": { - "Type": "AWS::ApplicationAutoScaling::ScalingPolicy", - "Properties": { - "PolicyName": "AStepPolicy", - "PolicyType": "StepScaling", - "ScalingTargetId": "ServiceScalingTarget", - "StepScalingPolicyConfiguration": { - "AdjustmentType": "PercentChangeInCapacity", - "Cooldown": 60, - "MetricAggregationType": "Average", - "StepAdjustments": [ - { - "MetricIntervalLowerBound": 0, - "ScalingAdjustment": 200 - } - ] - } - } - }, - "EC2Role": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Principal": { - "Service": [ - "ec2.amazonaws.com" - ] - }, - "Action": [ - "sts:AssumeRole" - ], - "Effect": "Allow" - } - ] - }, - "Path": "/", - "Policies": [ - { - "PolicyName": "ecs-service", - "PolicyDocument": { - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "ecs:CreateCluster", - "ecs:DeregisterContainerInstance", - "ecs:DiscoverPollEndpoint", - "ecs:Poll", - "ecs:RegisterContainerInstance", - "ecs:StartTelemetrySession", - "ecs:Submit*", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Resource": "*" - } - ] - } - } - ] - } - }, - "EC2InstanceProfile": { - "Properties": { - "Path": "/", - "Roles": [ - "EC2Role" - ] - }, - "Type": "AWS::IAM::InstanceProfile" - } - }, - "AWSTemplateFormatVersion": "2010-09-09", - "Parameters": { - "VpcId": { - "Type": "AWS::EC2::VPC::Id", - "Description": "Select a VPC that allows instances access to the Internet." - }, - "SubnetId": { - "Type": "List\u003cAWS::EC2::Subnet::Id\u003e", - "Description": "Select at two subnets in your selected VPC." - } - } -} diff --git a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive_expected_result.json index c7b36b92ce4..152afc34c12 100644 --- a/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/fully_open_ingress/test/positive_expected_result.json @@ -1,38 +1,50 @@ [ { - "fileName": "positive1.yaml", "queryName": "Fully Open Ingress", "severity": "HIGH", - "line": 32 + "line": 19, + "fileName": "positive1.yaml" }, { - "line": 24, - "fileName": "positive1.yaml", "queryName": "Fully Open Ingress", - "severity": "HIGH" + "severity": "HIGH", + "line": 23, + "fileName": "positive1.yaml" + }, + { + "queryName": "Fully Open Ingress", + "severity": "HIGH", + "line": 37, + "fileName": "positive1.yaml" }, { "queryName": "Fully Open Ingress", "severity": "HIGH", - "line": 24, - "fileName": "positive2.yaml" + "line": 46, + "fileName": "positive1.yaml" }, { "queryName": "Fully Open Ingress", "severity": "HIGH", - "line": 115, - "fileName": "positive3.json" + "line": 26, + "fileName": "positive2.json" }, { + "queryName": "Fully Open Ingress", + "severity": "HIGH", + "line": 32, + "fileName": "positive2.json" + }, + { + "queryName": "Fully Open Ingress", "severity": "HIGH", - "line": 326, - "fileName": "positive3.json", - "queryName": "Fully Open Ingress" + "line": 53, + "fileName": "positive2.json" }, { "queryName": "Fully Open Ingress", "severity": "HIGH", - "line": 268, - "fileName": "positive4.json" + "line": 65, + "fileName": "positive2.json" } ] diff --git a/assets/queries/cloudFormation/aws/http_port_open/query.rego b/assets/queries/cloudFormation/aws/http_port_open/query.rego index 6fa5cec6f48..4a4c1993e48 100644 --- a/assets/queries/cloudFormation/aws/http_port_open/query.rego +++ b/assets/queries/cloudFormation/aws/http_port_open/query.rego @@ -4,38 +4,71 @@ import data.generic.cloudformation as cf_lib import data.generic.common as common_lib CxPolicy[result] { - resource := input.document[i].Resources[name] - resource.Type == "AWS::EC2::SecurityGroup" + doc := input.document[i] + sec_group := doc.Resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" - rule := resource.Properties.SecurityGroupIngress[index] + ingresses_with_names := search_for_standalone_ingress(sec_group_name, doc) - entireNetwork(rule) - isTCP(rule.IpProtocol) - rule.FromPort <= 80 - rule.ToPort >= 80 + ingress_list := array.concat(ingresses_with_names.ingress_list, get_ingress_list_if_exists(sec_group)) + ingress := ingress_list[ing_index] + + cf_lib.entireNetwork(ingress) + isTCP_and_port_exposed(ingress, 80) + + results := get_search_values(ing_index, sec_group_name, ingresses_with_names.names) result := { - "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("Resources.%s.Properties.SecurityGroupIngress", [name]), - "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupIngress", index], []), + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d] should not open the HTTP port (80)", [name, index]), - "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d] opens the HTTP port (80)", [name, index]), + "keyExpectedValue": sprintf("'%s' should not open the HTTP port (80)", [results.searchKey]), + "keyActualValue": sprintf("'%s' opens the HTTP port (80)", [results.searchKey]), + "searchLine": results.searchLine, } } -entireNetwork(rule) { - rule.CidrIp == "0.0.0.0/0" +isTCP_and_port_exposed(ingress, port) { + ingress.IpProtocol == ["tcp","6"][_] + cf_lib.containsPort(ingress.FromPort, ingress.ToPort, port) +} else { + ingress.IpProtocol == "-1" } -entireNetwork(rule) { - rule.CidrIpv6 == "::/0" -} +search_for_standalone_ingress(sec_group_name, doc) = ingresses_with_names { + resources := doc.Resources + + names := [name | + ingress := resources[name] + ingress.Type == "AWS::EC2::SecurityGroupIngress" + cf_lib.get_name(ingress.Properties.GroupId) == sec_group_name + ] -isTCP("tcp") := true + ingresses_with_names := { + "ingress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = {"ingress_list": [], "names": []} -isTCP("-1") := true +get_search_values(ing_index, sec_group_name, names_list) = results { + ing_index < count(names_list) # if ingress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[ing_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[ing_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupIngress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupIngress[%d]", [sec_group_name, ing_index-count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupIngress", ing_index-count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" + } +} -isTCP("6") := true +get_ingress_list_if_exists(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupIngress") +} else = group.Properties.SecurityGroupIngress diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/negative1.yaml b/assets/queries/cloudFormation/aws/http_port_open/test/negative1.yaml index 6f8d672ce55..537e960e388 100644 --- a/assets/queries/cloudFormation/aws/http_port_open/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/http_port_open/test/negative1.yaml @@ -1,12 +1,82 @@ Resources: - InstanceSecurityGroup: +# IPv4 Rules + Negative1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow http to client host VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: tcp + - IpProtocol: "udp" # wrong protocol FromPort: 80 ToPort: 80 - CidrIp: 192.168.0.0/16 + CidrIp: 0.0.0.0/0 + + Negative1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 100 + ToPort: 200 # not catching port 80 + CidrIp: 0.0.0.0/0 + + Negative1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 0 + ToPort: 1000 + CidrIp: 192.0.0.0/16 # CidrIP is not 0:0:0:0/0 + - IpProtocol: "udp" # all fields "incorrect" + FromPort: 1000 + ToPort: 2000 + CidrIp: 192.120.0.0/16 + +# IPv6 Rules + Negative1IPv6_1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "udp" # wrong protocol + FromPort: 80 + ToPort: 80 + CidrIpv6: "::/0" + + Negative1IPv6_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 5000 + ToPort: 5000 # not catching port 80 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" + + Negative1ArrayTestIPv6: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 0 + ToPort: 1000 + CidrIpv6: "2400:cb00::/32" # CidrIpv6 is not ::/0 + - IpProtocol: "udp" # all fields "incorrect" + FromPort: 1000 + ToPort: 2000 + CidrIpv6: "2400:cb00::/32" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/negative2.json b/assets/queries/cloudFormation/aws/http_port_open/test/negative2.json deleted file mode 100644 index 1fa7af2dbe6..00000000000 --- a/assets/queries/cloudFormation/aws/http_port_open/test/negative2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Resources": { - "InstanceSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http to client host", - "VpcId": { - "Ref": "myVPC" - }, - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "192.168.0.0/16" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/negative2.yaml b/assets/queries/cloudFormation/aws/http_port_open/test/negative2.yaml new file mode 100644 index 00000000000..5da3f898dd6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/negative2.yaml @@ -0,0 +1,81 @@ +Resources: + + Negative2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for negative test cases" + VpcId: !Ref MyVPC + +# IPv4 Rules + Negative2IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # incorrect protocol + FromPort: 80 + ToPort: 80 + CidrIp: "0.0.0.0/0" + + Negative2IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 100 # not catching port 80 + ToPort: 200 + CidrIp: "0.0.0.0/0" + + Negative2IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "-1" + FromPort: 0 + ToPort: 100 + CidrIp: "8.8.0.0/16" # CidrIP is not 0:0:0:0/0 + + Negative2IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # all fields "incorrect" + FromPort: 5000 + ToPort: 5000 + CidrIp: "8.8.0.0/16" + +# IPv6 Rules + Negative2IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # incorrect protocol + FromPort: 80 + ToPort: 80 + CidrIpv6: "::/0" + + Negative2IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # not catching port 80 + ToPort: 5000 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" + + Negative2IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "-1" + FromPort: 0 + ToPort: 100 + CidrIpv6: "2400:cb00::/32" # CidrIP is not 0:0:0:0/0 + + Negative2IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "udp" + FromPort: 5000 + ToPort: 5000 + CidrIpv6: "2400:cb00::/32" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/negative3.json b/assets/queries/cloudFormation/aws/http_port_open/test/negative3.json new file mode 100644 index 00000000000..f4ffc49d7d5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/negative3.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "Negative1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Negative1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 100, + "ToPort": 200, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Negative1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 0, + "ToPort": 1000, + "CidrIp": "192.0.0.0/16" + }, + { + "IpProtocol": "udp", + "FromPort": 1000, + "ToPort": 2000, + "CidrIp": "192.120.0.0/16" + } + ] + } + }, + "Negative1IPv6_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 80, + "ToPort": 80, + "CidrIpv6": "::/0" + } + ] + } + }, + "Negative1IPv6_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + ] + } + }, + "Negative1ArrayTestIPv6": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 0, + "ToPort": 1000, + "CidrIpv6": "2400:cb00::/32" + }, + { + "IpProtocol": "udp", + "FromPort": 1000, + "ToPort": 2000, + "CidrIpv6": "2400:cb00::/32" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/negative4.json b/assets/queries/cloudFormation/aws/http_port_open/test/negative4.json new file mode 100644 index 00000000000..85f440114d6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/negative4.json @@ -0,0 +1,109 @@ +{ + "Resources": { + "Negative2SecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for negative test cases", + "VpcId": { + "Ref": "MyVPC" + } + } + }, + "Negative2IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative2IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 100, + "ToPort": 200, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative2IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 0, + "ToPort": 100, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "::/0" + } + }, + "Negative2IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + }, + "Negative2IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, + "CidrIpv6": "2400:cb00::/32" + } + }, + "Negative2IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "2400:cb00::/32" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive1.yaml b/assets/queries/cloudFormation/aws/http_port_open/test/positive1.yaml index 317c8ee5eda..0e20bcc52fc 100644 --- a/assets/queries/cloudFormation/aws/http_port_open/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/http_port_open/test/positive1.yaml @@ -1,12 +1,82 @@ Resources: - InstanceSecurityGroup: +# IPv4 Rules + Positive1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow http to client host VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: tcp + - IpProtocol: "tcp" FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 + + Positive1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIp: 0.0.0.0/0 + + Positive1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 0 + ToPort: 1000 + CidrIp: 192.0.0.0/16 + - IpProtocol: "6" + FromPort: 0 + ToPort: 100 + CidrIp: 0.0.0.0/0 + +# IPv6 Rules + Positive1IPv6_1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 80 + ToPort: 80 + CidrIpv6: "::/0" + + Positive1IPv6_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIpv6: "::/0" + + Positive1ArrayTestIPv6: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 0 + ToPort: 1000 + CidrIpv6: "2400:cb00::/32" #should not flag - used to test array index search + - IpProtocol: "6" + FromPort: 70 + ToPort: 90 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive2.json b/assets/queries/cloudFormation/aws/http_port_open/test/positive2.json deleted file mode 100644 index a21416ad6fc..00000000000 --- a/assets/queries/cloudFormation/aws/http_port_open/test/positive2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Resources": { - "InstanceSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow http to client host", - "VpcId": { - "Ref": "myVPC" - }, - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "0.0.0.0/0" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive2.yaml b/assets/queries/cloudFormation/aws/http_port_open/test/positive2.yaml new file mode 100644 index 00000000000..98338ef13b6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/positive2.yaml @@ -0,0 +1,45 @@ +Resources: + + DualStackSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for IPv4 and IPv6 ingress rules" + VpcId: !Ref MyVPC + +# IPv4 Rules + IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIp: "0.0.0.0/0" + + IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 70 + ToPort: 90 + CidrIp: "0.0.0.0/0" + +# IPv6 Rules + IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 80 + ToPort: 80 + CidrIpv6: "::/0" + + IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 70 + ToPort: 90 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive3.json b/assets/queries/cloudFormation/aws/http_port_open/test/positive3.json new file mode 100644 index 00000000000..db005496e1b --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/positive3.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "Positive1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 1000, + "CidrIp": "192.0.0.0/16" + }, + { + "IpProtocol": "6", + "FromPort": 0, + "ToPort": 100, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1IPv6_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIpv6": "::/0" + } + ] + } + }, + "Positive1IPv6_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIpv6": "::/0" + } + ] + } + }, + "Positive1ArrayTestIPv6": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 1000, + "CidrIpv6": "2400:cb00::/32" + }, + { + "IpProtocol": "6", + "FromPort": 70, + "ToPort": 90, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive3.yaml b/assets/queries/cloudFormation/aws/http_port_open/test/positive3.yaml deleted file mode 100644 index ee275a01ac3..00000000000 --- a/assets/queries/cloudFormation/aws/http_port_open/test/positive3.yaml +++ /dev/null @@ -1,12 +0,0 @@ -Resources: - InstanceSecurityGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http to client host - VpcId: - Ref: myVPC - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 70 - ToPort: 90 - CidrIp: 0.0.0.0/0 diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive4.json b/assets/queries/cloudFormation/aws/http_port_open/test/positive4.json new file mode 100644 index 00000000000..bce042b05f6 --- /dev/null +++ b/assets/queries/cloudFormation/aws/http_port_open/test/positive4.json @@ -0,0 +1,61 @@ +{ + "Resources": { + "DualStackSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for IPv4 and IPv6 ingress rules", + "VpcId": { + "Ref": "MyVPC" + } + } + }, + "IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIp": "0.0.0.0/0" + } + }, + "IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 70, + "ToPort": 90, + "CidrIp": "0.0.0.0/0" + } + }, + "IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIpv6": "::/0" + } + }, + "IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 70, + "ToPort": 90, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/http_port_open/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/http_port_open/test/positive_expected_result.json index afb21f9ee29..b8eae749e61 100644 --- a/assets/queries/cloudFormation/aws/http_port_open/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/http_port_open/test/positive_expected_result.json @@ -2,19 +2,121 @@ { "queryName": "HTTP Port Open To Internet", "severity": "MEDIUM", - "line": 9, + "line": 10, "fileName": "positive1.yaml" }, { - "fileName": "positive2.json", "queryName": "HTTP Port Open To Internet", "severity": "MEDIUM", - "line": 12 + "line": 22, + "fileName": "positive1.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 38, + "fileName": "positive1.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 51, + "fileName": "positive1.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 63, + "fileName": "positive1.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 79, + "fileName": "positive1.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 12, + "fileName": "positive2.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 21, + "fileName": "positive2.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 31, + "fileName": "positive2.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 40, + "fileName": "positive2.yaml" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 10, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 25, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 46, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 61, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 76, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 97, + "fileName": "positive3.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 14, + "fileName": "positive4.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 26, + "fileName": "positive4.json" + }, + { + "queryName": "HTTP Port Open To Internet", + "severity": "MEDIUM", + "line": 38, + "fileName": "positive4.json" }, { "queryName": "HTTP Port Open To Internet", "severity": "MEDIUM", - "line": 9, - "fileName": "positive3.yaml" + "line": 50, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/metadata.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/metadata.json index 06866d81da3..818ec2b56c5 100644 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/metadata.json +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/metadata.json @@ -8,6 +8,6 @@ "platform": "CloudFormation", "descriptionID": "2e4ef03f", "cloudProvider": "aws", - "cwe": "668", + "cwe": "1188", "riskScore": "7.7" } \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/query.rego b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/query.rego index ec49d2ace70..4ff7ad292f6 100644 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/query.rego +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/query.rego @@ -1,41 +1,74 @@ package Cx import data.generic.cloudformation as cf_lib +import data.generic.common as common_lib CxPolicy[result] { - docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] - resource.Type == "AWS::EC2::SecurityGroup" + doc := input.document[i] + sec_group := doc.Resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" - rule := resource.Properties.SecurityGroupIngress[index] + ingresses_with_names := search_for_standalone_ingress(sec_group_name, doc) - entireNetwork(rule) - isTCP(rule.IpProtocol) - rule.FromPort <= 3389 - rule.ToPort >= 3389 + ingress_list := array.concat(ingresses_with_names.ingress_list, get_ingress_list_if_exists(sec_group)) + ingress := ingress_list[ing_index] + + cf_lib.entireNetwork(ingress) + isTCP_and_port_exposed(ingress, 3389) + + results := get_search_values(ing_index, sec_group_name, ingresses_with_names.names) result := { - "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupIngress", [cf_lib.getPath(path), name]), + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d] should not open the remote desktop port (3389)", [name, index]), - "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d] opens the remote desktop port (3389)", [name, index]), + "keyExpectedValue": sprintf("'%s' should not open the remote desktop port (3389)", [results.searchKey]), + "keyActualValue": sprintf("'%s' opens the remote desktop port (3389)", [results.searchKey]), + "searchLine": results.searchLine, } } -entireNetwork(rule) { - rule.CidrIp == "0.0.0.0/0" +isTCP_and_port_exposed(ingress, port) { + ingress.IpProtocol == ["tcp","6"][_] + cf_lib.containsPort(ingress.FromPort, ingress.ToPort, port) +} else { + ingress.IpProtocol == "-1" } -entireNetwork(rule) { - rule.CidrIpv6 == "::/0" -} +search_for_standalone_ingress(sec_group_name, doc) = ingresses_with_names { + resources := doc.Resources + + names := [name | + ingress := resources[name] + ingress.Type == "AWS::EC2::SecurityGroupIngress" + cf_lib.get_name(ingress.Properties.GroupId) == sec_group_name + ] -isTCP("tcp") = true + ingresses_with_names := { + "ingress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = {"ingress_list": [], "names": []} -isTCP("-1") = true +get_search_values(ing_index, sec_group_name, names_list) = results { + ing_index < count(names_list) # if ingress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[ing_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[ing_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupIngress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupIngress[%d]", [sec_group_name, ing_index-count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupIngress", ing_index-count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" + } +} -isTCP("6") = true +get_ingress_list_if_exists(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupIngress") +} else = group.Properties.SecurityGroupIngress diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative1.yaml b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative1.yaml index 1eb4a85052f..584d7295bf2 100644 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative1.yaml @@ -1,12 +1,82 @@ Resources: - InstanceSecurityGroup: +# IPv4 Rules + Negative1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow rdp to client host + GroupDescription: Allow http to client host VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: tcp + - IpProtocol: "udp" # wrong protocol FromPort: 3389 ToPort: 3389 - CidrIp: 192.168.0.0/16 + CidrIp: 0.0.0.0/0 + + Negative1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 100 + ToPort: 200 # not catching port 3389 + CidrIp: 0.0.0.0/0 + + Negative1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 2000 + ToPort: 4000 + CidrIp: 192.0.0.0/16 # CidrIP is not 0:0:0:0/0 + - IpProtocol: udp # all fields "incorrect" + FromPort: 1000 + ToPort: 2000 + CidrIp: 192.120.0.0/16 + +# IPv6 Rules + Negative1IPv6_1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "udp" # wrong protocol + FromPort: 3389 + ToPort: 3389 + CidrIpv6: "::/0" + + Negative1IPv6_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 5000 + ToPort: 5000 # not catching port 80 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" + + Negative1ArrayTestIPv6: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 2000 + ToPort: 4000 + CidrIpv6: "2400:cb00::/32" # CidrIPv6 is not ::/0 + - IpProtocol: "udp" # all fields "incorrect" + FromPort: 5000 + ToPort: 5000 + CidrIpv6: "2400:cb00::/32" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.json deleted file mode 100644 index 86a97f45712..00000000000 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Resources": { - "InstanceSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow rdp to client host", - "VpcId": { - "Ref": "myVPC" - }, - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 3389, - "ToPort": 3389, - "CidrIp": "192.168.0.0/16" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.yaml b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.yaml new file mode 100644 index 00000000000..77e5e597f19 --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative2.yaml @@ -0,0 +1,81 @@ +Resources: + + Negative2SecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for negative test cases" + VpcId: !Ref MyVPC + +# IPv4 Rules + Negative2IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # incorrect protocol + FromPort: 3389 + ToPort: 3389 + CidrIp: "0.0.0.0/0" + + Negative2IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 100 # not catching port 3389 + ToPort: 200 + CidrIp: "0.0.0.0/0" + + Negative2IPv4Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "-1" + FromPort: 2000 + ToPort: 4000 + CidrIp: "8.8.0.0/16" # CidrIP is not 0:0:0:0/0 + + Negative2IPv4Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # all fields "incorrect" + FromPort: 5000 + ToPort: 5000 + CidrIp: "8.8.0.0/16" + +# IPv6 Rules + Negative2IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "udp" # incorrect protocol + FromPort: 3389 + ToPort: 3389 + CidrIpv6: "::/0" + + Negative2IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "tcp" + FromPort: 5000 # not catching port 3389 + ToPort: 5000 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" + + Negative2IPv6Ingress3: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup + IpProtocol: "-1" + FromPort: 2000 + ToPort: 4000 + CidrIpv6: "2400:cb00::/32" # CidrIPv6 is not ::/0 + + Negative2IPv6Ingress4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative2SecurityGroup # all fields "incorrect" + IpProtocol: "udp" + FromPort: 5000 + ToPort: 5000 + CidrIpv6: "2400:cb00::/32" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative3.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative3.json new file mode 100644 index 00000000000..3be1638b44f --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative3.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "Negative1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Negative1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 100, + "ToPort": 200, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Negative1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 2000, + "ToPort": 4000, + "CidrIp": "192.0.0.0/16" + }, + { + "IpProtocol": "udp", + "FromPort": 1000, + "ToPort": 2000, + "CidrIp": "192.120.0.0/16" + } + ] + } + }, + "Negative1IPv6_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "udp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIpv6": "::/0" + } + ] + } + }, + "Negative1IPv6_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + ] + } + }, + "Negative1ArrayTestIPv6": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 2000, + "ToPort": 4000, + "CidrIpv6": "2400:cb00::/32" + }, + { + "IpProtocol": "udp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "2400:cb00::/32" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative4.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative4.json new file mode 100644 index 00000000000..1faa267e7c5 --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/negative4.json @@ -0,0 +1,109 @@ +{ + "Resources": { + "Negative2SecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for negative test cases", + "VpcId": { + "Ref": "MyVPC" + } + } + }, + "Negative2IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative2IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 100, + "ToPort": 200, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative2IPv4Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 2000, + "ToPort": 4000, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv4Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "8.8.0.0/16" + } + }, + "Negative2IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIpv6": "::/0" + } + }, + "Negative2IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + }, + "Negative2IPv6Ingress3": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 2000, + "ToPort": 4000, + "CidrIpv6": "2400:cb00::/32" + } + }, + "Negative2IPv6Ingress4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative2SecurityGroup" + }, + "IpProtocol": "udp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "2400:cb00::/32" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive1.yaml b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive1.yaml index a886a483bfb..fbc1a715503 100644 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive1.yaml @@ -1,12 +1,82 @@ Resources: - InstanceSecurityGroup: +# IPv4 Rules + Positive1IPv4_1: Type: AWS::EC2::SecurityGroup Properties: - GroupDescription: Allow rdp to client host + GroupDescription: Allow http to client host VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: tcp + - IpProtocol: "tcp" FromPort: 3389 ToPort: 3389 CidrIp: 0.0.0.0/0 + + Positive1IPv4_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIp: 0.0.0.0/0 + + Positive1ArrayTestIPv4: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 1000 + ToPort: 4000 + CidrIp: 192.0.0.0/16 + - IpProtocol: "6" + FromPort: 2000 + ToPort: 3400 + CidrIp: 0.0.0.0/0 + +# IPv6 Rules + Positive1IPv6_1: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 3389 + ToPort: 3389 + CidrIpv6: "::/0" + + Positive1IPv6_2: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIpv6: "::/0" + + Positive1ArrayTestIPv6: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Allow http to client host + VpcId: + Ref: myVPC + SecurityGroupIngress: + - IpProtocol: "tcp" + FromPort: 1000 + ToPort: 4000 + CidrIpv6: "2400:cb00::/32" #should not flag - used to test array index search + - IpProtocol: "6" + FromPort: 2000 + ToPort: 3400 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.json deleted file mode 100644 index 45a37248f8b..00000000000 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "Resources": { - "InstanceSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", - "Properties": { - "GroupDescription": "Allow rdp to client host", - "VpcId": { - "Ref": "myVPC" - }, - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 3389, - "ToPort": 3389, - "CidrIp": "0.0.0.0/0" - } - ] - } - } - } -} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.yaml b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.yaml new file mode 100644 index 00000000000..03949a43967 --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive2.yaml @@ -0,0 +1,45 @@ +Resources: + + DualStackSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: "Security group for IPv4 and IPv6 ingress rules" + VpcId: !Ref MyVPC + +# IPv4 Rules + IPv4Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "-1" + FromPort: 10 + ToPort: 10 + CidrIp: "0.0.0.0/0" + + IPv4Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 3200 + ToPort: 3500 + CidrIp: "0.0.0.0/0" + +# IPv6 Rules + IPv6Ingress1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 1000 + ToPort: 4000 + CidrIpv6: "::/0" + + IPv6Ingress2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref DualStackSecurityGroup + IpProtocol: "tcp" + FromPort: 3200 + ToPort: 3500 + CidrIpv6: "0000:0000:0000:0000:0000:0000:0000:0000/0" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive3.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive3.json new file mode 100644 index 00000000000..7cd10eb7d06 --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive3.json @@ -0,0 +1,106 @@ +{ + "Resources": { + "Positive1IPv4_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1IPv4_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1ArrayTestIPv4": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 1000, + "ToPort": 4000, + "CidrIp": "192.0.0.0/16" + }, + { + "IpProtocol": "6", + "FromPort": 2000, + "ToPort": 3400, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, + "Positive1IPv6_1": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 3389, + "ToPort": 3389, + "CidrIpv6": "::/0" + } + ] + } + }, + "Positive1IPv6_2": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIpv6": "::/0" + } + ] + } + }, + "Positive1ArrayTestIPv6": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Allow http to client host", + "VpcId": { "Ref": "myVPC" }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 1000, + "ToPort": 4000, + "CidrIpv6": "2400:cb00::/32" + }, + { + "IpProtocol": "6", + "FromPort": 2000, + "ToPort": 3400, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + ] + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive4.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive4.json new file mode 100644 index 00000000000..39aea0210d8 --- /dev/null +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive4.json @@ -0,0 +1,61 @@ +{ + "Resources": { + "DualStackSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "GroupDescription": "Security group for IPv4 and IPv6 ingress rules", + "VpcId": { + "Ref": "MyVPC" + } + } + }, + "IPv4Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "-1", + "FromPort": 10, + "ToPort": 10, + "CidrIp": "0.0.0.0/0" + } + }, + "IPv4Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 3200, + "ToPort": 3500, + "CidrIp": "0.0.0.0/0" + } + }, + "IPv6Ingress1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 1000, + "ToPort": 4000, + "CidrIpv6": "::/0" + } + }, + "IPv6Ingress2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "DualStackSecurityGroup" + }, + "IpProtocol": "tcp", + "FromPort": 3200, + "ToPort": 3500, + "CidrIpv6": "0000:0000:0000:0000:0000:0000:0000:0000/0" + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive_expected_result.json index 7bea2341887..f3ae9087040 100644 --- a/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/remote_desktop_port_open_to_internet/test/positive_expected_result.json @@ -2,13 +2,121 @@ { "queryName": "Remote Desktop Port Open To Internet", "severity": "HIGH", - "line": 8, + "line": 10, "fileName": "positive1.yaml" }, { - "fileName": "positive2.json", "queryName": "Remote Desktop Port Open To Internet", "severity": "HIGH", - "line": 10 + "line": 22, + "fileName": "positive1.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 38, + "fileName": "positive1.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 51, + "fileName": "positive1.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 63, + "fileName": "positive1.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 79, + "fileName": "positive1.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 12, + "fileName": "positive2.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 21, + "fileName": "positive2.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 31, + "fileName": "positive2.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 40, + "fileName": "positive2.yaml" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 10, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 25, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 46, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 61, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 76, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 97, + "fileName": "positive3.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 14, + "fileName": "positive4.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 26, + "fileName": "positive4.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 38, + "fileName": "positive4.json" + }, + { + "queryName": "Remote Desktop Port Open To Internet", + "severity": "HIGH", + "line": 50, + "fileName": "positive4.json" } ] diff --git a/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/query.rego b/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/query.rego index e8603cf89fc..578c30f9795 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/query.rego +++ b/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/query.rego @@ -1,11 +1,11 @@ package Cx +import data.generic.common as common_lib import data.generic.cloudformation as cf_lib CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroupEgress" properties := resource.Properties @@ -16,17 +16,17 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.CidrIp", [cf_lib.getPath(path), name]), + "searchKey": sprintf("Resources.%s.Properties.CidrIp", [name]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.CidrIp should not be open to the world", [name]), "keyActualValue": sprintf("Resources.%s.Properties.CidrIp is open to the world", [name]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], ["CidrIp"]), } } CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroupEgress" properties := resource.Properties @@ -37,17 +37,17 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.CidrIpv6", [cf_lib.getPath(path), name]), + "searchKey": sprintf("Resources.%s.Properties.CidrIpv6", [name]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.CidrIpv6 should not be open to the world", [name]), "keyActualValue": sprintf("Resources.%s.Properties.CidrIpv6 is open to the world", [name]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], ["CidrIpv6"]), } } CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroup" properties := resource.Properties @@ -58,17 +58,17 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupEgress[%d].CidrIp", [cf_lib.getPath(path), name, index]), + "searchKey": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIp", [name, index]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIp should not be open to the world", [name, index]), "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIp is open to the world", [name, index]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupEgress", index], ["CidrIp"]), } } CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroup" properties := resource.Properties @@ -79,9 +79,10 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupEgress[%d].CidrIpv6", [cf_lib.getPath(path), name, index]), + "searchKey": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIpv6", [name, index]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIpv6 should not be open to the world", [name, index]), "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].CidrIpv6 is open to the world", [name, index]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupEgress", index], ["CidrIpv6"]), } } diff --git a/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/test/positive_expected_result.json index f6c2c1b75d0..74022745366 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/security_group_egress_cidr_open_to_world/test/positive_expected_result.json @@ -2,7 +2,7 @@ { "queryName": "Security Group Egress CIDR Open To World", "severity": "MEDIUM", - "line": 4, + "line": 19, "fileName": "positive1.yaml" }, { @@ -14,7 +14,7 @@ { "queryName": "Security Group Egress CIDR Open To World", "severity": "MEDIUM", - "line": 5, + "line": 17, "fileName": "positive2.json" }, { diff --git a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/query.rego b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/query.rego index e18834e1a93..07559362eca 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/query.rego +++ b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { properties := resource.Properties - properties.IpProtocol == -1 + properties.IpProtocol == "-1" result := { "documentId": input.document[i].id, @@ -17,8 +17,8 @@ CxPolicy[result] { "resourceName": cf_lib.get_resource_name(resource, name), "searchKey": sprintf("Resources.%s.Properties.IpProtocol", [name]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.IpProtocol should not be set to -1", [name]), - "keyActualValue": sprintf("Resources.%s.Properties.IpProtocol is set to -1", [name]), + "keyExpectedValue": sprintf("Resources.%s.Properties.IpProtocol should not be set to '-1'", [name]), + "keyActualValue": sprintf("Resources.%s.Properties.IpProtocol is set to '-1'", [name]), "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], ["IpProtocol"]), } } @@ -29,7 +29,7 @@ CxPolicy[result] { properties := resource.Properties - properties.SecurityGroupEgress[index].IpProtocol == -1 + properties.SecurityGroupEgress[index].IpProtocol == "-1" result := { "documentId": input.document[i].id, @@ -37,8 +37,8 @@ CxPolicy[result] { "resourceName": cf_lib.get_resource_name(resource, name), "searchKey": sprintf("Resources.%s.Properties.SecurityGroupEgress.IpProtocol", [name]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].IpProtocol should not be set to -1", [name, index]), - "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].IpProtocol is set to -1", [name, index]), + "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].IpProtocol should not be set to '-1'", [name, index]), + "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].IpProtocol is set to '-1'", [name, index]), "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupEgress", index], ["IpProtocol"]), } } diff --git a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive1.yaml b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive1.yaml index 8e27eee0c26..d2c2d1bc4f5 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive1.yaml @@ -6,19 +6,19 @@ Resources: VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: -1 + - IpProtocol: "-1" FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - - IpProtocol: -1 + - IpProtocol: "-1" FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 OutboundRule: Type: AWS::EC2::SecurityGroupEgress Properties: - IpProtocol: -1 + IpProtocol: "-1" FromPort: 0 ToPort: 65535 DestinationSecurityGroupId: @@ -32,7 +32,7 @@ Resources: InboundRule: Type: AWS::EC2::SecurityGroupIngress Properties: - IpProtocol: -1 + IpProtocol: "-1" FromPort: 0 ToPort: 65535 SourceSecurityGroupId: diff --git a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive2.json b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive2.json index d801d5248f7..64fb9341a45 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive2.json +++ b/assets/queries/cloudFormation/aws/security_group_egress_with_all_protocols/test/positive2.json @@ -10,7 +10,7 @@ "SecurityGroupIngress": [ { "CidrIp": "0.0.0.0/0", - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 80, "ToPort": 80 } @@ -18,7 +18,7 @@ "SecurityGroupEgress": [ { "CidrIp": "0.0.0.0/0", - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 80, "ToPort": 80 } @@ -40,7 +40,7 @@ "GroupId" ] }, - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 0, "ToPort": 65535 } @@ -53,7 +53,7 @@ "GroupId" ] }, - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 0, "ToPort": 65535, "SourceSecurityGroupId": { diff --git a/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/query.rego b/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/query.rego index 768ff2ec79c..9c7ade2675e 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/query.rego +++ b/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/query.rego @@ -1,11 +1,11 @@ package Cx +import data.generic.common as common_lib import data.generic.cloudformation as cf_lib CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroupEgress" properties := resource.Properties @@ -16,17 +16,17 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties", [cf_lib.getPath(path), name]), + "searchKey": sprintf("Resources.%s.Properties", [name]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.FromPort should equal to Resources.%s.Properties.ToPort", [name, name]), "keyActualValue": sprintf("Resources.%s.Properties.FromPort is not equal to Resources.%s.Properties.ToPort", [name, name]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], []), } } CxPolicy[result] { docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + resource := docs.Resources[name] resource.Type == "AWS::EC2::SecurityGroup" properties := resource.Properties @@ -37,9 +37,10 @@ CxPolicy[result] { "documentId": input.document[i].id, "resourceType": resource.Type, "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupEgress[%d]", [cf_lib.getPath(path), name, index]), + "searchKey": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d]", [name, index]), "issueType": "IncorrectValue", "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].FromPort should equal to Resources.%s.Properties.SecurityGroupEgress[%d].ToPort", [name, index, name, index]), "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d].FromPort is not equal to Resources.%s.Properties.SecurityGroupEgress[%d].ToPort", [name, index, name, index]), + "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupEgress", index], []), } } diff --git a/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/test/positive_expected_result.json index 88a78844ae8..07c66a046af 100644 --- a/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/security_group_egress_with_port_range/test/positive_expected_result.json @@ -1,20 +1,20 @@ [ { - "line": 4, - "fileName": "positive1.yaml", "queryName": "Security Group Egress With Port Range", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 15, + "fileName": "positive1.yaml" }, { - "fileName": "positive1.yaml", "queryName": "Security Group Egress With Port Range", "severity": "MEDIUM", - "line": 22 + "line": 22, + "fileName": "positive1.yaml" }, { "queryName": "Security Group Egress With Port Range", "severity": "MEDIUM", - "line": 5, + "line": 21, "fileName": "positive2.json" }, { diff --git a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/query.rego b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/query.rego index 4e3041c3ee1..946c9eca542 100644 --- a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/query.rego +++ b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/query.rego @@ -9,7 +9,7 @@ CxPolicy[result] { properties := resource.Properties - properties.IpProtocol == -1 + properties.IpProtocol == "-1" result := { "documentId": input.document[i].id, @@ -17,8 +17,8 @@ CxPolicy[result] { "resourceName": cf_lib.get_resource_name(resource, name), "searchKey": sprintf("Resources.%s.Properties.IpProtocol", [name]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.IpProtocol should not be set to -1", [name]), - "keyActualValue": sprintf("Resources.%s.Properties.IpProtocol is set to -1", [name]), + "keyExpectedValue": sprintf("Resources.%s.Properties.IpProtocol should not be set to '-1'", [name]), + "keyActualValue": sprintf("Resources.%s.Properties.IpProtocol is set to '-1'", [name]), "searchLine": common_lib.build_search_line(["Resources", name, "Properties"], ["IpProtocol"]), } } @@ -29,7 +29,7 @@ CxPolicy[result] { properties := resource.Properties - properties.SecurityGroupIngress[index].IpProtocol == -1 + properties.SecurityGroupIngress[index].IpProtocol == "-1" result := { "documentId": input.document[i].id, @@ -37,8 +37,8 @@ CxPolicy[result] { "resourceName": cf_lib.get_resource_name(resource, name), "searchKey": sprintf("Resources.%s.Properties.SecurityGroupIngress.IpProtocol", [name]), "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d].IpProtocol should not be set to -1", [name, index]), - "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d].IpProtocol is set to -1", [name, index]), + "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d].IpProtocol should not be set to '-1'", [name, index]), + "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupIngress[%d].IpProtocol is set to '-1'", [name, index]), "searchLine": common_lib.build_search_line(["Resources", name, "Properties", "SecurityGroupIngress", index], ["IpProtocol"]), } } diff --git a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive1.yaml b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive1.yaml index 135760956d1..34a80771580 100644 --- a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive1.yaml @@ -6,7 +6,7 @@ Resources: VpcId: Ref: myVPC SecurityGroupIngress: - - IpProtocol: -1 + - IpProtocol: "-1" FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 @@ -32,7 +32,7 @@ Resources: InboundRule: Type: AWS::EC2::SecurityGroupIngress Properties: - IpProtocol: -1 + IpProtocol: "-1" FromPort: 0 ToPort: 65535 SourceSecurityGroupId: diff --git a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive2.json b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive2.json index 057430b20c8..7cbc33dfa07 100644 --- a/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive2.json +++ b/assets/queries/cloudFormation/aws/security_group_ingress_with_all_protocols/test/positive2.json @@ -8,7 +8,7 @@ }, "SecurityGroupIngress": [ { - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" @@ -48,7 +48,7 @@ "InboundRule": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { - "IpProtocol": -1, + "IpProtocol": "-1", "FromPort": 0, "ToPort": 65535, "SourceSecurityGroupId": { diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/query.rego b/assets/queries/cloudFormation/aws/security_group_rule_without_description/query.rego index 8ae0e79831a..361cb29da80 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/query.rego +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/query.rego @@ -3,9 +3,11 @@ package Cx import data.generic.common as common_lib import data.generic.cloudformation as cf_lib +types := ["AWS::RDS::DBSecurityGroup", "AWS::EC2::SecurityGroup"] + CxPolicy[result] { resource := input.document[i].Resources[name] - resource.Type == "AWS::EC2::SecurityGroup" + resource.Type == types[_] not common_lib.valid_key(resource.Properties, "GroupDescription") diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative1.yaml b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative1.yaml index 2f4bbf91c06..ef21b012c16 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative1.yaml @@ -46,4 +46,9 @@ Resources: GroupId: Fn::GetAtt: - TargetSG - - GroupId \ No newline at end of file + - GroupId + LegacySecurityGroup: + Type: AWS::RDS::DBSecurityGroup + Properties: + DBSecurityGroupName: "sample" + GroupDescription: Legacy description \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative2.json b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative2.json index fc2554add2b..f56446d3be4 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative2.json +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/negative2.json @@ -4,9 +4,7 @@ "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Allow http to client host", - "VpcId": { - "Ref": "myVPC" - }, + "VpcId": { "Ref": "myVPC" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", @@ -18,11 +16,11 @@ ], "SecurityGroupEgress": [ { + "IpProtocol": "tcp", + "Description": "TCP", "FromPort": 80, "ToPort": 80, - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "Description": "TCP" + "CidrIp": "0.0.0.0/0" } ] } @@ -30,21 +28,15 @@ "OutboundRule": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties": { - "GroupId": { - "Fn::GetAtt": [ - "SourceSG", - "GroupId" - ] - }, "Description": "TCP", "IpProtocol": "tcp", "FromPort": 0, "ToPort": 65535, "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "TargetSG", - "GroupId" - ] + "Fn::GetAtt": ["TargetSG", "GroupId"] + }, + "GroupId": { + "Fn::GetAtt": ["SourceSG", "GroupId"] } } }, @@ -56,18 +48,19 @@ "FromPort": 0, "ToPort": 65535, "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "SourceSG", - "GroupId" - ] + "Fn::GetAtt": ["SourceSG", "GroupId"] }, "GroupId": { - "Fn::GetAtt": [ - "TargetSG", - "GroupId" - ] + "Fn::GetAtt": ["TargetSG", "GroupId"] } } + }, + "LegacySecurityGroup": { + "Type": "AWS::RDS::DBSecurityGroup", + "Properties": { + "DBSecurityGroupName": "sample", + "GroupDescription": "Legacy description" + } } } } diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive1.yaml b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive1.yaml index e41e86d9f21..526b56cabcf 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive1.yaml @@ -41,4 +41,8 @@ Resources: GroupId: Fn::GetAtt: - TargetSG - - GroupId \ No newline at end of file + - GroupId + LegacySecurityGroup: + Type: AWS::RDS::DBSecurityGroup + Properties: + DBSecurityGroupName: "sample" \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive2.json b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive2.json index b58b98abff8..9ee4f01f545 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive2.json +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive2.json @@ -1,5 +1,29 @@ { "Resources": { + "InstanceSecurityGroup": { + "Type": "AWS::EC2::SecurityGroup", + "Properties": { + "VpcId": { + "Ref": "myVPC" + }, + "SecurityGroupIngress": [ + { + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + } + ], + "SecurityGroupEgress": [ + { + "IpProtocol": "tcp", + "FromPort": 80, + "ToPort": 80, + "CidrIp": "0.0.0.0/0" + } + ] + } + }, "OutboundRule": { "Type": "AWS::EC2::SecurityGroupEgress", "Properties": { @@ -23,6 +47,9 @@ "InboundRule": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 65535, "SourceSecurityGroupId": { "Fn::GetAtt": [ "SourceSG", @@ -34,34 +61,13 @@ "TargetSG", "GroupId" ] - }, - "IpProtocol": "tcp", - "FromPort": 0, - "ToPort": 65535 + } } }, - "InstanceSecurityGroup": { - "Type": "AWS::EC2::SecurityGroup", + "LegacySecurityGroup": { + "Type": "AWS::RDS::DBSecurityGroup", "Properties": { - "SecurityGroupIngress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "0.0.0.0/0" - } - ], - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80 - } - ], - "VpcId": { - "Ref": "myVPC" - } + "DBSecurityGroupName": "sample" } } } diff --git a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive_expected_result.json index 746d4d7a353..640f5f33e9e 100644 --- a/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/security_group_rule_without_description/test/positive_expected_result.json @@ -1,9 +1,9 @@ [ { - "line": 4, - "fileName": "positive1.yaml", "queryName": "Security Group Rule Without Description", - "severity": "INFO" + "severity": "INFO", + "line": 4, + "fileName": "positive1.yaml" }, { "queryName": "Security Group Rule Without Description", @@ -12,10 +12,10 @@ "fileName": "positive1.yaml" }, { + "queryName": "Security Group Rule Without Description", "severity": "INFO", "line": 13, - "fileName": "positive1.yaml", - "queryName": "Security Group Rule Without Description" + "fileName": "positive1.yaml" }, { "queryName": "Security Group Rule Without Description", @@ -30,33 +30,45 @@ "fileName": "positive1.yaml" }, { + "queryName": "Security Group Rule Without Description", + "severity": "INFO", + "line": 47, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Group Rule Without Description", "severity": "INFO", "line": 5, - "fileName": "positive2.json", - "queryName": "Security Group Rule Without Description" + "fileName": "positive2.json" + }, + { + "queryName": "Security Group Rule Without Description", + "severity": "INFO", + "line": 11, + "fileName": "positive2.json" }, { "queryName": "Security Group Rule Without Description", "severity": "INFO", - "line": 25, + "line": 19, "fileName": "positive2.json" }, { - "fileName": "positive2.json", "queryName": "Security Group Rule Without Description", "severity": "INFO", - "line": 45 + "line": 29, + "fileName": "positive2.json" }, { "queryName": "Security Group Rule Without Description", "severity": "INFO", - "line": 48, + "line": 49, "fileName": "positive2.json" }, { "queryName": "Security Group Rule Without Description", "severity": "INFO", - "line": 56, + "line": 69, "fileName": "positive2.json" } ] diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/metadata.json b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/metadata.json index cb9831f5d84..ec540268774 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/metadata.json +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/metadata.json @@ -3,7 +3,7 @@ "queryName": "Security Groups Allows Unrestricted Outbound Traffic", "severity": "MEDIUM", "category": "Networking and Firewall", - "descriptionText": "No security group should allow unrestricted egress access", + "descriptionText": "Security group should never allow unrestricted egress access", "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html", "platform": "CloudFormation", "descriptionID": "05891eb1", diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/query.rego b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/query.rego index 0c0e8e943d3..8c66b6ba017 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/query.rego +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/query.rego @@ -1,25 +1,71 @@ package Cx import data.generic.cloudformation as cf_lib +import data.generic.common as common_lib CxPolicy[result] { - docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] + doc := input.document[i] + sec_group := doc.Resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" - resource.Type == "AWS::EC2::SecurityGroup" + egresses_with_names := search_for_standalone_egress(sec_group_name, doc) - properties := resource.Properties - properties.SecurityGroupEgress[j].IpProtocol == "ALL" - properties.SecurityGroupEgress[j].CidrIp == "0.0.0.0/0" + egress_list := array.concat(egresses_with_names.egress_list, get_egress_list_if_exists(sec_group)) + egress := egress_list[eg_index] + + egress.IpProtocol == "-1" + + cidr_types := {"CidrIp", "CidrIpv6"} + exposed_addresses := ["0.0.0.0/0", common_lib.unrestricted_ipv6[_]] + egress[cidr_types[c]] == exposed_addresses[a] + + results := get_search_values(eg_index, sec_group_name, egresses_with_names.names) result := { - "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupEgress[%d]", [cf_lib.getPath(path), name, j]), + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d] should have different IpProtocol from 'ALL' and CidrIp from '0.0.0.0/0'.", [name, j]), - "keyActualValue": sprintf("Resources.%s.Properties.SecurityGroupEgress[%d] must not have IpProtocol as 'ALL' and CidrIp as '0.0.0.0/0'.", [name, j]), + "keyExpectedValue": sprintf("'%s' should not have IpProtocol set to '-1' and %s set to '%s' simultaneously", [results.searchKey, cidr_types[c], exposed_addresses[a]]), + "keyActualValue": sprintf("'%s' has IpProtocol set to '-1' and %s set to '%s'.", [results.searchKey, cidr_types[c], exposed_addresses[a]]), + "searchLine": results.searchLine, } } + +search_for_standalone_egress(sec_group_name, doc) = egresses_with_names { + resources := doc.Resources + + names := [name | + egress := resources[name] + egress.Type == "AWS::EC2::SecurityGroupEgress" + cf_lib.get_name(egress.Properties.GroupId) == sec_group_name + ] + + egresses_with_names := { + "egress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = {"egress_list": [], "names": []} + +get_search_values(eg_index, sec_group_name, names_list) = results { + eg_index < count(names_list) # if egress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[eg_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[eg_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupEgress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupEgress[%d]", [sec_group_name, eg_index - count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupEgress", eg_index - count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" + } +} + +get_egress_list_if_exists(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupEgress") +} else = group.Properties.SecurityGroupEgress + diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative1.yaml b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative1.yaml index a7fbecafb2e..65063f6171e 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative1.yaml @@ -1,27 +1,53 @@ -Parameters: - KeyName: - Description: The EC2 Key Pair to allow SSH access to the instance - Type: 'AWS::EC2::KeyPair::KeyName' Resources: - Ec2Instance: - Type: 'AWS::EC2::Instance' - Properties: - SecurityGroups: - - !Ref InstanceSecurityGroup - - MyExistingSecurityGroup - KeyName: !Ref KeyName - ImageId: ami-7a11e213 - InstanceSecurityGroup: + Negative1_security_group: Type: 'AWS::EC2::SecurityGroup' Properties: - GroupDescription: Enable SSH access via port 22 - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: '22' - ToPort: '22' - CidrIp: 0.0.0.0/0 + GroupDescription: Open security group + VpcId: !Ref MyVPC SecurityGroupEgress: - - IpProtocol: tcp - FromPort: '22' - ToPort: '22' - CidrIp: 0.0.0.0/0 \ No newline at end of file + - IpProtocol: tcp # protocol is not "-1" + FromPort: 2000 + ToPort: 2000 + CidrIp: 0.0.0.0/0 + - IpProtocol: "-1" + FromPort: 2000 + ToPort: 2000 + CidrIp: 192.162.0.0/16 # cidr is not 0.0.0.0/0 + + # Standalone IPv4 egress rules + Negative1_egress_ipv4_1: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: tcp # protocol is not "-1" + FromPort: 3000 + ToPort: 3000 + CidrIp: 0.0.0.0/0 + + Negative1_egress_ipv4_2: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: "-1" + FromPort: 3000 + ToPort: 3000 + CidrIp: 192.162.0.0/16 # cidr is not 0.0.0.0/0 + + # Standalone IPv6 egress rules + Negative1_egress_ipv6_1: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: tcp # protocol is not "-1" + FromPort: 4000 + ToPort: 4000 + CidrIpv6: ::/0 + + Negative1_egress_ipv6_2: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: "-1" + FromPort: 4000 + ToPort: 4000 + CidrIpv6: 2001:0db8::/32 # cidr is not ::/0 diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative2.json b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative2.json index 2c217922f7b..eeed67e101e 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative2.json +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/negative2.json @@ -1,43 +1,75 @@ { - "Parameters": { - "KeyName": { - "Description": "The EC2 Key Pair to allow SSH access to the instance", - "Type": "AWS::EC2::KeyPair::KeyName" - } - }, "Resources": { - "Ec2Instance": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "InstanceSecurityGroup", - "MyExistingSecurityGroup" - ], - "KeyName": "KeyName", - "ImageId": "ami-7a11e213" - } - }, - "InstanceSecurityGroup": { + "Negative2_security_group": { "Type": "AWS::EC2::SecurityGroup", "Properties": { - "GroupDescription": "Enable SSH access via port 22", - "SecurityGroupIngress": [ + "GroupDescription": "Open security group", + "VpcId": { + "Ref": "MyVPC" + }, + "SecurityGroupEgress": [ { "IpProtocol": "tcp", - "FromPort": "22", - "ToPort": "22", + "FromPort": 2000, + "ToPort": 2000, "CidrIp": "0.0.0.0/0" - } - ], - "SecurityGroupEgress": [ + }, { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": "22", - "ToPort": "22" + "IpProtocol": "-1", + "FromPort": 2000, + "ToPort": 2000, + "CidrIp": "192.162.0.0/16" } ] } + }, + "Negative2_egress_ipv4_1": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Negative2_security_group" + }, + "IpProtocol": "tcp", + "FromPort": 3000, + "ToPort": 3000, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative2_egress_ipv4_2": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Negative2_security_group" + }, + "IpProtocol": "-1", + "FromPort": 3000, + "ToPort": 3000, + "CidrIp": "192.162.0.0/16" + } + }, + "Negative2_egress_ipv6_1": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Negative2_security_group" + }, + "IpProtocol": "tcp", + "FromPort": 4000, + "ToPort": 4000, + "CidrIpv6": "::/0" + } + }, + "Negative2_egress_ipv6_2": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Negative2_security_group" + }, + "IpProtocol": "-1", + "FromPort": 4000, + "ToPort": 4000, + "CidrIpv6": "2001:0db8::/32" + } } } } diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive1.yaml b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive1.yaml index 809226a0e8e..356fe1c66e9 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive1.yaml @@ -1,27 +1,31 @@ -Parameters: - KeyName: - Description: The EC2 Key Pair to allow SSH access to the instance - Type: 'AWS::EC2::KeyPair::KeyName' Resources: - Ec2Instance: - Type: 'AWS::EC2::Instance' - Properties: - SecurityGroups: - - !Ref InstanceSecurityGroup - - MyExistingSecurityGroup - KeyName: !Ref KeyName - ImageId: ami-7a11e213 - InstanceSecurityGroup: + Positive1_security_group: Type: 'AWS::EC2::SecurityGroup' Properties: - GroupDescription: Enable SSH access via port 22 - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: '22' - ToPort: '22' - CidrIp: 0.0.0.0/0 + GroupDescription: Open security group + VpcId: !Ref MyVPC SecurityGroupEgress: - - IpProtocol: ALL - FromPort: '22' - ToPort: '22' - CidrIp: 0.0.0.0/0 \ No newline at end of file + - IpProtocol: "-1" + FromPort: 2000 + ToPort: 2000 + CidrIp: 0.0.0.0/0 + + # Standalone IPv4 egress rule + Positive1_egress_ipv4: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Positive1_security_group + IpProtocol: "-1" + FromPort: 3000 + ToPort: 3000 + CidrIp: 0.0.0.0/0 + + # Standalone IPv6 egress rule + Positive1_egress_ipv6: + Type: AWS::EC2::SecurityGroupEgress + Properties: + GroupId: !Ref Positive1_security_group + IpProtocol: "-1" + FromPort: 4000 + ToPort: 4000 + CidrIpv6: ::/0 diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive2.json b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive2.json index 365741bb749..0969762d7ad 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive2.json +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive2.json @@ -1,43 +1,45 @@ { - "Parameters": { - "KeyName": { - "Description": "The EC2 Key Pair to allow SSH access to the instance", - "Type": "AWS::EC2::KeyPair::KeyName" - } - }, "Resources": { - "Ec2Instance": { - "Type": "AWS::EC2::Instance", - "Properties": { - "ImageId": "ami-7a11e213", - "SecurityGroups": [ - "InstanceSecurityGroup", - "MyExistingSecurityGroup" - ], - "KeyName": "KeyName" - } - }, - "InstanceSecurityGroup": { + "Positive2_security_group": { + "Type": "AWS::EC2::SecurityGroup", "Properties": { - "SecurityGroupIngress": [ - { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": "22", - "ToPort": "22" - } - ], + "GroupDescription": "Open security group", + "VpcId": { + "Ref": "MyVPC" + }, "SecurityGroupEgress": [ { - "IpProtocol": "ALL", - "FromPort": "22", - "ToPort": "22", + "IpProtocol": "-1", + "FromPort": 2000, + "ToPort": 2000, "CidrIp": "0.0.0.0/0" } - ], - "GroupDescription": "Enable SSH access via port 22" - }, - "Type": "AWS::EC2::SecurityGroup" + ] + } + }, + "Positive2_egress_ipv4": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Positive2_security_group" + }, + "IpProtocol": "-1", + "FromPort": 3000, + "ToPort": 3000, + "CidrIp": "0.0.0.0/0" + } + }, + "Positive2_egress_ipv6": { + "Type": "AWS::EC2::SecurityGroupEgress", + "Properties": { + "GroupId": { + "Ref": "Positive2_security_group" + }, + "IpProtocol": "-1", + "FromPort": 4000, + "ToPort": 4000, + "CidrIpv6": "::/0" + } } } } diff --git a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive_expected_result.json index 85acb6a7e9c..056b9ac4b8f 100644 --- a/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/security_groups_allows_unrestricted_outbound_traffic/test/positive_expected_result.json @@ -1,14 +1,38 @@ [ { + "queryName": "Security Groups Allows Unrestricted Outbound Traffic", + "severity": "MEDIUM", + "line": 8, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Groups Allows Unrestricted Outbound Traffic", + "severity": "MEDIUM", "line": 16, - "fileName": "positive1.yaml", + "fileName": "positive1.yaml" + }, + { "queryName": "Security Groups Allows Unrestricted Outbound Traffic", - "severity": "MEDIUM" + "severity": "MEDIUM", + "line": 26, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Groups Allows Unrestricted Outbound Traffic", + "severity": "MEDIUM", + "line": 12, + "fileName": "positive2.json" + }, + { + "queryName": "Security Groups Allows Unrestricted Outbound Traffic", + "severity": "MEDIUM", + "line": 22, + "fileName": "positive2.json" }, { "queryName": "Security Groups Allows Unrestricted Outbound Traffic", "severity": "MEDIUM", - "line": 21, + "line": 34, "fileName": "positive2.json" } ] \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/security_groups_unrestricted_access_to_rdp/query.rego b/assets/queries/cloudFormation/aws/security_groups_unrestricted_access_to_rdp/query.rego index de60938cdf7..d8325e9a6fc 100644 --- a/assets/queries/cloudFormation/aws/security_groups_unrestricted_access_to_rdp/query.rego +++ b/assets/queries/cloudFormation/aws/security_groups_unrestricted_access_to_rdp/query.rego @@ -2,7 +2,7 @@ package Cx import data.generic.cloudformation as cf_lib -CxPolicy[result] { +CxPolicy[result] { # Fulfilled by c9846969-d066-431f-9b34-8c4abafe422a docs := input.document[i] [path, Resources] := walk(docs) resource := Resources[name] diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/metadata.json b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/metadata.json index 05db562b994..9dd1f52d52f 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/metadata.json +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/metadata.json @@ -3,7 +3,7 @@ "queryName": "Security Groups With Exposed Admin Ports", "severity": "HIGH", "category": "Networking and Firewall", - "descriptionText": "Security Groups should not have ports open in (20, 21, 22, 23, 115, 137, 138, 139, 2049, 3389)", + "descriptionText": "Security Groups should not have ports 20, 21, 22, 23, 115, 137, 138, 139, 2049 or 3389 open", "descriptionUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html", "platform": "CloudFormation", "descriptionID": "e14121d4", diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/query.rego b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/query.rego index bf482f6ae1f..fc409c4a274 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/query.rego +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/query.rego @@ -1,37 +1,76 @@ package Cx import data.generic.cloudformation as cf_lib +import data.generic.common as common_lib + +admin_ports := ["20", "21", "22", "23", "115", "137", "138", "139", "2049", "3389"] CxPolicy[result] { - docs := input.document[i] - [path, Resources] := walk(docs) - resource := Resources[name] - ports := [20, 21, 22, 23, 115, 137, 138, 139, 2049, 3389] + doc := input.document[i] + sec_group := doc.Resources[sec_group_name] + sec_group.Type == "AWS::EC2::SecurityGroup" + + ingresses_with_names := search_for_standalone_ingress(sec_group_name, doc) + + ingress_list := array.concat(ingresses_with_names.ingress_list, get_ingress_list_if_exists(sec_group)) + ingress := ingress_list[ing_index] - check_cidrip(resource.Properties) - check_security_groups_ingress(resource.Properties, ports) + cf_lib.entireNetwork(ingress) + exposed_ports := get_exposed_ports(ingress) + + results := get_search_values(ing_index, sec_group_name, ingresses_with_names.names) result := { - "documentId": input.document[i].id, - "resourceType": resource.Type, - "resourceName": cf_lib.get_resource_name(resource, name), - "searchKey": sprintf("%s%s.Properties.SecurityGroupIngress", [cf_lib.getPath(path), name]), + "documentId": doc.id, + "resourceType": results.type, + "resourceName": cf_lib.get_resource_name(sec_group, sec_group_name), + "searchKey": results.searchKey, "issueType": "IncorrectValue", - "keyExpectedValue": sprintf("None of the Resources.%s.Properties.SecurityGroupIngress should have an exposed port", [name]), - "keyActualValue": sprintf("One of the Resources.%s.Properties.SecurityGroupIngress has a exposed port (20,21,22,23,115,137,138,2049,3389)", [name]), + "keyExpectedValue": "No exposed ingress rule should contain admin ports: 20, 21, 22, 23, 115, 137, 138, 139, 2049 or 3389", + "keyActualValue": sprintf("'%s' is exposed and contains port(s): %s", [results.searchKey, concat(", ", exposed_ports)]), + "searchLine": results.searchLine, } } -check_cidrip(group) { - group.SecurityGroupIngress[_].CidrIp == "0.0.0.0/0" +get_exposed_ports(ingress) = admin_ports { + ingress.IpProtocol == "-1" +} else = exposed_ports { + exposed_ports := [admin_ports[i2] | cf_lib.containsPort(ingress.FromPort, ingress.ToPort, to_number(admin_ports[i2]))] + exposed_ports != [] } -check_security_groups_ingress(group, ports) { - some p - group.SecurityGroupIngress[_].FromPort == ports[p] -} +search_for_standalone_ingress(sec_group_name, doc) = ingresses_with_names { + resources := doc.Resources + + names := [name | + ingress := resources[name] + ingress.Type == "AWS::EC2::SecurityGroupIngress" + cf_lib.get_name(ingress.Properties.GroupId) == sec_group_name + ] -check_security_groups_ingress(group, ports) { - some p - group.SecurityGroupIngress[_].ToPort == ports[p] + ingresses_with_names := { + "ingress_list": [resources[name].Properties | name := names[_]], + "names": names + } +} else = {"ingress_list": [], "names": []} + +get_search_values(ing_index, sec_group_name, names_list) = results { + ing_index < count(names_list) # if ingress is standalone + + results := { + "searchKey" : sprintf("Resources.%s.Properties", [names_list[ing_index]]), + "searchLine" : common_lib.build_search_line(["Resources", names_list[ing_index], "Properties"], []), + "type" : "AWS::EC2::SecurityGroupIngress" + } +} else = results { + + results := { + "searchKey" : sprintf("Resources.%s.Properties.SecurityGroupIngress[%d]", [sec_group_name, ing_index-count(names_list)]), + "searchLine" : common_lib.build_search_line(["Resources", sec_group_name, "Properties", "SecurityGroupIngress", ing_index-count(names_list)], []), + "type" : "AWS::EC2::SecurityGroup" + } } + +get_ingress_list_if_exists(group) = [] { + not common_lib.valid_key(group.Properties,"SecurityGroupIngress") +} else = group.Properties.SecurityGroupIngress \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative1.yaml b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative1.yaml index 79beb49d2ec..d72fc433d93 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative1.yaml +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative1.yaml @@ -1,24 +1,53 @@ Resources: - Ec2Instance: - Type: 'AWS::EC2::Instance' + Negative1_security_group: + Type: 'AWS::EC2::SecurityGroup' Properties: - SecurityGroups: - - !Ref InstanceSecurityGroup - KeyName: mykey - ImageId: '' - InstanceSecurityGroup: - Type: AWS::EC2::SecurityGroup + GroupDescription: Open security group + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 5000 # does not expose admin port + ToPort: 5000 + CidrIp: 0.0.0.0/0 + - IpProtocol: "-1" + FromPort: 0 + ToPort: 0 + CidrIp: 192.162.0.0/16 # cidr is not 0.0.0.0/0 + + # Standalone IPv4 ingress rules + Negative1_ingress_ipv4_1: + Type: AWS::EC2::SecurityGroupIngress Properties: - GroupDescription: Allow http to client host - VpcId: - Ref: myVPC - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/32 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 127.0.0.1/33 \ No newline at end of file + GroupId: !Ref Negative1_security_group + IpProtocol: tcp + FromPort: 5000 # does not expose admin port + ToPort: 5000 + CidrIp: 0.0.0.0/0 + + Negative1_ingress_ipv4_2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: "-1" + FromPort: 3000 + ToPort: 3000 + CidrIp: 192.162.0.0/16 # cidr is not 0.0.0.0/0 + + # Standalone IPv6 ingress rules + Negative1_ingress_ipv6_1: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: tcp + FromPort: 5000 # does not expose admin port + ToPort: 5000 + CidrIpv6: ::/0 + + Negative1_ingress_ipv6_2: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Negative1_security_group + IpProtocol: udp + FromPort: 0 + ToPort: 20000 + CidrIpv6: 2001:0db8::/32 # cidr is not ::/0 diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative2.json b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative2.json index 5111dfcd716..7d5270bd073 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative2.json +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative2.json @@ -1,39 +1,75 @@ { "Resources": { - "Ec2Instance": { - "Type": "AWS::EC2::Instance", - "Properties": { - "SecurityGroups": [ - "InstanceSecurityGroup" - ], - "KeyName": "mykey", - "ImageId": "" - } - }, - "InstanceSecurityGroup": { + "Negative1_security_group": { + "Type": "AWS::EC2::SecurityGroup", "Properties": { + "GroupDescription": "Open security group", "VpcId": { - "Ref": "myVPC" + "Ref": "MyVPC" }, "SecurityGroupIngress": [ { "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, - "CidrIp": "127.0.0.1/32" - } - ], - "SecurityGroupEgress": [ + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "0.0.0.0/0" + }, { - "CidrIp": "127.0.0.1/33", - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80 + "IpProtocol": "-1", + "FromPort": 0, + "ToPort": 0, + "CidrIp": "192.162.0.0/16" } - ], - "GroupDescription": "Allow http to client host" - }, - "Type": "AWS::EC2::SecurityGroup" + ] + } + }, + "Negative1_ingress_ipv4_1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative1_security_group" + }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIp": "0.0.0.0/0" + } + }, + "Negative1_ingress_ipv4_2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative1_security_group" + }, + "IpProtocol": "-1", + "FromPort": 3000, + "ToPort": 3000, + "CidrIp": "192.162.0.0/16" + } + }, + "Negative1_ingress_ipv6_1": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative1_security_group" + }, + "IpProtocol": "tcp", + "FromPort": 5000, + "ToPort": 5000, + "CidrIpv6": "::/0" + } + }, + "Negative1_ingress_ipv6_2": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Negative1_security_group" + }, + "IpProtocol": "udp", + "FromPort": 0, + "ToPort": 20000, + "CidrIpv6": "2001:0db8::/32" + } } } } diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative3.yaml b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative3.yaml deleted file mode 100644 index 1e3850a3eee..00000000000 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/negative3.yaml +++ /dev/null @@ -1,13 +0,0 @@ -AWSTemplateFormatVersion: 2010-09-09 -Resources: - InstanceSecurityGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http to client host - VpcId: - Ref: myVPC - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 11.22.33.44/32 \ No newline at end of file diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive1.yaml b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive1.yaml index 13d0734a2eb..78ad8f623b5 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive1.yaml +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive1.yaml @@ -1,24 +1,31 @@ Resources: - Ec2Instance: - Type: 'AWS::EC2::Instance' + Positive1_security_group: + Type: 'AWS::EC2::SecurityGroup' Properties: - SecurityGroups: - - !Ref InstanceSecurityGroup - KeyName: mykey - ImageId: '' - InstanceSecurityGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: Allow http to client host - VpcId: - Ref: myVPC - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 20 - ToPort: 20 + GroupDescription: Enable SSH access via port 22 + VpcId: !Ref MyVPC + SecurityGroupIngress: + - IpProtocol: "-1" + FromPort: 22 + ToPort: 22 CidrIp: 0.0.0.0/0 - SecurityGroupEgress: - - IpProtocol: tcp - FromPort: 80 - ToPort: 80 - CidrIp: 0.0.0.0/0 \ No newline at end of file + + # Standalone IPv4 ingress rule + Positive1_ingress_ipv4: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Positive1_security_group + IpProtocol: tcp + FromPort: 0 # exposes 20, 21, 22, 23 + ToPort: 100 + CidrIp: 0.0.0.0/0 + + # Standalone IPv6 ingress rule + Positive1_ingress_ipv6: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: !Ref Positive1_security_group + IpProtocol: udp + FromPort: 2000 #exposes 2049 + ToPort: 2060 + CidrIpv6: ::/0 diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive2.json b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive2.json index 8b658c52c55..acc03d5c029 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive2.json +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive2.json @@ -1,38 +1,44 @@ { "Resources": { - "Ec2Instance": { - "Type": "AWS::EC2::Instance", - "Properties": { - "ImageId": "", - "SecurityGroups": [ - "InstanceSecurityGroup" - ], - "KeyName": "mykey" - } - }, - "InstanceSecurityGroup": { + "Positive1_security_group": { "Type": "AWS::EC2::SecurityGroup", "Properties": { + "GroupDescription": "Enable SSH access via port 22", "VpcId": { - "Ref": "myVPC" + "Ref": "MyVPC" }, "SecurityGroupIngress": [ { - "CidrIp": "0.0.0.0/0", - "IpProtocol": "tcp", - "FromPort": 20, - "ToPort": 20 - } - ], - "SecurityGroupEgress": [ - { - "IpProtocol": "tcp", - "FromPort": 80, - "ToPort": 80, + "IpProtocol": "-1", + "FromPort": 22, + "ToPort": 22, "CidrIp": "0.0.0.0/0" } - ], - "GroupDescription": "Allow http to client host" + ] + } + }, + "Positive1_ingress_ipv4": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Positive1_security_group" + }, + "IpProtocol": "tcp", + "FromPort": 0, + "ToPort": 100, + "CidrIp": "0.0.0.0/0" + } + }, + "Positive1_ingress_ipv6": { + "Type": "AWS::EC2::SecurityGroupIngress", + "Properties": { + "GroupId": { + "Ref": "Positive1_security_group" + }, + "IpProtocol": "udp", + "FromPort": 2000, + "ToPort": 2060, + "CidrIpv6": "::/0" } } } diff --git a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive_expected_result.json b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive_expected_result.json index e95d7d93867..7093bfd1c01 100644 --- a/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive_expected_result.json +++ b/assets/queries/cloudFormation/aws/security_groups_with_exhibited_admin_ports/test/positive_expected_result.json @@ -1,14 +1,38 @@ [ { + "queryName": "Security Groups With Exposed Admin Ports", + "severity": "HIGH", + "line": 8, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Groups With Exposed Admin Ports", "severity": "HIGH", - "line": 15, - "fileName": "positive1.yaml", - "queryName": "Security Groups With Exposed Admin Ports" + "line": 16, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Groups With Exposed Admin Ports", + "severity": "HIGH", + "line": 26, + "fileName": "positive1.yaml" + }, + { + "queryName": "Security Groups With Exposed Admin Ports", + "severity": "HIGH", + "line": 12, + "fileName": "positive2.json" + }, + { + "queryName": "Security Groups With Exposed Admin Ports", + "severity": "HIGH", + "line": 22, + "fileName": "positive2.json" }, { "queryName": "Security Groups With Exposed Admin Ports", "severity": "HIGH", - "line": 19, + "line": 34, "fileName": "positive2.json" } -] +] \ No newline at end of file diff --git a/e2e/fixtures/E2E_CLI_031_RESULT.html b/e2e/fixtures/E2E_CLI_031_RESULT.html index 7622f31b24d..8b921c51923 100644 --- a/e2e/fixtures/E2E_CLI_031_RESULT.html +++ b/e2e/fixtures/E2E_CLI_031_RESULT.html @@ -1,19 +1,13 @@ -KICS Scan ResultCheckmarx logo
KICS development +KICS Scan ResultCheckmarx logo
KICS development Scanned paths: /path/e2e/fixtures/samples/positive.yaml -Platforms: CloudFormation, CommonStart time: 10:52:07, Aug 21 2025 -End time: 10:53:14, Aug 21 2025

Vulnerabilities:

0 -CRITICAL
6 -HIGH
12 +Platforms: Common, CloudFormationStart time: 17:10:30, Oct 07 2025 +End time: 17:10:57, Oct 07 2025

Vulnerabilities:

0 +CRITICAL
4 +HIGH
10 MEDIUM
5 LOW
3 -INFO
26 -TOTAL

Fully Open Ingress

Platform: CloudFormation -CWE: 668 -Category: Networking and Firewall
ECS Service's security group should not allow unrestricted access to all ports from all IPv4 addresseshttps://docs.aws.amazon.com/AmazonECS/latest/developerguide/get-set-up-for-amazon-ecs.html#create-a-base-security-group
Results (2)
File: /path/e2e/fixtures/samples/positive.yaml -Line 24
Expected: Resource name 'EcsSecurityGroupHTTPinbound02' of type 'AWS::EC2::SecurityGroupIngress' should not accept ingress connections from all IPv4 adresses and to all available ports -Found: Resource name 'EcsSecurityGroupHTTPinbound02' of type 'AWS::EC2::SecurityGroupIngress' should not accept ingress connections from CIDR 0.0.0.0/0 to all available ports
23 ToPort: 0
24 CidrIp: 0.0.0.0/0
25 EcsSecurityGroupSSHinbound:
File: /path/e2e/fixtures/samples/positive.yaml -Line 32
Expected: Resource name 'EcsSecurityGroupSSHinbound' of type 'AWS::EC2::SecurityGroupIngress' should not accept ingress connections from all IPv4 adresses and to all available ports -Found: Resource name 'EcsSecurityGroupSSHinbound' of type 'AWS::EC2::SecurityGroupIngress' should not accept ingress connections from CIDR 0.0.0.0/0 to all available ports
31 ToPort: 0
32 CidrIp: 0.0.0.0/0
33 EcsSecurityGroupALBports:

Passwords And Secrets - CloudFormation Secret Template

Platform: Common +INFO
22 +TOTAL

Passwords And Secrets - CloudFormation Secret Template

Platform: Common CWE: 798 Category: Secret Management
Query to find passwords and secrets in infrastructure code.https://docs.kics.io/latest/secrets/
Results (1)
File: /path/e2e/fixtures/samples/positive.yaml Line 273
Expected: Hardcoded secret key should not appear in source @@ -24,10 +18,10 @@ Found: Hardcoded secret key appears in source
275 EncryptionKey: 'password'
276 Password: <SECRET-MASKED-ON-PURPOSE>
277 PasswordLength: 16

Unrestricted Security Group Ingress

Platform: CloudFormation CWE: 668 Category: Networking and Firewall
Results (2)
File: /path/e2e/fixtures/samples/positive.yaml -Line 32
Expected: Resources.EcsSecurityGroupSSHinbound.Properties.CidrIp should not be open to the world (0.0.0.0/0) -Found: Resources.EcsSecurityGroupSSHinbound.Properties.CidrIp is open to the world (0.0.0.0/0)
31 ToPort: 0
32 CidrIp: 0.0.0.0/0
33 EcsSecurityGroupALBports:
File: /path/e2e/fixtures/samples/positive.yaml Line 24
Expected: Resources.EcsSecurityGroupHTTPinbound02.Properties.CidrIp should not be open to the world (0.0.0.0/0) -Found: Resources.EcsSecurityGroupHTTPinbound02.Properties.CidrIp is open to the world (0.0.0.0/0)
23 ToPort: 0
24 CidrIp: 0.0.0.0/0
25 EcsSecurityGroupSSHinbound:

ALB Is Not Integrated With WAF

Platform: CloudFormation +Found: Resources.EcsSecurityGroupHTTPinbound02.Properties.CidrIp is open to the world (0.0.0.0/0)
23 ToPort: 80
24 CidrIp: 0.0.0.0/0
25 EcsSecurityGroupSSHinbound:
File: /path/e2e/fixtures/samples/positive.yaml +Line 32
Expected: Resources.EcsSecurityGroupSSHinbound.Properties.CidrIp should not be open to the world (0.0.0.0/0) +Found: Resources.EcsSecurityGroupSSHinbound.Properties.CidrIp is open to the world (0.0.0.0/0)
31 ToPort: 22
32 CidrIp: 0.0.0.0/0
33 EcsSecurityGroupALBports:

ALB Is Not Integrated With WAF

Platform: CloudFormation CWE: 778 Category: Networking and Firewall
All Application Load Balancers (ALB) must be protected with Web Application Firewall (WAF) servicehttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafregional-webaclassociation.html
Results (1)
File: /path/e2e/fixtures/samples/positive.yaml Line 86
Expected: 'Resources.ECSALB' should not have an 'internal' scheme and should have a 'WebACLAssociation' associated @@ -65,13 +59,9 @@ Line 270
Expected: 'Resources.MyAmpAppSecretManagerRotater.Properties.KmsKeyId' should be defined and not null Found: 'Resources.MyAmpAppSecretManagerRotater.Properties.KmsKeyId' is undefined or null
269 Type: AWS::SecretsManager::Secret
270 Properties:
271 Description: 'This is my amp app instance secret'

Security Group Ingress With Port Range

Platform: CloudFormation CWE: 665 -Category: Networking and Firewall
Results (3)
File: /path/e2e/fixtures/samples/positive.yaml -Line 27
Expected: Resources.EcsSecurityGroupSSHinbound.Properties.FromPort should equal to Resources.EcsSecurityGroupSSHinbound.Properties.ToPort -Found: Resources.EcsSecurityGroupSSHinbound.Properties.FromPort is not equal to Resources.EcsSecurityGroupSSHinbound.Properties.ToPort
26 Type: AWS::EC2::SecurityGroupIngress
27 Properties:
28 GroupId: !Ref 'EcsSecurityGroup'
File: /path/e2e/fixtures/samples/positive.yaml +Category: Networking and Firewall
Results (1)
File: /path/e2e/fixtures/samples/positive.yaml Line 35
Expected: Resources.EcsSecurityGroupALBports.Properties.FromPort should equal to Resources.EcsSecurityGroupALBports.Properties.ToPort -Found: Resources.EcsSecurityGroupALBports.Properties.FromPort is not equal to Resources.EcsSecurityGroupALBports.Properties.ToPort
34 Type: AWS::EC2::SecurityGroupIngress
35 Properties:
36 GroupId: !Ref 'EcsSecurityGroup'
File: /path/e2e/fixtures/samples/positive.yaml -Line 19
Expected: Resources.EcsSecurityGroupHTTPinbound02.Properties.FromPort should equal to Resources.EcsSecurityGroupHTTPinbound02.Properties.ToPort -Found: Resources.EcsSecurityGroupHTTPinbound02.Properties.FromPort is not equal to Resources.EcsSecurityGroupHTTPinbound02.Properties.ToPort
18 Type: AWS::EC2::SecurityGroupIngress
19 Properties:
20 GroupId: !Ref 'EcsSecurityGroup'

ECS Service Without Running Tasks

Platform: CloudFormation +Found: Resources.EcsSecurityGroupALBports.Properties.FromPort is not equal to Resources.EcsSecurityGroupALBports.Properties.ToPort
34 Type: AWS::EC2::SecurityGroupIngress
35 Properties:
36 GroupId: !Ref 'EcsSecurityGroup'

ECS Service Without Running Tasks

Platform: CloudFormation CWE: 665 Category: Availability
Results (1)
File: /path/e2e/fixtures/samples/positive.yaml Line 159
Expected: Resources.service.Properties.DeploymentConfiguration should be defined and not null @@ -92,10 +82,10 @@ Found: Resources.MyAmpAppSecretManagerRotater.Properties.KmsKeyId is undefined
269 Type: AWS::SecretsManager::Secret
270 Properties:
271 Description: 'This is my amp app instance secret'

Security Group Rule Without Description

Platform: CloudFormation CWE: 710 Category: Best Practices
It's considered a best practice for AWS Security Group to have a descriptionhttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html
Results (3)
File: /path/e2e/fixtures/samples/positive.yaml -Line 35
Expected: Resources.EcsSecurityGroupALBports.Properties.Description should be set -Found: Resources.EcsSecurityGroupALBports.Properties.Description is undefined
34 Type: AWS::EC2::SecurityGroupIngress
35 Properties:
36 GroupId: !Ref 'EcsSecurityGroup'
File: /path/e2e/fixtures/samples/positive.yaml Line 19
Expected: Resources.EcsSecurityGroupHTTPinbound02.Properties.Description should be set Found: Resources.EcsSecurityGroupHTTPinbound02.Properties.Description is undefined
18 Type: AWS::EC2::SecurityGroupIngress
19 Properties:
20 GroupId: !Ref 'EcsSecurityGroup'
File: /path/e2e/fixtures/samples/positive.yaml +Line 35
Expected: Resources.EcsSecurityGroupALBports.Properties.Description should be set +Found: Resources.EcsSecurityGroupALBports.Properties.Description is undefined
34 Type: AWS::EC2::SecurityGroupIngress
35 Properties:
36 GroupId: !Ref 'EcsSecurityGroup'
File: /path/e2e/fixtures/samples/positive.yaml Line 27
Expected: Resources.EcsSecurityGroupSSHinbound.Properties.Description should be set Found: Resources.EcsSecurityGroupSSHinbound.Properties.Description is undefined
26 Type: AWS::EC2::SecurityGroupIngress
27 Properties:
28 GroupId: !Ref 'EcsSecurityGroup'

KICS is open and will always stay such. Both the scanning engine and the security queries are clear and open for the software development community.
Spread the love: