Skip to content

Commit

Permalink
feat(query): added "Network ACL With Unrestricted Access To SSH" and…
Browse files Browse the repository at this point in the history
… "Network ACL With Unrestricted Access To RDP" for Terraform #4032
  • Loading branch information
rafaela-soares authored Aug 13, 2021
1 parent 9dcf287 commit a71c25b
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 38 deletions.
10 changes: 8 additions & 2 deletions assets/libraries/terraform/library.rego
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package generic.terraform

check_cidr(rule) {
rule.cidr_blocks[_] == "0.0.0.0/0"
} else {
rule.cidr_block == "0.0.0.0/0"
}

# Checks if a TCP port is open in a rule
openPort(rule, port) {
rule.cidr_blocks[_] == "0.0.0.0/0"
check_cidr(rule)
rule.protocol == "tcp"
containsPort(rule, port)
}

openPort(rules, port) {
rule := rules[_]
rule.cidr_blocks[_] == "0.0.0.0/0"
check_cidr(rule)
rule.protocol == "tcp"
containsPort(rule, port)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "a20be318-cac7-457b-911d-04cc6e812c25",
"queryName": "Network ACL With Unrestricted Access To RDP",
"severity": "HIGH",
"category": "Networking and Firewall",
"descriptionText": "'RDP' (TCP:3389) should not be public in AWS Network ACL",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl",
"platform": "Terraform",
"descriptionID": "ed220e0d",
"cloudProvider": "aws"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package Cx

import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_network_acl[name]

terra_lib.openPort(resource.ingress[idx], 3389)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("aws_network_acl[%s].ingress", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_network_acl[%s].ingress[%d] 'RDP' (TCP:3389) is not public", [name, idx]),
"keyActualValue": sprintf("aws_network_acl[%s].ingress[%d] 'RDP' (TCP:3389) is public", [name, idx]),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_network_acl" "negative1" {
vpc_id = aws_vpc.main.id

egress = [
{
protocol = "tcp"
rule_no = 200
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 443
to_port = 443
}
]

ingress = [
{
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 3389
to_port = 3389
}
]

tags = {
Name = "main"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_network_acl" "positive1" {
vpc_id = aws_vpc.main.id

egress = [
{
protocol = "tcp"
rule_no = 200
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 443
to_port = 443
}
]

ingress = [
{
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 3389
to_port = 3389
}
]

tags = {
Name = "main"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"queryName": "Network ACL With Unrestricted Access To RDP",
"severity": "HIGH",
"line": 15
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"id": "3af7f2fd-06e6-4dab-b996-2912bea19ba4",
"queryName": "Network ACL With Unrestricted Access To SSH",
"severity": "HIGH",
"category": "Networking and Firewall",
"descriptionText": "'SSH' (TCP:22) should not be public in AWS Network ACL",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl",
"platform": "Terraform",
"descriptionID": "215ffb15",
"cloudProvider": "aws"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package Cx

import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_network_acl[name]

terra_lib.openPort(resource.ingress[idx], 22)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("aws_network_acl[%s].ingress", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_network_acl[%s].ingress[%d] 'SSH' (Port:22) is not public", [name, idx]),
"keyActualValue": sprintf("aws_network_acl[%s].ingress[%d] 'SSH' (Port:22) is public", [name, idx]),
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_network_acl" "negative1" {
vpc_id = aws_vpc.main.id

egress = [
{
protocol = "tcp"
rule_no = 200
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 443
to_port = 443
}
]

ingress = [
{
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 22
to_port = 22
}
]

tags = {
Name = "main"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
resource "aws_network_acl" "positive1" {
vpc_id = aws_vpc.main.id

egress = [
{
protocol = "tcp"
rule_no = 200
action = "allow"
cidr_block = "10.3.0.0/18"
from_port = 443
to_port = 443
}
]

ingress = [
{
protocol = "tcp"
rule_no = 100
action = "allow"
cidr_block = "0.0.0.0/0"
from_port = 22
to_port = 22
}
]

tags = {
Name = "main"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"queryName": "Network ACL With Unrestricted Access To SSH",
"severity": "HIGH",
"line": 15
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"queryName": "Security Group With Unrestricted Access To SSH",
"severity": "HIGH",
"category": "Networking and Firewall",
"descriptionText": "SSH' (TCP:22) should not be public in AWS Security Group",
"descriptionText": "'SSH' (TCP:22) should not be public in AWS Security Group",
"descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group",
"platform": "Terraform",
"descriptionID": "51e59188",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,17 @@
package Cx

import data.generic.terraform as terra_lib

CxPolicy[result] {
resource := input.document[i].resource.aws_security_group[name]
ingress := getIngressList(resource.ingress)
currentFromPort := ingress[j].from_port
currentToPort := ingress[j].to_port
cidr := ingress[j].cidr_blocks

isSSH(currentFromPort, currentToPort)

not isPrivate(cidr)
terra_lib.openPort(resource.ingress, 22)

result := {
"documentId": input.document[i].id,
"searchKey": sprintf("aws_security_group[%s].ingress.cidr_blocks", [name]),
"issueType": "IncorrectValue",
"keyExpectedValue": sprintf("aws_security_group[%s] SSH' (Port:22) is not public", [name]),
"keyActualValue": sprintf("aws_security_group[%s] SSH' (Port:22) is public", [name]),
"keyExpectedValue": sprintf("aws_security_group[%s] 'SSH' (Port:22) is not public", [name]),
"keyActualValue": sprintf("aws_security_group[%s] 'SSH' (Port:22) is public", [name]),
}
}

getIngressList(ingress) = list {
is_array(ingress)
list := ingress
} else = list {
is_object(ingress)
list := [ingress]
} else = null {
true
}

isSSH(currentFromPort, currentToPort) {
currentFromPort <= 22
currentToPort >= 22
}

isPrivate(cidr) {
privateIPs = ["192.120.0.0/16", "75.132.0.0/16", "79.32.0.0/8", "73.16.0.0/12"]

cidrLength := count(cidr)

privLen := count({x | cidr[x]; cidr[x] == privateIPs[j]})
varLen := count({b | cidr[b]; contains(cidr[b], "$")}) # check if all CIDR blocks are stored in variables, which cannot be evaluated in the static scanning

privLen + varLen == cidrLength
}

0 comments on commit a71c25b

Please sign in to comment.