Ejemplo n.º 1
0
 def test_of_email_body_problematic_resources_with_reason(
         self, mock_get_account_alias):
     mock_get_account_alias.return_value = "test-account"
     unwanted_resources = [
         Resource(
             42,
             "ec2 instance",
             "12345",
             "date1",
             "us",
             reason=
             'Please follow the principal of least privilege and do not use Action : *'
         ),
         Resource(42, "ec2 volume", "3312345", "date2", "us")
     ]
     problematic_resources = []
     dry_run = False
     test_status_mail_plugin = StatusMailPlugin(
         unwanted_resources,
         problematic_resources,
         dry_run,
         region=self.test_region,
         sender=self.test_sender,
         recipients=self.test_recipients)
     body = test_status_mail_plugin.body
     expected_body = (EXPECTED_PART_HEADER + EXPECTED_PART_NO_DRY_RUN +
                      EXPECTED_PART_UNWANTED_FILLED_WITH_REASON +
                      EXPECTED_PART_FOOTER)
     self.maxDiff = None
     self.assertEqual(body, expected_body)
Ejemplo n.º 2
0
 def fetch_unwanted_resources(self):
     return [
         Resource(Mock(), "ec2 instance", "123456789",
                  datetime.datetime.now(), "us"),
         Resource(Mock(), "ec2 volume", "33123456789",
                  datetime.datetime.now(), "us")
     ]
Ejemplo n.º 3
0
    def _fetch_unwanted_resources(self, region_name):
        client = boto3.client('acm', region_name=region_name)
        response = client.list_certificates(CertificateStatuses=['ISSUED'])
        certificate_arns = [
            summary['CertificateArn']
            for summary in response['CertificateSummaryList']
        ]

        limit = datetime.datetime.now() + datetime.timedelta(
            days=MIN_VALID_DAYS)

        for certificate_arn in certificate_arns:
            response = client.describe_certificate(
                CertificateArn=certificate_arn)
            certificate = response['Certificate']

            # Remove time zone information so we can compare with normal datetimes.
            not_after = datetime.datetime.replace(certificate['NotAfter'],
                                                  tzinfo=None)

            if not_after > limit:
                continue

            resource_wrapper = Resource(
                resource="Certificate for " + certificate['DomainName'],
                resource_type=self.resource_type,
                resource_id=certificate_arn,
                creation_date=certificate.get('CreatedAt',
                                              certificate.get('ImportedAt')),
                region="global",
                reason="will expired soon")
            yield resource_wrapper
Ejemplo n.º 4
0
    def test_fetch_unwanted_resources_returns_true_if_forbidden_action(self):
        iam_policy = 'iam.IamPolicy'
        policyVersionMock = MagicMock(
            document={
                'Statement': [{
                    'Action': ['s3:test3', '*:*'],
                    'Resource': 'aws:s2222'
                }]
            })
        self.iamResourceMock.PolicyVersion.return_value = policyVersionMock
        policy = {
            'IsTruncated':
            False,
            'Policies': [{
                'Arn': 'arn:aws:iam:123456789',
                'DefaultVersionId': 'v1',
                'CreateDate': '2012-06-12'
            }]
        }
        expected_unwanted_user = Resource(
            resource=policy['Policies'][0],
            resource_type=iam_policy,
            resource_id=policy['Policies'][0]['Arn'],
            creation_date=policy['Policies'][0]['CreateDate'],
            region='global',
            reason=self.reason)

        self.iamClientMock.list_policies.return_value = policy
        unwanted_resource = self.policy_handler.fetch_unwanted_resources()
        self.assertEqual(list(unwanted_resource)[0], expected_unwanted_user)
Ejemplo n.º 5
0
    def fetch_unwanted_resources(self):
        client = self.get_client()
        response = client.list_buckets()
        buckets = [(bucket['Name'], bucket['CreationDate'])
                   for bucket in response['Buckets']]
        region_names = [region.name for region in self.regions]

        for bucket_name, creation_date in buckets:
            try:
                response = client.get_bucket_location(Bucket=bucket_name)
            except Exception:
                # This happens when a bucket was deleted shortly after we
                # found it. E.g. during concurrent integration tests.
                self.logger.exception("Failed to get location for bucket %r:",
                                      bucket_name)
                continue
            region_name = self.map_location(response['LocationConstraint'])
            if region_name not in region_names:
                self.logger.debug("Bucket %s in region %s is OK.", bucket_name,
                                  region_name)
                continue

            self.logger.info("Reporting bucket %s in region %s as unwanted.",
                             bucket_name, region_name)
            resource_wrapper = Resource(resource="Bucket " + bucket_name,
                                        resource_type=self.resource_type,
                                        resource_id=bucket_name,
                                        creation_date=creation_date,
                                        region=region_name)
            yield resource_wrapper
Ejemplo n.º 6
0
 def test_skip_deletion_in_dry_run(self):
     resource = Resource(self.stack_mock, self.resource_type,
                         self.stack_mock.stack_id,
                         self.stack_mock.creation_time,
                         self.negative_fake_region.name)
     self.cloudformation_handler.dry_run = True
     self.cloudformation_handler.delete(resource)
     self.assertFalse(self.cloudformation_mock.connect_to_region.
                      return_value.delete_stack.called)
Ejemplo n.º 7
0
 def setUp(self):
     self.test_recipients = ["*****@*****.**", "*****@*****.**"]
     self.unwanted_resources = [
         Resource(42, "ec2 instance", "12345", "date1", "us"),
         Resource(42, "ec2 volume", "3312345", "date2", "us")]
     self.problematic_resources = [
         Resource(23, "ec2 instance", "67890", "date1", "us"),
         Resource(23, "ec2 volume", "1112345", "date2", "us")]
     self.dry_run = True
     self.reason = 'Do not do it'
     self.test_region = "eu-west-1"
     self.test_sender = "*****@*****.**"
     self.test_status_mail_plugin = StatusMailPlugin(self.unwanted_resources,
                                                     self.problematic_resources,
                                                     self.dry_run,
                                                     region=self.test_region,
                                                     sender=self.test_sender,
                                                     recipients=self.test_recipients)
Ejemplo n.º 8
0
    def test_skip_deletion_if_already_deleted(self):
        self.rds_instance.dry_run = False
        self.instance_mock["DBInstanceStatus"] = rds2.DELETION_STATUS

        resource = Resource(self.instance_mock, self.resource_type,
                            self.instance_mock["DBInstanceIdentifier"],
                            self.instance_mock["InstanceCreateTime"],
                            self.negative_fake_region.name)

        self.assertRaises(Warning, self.rds_instance.delete, resource)
Ejemplo n.º 9
0
    def test_skip_deletion_in_dry_run(self):
        self.rds_instance.dry_run = True
        resource = Resource(self.instance_mock, self.resource_type,
                            self.instance_mock["DBInstanceIdentifier"],
                            self.instance_mock["InstanceCreateTime"],
                            self.negative_fake_region.name)

        deleted_resource = self.rds_instance.delete(resource)

        self.assertEqual(None, deleted_resource)
Ejemplo n.º 10
0
    def test_skip_deletion_if_autogenerated(self):
        self.rds_snapshot.dry_run = False
        self.snapshot_mock["SnapshotType"] = rds2.AUTOMATED_STATUS

        resource = Resource(self.snapshot_mock, self.resource_type,
                            self.snapshot_mock["DBSnapshotIdentifier"],
                            self.snapshot_mock["SnapshotCreateTime"],
                            self.negative_fake_region.name)

        self.assertRaises(Warning, self.rds_snapshot.delete, resource)
Ejemplo n.º 11
0
    def test_skip_deletion_in_dry_run(self):
        self.rds_snapshot.dry_run = True
        resource = Resource(self.snapshot_mock, self.resource_type,
                            self.snapshot_mock["DBSnapshotIdentifier"],
                            self.snapshot_mock["SnapshotCreateTime"],
                            self.negative_fake_region.name)

        deleted_resource = self.rds_snapshot.delete(resource)

        self.assertEqual(None, deleted_resource)
Ejemplo n.º 12
0
 def test_does_delete_if_not_dry_run(self):
     resource = Resource(self.stack_mock, self.resource_type,
                         self.stack_mock.stack_id,
                         self.stack_mock.creation_time,
                         self.negative_fake_region.name)
     self.cloudformation_handler.dry_run = False
     self.cloudformation_handler.delete(resource)
     self.logger_mock.getLogger.return_value.info.assert_called_with(
         DELETION_STATEMENT % self.stack_mock.stack_name)
     self.assertTrue(self.cloudformation_mock.connect_to_region.
                     return_value.delete_stack.called)
Ejemplo n.º 13
0
 def test_skip_deletion_if_already_deleted(self):
     self.stack_mock.stack_status = "DELETE_COMPLETE"
     resource = Resource(self.stack_mock, self.resource_type,
                         self.stack_mock.stack_id,
                         self.stack_mock.creation_time,
                         self.negative_fake_region.name)
     self.cloudformation_handler.dry_run = False
     self.assertRaises(Warning, self.cloudformation_handler.delete,
                       resource)
     self.assertFalse(self.cloudformation_mock.connect_to_region.
                      return_value.delete_stack.called)
Ejemplo n.º 14
0
    def test_delete(self):
        resource = Resource(self.instance_mock, self.resource_type,
                            self.instance_mock.id,
                            self.instance_mock.launch_time,
                            self.negative_fake_region.name)
        connection = self.ec2_mock.connect_to_region.return_value

        e = boto.exception.EC2ResponseError(412, 'boom')
        e.message = "test"
        connection.terminate_instances.side_effect = e
        self.assertRaises(Warning, self.ec2_handler.delete, resource)
Ejemplo n.º 15
0
    def test_handle_service(self):
        handler = Mock()
        handler.fetch_unwanted_resources.return_value = [
            Resource("foo", "test_type", "test_id", datetime.datetime.now(),
                     "test_region")
        ]
        handler.to_string.return_value = "test handler"
        self.monocyte.handle_service(handler)

        self.logger_mock.getLogger.return_value.warning.assert_called_with(
            REGION_NOT_ALLOWED)
Ejemplo n.º 16
0
    def fetch_unwanted_resources(self):
        for user in self.get_users():
            if self.is_user_in_whitelist(user) or self.is_user_in_ignored_resources(user):
                self.logger.info('IGNORE user with {0}'.format(user['Arn']))
                continue

            unwanted_resource = Resource(resource=user,
                                         resource_type=self.resource_type,
                                         resource_id=user['Arn'],
                                         creation_date=user['CreateDate'],
                                         region='global', reason=self.email_string())
            yield unwanted_resource
Ejemplo n.º 17
0
 def fetch_unwanted_resources(self):
     for policy in self.get_policies():
         if self.is_arn_in_whitelist(policy):
             continue
         policy_document = self.get_policy_document(policy['Arn'], policy['DefaultVersionId'])
         actions = self.gather_actions(policy_document)
         if self.check_policy_action_for_forbidden_string(actions):
             unwanted_resource = Resource(resource=policy,
                                          resource_type=self.resource_type,
                                          resource_id=policy['Arn'],
                                          creation_date=policy['CreateDate'],
                                          region='global', reason=self.email_string())
             yield unwanted_resource
Ejemplo n.º 18
0
 def fetch_unwanted_resources(self):
     for region_name in self.region_names:
         connection = rds2.connect_to_region(region_name)
         resources = connection.describe_db_snapshots() or []
         for resource in resources["DescribeDBSnapshotsResponse"]["DescribeDBSnapshotsResult"]["DBSnapshots"]:
             resource_wrapper = Resource(resource=resource,
                                         resource_type=self.resource_type,
                                         resource_id=resource["DBSnapshotIdentifier"],
                                         creation_date=resource["SnapshotCreateTime"],
                                         region=region_name)
             if resource['DBSnapshotIdentifier'] in self.ignored_resources:
                 self.logger.info('IGNORE ' + self.to_string(resource_wrapper))
                 continue
             yield resource_wrapper
Ejemplo n.º 19
0
    def test_fetch_unwanted_resources_returns_resource_wrapper_if_users_are_not_emtpy(
            self):
        iam_user = '******'
        expected_unwanted_user = Resource(
            resource=self.user,
            resource_type=iam_user,
            resource_id=self.user['Arn'],
            creation_date=self.user['CreateDate'],
            region='global',
            reason="Do not use user with static credentials.")

        unwanted_users = self.user_handler.fetch_unwanted_resources()

        self.assertEqual(list(unwanted_users)[0], expected_unwanted_user)
        self.assertEqual(len(list(unwanted_users)), 0)
Ejemplo n.º 20
0
 def fetch_unwanted_resources(self):
     for region_name in self.region_names:
         connection = ec2.connect_to_region(region_name)
         resources = connection.get_all_volumes() or []
         for resource in resources:
             resource_wrapper = Resource(resource=resource,
                                         resource_type=self.resource_type,
                                         resource_id=resource.id,
                                         creation_date=resource.create_time,
                                         region=region_name)
             if resource.id in self.ignored_resources:
                 self.logger.info('IGNORE ' +
                                  self.to_string(resource_wrapper))
                 continue
             yield resource_wrapper
Ejemplo n.º 21
0
 def fetch_unwanted_resources(self):
     for role in self.get_all_iam_roles_in_account():
         if self.is_arn_in_whitelist(role):
             continue
         policies = self.get_all_inline_policies_for_role(role['RoleName'])
         for policy in policies:
             actions = self.gather_actions(policy.policy_document)
             if self.check_policy_action_for_forbidden_string(
                     actions):
                 unwanted_resource = Resource(resource=role,
                                              resource_type=self.resource_type,
                                              resource_id=role['Arn'],
                                              creation_date=role['CreateDate'],
                                              region='global', reason=self.email_string())
                 yield unwanted_resource
Ejemplo n.º 22
0
    def test_fetch_unwanted_resources_return_true_if_action_and_resource_string_found(
            self):
        inline_policy = 'iam.InlinePolicy'
        role_mock = MagicMock()
        sample_role = {
            'Arn': 'arn:aws:iam::123456789101:role/foo-bar-file',
            'AssumeRolePolicyDocument': {
                'Statement': [{
                    'Action': 'sts:AssumeRole',
                    'Effect': 'Allow',
                    'Principal': {
                        'AWS': 'arn:aws:iam::9876543210:root'
                    },
                    'Sid': ''
                }],
                'Version':
                '2012-10-17'
            },
            'CreateDate': '01.01.1989',
            'Path': '/',
            'RoleId': 'FOOAJ4DHXC5V55TMCIBAR',
            'RoleName': 'foo-bar-file'
        }
        list_role_mock = {'Roles': [sample_role]}
        self.iamClientMock.list_roles.return_value = list_role_mock

        policy_mock = MagicMock(
            policy_document={
                'Statement': [{
                    'Action': ['elasticloadbalancing:test3', '*:*'],
                    'Resource': ['arn:aws:s3:::test3']
                }]
            })
        role_mock.policies.all.return_value = [policy_mock]

        self.iamResourceMock.Role.return_value = role_mock
        expected_unwanted_role = Resource(
            resource=sample_role,
            resource_type=inline_policy,
            resource_id=sample_role['Arn'],
            creation_date=sample_role['CreateDate'],
            region='global',
            reason=self.reason)

        unwanted_resource = self.policy_handler.fetch_unwanted_resources()
        unwanted_resource_list = list(unwanted_resource)
        self.assertEqual(len(list(unwanted_resource_list)), 1)
        self.assertEqual(expected_unwanted_role, unwanted_resource_list[0])
Ejemplo n.º 23
0
    def test_does_delete_if_not_dry_run(self):
        self.rds_snapshot.dry_run = False
        resource = Resource(self.snapshot_mock, self.resource_type,
                            self.snapshot_mock["DBSnapshotIdentifier"],
                            self.snapshot_mock["SnapshotCreateTime"],
                            self.negative_fake_region.name)

        self.rds2_mock.connect_to_region.return_value.delete_db_snapshot.return_value = \
            self._given_delete_db_snapshot_response()

        self.rds_snapshot.delete(resource)
        self.logger_mock.getLogger.return_value.info.assert_called_with(
            rds2.DELETION_STATEMENT %
            self.snapshot_mock["DBSnapshotIdentifier"])
        self.assertEqual(self.snapshot_mock["DBSnapshotIdentifier"],
                         resource.wrapped["DBSnapshotIdentifier"])
Ejemplo n.º 24
0
    def fetch_unwanted_resources(self):
        for region_name in self.region_names:
            connection = dynamodb2.connect_to_region(region_name)
            names = connection.list_tables(limit=100) or {}
            for name in names.get("TableNames"):
                resource = connection.describe_table(name)
                resource_wrapper = Resource(
                    resource=resource["Table"],
                    resource_type=self.resource_type,
                    resource_id=resource["Table"]["TableName"],
                    creation_date=resource["Table"]["CreationDateTime"],
                    region=region_name)
                if name in self.ignored_resources:
                    self.logger.info('IGNORE ' +
                                     self.to_string(resource_wrapper))
                    continue

                yield resource_wrapper
Ejemplo n.º 25
0
    def fetch_unwanted_resources(self):
        for region_name in self.region_names:
            connection = cloudformation.connect_to_region(region_name)
            unwanted_states = set(connection.valid_states)
            unwanted_states.remove("DELETE_COMPLETE")
            resources = connection.list_stacks(
                stack_status_filters=list(unwanted_states)) or []
            for resource in resources:
                resource_wrapper = Resource(
                    resource=resource,
                    resource_type=self.resource_type,
                    resource_id=resource.stack_id,
                    creation_date=resource.creation_time,
                    region=region_name)
                if resource.stack_name in self.ignored_resources:
                    self.logger.info('IGNORE ' +
                                     self.to_string(resource_wrapper))
                    continue

                yield resource_wrapper