Beispiel #1
0
 def test_create_resource_is_ok(self):
     """Test the ResourceUtil.create_resource() creates the types."""
     expect_org = Organization(12345, 'Org a')
     actual_org = ResourceUtil.create_resource(12345, 'Org a')
     self.assertEqual(expect_org, actual_org)
     expect_proj = Project('abcd', 'Proj a')
     actual_proj = ResourceUtil.create_resource('abcd', 'Proj a')
     self.assertEqual(expect_proj, expect_proj)
Beispiel #2
0
def _build_scan_summary(all_violations, total_resources):
    """Build the scan summary.

    Args:
        all_violations: List of violations.
        total_resources: A dict of the resources and their count.

    Returns:
        Total counts and summaries.
    """
    resource_summaries = {}
    total_violations = 0
    # Build a summary of the violations and counts for the email.
    # resource summary:
    # {
    #     RESOURCE_TYPE: {
    #         'total': TOTAL,
    #         'ids': [...] # resource_ids
    #     },
    #     ...
    # }
    for violation in all_violations:
        resource_type = violation.resource_type
        if resource_type not in resource_summaries:
            resource_summaries[resource_type] = {
                'pluralized_resource_type':
                ResourceUtil.pluralize(resource_type),
                'total': total_resources[resource_type],
                'violations': {}
            }

        # Keep track of # of violations per resource id.
        if (violation.resource_id
                not in resource_summaries[resource_type]['violations']):
            resource_summaries[resource_type]['violations'][
                violation.resource_id] = 0

        # Make sure to count each member violation as a separate one.
        for member in violation.members:
            resource_summaries[resource_type]['violations'][
                violation.resource_id] += 1

            total_violations += 1

    return total_violations, resource_summaries
Beispiel #3
0
    def _add_rule(self, rule_def, rule_index):
        """Add a rule to the rule book.

        The rule supplied to this method is the dictionary parsed from
        the rules definition file.

        For example, this rule...

            # rules yaml:
            rules:
              - name: a rule
                mode: whitelist
                resource:
                  - type: project
                    applies_to: self
                    resource_ids:
                      - my-project-123
                inherit_from_parents: true
                bindings:
                  - role: roles/editor
                    members:
                      - users:[email protected]

        ... gets parsed into:

            {
                'name': 'a rule',
                'mode': 'whitelist',
                'resource': {
                    'type': 'project',
                    'applies_to': self,
                    'resource_ids': ['my-project-id']
                },
                'inherit_from_parents': true,
                'bindings': [
                    {
                        'role': 'roles/editor',
                        'members': ['users:[email protected]']
                    }
                ]
            }

        Args:
            rule_def: A dictionary containing rule definition properties.
            rule_index: The index of the rule from the rule definitions.
                Assigned automatically when the rule book is built.
        """
        with self._lock:
            resources = rule_def.get('resource')

            for resource in resources:
                resource_ids = resource.get('resource_ids')
                resource_type = None
                # TODO: collect these errors and output them in a log.
                # Question: should we ever fail fast? I'm thinking "no"
                # since we still want to try and run as many rules as
                # possible.
                try:
                    resource_type = ResourceType.verify(resource.get('type'))
                except InvalidResourceTypeError:
                    raise InvalidRulesSchemaError(
                        'Missing resource type in rule {}'.format(rule_index))

                if not resource_ids or len(resource_ids) < 1:
                    raise InvalidRulesSchemaError(
                        'Missing resource ids in rule {}'.format(rule_index))

                # For each resource id associated with the rule, create a
                # mapping of resource => rules.
                for resource_id in resource_ids:
                    gcp_resource = ResourceUtil.create_resource(
                        resource_id=resource_id, resource_type=resource_type)
                    # Verify that this resource actually exists in GCP.
                    if (self.verify_resource_exists
                            and not gcp_resource.exists()):

                        self.logger.error(
                            'Resource does not exist: {}'.format(gcp_resource))
                        continue

                    rule = Rule(rule_name=rule_def.get('name'),
                                rule_index=rule_index,
                                bindings=rule_def.get('bindings', []),
                                mode=rule_def.get('mode'))

                    # See if we have a mapping of the resource and rule
                    resource_rules = self.resource_rules_map.get(gcp_resource)

                    # If no mapping exists, create it.
                    if not resource_rules:
                        resource_rules = ResourceRules(
                            resource=gcp_resource,
                            applies_to=resource.get('applies_to'),
                            inherit_from_parents=rule_def.get(
                                'inherit_from_parents', False))
                        self.resource_rules_map[gcp_resource] = resource_rules

                    # If the rule isn't in the mapping, add it.
                    if rule not in resource_rules.rules:
                        resource_rules.rules.add(rule)
Beispiel #4
0
    def get_project_policies(self, timestamp):
        """Get the project policies.

        Args:
            timestamp: The timestamp of the snapshot.

        Returns:
            A dict containing the projects (gcp_type.project.Project)
            and their iam policies (dict).
        """
        project_policies = {}
        prev_proj_id = None
        prev_proj = None
        try:
            cursor = self.conn.cursor()
            cursor.execute(
                select_data.PROJECT_IAM_POLICIES.format(timestamp, timestamp))
            rows = cursor.fetchall()
            for row in rows:
                proj_id = row[1]
                if prev_proj_id != proj_id:
                    project = Project(project_id=row[1],
                                      project_name=row[2],
                                      project_number=row[0],
                                      lifecycle_state=row[3])
                    project.parent = ResourceUtil.create_resource(
                        resource_id=row[5], resource_type=row[4])
                else:
                    project = prev_proj
                policy = project_policies.get(project)
                if not policy:
                    policy = {'bindings': []}

                role = row[6]
                member_type = row[7]
                member_name = row[8]
                member_domain = row[9]
                member = ''
                if member_name:
                    member = '{}:{}@{}'.format(member_type, member_name,
                                               member_domain)
                else:
                    member = '{}:{}'.format(member_type, member_domain)

                member = member.strip()
                added_to_role = False

                for binding in policy.get('bindings'):
                    if binding.get('role') == role:
                        binding.get('members').append(member)
                        added_to_role = True

                if not added_to_role:
                    policy['bindings'].append({
                        'role': role,
                        'members': [member]
                    })

                project_policies[project] = policy
                prev_proj = project
        except (DataError, IntegrityError, InternalError, NotSupportedError,
                OperationalError, ProgrammingError) as e:
            LOGGER.error(MySQLError('projects', e))
        return project_policies
Beispiel #5
0
 def test_plural_is_correct(self):
     """Test that the resource type is pluralized correctly."""
     self.assertEqual('Organizations',
                      ResourceUtil.pluralize(ResourceType.ORGANIZATION))
     self.assertEqual('Projects',
                      ResourceUtil.pluralize(ResourceType.PROJECT))