Skip to content

Commit dfbeddf

Browse files
committed
cover aws_security_group too
1 parent 2145e0a commit dfbeddf

File tree

4 files changed

+529
-9
lines changed

4 files changed

+529
-9
lines changed

governance/second-generation/aws/restrict-ingress-sg-rule-cidr-blocks.sentinel

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# This policy uses the Sentinel tfplan import to validate that
2-
# no security group rules have the CIDR "0.0.0.0/0"
1+
# This policy uses the Sentinel tfplan import to validate that no security group
2+
# rules have the CIDR "0.0.0.0/0". It covers both the aws_security_group and
3+
# the aws_security_group_rule resources.
34

45
##### Imports #####
56

@@ -42,21 +43,21 @@ find_resources_from_plan = func(type) {
4243

4344
# Validate that all AWS ingress security group rules
4445
# do not have cidr_block 0.0.0.0/0
45-
validate_sgr_cidr_blocks = func() {
46+
validate_cidr_blocks = func() {
4647

4748
validated = true
4849

49-
# Get all resources of specified type
50-
resource_instances = find_resources_from_plan("aws_security_group_rule")
50+
# Get all AWS security group rules
51+
sgr_instances = find_resources_from_plan("aws_security_group_rule")
5152

5253
# Loop through the resource instances
53-
for resource_instances as address, r {
54+
for sgr_instances as address, r {
5455

5556
# Skip resources that are being destroyed
5657
# to avoid unnecessary policy violations.
5758
# Used to be: if length(r.diff) == 0
5859
if r.destroy and not r.requires_new {
59-
print("Skipping resource", address, "that is being destroyed.")
60+
print("Skipping security group rule", address, "that is being destroyed.")
6061
continue
6162
}
6263

@@ -83,15 +84,76 @@ validate_sgr_cidr_blocks = func() {
8384
}
8485
} // end computed check
8586

86-
} // end resource instances
87+
} // end security group rule instances
88+
89+
# Get all AWS security groups
90+
sg_instances = find_resources_from_plan("aws_security_group")
91+
92+
# Loop through the resource instances
93+
for sg_instances as address, r {
94+
95+
# Skip resources that are being destroyed
96+
# to avoid unnecessary policy violations.
97+
# Used to be: if length(r.diff) == 0
98+
if r.destroy and not r.requires_new {
99+
print("Skipping security group", address, "that is being destroyed.")
100+
continue
101+
}
102+
103+
# Check if there are ingress blocks that are not computed
104+
if (r.diff["ingress.#"].computed else false) is true {
105+
print("Security group", address, "does not have any ingress blocks",
106+
"or, they are computed.")
107+
# If you want computed values to cause the policy to fail,
108+
# uncomment the next line.
109+
# validated = false
110+
} else {
111+
# Check if r.applied.ingress is a list (to be safe)
112+
if types.type_of(r.applied.ingress) is "list" {
113+
114+
ingress_count = 0
115+
116+
for r.applied.ingress as i {
117+
118+
# Determine if ingress.<n>.cidr_blocks.# attribute is computed
119+
ingress_cidr_blocks = "ingress." + string(ingress_count) + ".cidr_blocks.#"
120+
if (r.diff[ingress_cidr_blocks].computed else false) is true {
121+
print("Ingress block #", ingress_count, "of security group",
122+
address, "has cidr_blocks that is computed.")
123+
# If you want computed values to cause the policy to fail,
124+
# uncomment the next line.
125+
# validated = false
126+
} else {
127+
# Validate that the ingress rule does not have disallowed value
128+
# Since cidr_blocks is optional and could be computed,
129+
# We check that it is present and really a list
130+
# before checking whether it contains "0.0.0.0/0"
131+
if i.cidr_blocks else null is not null and
132+
types.type_of(i.cidr_blocks) is "list" and
133+
i.cidr_blocks contains "0.0.0.0/0" {
134+
print("Ingress block #", ingress_count, "of security group",
135+
address, "contains disallowed cidr_block 0.0.0.0/0" )
136+
validated = false
137+
}
138+
} // end cidr_blocks.# computed check
139+
140+
# increment ingress_count
141+
ingress_count += 1
142+
143+
} // end ingress loop
144+
145+
} // end if r.applied.ingress a list
146+
} // end if diff[ingress.#] computed
147+
148+
} // end security group instances
87149

88150
return validated
89151
}
90152

91153
##### Rules #####
92154

93155
# Call the validation function and assign results
94-
sgrs_validated = validate_sgr_cidr_blocks()
156+
sgrs_validated = validate_cidr_blocks()
95157

96158
# Main rule
97159
main = rule {

governance/second-generation/aws/test/restrict-ingress-sg-rule-cidr-blocks/mock-tfplan-fail-0.12.sentinel

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,161 @@ _modules = {
66
"data": {},
77
"path": [],
88
"resources": {
9+
"aws_security_group": {
10+
"allow_tls": {
11+
0: {
12+
"applied": {
13+
"description": "Allow TLS inbound traffic",
14+
"ingress": [
15+
{
16+
"cidr_blocks": [
17+
"0.0.0.0/0",
18+
],
19+
"description": "",
20+
"from_port": 443,
21+
"ipv6_cidr_blocks": [],
22+
"prefix_list_ids": [],
23+
"protocol": "tcp",
24+
"security_groups": [],
25+
"self": false,
26+
"to_port": 443,
27+
},
28+
],
29+
"name": "allow_tls",
30+
"name_prefix": null,
31+
"revoke_rules_on_delete": false,
32+
"tags": {
33+
"Name": "allow_all",
34+
},
35+
"timeouts": null,
36+
},
37+
"destroy": false,
38+
"diff": {
39+
"arn": {
40+
"computed": true,
41+
"new": "",
42+
"old": "",
43+
},
44+
"description": {
45+
"computed": false,
46+
"new": "Allow TLS inbound traffic",
47+
"old": "",
48+
},
49+
"egress.#": {
50+
"computed": true,
51+
"new": "",
52+
"old": "",
53+
},
54+
"id": {
55+
"computed": true,
56+
"new": "",
57+
"old": "",
58+
},
59+
"ingress.#": {
60+
"computed": false,
61+
"new": "1",
62+
"old": "",
63+
},
64+
"ingress.0.%": {
65+
"computed": false,
66+
"new": "9",
67+
"old": "",
68+
},
69+
"ingress.0.cidr_blocks.#": {
70+
"computed": false,
71+
"new": "1",
72+
"old": "",
73+
},
74+
"ingress.0.cidr_blocks.0": {
75+
"computed": false,
76+
"new": "0.0.0.0/0",
77+
"old": "",
78+
},
79+
"ingress.0.description": {
80+
"computed": false,
81+
"new": "",
82+
"old": "",
83+
},
84+
"ingress.0.from_port": {
85+
"computed": false,
86+
"new": "443",
87+
"old": "",
88+
},
89+
"ingress.0.ipv6_cidr_blocks.#": {
90+
"computed": false,
91+
"new": "0",
92+
"old": "",
93+
},
94+
"ingress.0.prefix_list_ids.#": {
95+
"computed": false,
96+
"new": "0",
97+
"old": "",
98+
},
99+
"ingress.0.protocol": {
100+
"computed": false,
101+
"new": "tcp",
102+
"old": "",
103+
},
104+
"ingress.0.security_groups.#": {
105+
"computed": false,
106+
"new": "0",
107+
"old": "",
108+
},
109+
"ingress.0.self": {
110+
"computed": false,
111+
"new": "false",
112+
"old": "",
113+
},
114+
"ingress.0.to_port": {
115+
"computed": false,
116+
"new": "443",
117+
"old": "",
118+
},
119+
"name": {
120+
"computed": false,
121+
"new": "allow_tls",
122+
"old": "",
123+
},
124+
"name_prefix": {
125+
"computed": false,
126+
"new": "",
127+
"old": "",
128+
},
129+
"owner_id": {
130+
"computed": true,
131+
"new": "",
132+
"old": "",
133+
},
134+
"revoke_rules_on_delete": {
135+
"computed": false,
136+
"new": "false",
137+
"old": "",
138+
},
139+
"tags.%": {
140+
"computed": false,
141+
"new": "1",
142+
"old": "",
143+
},
144+
"tags.Name": {
145+
"computed": false,
146+
"new": "allow_all",
147+
"old": "",
148+
},
149+
"timeouts": {
150+
"computed": false,
151+
"new": "",
152+
"old": "",
153+
},
154+
"vpc_id": {
155+
"computed": true,
156+
"new": "",
157+
"old": "",
158+
},
159+
},
160+
"requires_new": false,
161+
},
162+
},
163+
},
9164
"aws_security_group_rule": {
10165
"allow_all": {
11166
0: {

0 commit comments

Comments
 (0)