Skip to content

Commit c89335c

Browse files
committed
fix(checks): align AVD-AWS-0107 and AVD-AWS-0105 checks with CIS Benchmarks
Signed-off-by: Nikita Pivkin <nikita.pivkin@smartforce.io>
1 parent 8b5a6a1 commit c89335c

14 files changed

+189
-30
lines changed

avd_docs/aws/ec2/AVD-AWS-0105/CloudFormation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
Set a more restrictive cidr range
2+
Set a more restrictive CIDR range
33

44
```yaml---
55
AWSTemplateFormatVersion: 2010-09-09

avd_docs/aws/ec2/AVD-AWS-0105/Terraform.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
Set a more restrictive cidr range
2+
Set a more restrictive CIDR range
33

44
```hcl
55
resource "aws_network_acl_rule" "good_example" {

avd_docs/aws/ec2/AVD-AWS-0105/docs.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11

2-
Opening up ACLs to the public internet is potentially dangerous. You should restrict access to IP addresses or ranges that explicitly require it where possible.
2+
The Network Access Control List (NACL) function provide stateless filtering of ingress and
3+
egress network traffic to AWS resources. It is recommended that no NACL allows
4+
unrestricted ingress access to remote server administration ports, such as SSH to port 22
5+
and RDP to port 3389.
36

47

58
### Impact
@@ -11,4 +14,6 @@ Opening up ACLs to the public internet is potentially dangerous. You should rest
1114
### Links
1215
- https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html
1316

17+
- https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-21
18+
1419

avd_docs/aws/ec2/AVD-AWS-0107/CloudFormation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
Set a more restrictive cidr range
2+
Set a more restrictive CIDR range
33

44
```yaml---
55
Resources:

avd_docs/aws/ec2/AVD-AWS-0107/Terraform.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
Set a more restrictive cidr range
2+
Set a more restrictive CIDR range
33

44
```hcl
55
resource "aws_security_group_rule" "good_example" {

avd_docs/aws/ec2/AVD-AWS-0107/docs.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2-
Opening up ports to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that explicitly require it where possible.
2+
Security groups provide stateful filtering of ingress and egress network traffic to AWS
3+
resources. It is recommended that no security group allows unrestricted ingress access to
4+
remote server administration ports, such as SSH to port 22 and RDP to port 3389.
35

46

57
### Impact
@@ -11,4 +13,8 @@ Opening up ports to the public internet is generally to be avoided. You should r
1113
### Links
1214
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html
1315

16+
- https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-13
17+
18+
- https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-14
19+
1420

checks/cloud/aws/ec2/no_public_ingress_acl.rego

+18-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,29 @@
11
# METADATA
2-
# title: An ingress Network ACL rule allows specific ports from /0.
2+
# title: Network ACLs should not allow ingress from 0.0.0.0/0 to port 22 or port 3389.
33
# description: |
4-
# Opening up ACLs to the public internet is potentially dangerous. You should restrict access to IP addresses or ranges that explicitly require it where possible.
4+
# The Network Access Control List (NACL) function provide stateless filtering of ingress and
5+
# egress network traffic to AWS resources. It is recommended that no NACL allows
6+
# unrestricted ingress access to remote server administration ports, such as SSH to port 22
7+
# and RDP to port 3389.
58
# scope: package
69
# schemas:
710
# - input: schema["cloud"]
811
# related_resources:
912
# - https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html
13+
# - https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-21
1014
# custom:
1115
# id: AVD-AWS-0105
1216
# avd_id: AVD-AWS-0105
1317
# provider: aws
1418
# service: ec2
15-
# severity: CRITICAL
19+
# severity: MEDIUM
1620
# short_code: no-public-ingress-acl
17-
# recommended_action: Set a more restrictive cidr range
21+
# recommended_action: Set a more restrictive CIDR range
22+
# frameworks:
23+
# default:
24+
# - null
25+
# cis-aws-1.4:
26+
# - "5.1"
1827
# input:
1928
# selector:
2029
# - type: cloud
@@ -33,14 +42,17 @@ package builtin.aws.ec2.aws0105
3342

3443
import rego.v1
3544

45+
import data.lib.net
46+
3647
deny contains res if {
3748
some acl in input.aws.ec2.networkacls
3849
some rule in acl.rules
3950
is_ingress(rule)
4051
is_allow(rule)
52+
net.is_tcp_protocol(rule.protocol.value)
53+
net.is_ssh_or_rdp_port(rule)
4154
some block in rule.cidrs
42-
cidr.is_public(block.value)
43-
cidr.count_addresses(block.value) > 1
55+
net.cidr_allows_all_ips(block.value)
4456
res := result.new(
4557
"Network ACL rule allows ingress from public internet.",
4658
block,

checks/cloud/aws/ec2/no_public_ingress_acl_test.rego

+29-6
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,45 @@ import rego.v1
55
import data.builtin.aws.ec2.aws0105 as check
66
import data.lib.test
77

8-
test_deny_acl_rule_with_wildcard_address if {
9-
inp := {"aws": {"ec2": {"networkacls": [{"rules": [{
8+
import data.lib.net
9+
10+
test_deny_acl_rule_all_ips_for_ssh_port_and_tcp if {
11+
inp := build_input({
12+
"protocol": {"value": "tcp"},
1013
"type": {"value": "ingress"},
1114
"action": {"value": "allow"},
1215
"cidrs": [{"value": "0.0.0.0/0"}],
13-
}]}]}}}
16+
"fromport": {"value": net.ssh_port},
17+
"toport": {"value": net.ssh_port},
18+
})
1419

1520
test.assert_count(check.deny, 1) with input as inp
1621
}
1722

18-
test_allow_acl_rule_with_specific_address if {
19-
inp := {"aws": {"ec2": {"networkacls": [{"rules": [{
23+
test_deny_ingress_sq_all_ips_for_all_ports_and_all_ports if {
24+
inp := build_input({
25+
"protocol": {"value": "-1"},
26+
"type": {"value": "ingress"},
27+
"action": {"value": "allow"},
28+
"cidrs": [{"value": "0.0.0.0/0"}],
29+
"fromport": {"value": 0},
30+
"toport": {"value": 0},
31+
})
32+
33+
test.assert_count(check.deny, 1) with input as inp
34+
}
35+
36+
test_allow_acl_rule_restrictive_cidr_range if {
37+
inp := build_input({
38+
"protocol": {"value": "tcp"},
2039
"type": {"value": "ingress"},
2140
"action": {"value": "allow"},
2241
"cidrs": [{"value": "10.0.0.0/16"}],
23-
}]}]}}}
42+
"fromport": {"value": net.ssh_port},
43+
"toport": {"value": net.ssh_port},
44+
})
2445

2546
test.assert_empty(check.deny) with input as inp
2647
}
48+
49+
build_input(rule) := {"aws": {"ec2": {"networkacls": [{"rules": [rule]}]}}}

checks/cloud/aws/ec2/no_public_ingress_sgr.rego

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
# METADATA
2-
# title: An ingress security group rule allows traffic from /0.
2+
# title: Security groups should not allow ingress from 0.0.0.0/0 or ::/0 to port 22 or port 3389.
33
# description: |
4-
# Opening up ports to the public internet is generally to be avoided. You should restrict access to IP addresses or ranges that explicitly require it where possible.
4+
# Security groups provide stateful filtering of ingress and egress network traffic to AWS
5+
# resources. It is recommended that no security group allows unrestricted ingress access to
6+
# remote server administration ports, such as SSH to port 22 and RDP to port 3389.
57
# scope: package
68
# schemas:
79
# - input: schema["cloud"]
810
# related_resources:
911
# - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-rules-reference.html
12+
# - https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-13
13+
# - https://docs.aws.amazon.com/securityhub/latest/userguide/ec2-controls.html#ec2-14
1014
# custom:
1115
# id: AVD-AWS-0107
1216
# avd_id: AVD-AWS-0107
1317
# provider: aws
1418
# service: ec2
15-
# severity: CRITICAL
19+
# severity: HIGH
1620
# short_code: no-public-ingress-sgr
17-
# recommended_action: Set a more restrictive cidr range
21+
# recommended_action: Set a more restrictive CIDR range
1822
# frameworks:
1923
# default:
2024
# - null
@@ -39,12 +43,15 @@ package builtin.aws.ec2.aws0107
3943

4044
import rego.v1
4145

46+
import data.lib.net
47+
4248
deny contains res if {
4349
some group in input.aws.ec2.securitygroups
4450
some rule in group.ingressrules
51+
net.is_tcp_or_udp_protocol(rule.protocol.value)
52+
net.is_ssh_or_rdp_port(rule)
4553
some block in rule.cidrs
46-
cidr.is_public(block.value)
47-
cidr.count_addresses(block.value) > 1
54+
net.cidr_allows_all_ips(block.value)
4855
res := result.new(
4956
"Security group rule allows ingress from public internet.",
5057
block,

checks/cloud/aws/ec2/no_public_ingress_sgr_test.rego

+40-4
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,50 @@ import rego.v1
55
import data.builtin.aws.ec2.aws0107 as check
66
import data.lib.test
77

8-
test_deny_ingress_sq_with_wildcard_address if {
9-
inp := {"aws": {"ec2": {"securitygroups": [{"ingressrules": [{"cidrs": [{"value": "0.0.0.0/0"}]}]}]}}}
8+
import data.lib.net
9+
10+
test_deny_ingress_sq_all_ips_for_ssh_port_and_tcp if {
11+
inp := build_input({
12+
"protocol": {"value": "tcp"},
13+
"cidrs": [{"value": "0.0.0.0/0"}],
14+
"fromport": {"value": net.ssh_port},
15+
"toport": {"value": net.ssh_port},
16+
})
17+
18+
test.assert_count(check.deny, 1) with input as inp
19+
}
20+
21+
test_deny_ingress_sq_all_ips_for_rdp_port_and_udp if {
22+
inp := build_input({
23+
"protocol": {"value": "udp"},
24+
"cidrs": [{"value": "0.0.0.0/0"}],
25+
"fromport": {"value": net.rdp_port},
26+
"toport": {"value": net.rdp_port},
27+
})
1028

1129
test.assert_count(check.deny, 1) with input as inp
1230
}
1331

14-
test_allow_ingress_sg_with_private_address if {
15-
inp := {"aws": {"ec2": {"securitygroups": [{"ingressrules": [{"cidrs": [{"value": "10.0.0.0/16"}]}]}]}}}
32+
test_deny_ingress_sq_all_ips_for_all_ports_and_all_protocols if {
33+
inp := build_input({
34+
"protocol": {"value": "-1"},
35+
"cidrs": [{"value": "0.0.0.0/0"}],
36+
"fromport": {"value": 0},
37+
"toport": {"value": 0},
38+
})
39+
40+
test.assert_count(check.deny, 1) with input as inp
41+
}
42+
43+
test_allow_ingress_sg_restrictive_cidr_range if {
44+
inp := build_input({
45+
"protocol": {"value": "tcp"},
46+
"cidrs": [{"value": "10.0.0.0/16"}],
47+
"fromport": {"value": net.ssh_port},
48+
"toport": {"value": net.ssh_port},
49+
})
1650

1751
test.assert_empty(check.deny) with input as inp
1852
}
53+
54+
build_input(rule) := {"aws": {"ec2": {"securitygroups": [{"ingressrules": [rule]}]}}}

lib/cloud/net.rego

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# METADATA
2+
# custom:
3+
# library: true
4+
# input:
5+
# selector:
6+
# - type: cloud
7+
package lib.net
8+
9+
import rego.v1
10+
11+
ssh_port := 22
12+
13+
rdp_port := 3389
14+
15+
all_ips := {"0.0.0.0/0", "0000:0000:0000:0000:0000:0000:0000:0000/0", "::/0"}
16+
17+
# "-1" or "all" equivalent to all protocols
18+
# https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AuthorizeSecurityGroupIngress.html
19+
# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_firewall#protocol
20+
all_protocols := {"-1", "all"}
21+
22+
# "6" is ID of TCP
23+
# https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
24+
is_tcp_protocol(protocol) if protocol in {"tcp", "6"}
25+
26+
is_tcp_protocol(protocol) if protocol in all_protocols
27+
28+
# "6" is ID of TCP
29+
# https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
30+
is_udp_protocol(protocol) if protocol in {"udp", "17"}
31+
32+
is_udp_protocol(protocol) if protocol in all_protocols
33+
34+
is_tcp_or_udp_protocol(protocol) if is_tcp_protocol(protocol)
35+
36+
is_tcp_or_udp_protocol(protocol) if is_udp_protocol(protocol)
37+
38+
# protocol "-1" allows traffic on all ports, regardless of any port range you specify.
39+
# https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_AuthorizeSecurityGroupIngress.html
40+
is_ssh_or_rdp_port(rule) if rule.protocol.value in {"-1"}
41+
42+
is_ssh_or_rdp_port(rule) if is_port_range_include(rule.fromport.value, rule.toport.value, ssh_port)
43+
44+
is_ssh_or_rdp_port(rule) if is_port_range_include(rule.fromport.value, rule.toport.value, rdp_port)
45+
46+
is_port_range_include(from, to, port) if {
47+
from <= port
48+
port <= to
49+
}
50+
51+
# check if CIDR defines an IP block containing all possible IP addresses
52+
cidr_allows_all_ips(cidr) if cidr in all_ips

pkg/specs/compliance/aws-cis-1.2.yaml

+8-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,13 @@ spec:
206206
severity: LOW
207207
- id: "4.1"
208208
name: no-public-ingress-sgr
209-
description: An ingress security group rule allows traffic from /0.
209+
description: Security groups should not allow ingress from 0.0.0.0/0 or ::/0 to port 22 or port 3389.
210210
checks:
211211
- id: AVD-AWS-0107
212-
severity: CRITICAL
212+
severity: HIGH
213+
- id: "4.2"
214+
name: no-public-ingress-sgr
215+
description: Security groups should not allow ingress from 0.0.0.0/0 or ::/0 to port 22 or port 3389.
216+
checks:
217+
- id: AVD-AWS-0107
218+
severity: HIGH

pkg/specs/compliance/aws-cis-1.4.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ spec:
233233
checks:
234234
- id: AVD-AWS-0155
235235
severity: LOW
236+
- id: "5.1"
237+
name: aws-vpc-no-public-ingress-acl
238+
description: Network ACLs should not allow ingress from 0.0.0.0/0 to port 22 or port 3389.
239+
checks:
240+
- id: AVD-AWS-0105
241+
severity: HIGH
236242
- id: "5.3"
237243
name: restrict-all-in-default-sg
238244
description: Default security group should restrict all traffic

test/rego/aws_ec2_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ var awsEc2TestCases = testCases{
498498
Metadata: trivyTypes.NewTestMetadata(),
499499
Type: trivyTypes.String(ec2.TypeIngress, trivyTypes.NewTestMetadata()),
500500
Action: trivyTypes.String(ec2.ActionAllow, trivyTypes.NewTestMetadata()),
501+
Protocol: trivyTypes.StringTest("tcp"),
502+
FromPort: trivyTypes.IntTest(22),
503+
ToPort: trivyTypes.IntTest(22),
501504
CIDRs: []trivyTypes.StringValue{
502505
trivyTypes.String("0.0.0.0/0", trivyTypes.NewTestMetadata()),
503506
},
@@ -543,6 +546,9 @@ var awsEc2TestCases = testCases{
543546
CIDRs: []trivyTypes.StringValue{
544547
trivyTypes.String("0.0.0.0/0", trivyTypes.NewTestMetadata()),
545548
},
549+
Protocol: trivyTypes.StringTest("tcp"),
550+
FromPort: trivyTypes.IntTest(22),
551+
ToPort: trivyTypes.IntTest(22),
546552
},
547553
},
548554
},

0 commit comments

Comments
 (0)