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.
3
4
4
5
##### Imports #####
5
6
@@ -42,21 +43,21 @@ find_resources_from_plan = func(type) {
42
43
43
44
# Validate that all AWS ingress security group rules
44
45
# do not have cidr_block 0.0.0.0/0
45
- validate_sgr_cidr_blocks = func() {
46
+ validate_cidr_blocks = func() {
46
47
47
48
validated = true
48
49
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")
51
52
52
53
# Loop through the resource instances
53
- for resource_instances as address, r {
54
+ for sgr_instances as address, r {
54
55
55
56
# Skip resources that are being destroyed
56
57
# to avoid unnecessary policy violations.
57
58
# Used to be: if length(r.diff) == 0
58
59
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.")
60
61
continue
61
62
}
62
63
@@ -83,15 +84,76 @@ validate_sgr_cidr_blocks = func() {
83
84
}
84
85
} // end computed check
85
86
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
87
149
88
150
return validated
89
151
}
90
152
91
153
##### Rules #####
92
154
93
155
# Call the validation function and assign results
94
- sgrs_validated = validate_sgr_cidr_blocks ()
156
+ sgrs_validated = validate_cidr_blocks ()
95
157
96
158
# Main rule
97
159
main = rule {
0 commit comments