def find_violations(self, project, audit_config): """Find Cloud Audit Logging violations in the rule book. Args: project (gcp_type): The project that has this configuation. audit_config (IamAuditConfig): The audit config for this project, merged with ancestor configs. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() # Check for rules on all ancestors, and the wildcard rule. resource_ancestors = (relationship.find_ancestors( project, project.full_name)) resource_ancestors.append( resource_util.create_resource(resource_id='*', resource_type='project')) for curr_resource in resource_ancestors: resource_rules = self.resource_rules_map.get(curr_resource, []) for resource_rule in resource_rules: violations = itertools.chain( violations, resource_rule.find_violations(project, audit_config)) return violations
def find_violations(self, resource, policies): """Find policy binding violations in the rule book. Args: resource (Resource): The GCP resource associated with the policy binding. This is where we start looking for rule violations and we move up the resource hierarchy (if permitted by the resource's "inherit_from_parents" property). policies(list): A list of FirewallRule policies. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() resource_ancestors = (relationship.find_ancestors( resource, policies[0].full_name)) for curr_resource in resource_ancestors: if curr_resource in self.org_policy_rules_map: org_policy_rules = self.org_policy_rules_map.get( curr_resource, []) for rule_id in org_policy_rules: rule = self.rules_map[rule_id] violations = itertools.chain( violations, rule.find_violations(policies)) break # Only the first rules found in the ancestry are applied return violations
def find_violations(self, resource, bq_acl): """Find acl violations in the rule book. Args: resource (gcp_type): The GCP resource associated with the acl. This is where we start looking for rule violations and we move up the resource hierarchy (if permitted by the resource's "inherit_from_parents" property). bq_acl (BigqueryAccessControls): The acl to compare the rules against. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() resource_ancestors = (relationship.find_ancestors( resource, resource.full_name)) for res in resource_ancestors: for rule in self.resource_rules_map.get(res, []): violations = itertools.chain(violations, rule.find_violations(bq_acl)) return violations
def find_violations(self, project, enabled_apis): """Find enabled APIs violations in the rule book. Args: project (gcp_type): The project that these APIs are enabled on. enabled_apis (list): list of enabled APIs. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() # Check for rules on all ancestors, and the wildcard rule. resource_ancestors = (relationship.find_ancestors( project, project.full_name)) resource_ancestors.append( resource_util.create_resource(resource_id='*', resource_type='project')) for curr_resource in resource_ancestors: resource_rules = self.resource_rules_map.get(curr_resource, []) for resource_rule in resource_rules: violations = itertools.chain( violations, resource_rule.find_violations(project, enabled_apis)) return violations
def find_violations(self, resource, log_sinks): """Find Log Sink violations in the rule book. Args: resource (gcp_type): The resource that the log sinks belong to. log_sinks (list): list of LogSinks for resource. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() # Check for rules that apply to this resource directly. resource_rules = self.resource_rules_map['self'].get(resource, []) for rule in resource_rules: violations = itertools.chain( violations, rule.find_violations(resource, log_sinks)) # If resource is a project, check for ancestor rules that apply to # children. if resource.type == 'project': resource_ancestors = (relationship.find_ancestors( resource, resource.full_name)) for curr_resource in resource_ancestors: resource_rules = self.resource_rules_map['children'].get( curr_resource, []) for rule in resource_rules: violations = itertools.chain( violations, rule.find_violations(resource, log_sinks)) return violations
def find_violations(self, parent_resource, liens): """Find lien violations in the rule book. Args: parent_resource (Resource): The GCP resource associated with the liens. This is where we start looking for rule violations and we move up the resource hierarchy (if permitted by the resource's "inherit_from_parents" property). liens (List[Lien]): The liens to look for violations. Yields: RuleViolation: lien rule violations. """ all_restrictions = set() for lien in liens: for restriction in lien.restrictions: all_restrictions.add(restriction) resource_ancestors = relationship.find_ancestors( parent_resource, parent_resource.full_name) applicable_rules = [] for res in resource_ancestors: applicable_rules.extend(self.resource_to_rules.get(res, [])) wildcard_res = resource_util.create_resource( resource_id='*', resource_type=res.type) applicable_rules.extend( self.resource_to_rules.get(wildcard_res, [])) for rule in applicable_rules: for violation in rule.find_violations(parent_resource, all_restrictions): yield violation
def find_violations(self, res): """Find resource locations violations in the rule book. Args: res (Resource): The GCP resource to check locations for. This is where we start looking for rule violations and we move up the resource hierarchy. Yields: RuleViolation: resource locations rule violations. """ resource_ancestors = relationship.find_ancestors(res, res.full_name) rules = [] for ancestor_res in resource_ancestors: rules.extend(self.resource_to_rules.get(ancestor_res, [])) type_resource_wildcard = resource_util.create_resource( resource_id='*', resource_type=res.type) rules.extend(self.resource_to_rules.get(type_resource_wildcard, [])) for rule in rules: for violation in rule.find_violations(res): yield violation
def find_violations(self, resource, force_rebuild=False): """Determine whether supported resources violates rules. Args: resource (Resource): Object containing retention data force_rebuild (bool): If True, rebuilds the rule book. This will reload the rules definition file and add the rules to the book. Returns: generator: A generator of rule violations. """ if self.rule_book is None or force_rebuild: self.build_rule_book() violations = itertools.chain() resource_rules = self.rule_book.get_resource_rules(resource.type) resource_ancestors = (relationship.find_ancestors( resource, resource.full_name)) for related_resources in resource_ancestors: rules = resource_rules.get(related_resources, []) for rule in rules: violations = itertools.chain(violations, rule.find_violations(resource)) return set(violations)
def find_violations(self, resource, policy, policy_bindings): """Find policy binding violations in the rule book. Args: resource (gcp_type): The GCP resource associated with the policy binding. This is where we start looking for rule violations and we move up the resource hierarchy (if permitted by the resource's "inherit_from_parents" property). policy (forseti_data_model_resource): The policy to compare against the rules. See https://cloud.google.com/iam/reference/rest/v1/Policy. policy_bindings (list): A list of IamPolicyBindings. Returns: iterable: A generator of the rule violations. """ violations = itertools.chain() resource_ancestors = (relationship.find_ancestors( resource, policy.full_name)) for curr_resource in resource_ancestors: wildcard_resource = resource_util.create_resource( resource_id='*', resource_type=curr_resource.type) resource_rules = self._get_resource_rules(curr_resource) resource_rules.extend(self._get_resource_rules(wildcard_resource)) # Set to None, because if the direct resource (e.g. project) # doesn't have a specific rule, we still should check the # ancestry to see if the resource's parents have any rules # that apply to the children. inherit_from_parents = None for resource_rule in resource_rules: if not self._rule_applies_to_resource(resource, curr_resource, resource_rule): continue violations = itertools.chain( violations, resource_rule.find_mismatches(resource, policy_bindings)) inherit_from_parents = resource_rule.inherit_from_parents # If the rule does not inherit the parents' rules, stop. # Due to the way rules are structured, we only define the # "inherit" property once per rule. So even though a rule # may apply to multiple resources, it will only have one # value for "inherit_from_parents". if not inherit_from_parents and inherit_from_parents is not None: break return violations
def test_get_resource_ancestors_from_full_name(self): # resource is organization mock_starting_resource = mock.MagicMock() mock_starting_resource.type = 'organization' mock_starting_resource.id = 'org1' resource_ancestors = ( relationship.find_ancestors( mock_starting_resource, 'organization/org1/')) self.assertEquals(1, len(resource_ancestors)) # resource is project mock_starting_resource.type = 'project' mock_starting_resource.id = 'project3' resource_ancestors = ( relationship.find_ancestors( mock_starting_resource, 'organization/org1/folder/folder2/project/project3/')) self.assertEquals(3, len(resource_ancestors)) self.assertEquals(mock_starting_resource, resource_ancestors[0]) self.assertEquals('folder2', resource_ancestors[1].id) self.assertEquals('org1', resource_ancestors[2].id) # resource has multiple folders, and subproject resources mock_starting_resource.type = 'firewall' mock_starting_resource.id = 'firewall5' resource_ancestors = ( relationship.find_ancestors( mock_starting_resource, ('organization/org1/folder/folder2/folder/folder3/' 'project/project4/firewall/firewall5/'))) self.assertEquals(5, len(resource_ancestors)) self.assertEquals(mock_starting_resource, resource_ancestors[0]) self.assertEquals('project4', resource_ancestors[1].id) self.assertEquals('folder3', resource_ancestors[2].id) self.assertEquals('folder2', resource_ancestors[3].id) self.assertEquals('org1', resource_ancestors[4].id)
def find_violations_in_role(role): """Get a generator for violations. Args: role (role): Find violation from the role. Returns: RuleViolation: All violations of the role breaking the rule. """ resource_ancestors = (relationship.find_ancestors( role, role.full_name)) violations = itertools.chain() for related_resources in resource_ancestors: violations = itertools.chain( violations, self.find_violations_by_ancestor(related_resources, role)) return violations