@@ -3,6 +3,15 @@ package Cx
33import data.generic.common as common_lib
44import data.generic.terraform as tf_lib
55
6+ types := {" google_logging_metric" , " google_monitoring_alert_policy" }
7+
8+ service_name_pattern := " protopayload\\ .servicename=\" cloudresourcemanager\\ .googleapis\\ .com\" "
9+ ownership_pattern_1 := " \\ (projectownershiporprojectownerinvitee\\ )"
10+ ownership_pattern_2 := " \\ (projectownerinviteeorprojectownership\\ )"
11+ binding_action_remove := " protopayload\\ .servicedata\\ .policydelta\\ .bindingdeltas\\ .action=\" remove\" "
12+ binding_action_add := " protopayload\\ .servicedata\\ .policydelta\\ .bindingdeltas\\ .action=\" add\" "
13+ binding_role_owner := " protopayload\\ .servicedata\\ .policydelta\\ .bindingdeltas\\ .role=\" roles/owner\" "
14+
615CxPolicy[result] {
716 log_resources := [{" value" : object.get (input.document[index].resource, " google_logging_metric" , []), " document_index" : index}]
817 alert_resources := [{" value" : object.get (input.document[index].resource, " google_monitoring_alert_policy" , []), " document_index" : index}]
@@ -23,9 +32,10 @@ CxPolicy[result] {
2332not_one_valid_log_and_alert_pair (log_resources, alert_resources) = results {
2433 log_resources[_].value != []
2534 logs_filters_data := [log | log := get_data (log_resources[_].value[log_name], " google_logging_metric" , log_name, log_resources[_].document_index)]
26- results := [res | filters_data := logs_filters_data[i]
27- keyActualValue := single_match (filters_data)
28- keyActualValue != null
35+
36+ results := [res |
37+ filters_data := logs_filters_data[i]
38+ not single_match (filters_data.filter)
2939 res := {
3040 " documentId" : input.document[logs_filters_data[i].doc_index].id,
3141 " resourceType" : " google_logging_metric" ,
@@ -35,16 +45,16 @@ not_one_valid_log_and_alert_pair(log_resources, alert_resources) = results {
3545 " keyExpectedValue" : " At least one 'google_logging_metric' resource should capture project ownership assignment and changes" ,
3646 " keyActualValue" : " No 'google_logging_metric' resource captures project ownership assignment and changes" ,
3747 " searchLine" : common_lib.build_search_line (logs_filters_data[i].searchArray, [])
38- }]
48+ }
49+ ]
3950 count (results) == count (logs_filters_data) # if a single filter is valid it should not flag
4051} else = results {
4152 log_resources[_].value != []
4253 alert_resources[_].value != []
4354 logs_filters_data := [log | log := get_data (log_resources[_].value[log_name], " google_logging_metric" , log_name, log_resources[_].document_index)]
4455
4556 valid_logs_names := [logs_filters_data[i2].name |
46- lines := process_filter (logs_filters_data[i2].filter)
47- is_improper_filter (lines) == null
57+ single_match (logs_filters_data[i2].filter)
4858 ]
4959
5060 alerts_filters_data := [alert | alert := get_data (alert_resources[_].value[name_al], " google_monitoring_alert_policy" , name_al, log_resources[_].document_index)]
@@ -96,24 +106,27 @@ get_data(resource, type, name, doc_index) = filter {
96106 }
97107}
98108
99- single_match (filter){
109+ single_match (filter) {
100110 processed_filter := lower (regex.replace (filter, " \\ s+" , " " ))
101111 is_valid_filter (processed_filter)
102- # lines := process_filter(filters_data.filter)
103- # keyActualValue := is_improper_filter(lines)
112+ }
113+
114+ is_valid_filter (filter) {
115+ service_name_valid (filter) # checks if serviceName is defined to "cloudresourcemanager.googleapis.com"
116+ ownership_valid (filter) # checks if (ProjectOwnership OR projectOwnerInvitee) is present
117+ remove_owner_valid (filter) # checks if (action="REMOVE" AND role="roles/owner") is present
118+ add_owner_valid (filter) # checks if (action="ADD" AND role="roles/owner") is present
104119}
105120
106121has_regex_match_or_reference (alerts_filters_data, valid_logs_names) = true {
107- lines := process_filter (alerts_filters_data[i].filter)
108- is_improper_filter (lines) == null
122+ single_match (alerts_filters_data[i].filter)
109123 alerts_filters_data[i].resource.notification_channels
110124} else = true {
111125 alerts_filters_data[i].allows_ref == true
112126 alerts_filters_data[i].resource.notification_channels
113127 contains (alerts_filters_data[i].filter, sprintf (" logging.googleapis.com/user/%s" ,[valid_logs_names[_]]))
114- } else = index {
115- lines := process_filter (alerts_filters_data[index].filter)
116- is_improper_filter (lines) == null
128+ } else = index { # correct filter but missing notification_channels
129+ single_match (alerts_filters_data[index].filter)
117130} else = index {
118131 alerts_filters_data[index].allows_ref == true
119132 contains (alerts_filters_data[index].filter, sprintf (" logging.googleapis.com/user/%s" ,[valid_logs_names[_]]))
@@ -145,71 +158,40 @@ get_results(alerts_filters_data, value) = results {
145158 }]
146159}
147160
148- # definir aqui algo como o is_improper_filter
149- is_improper_filter (lines) = keyActualValue { # serviceName not defined to 'cloudresourcemanager.googleapis.com'
150- not correct_proto_payload_service_name (lines)
151- keyActualValue := " is applied to the wrong serviceName"
152- } else = keyActualValue {
153- not has_project_ownership_or_invitee (lines) # does not have ProjectOwnership or projectOwnerInvitee
154- keyActualValue := " is not applied to ProjectOwnershop or projectOwnerInvitee"
155- } else = keyActualValue { # bindingDeltas.action not defined to "REMOVED" and "ADD" for bingingDeltas.role="roles/owner"
156- not has_add_or_remove_owner_or (lines)
157- keyActualValue := " does not bind both the actions 'REMOVE' and 'ADD' to 'roles/owner' role"
158- } else = null
159-
160- process_filter (raw_filter) = lines {
161- normalized := normalize_filter (raw_filter)
162- marked := regex.replace (normalized, " \\ )\\ s+(AND|OR)\\ s+\\ (" , " )\n $1(" )
163- lines := split (marked, " \n " )
164- }
165-
166- normalize_filter (raw_filter) = normalized {
167- step1 := regex.replace (raw_filter, " \\ n" , " " )
168- step2 := regex.replace (step1, " \\ s+" , " " )
169- step3 := regex.replace (step2, " \\ (\\ s+" , " (" )
170- step4 := regex.replace (step3, " \\ s+\\ )" , " )" )
171- step5 := regex.replace (step4, " \\ s+AND\\ s+" , " AND " )
172- step6 := regex.replace (step5, " \\ s+OR\\ s+" , " OR " )
173- normalized := regex.replace (step6, " \\ s*=\\ s*" , " =" )
174- }
175-
176- correct_proto_payload_service_name (lines) {
177- regex.match (" (?i)protoPayload\\ .serviceName\\ s*=\\ s*(\\ (((\\ s*OR\\ s*)?\" .+\" (\\ s*OR\\ s*)?)*)?\" cloudresourcemanager.googleapis.com\" " , concat (" " , lines))
178- } else {
179- regex.match (" (?i)NOT\\ s*protoPayload\\ .serviceName\\ s*!=\\ s*\" cloudresourcemanager.googleapis.com\" " , concat (" " , lines))
180- }
181-
182- has_project_ownership_or_invitee (lines) {
183- regex.match (" (?i)\\ (\\ s*(ProjectOwnership\\ s*OR\\ s*projectOwnerInvitee|projectOwnerInvitee\\ s*OR\\ s*ProjectOwnership)\\ s*\\ )" , concat (" " , lines))
184- }
185-
186- has_add_or_remove_owner_or (lines) {
187- has_or_add_owner (lines)
188- has_or_remove_owner (lines)
161+ at_least_one_log (log_resources){
162+ log_resources[_].value != []
189163}
190164
191- has_or_add_owner (lines) {
192- line := lines[_]
193- startswith (trim (line, " " ), " OR(" )
194- is_add_owner_block (line)
195- }
196165
197- has_or_remove_owner (lines) {
198- line := lines[_]
199- startswith (trim (line, " " ), " OR(" )
200- is_remove_owner_block (line)
166+ service_name_valid (filter) { # checks if serviceName is defined to "cloudresourcemanager.googleapis.com"
167+ regex.match (service_name_pattern, filter)
168+ not regex.match (concat (" " , [" not" , service_name_pattern]), filter)
201169}
202170
203- is_add_owner_block (line) {
204- contains (line, " protoPayload.serviceData.policyDelta.bindingDeltas.action=\" ADD\" " )
205- contains (line, " protoPayload.serviceData.policyDelta.bindingDeltas.role=\" roles/owner\" " )
171+ ownership_valid (filter) { # (ProjectOwnership OR projectOwnerInvitee)
172+ regex.match (ownership_pattern_1, filter)
173+ not regex.match (concat (" " , [" not" , ownership_pattern_1]), filter)
174+ } else { # (projectOwnerInvitee OR ProjectOwnership)
175+ regex.match (ownership_pattern_2, filter)
176+ not regex.match (concat (" " , [" not" , ownership_pattern_2]), filter)
206177}
207178
208- is_remove_owner_block (line) {
209- contains (line, " protoPayload.serviceData.policyDelta.bindingDeltas.action=\" REMOVE\" " )
210- contains (line, " protoPayload.serviceData.policyDelta.bindingDeltas.role=\" roles/owner\" " )
179+ remove_owner_valid (filter) { # action="REMOVE" AND role="roles/owner"
180+ pattern := concat (" " , [" \\ (" , binding_action_remove, " and" , binding_role_owner, " \\ )" ])
181+ regex.match (pattern, filter)
182+ not regex.match (concat (" " , [" not" , pattern]), filter)
183+ } else { # role="roles/owner" AND action="REMOVE"
184+ pattern := concat (" " , [" \\ (" , binding_role_owner, " and" , binding_action_remove, " \\ )" ])
185+ regex.match (pattern, filter)
186+ not regex.match (concat (" " , [" not" , pattern]), filter)
211187}
212188
213- at_least_one_log (log_resources){
214- log_resources[_].value != []
189+ add_owner_valid (filter) { # action="ADD" AND role="roles/owner"
190+ pattern := concat (" " , [" \\ (" , binding_action_add, " and" , binding_role_owner, " \\ )" ])
191+ regex.match (pattern, filter)
192+ not regex.match (concat (" " , [" not" , pattern]), filter)
193+ } else { # role="roles/owner" AND action="ADD"
194+ pattern := concat (" " , [" \\ (" , binding_role_owner, " and" , binding_action_add, " \\ )" ])
195+ regex.match (pattern, filter)
196+ not regex.match (concat (" " , [" not" , pattern]), filter)
215197}
0 commit comments