예제 #1
0
    def test_org_whitelist_rules_vs_policy_no_violations(self):
        """Test ruleset on an org with whitelist with no rule violations.

        Setup:
            * Create a RulesEngine with RULES1 rule set.
            * Create policy.

        Expected result:
            * Find no rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = OrgRulesEngine(rules_local_path)
        rules_engine.rule_book = OrgRuleBook(self.RULES1)

        policy = {
            'bindings': [{
                'role': 'roles/editor',
                'members': [
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = []
        actual_violations.extend(
            rules_engine.find_policy_violations(self.org789, policy))

        self.assertItemsEqual([], actual_violations)
예제 #2
0
    def test_build_rule_book_from_gcs_works(self, mock_load_rules_from_gcs):
        """Test that a RuleBook is built correctly with a mocked gcs file.

        Setup:
            * Create a mocked GCS object from a test yaml file.
            * Get the yaml file content.

        Expected results:
            There are 4 resources that have rules, in the rule book.
        """
        bucket_name = 'bucket-name'
        rules_path = 'input/test_rules_1.yaml'
        full_rules_path = 'gs://{}/{}'.format(bucket_name, rules_path)
        rules_engine = OrgRulesEngine(rules_file_path=full_rules_path)

        # Read in the rules file
        file_content = None
        with open(get_datafile_path(__file__, 'test_rules_1.yaml'),
                  'r') as rules_local_file:
            try:
                file_content = yaml.safe_load(rules_local_file)
            except yaml.YAMLError:
                raise

        mock_load_rules_from_gcs.return_value = file_content

        rules_engine.build_rule_book()
        self.assertEqual(4, len(rules_engine.rule_book.resource_rules_map))
예제 #3
0
def main(_):
    """Run the scanner."""
    logger = LogUtil.setup_logging(__name__)

    file_path = FLAGS.rules
    output_path = FLAGS.output_path

    logger.info(('Initializing the rules engine: '
                 '\n    rules: {}').format(file_path))

    rules_engine = OrgRulesEngine(rules_file_path=file_path)
    rules_engine.build_rule_book()

    snapshot_timestamp = _get_timestamp(logger)
    if not snapshot_timestamp:
        logger.info('No snapshot timestamp found. Exiting.')
        sys.exit()

    org_policies = _get_org_policies(logger, snapshot_timestamp)
    project_policies = _get_project_policies(logger, snapshot_timestamp)

    if not org_policies and not project_policies:
        logger.info('No policies found. Exiting.')
        sys.exit()

    all_violations = _find_violations(
        logger,
        itertools.chain(org_policies.iteritems(),
                        project_policies.iteritems()), rules_engine)

    csv_name = csv_writer.write_csv(resource_name='policy_violations',
                                    data=_write_violations_output(
                                        logger, all_violations),
                                    write_header=True)
    logger.info('CSV filename: {}'.format(csv_name))

    # scanner timestamp for output file and email
    now_utc = datetime.utcnow()
    output_filename = _get_output_filename(now_utc)

    if output_path:
        _upload_csv_to_gcs(logger, output_path, output_filename, csv_name)

    if all_violations:
        _send_email(
            csv_name, now_utc, all_violations, {
                ResourceType.ORGANIZATION: len(org_policies.keys()),
                ResourceType.PROJECT: len(project_policies.keys())
            })

    logger.info('Done!')
예제 #4
0
    def test_empty_policy_with_rules_no_violations(self):
        """Test an empty policy against the RulesEngine with rules.

        Setup:
            * Create a RulesEngine.
            * Created expected violations list.

        Expected results:
            No policy violations found.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = OrgRulesEngine(rules_local_path)
        rules_engine.rule_book = OrgRuleBook(self.RULES1)

        actual_violations = rules_engine.find_policy_violations(
            self.project1, {})

        # expected
        expected_violations = []

        self.assertEqual(expected_violations, actual_violations)
예제 #5
0
    def test_org_proj_rules_vs_policy_has_violations(self):
        """Test rules on org and project with whitelist, blacklist, required.

        Test whitelist, blacklist, and required rules against an org that has
        1 blacklist violation and a project that has 1 whitelist violation and
        1 required violation.

        Setup:
            * Create a RulesEngine with RULES3 rule set.
            * Create policy.

        Expected result:
            * Find 3 rule violations.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = OrgRulesEngine(rules_local_path)
        rules_engine.rule_book = OrgRuleBook(self.RULES3)

        org_policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        project_policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]',
                    'user:[email protected]',
                ]
            }]
        }

        actual_violations = []
        actual_violations.extend(
            rules_engine.find_policy_violations(self.org789, org_policy))
        actual_violations.extend(
            rules_engine.find_policy_violations(self.project1, project_policy))

        # expected
        expected_outstanding_org = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_outstanding_project = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')],
            'roles/viewer':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = [
            RuleViolation(rule_index=1,
                          rule_name='my blacklist rule',
                          resource_id=self.org789.resource_id,
                          resource_type=self.org789.resource_type,
                          violation_type='ADDED',
                          role=org_policy['bindings'][0]['role'],
                          members=expected_outstanding_org['roles/editor']),
            RuleViolation(
                rule_index=0,
                rule_name='my whitelist rule',
                resource_id=self.project1.resource_id,
                resource_type=self.project1.resource_type,
                violation_type='ADDED',
                role=project_policy['bindings'][0]['role'],
                members=expected_outstanding_project['roles/editor']),
            RuleViolation(
                rule_index=2,
                rule_name='my required rule',
                resource_id=self.project1.resource_id,
                resource_type=self.project1.resource_type,
                violation_type='REMOVED',
                role='roles/viewer',
                members=expected_outstanding_project['roles/viewer']),
        ]

        self.assertItemsEqual(expected_violations, actual_violations)
예제 #6
0
    def test_whitelist_blacklist_rules_vs_policy_has_violations(self):
        """Test a ruleset with whitelist and blacklist violating rules.

        Setup:
            * Create a RulesEngine with RULES2 rule set.
            * Create policy.

        Expected result:
            * Find 1 rule violation.
        """
        # actual
        rules_local_path = get_datafile_path(__file__, 'test_rules_1.yaml')
        rules_engine = OrgRulesEngine(rules_local_path)
        rules_engine.rule_book = OrgRuleBook(self.RULES2)

        policy = {
            'bindings': [{
                'role':
                'roles/editor',
                'members': [
                    'user:[email protected]', 'user:[email protected]',
                    'user:[email protected]'
                ]
            }]
        }

        actual_violations = []
        actual_violations.extend(
            rules_engine.find_policy_violations(self.project1, policy))
        actual_violations.extend(
            rules_engine.find_policy_violations(self.project2, policy))

        # expected
        expected_outstanding1 = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }
        expected_outstanding2 = {
            'roles/editor':
            [IamPolicyMember.create_from('user:[email protected]')]
        }

        expected_violations = [
            RuleViolation(rule_index=0,
                          rule_name='my rule',
                          resource_id=self.project1.resource_id,
                          resource_type=self.project1.resource_type,
                          violation_type='ADDED',
                          role=policy['bindings'][0]['role'],
                          members=expected_outstanding1['roles/editor']),
            RuleViolation(rule_index=0,
                          rule_name='my rule',
                          resource_type=self.project2.resource_type,
                          resource_id=self.project2.resource_id,
                          violation_type='ADDED',
                          role=policy['bindings'][0]['role'],
                          members=expected_outstanding1['roles/editor']),
            RuleViolation(rule_index=1,
                          rule_name='my other rule',
                          resource_type=self.project2.resource_type,
                          resource_id=self.project2.resource_id,
                          violation_type='ADDED',
                          role=policy['bindings'][0]['role'],
                          members=expected_outstanding2['roles/editor']),
            RuleViolation(rule_index=2,
                          rule_name='required rule',
                          resource_id=self.project1.resource_id,
                          resource_type=self.project1.resource_type,
                          violation_type='REMOVED',
                          role='roles/viewer',
                          members=[
                              IamPolicyMember.create_from(
                                  'user:[email protected]')
                          ])
        ]

        self.assertItemsEqual(expected_violations, actual_violations)
예제 #7
0
 def test_build_rule_book_no_resource_type_fails(self):
     """Test that a rule without a resource type cannot be created."""
     rules_local_path = get_datafile_path(__file__, 'test_rules_2.yaml')
     rules_engine = OrgRulesEngine(rules_file_path=rules_local_path)
     with self.assertRaises(InvalidRulesSchemaError):
         rules_engine.build_rule_book()
예제 #8
0
 def test_build_rule_book_from_local_json_file_works(self):
     """Test that a RuleBook is built correctly with a json file."""
     rules_local_path = get_datafile_path(__file__, 'test_rules_1.json')
     rules_engine = OrgRulesEngine(rules_file_path=rules_local_path)
     rules_engine.build_rule_book()
     self.assertEqual(4, len(rules_engine.rule_book.resource_rules_map))