Exemple #1
0
def generate_aws_account(arn=None, aws_account_id=None, user=None):
    """
    Generate an AwsAccount for testing.

    Any optional arguments not provided will be randomly generated.

    Args:
        arn (str): Optional ARN.
        aws_account_id (12-digit string): Optional AWS account ID.
        user (User): Optional Django auth User to be this account's owner.

    Returns:
        AwsAccount: The created AwsAccount.

    """
    if arn is None:
        if aws_account_id is None:
            arn = helper.generate_dummy_arn(generate_account_id=True)
        else:
            arn = helper.generate_dummy_arn(account_id=aws_account_id)

    if user is None:
        user = helper.generate_test_user()

    return AwsAccount.objects.create(
        account_arn=arn,
        aws_account_id=aws.AwsArn(arn).account_id,
        user=user,
    )
Exemple #2
0
    def test_success(self, mock_primary_id, mock_tasks_aws, mock_create):
        """Assert the task happy path upon normal operation."""
        # User that would ultimately own the created objects.
        user = User.objects.create()

        # Dummy values for the various interactions.
        session_account_id = util_helper.generate_dummy_aws_account_id()
        auth_id = _faker.pyint()
        application_id = _faker.pyint()
        source_id = _faker.pyint()

        customer_secret_access_key = util_helper.generate_dummy_arn(
            account_id=session_account_id)
        primary_account_id = util_helper.generate_dummy_aws_account_id()
        mock_primary_id.return_value = primary_account_id
        mock_tasks_aws.get_session_account_id.return_value = session_account_id
        mock_tasks_aws.AwsArn.return_value.account_id = session_account_id

        # Fake out the policy verification.
        policy_name = _faker.slug()
        policy_arn = util_helper.generate_dummy_arn(
            account_id=session_account_id)
        mock_ensure_policy = mock_tasks_aws.ensure_cloudigrade_policy
        mock_ensure_policy.return_value = (policy_name, policy_arn)

        # Fake out the role verification.
        role_name = _faker.slug()
        role_arn = util_helper.generate_dummy_arn(
            account_id=session_account_id)
        mock_ensure_role = mock_tasks_aws.ensure_cloudigrade_role
        mock_ensure_role.return_value = (role_name, role_arn)

        tasks.configure_customer_aws_and_create_cloud_account(
            user.username,
            customer_secret_access_key,
            auth_id,
            application_id,
            source_id,
        )

        cloud_account_name = api_util.get_standard_cloud_account_name(
            "aws", session_account_id)
        mock_create.assert_called_with(
            user,
            role_arn,
            cloud_account_name,
            auth_id,
            application_id,
            source_id,
        )
Exemple #3
0
    def test_remove_snapshot_ownership_unexpected_error(
            self, mock_aws, mock_boto3):
        """Assert remove snapshot ownership fails due to unexpected error."""
        mock_arn = util_helper.generate_dummy_arn()
        mock_customer_snapshot_id = util_helper.generate_dummy_snapshot_id()
        mock_snapshot_copy_id = util_helper.generate_dummy_snapshot_id()
        zone = settings.HOUNDIGRADE_AWS_AVAILABILITY_ZONE
        region = zone[:-1]

        client_error = ClientError(
            error_response={"Error": {
                "Code": "InvalidSnapshot.Unknown"
            }},
            operation_name=Mock(),
        )

        resource = mock_boto3.resource.return_value
        resource.Snapshot.side_effect = client_error

        with self.assertRaises(RuntimeError):
            tasks.remove_snapshot_ownership(
                mock_arn,
                mock_customer_snapshot_id,
                region,
                mock_snapshot_copy_id,
            )

        mock_aws.remove_snapshot_ownership.assert_not_called()
Exemple #4
0
    def test_create_fails_when_arn_access_denied(self):
        """Test that an account is not saved if ARN access is denied."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        validated_data = {
            'account_arn': arn,
        }

        mock_request = Mock()
        mock_request.user = util_helper.generate_test_user()
        context = {'request': mock_request}

        client_error = ClientError(
            error_response={'Error': {
                'Code': 'AccessDenied'
            }},
            operation_name=Mock(),
        )

        with patch.object(aws.sts, 'boto3') as mock_boto3:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.side_effect = client_error
            serializer = AwsAccountSerializer(context=context)

            with self.assertRaises(ValidationError) as cm:
                serializer.create(validated_data)
            raised_exception = cm.exception
            self.assertIn('account_arn', raised_exception.detail)
            self.assertIn(arn, raised_exception.detail['account_arn'][0])
Exemple #5
0
    def test_remove_snapshot_ownership_no_copy_snapshot(
            self, mock_aws, mock_boto3):
        """Assert remove snapshot ownership task succeeds with missing copy."""
        mock_arn = util_helper.generate_dummy_arn()
        mock_customer_snapshot_id = util_helper.generate_dummy_snapshot_id()
        mock_customer_snapshot = util_helper.generate_mock_snapshot(
            mock_customer_snapshot_id)
        mock_snapshot_copy_id = util_helper.generate_dummy_snapshot_id()
        mock_snapshot_copy = util_helper.generate_mock_snapshot(
            mock_snapshot_copy_id)
        zone = settings.HOUNDIGRADE_AWS_AVAILABILITY_ZONE
        region = zone[:-1]

        client_error = ClientError(
            error_response={"Error": {
                "Code": "InvalidSnapshot.NotFound"
            }},
            operation_name=Mock(),
        )

        resource = mock_boto3.resource.return_value
        resource.Snapshot.return_value = mock_snapshot_copy
        resource.Snapshot.side_effect = client_error

        mock_aws.check_snapshot_state.return_value = None
        mock_aws.get_snapshot.return_value = mock_customer_snapshot

        mock_aws.get_region_from_availability_zone.return_value = region

        tasks.remove_snapshot_ownership(mock_arn, mock_customer_snapshot_id,
                                        region, mock_snapshot_copy_id)

        mock_aws.remove_snapshot_ownership.assert_called_with(
            mock_customer_snapshot)
Exemple #6
0
    def test_copy_ami_to_customer_account_private_no_copy_dot_error(
            self, mock_aws):
        """Assert that the task marks private (no copy) image as in error."""
        arn = util_helper.generate_dummy_arn()
        reference_ami_id = util_helper.generate_dummy_image_id()
        source_region = util_helper.get_random_region()
        image = api_helper.generate_image(ec2_ami_id=reference_ami_id,
                                          status=MachineImage.INSPECTING)
        mock_reference_ami = Mock()
        mock_reference_ami.public = False
        mock_aws.get_ami.return_value = mock_reference_ami

        mock_aws.copy_ami.side_effect = ClientError(
            error_response={
                "Error": {
                    "Code":
                    "InvalidRequest",
                    "Message":
                    "You do not have permission to access the "
                    "storage of this ami.",
                }
            },
            operation_name=Mock(),
        )

        tasks.copy_ami_to_customer_account(arn, reference_ami_id,
                                           source_region)

        mock_aws.get_session.assert_called_with(arn)
        mock_aws.get_ami.assert_called_with(mock_aws.get_session.return_value,
                                            reference_ami_id, source_region)
        image.refresh_from_db()

        self.assertEqual(image.status, MachineImage.ERROR)
Exemple #7
0
    def test_copy_ami_to_customer_account_marketplace_with_dot_error(
            self, mock_aws):
        """Assert that the task marks marketplace image as inspected."""
        arn = util_helper.generate_dummy_arn()
        reference_ami_id = util_helper.generate_dummy_image_id()
        source_region = util_helper.get_random_region()
        image = api_helper.generate_image(ec2_ami_id=reference_ami_id,
                                          status=MachineImage.INSPECTING)

        mock_aws.copy_ami.side_effect = ClientError(
            error_response={
                "Error": {
                    "Code":
                    "InvalidRequest",
                    "Message":
                    "Images with EC2 BillingProduct codes cannot "
                    "be copied to another AWS account.",
                }
            },
            operation_name=Mock(),
        )

        tasks.copy_ami_to_customer_account(arn, reference_ami_id,
                                           source_region)

        mock_aws.get_session.assert_called_with(arn)
        mock_aws.get_ami.assert_called_with(mock_aws.get_session.return_value,
                                            reference_ami_id, source_region)
        image.refresh_from_db()
        aws_image = image.content_object
        aws_image.refresh_from_db()

        self.assertEqual(image.status, MachineImage.INSPECTED)
        self.assertTrue(aws_image.aws_marketplace_image)
Exemple #8
0
    def test_create_fails_when_account_not_verified(self):
        """Test that an account is not saved if verification fails."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        role = util_helper.generate_dummy_role()
        validated_data = {
            'account_arn': arn,
        }

        mock_request = Mock()
        mock_request.user = util_helper.generate_test_user()
        context = {'request': mock_request}

        failed_actions = ['foo', 'bar']

        with patch.object(aws, 'verify_account_access') as mock_verify, \
                patch.object(aws.sts, 'boto3') as mock_boto3:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = role
            mock_verify.return_value = False, failed_actions
            serializer = AwsAccountSerializer(context=context)

            with self.assertRaises(serializers.ValidationError) as cm:
                serializer.create(validated_data)

            exception = cm.exception
            self.assertIn('account_arn', exception.detail)
            for index in range(len(failed_actions)):
                self.assertIn(failed_actions[index],
                              exception.detail['account_arn'][index + 1])
Exemple #9
0
    def test_create_new_machine_images_with_windows_image(self):
        """Test that new windows machine images are marked appropriately."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = AwsAccount(
            account_arn=arn,
            aws_account_id=aws_account_id,
            user=util_helper.generate_test_user(),
        )
        account.save()

        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running
                )
            ]
        }
        running_instances[region][0]['Platform'] = 'Windows'
        ami_id = running_instances[region][0]['ImageId']

        result = util.create_new_machine_images(account, running_instances)

        amis = AwsMachineImage.objects.filter(account=account).all()

        self.assertEqual(result, [ami_id])
        for ami in amis:
            self.assertEqual(ami.ec2_ami_id, ami_id)
            self.assertEqual(ImageTag.objects.filter(
                description='windows').first(),
                ami.tags.filter(description='windows').first())
Exemple #10
0
    def test_create_new_machine_images_with_windows_image(self):
        """Test that new windows machine images are marked appropriately."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        api_helper.generate_cloud_account(arn=arn,
                                          aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        instances_data[region][0]["Platform"] = "Windows"
        ami_id = instances_data[region][0]["ImageId"]

        mock_session = Mock()
        described_amis = util_helper.generate_dummy_describe_image(
            image_id=ami_id, owner_id=aws_account_id)

        with patch.object(util.aws, "describe_images") as mock_describe_images:
            mock_describe_images.return_value = [described_amis]
            result = util.create_new_machine_images(mock_session,
                                                    instances_data)
            mock_describe_images.assert_called_with(mock_session, {ami_id},
                                                    region)

        self.assertEqual(result, [ami_id])

        images = list(AwsMachineImage.objects.all())
        self.assertEqual(len(images), 1)
        self.assertEqual(images[0].ec2_ami_id, ami_id)
        self.assertEqual(images[0].platform, AwsMachineImage.WINDOWS)
    def test_create_aws_clount_fails_with_different_user_same_account_id(
            self, mock_enable, mock_notify_sources):
        """Test create_aws_cloud_account failure message for different user."""
        # The first call just creates the existing objects.
        util.create_aws_cloud_account(self.user, self.arn, self.name,
                                      self.auth_id, self.app_id,
                                      self.source_id)

        other_arn = util_helper.generate_dummy_arn(
            account_id=self.aws_account_id, resource=_faker.word())
        other_auth_id = _faker.pyint()
        other_app_id = _faker.pyint()
        other_source_id = _faker.pyint()
        other_user = util_helper.generate_test_user()

        with self.assertRaises(ValidationError) as raise_context:
            util.create_aws_cloud_account(
                other_user,
                other_arn,
                self.name,
                other_auth_id,
                other_app_id,
                other_source_id,
            )
        exception_detail = raise_context.exception.detail
        self.assertIn("Could not set up cloud metering.",
                      exception_detail["account_arn"])
        self.assertNotIn("CG1002", exception_detail["account_arn"])
Exemple #12
0
    def setUp(self):
        """Set up shared values for kafka creation tests."""
        self.account_number = str(_faker.pyint())
        self.username = _faker.user_name()
        self.authentication_id = _faker.pyint()
        self.application_id = _faker.pyint()
        self.source_id = _faker.pyint()
        self.cloudigrade_sources_app_id = _faker.pyint()
        (
            self.message,
            self.headers,
        ) = util_helper.generate_applicationauthentication_create_message_value(
            account_number=self.account_number,
            application_id=self.application_id,
            authentication_id=self.authentication_id,
        )

        self.arn = util_helper.generate_dummy_arn()

        self.auth_return_value = {
            "username": self.arn,
            "resource_type": settings.SOURCES_RESOURCE_TYPE,
            "resource_id": self.application_id,
            "id": self.authentication_id,
            "authtype": settings.SOURCES_CLOUDMETER_ARN_AUTHTYPE,
        }
Exemple #13
0
    def test_create_from_sources_kafka_message_success(
        self,
        mock_task,
        mock_get_app,
        mock_get_app_type_id,
        mock_get_auth,
    ):
        """Assert create_from_sources_kafka_message happy path success."""
        mock_get_app.return_value = {
            "application_type_id": self.cloudigrade_sources_app_id,
            "source_id": self.source_id,
        }
        mock_get_app_type_id.return_value = self.cloudigrade_sources_app_id

        arn = util_helper.generate_dummy_arn()

        self.auth_return_value["username"] = arn
        mock_get_auth.return_value = self.auth_return_value
        tasks.create_from_sources_kafka_message(self.message, self.headers)

        user = User.objects.get(username=self.account_number)
        mock_task.delay.assert_called_with(
            user.username,
            arn,
            self.authentication_id,
            self.application_id,
            self.source_id,
        )
Exemple #14
0
    def test_update_from_sources_kafka_message_updates_arn_but_disables_cloud_account(
            self, mock_get_auth, mock_notify_sources, mock_get_app):
        """
        Assert update_from_source_kafka_message updates the arn and disables clount.

        This can happen if we get a well-formed ARN, but the AWS-side verification fails
        due to something like badly configured IAM Role or Policy. In this case, we do
        want to save the updated ARN, but we need to disable the Cloud Account until it
        can verify its permissions (at a later date).
        """
        message, headers = util_helper.generate_authentication_create_message_value(
            self.account_number, self.username, self.authentication_id)
        new_arn = util_helper.generate_dummy_arn(account_id=self.account_id)
        self.auth_return_value["username"] = new_arn

        mock_get_auth.return_value = self.auth_return_value
        mock_get_app.return_value = self.app_return_value

        validation_error = ValidationError(
            detail={_faker.slug(): _faker.slug()})
        with patch("api.clouds.aws.util.verify_permissions"
                   ) as mock_verify_permissions:
            mock_verify_permissions.side_effect = validation_error
            tasks.update_from_source_kafka_message(message, headers)
            mock_verify_permissions.assert_called()

        self.clount.refresh_from_db()
        self.assertEqual(self.clount.content_object.account_arn, new_arn)
        self.assertFalse(self.clount.is_enabled)
Exemple #15
0
    def setUp(self):
        """Set up shared variables."""
        self.authentication_id = _faker.pyint()
        self.account_id = util_helper.generate_dummy_aws_account_id()
        self.arn = util_helper.generate_dummy_arn(account_id=self.account_id)

        self.clount = api_helper.generate_cloud_account(
            arn=self.arn, platform_authentication_id=self.authentication_id)

        self.username = _faker.user_name()
        self.application_id = _faker.pyint()
        self.source_id = _faker.pyint()

        self.account_number = str(_faker.pyint())

        self.auth_return_value = {
            "username": self.arn,
            "resource_type": settings.SOURCES_RESOURCE_TYPE,
            "resource_id": self.application_id,
            "id": self.authentication_id,
            "authtype": settings.SOURCES_CLOUDMETER_ARN_AUTHTYPE,
        }
        self.app_return_value = {
            "source_id": self.source_id,
            "id": self.application_id,
        }
Exemple #16
0
    def test_update_from_sources_kafka_message_new_aws_account_id(
            self, mock_enable, mock_get_auth, mock_notify_sources,
            mock_get_app):
        """
        Assert the new cloud account created for new aws_account_id.

        A new CloudAccount will get created with the new arn. And the old
        CloudAccount will be removed.
        """
        message, headers = util_helper.generate_authentication_create_message_value(
            self.account_number, self.username, self.authentication_id)
        new_account_id = util_helper.generate_dummy_aws_account_id()
        new_arn = util_helper.generate_dummy_arn(account_id=new_account_id)

        self.auth_return_value["username"] = new_arn
        mock_get_auth.return_value = self.auth_return_value
        mock_get_app.return_value = self.app_return_value

        with patch.object(sts, "boto3") as mock_boto3, patch.object(
                aws_models, "_delete_cloudtrail"), patch(
                    "api.clouds.aws.util.verify_permissions"):
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = util_helper.generate_dummy_role()
            tasks.update_from_source_kafka_message(message, headers)

        mock_enable.assert_called()
Exemple #17
0
    def test_account_not_created_if_enable_fails(self, mock_enable,
                                                 mock_notify_sources):
        """
        Assert the account is not created if enable fails.

        Note:
            AwsCloudAccount.enable is responsible for performing AWS permission
            verification. This test effectively tests handling of AWS failures there.
        """
        user = User.objects.create()

        customer_secret_access_key = util_helper.generate_dummy_arn()
        auth_id = _faker.pyint()
        application_id = _faker.pyint()
        source_id = _faker.pyint()

        validation_error = ValidationError({"account_arn": "uh oh"})
        mock_enable.side_effect = validation_error

        tasks.configure_customer_aws_and_create_cloud_account(
            user.username,
            customer_secret_access_key,
            auth_id,
            application_id,
            source_id,
        )

        self.assertFalse(CloudAccount.objects.filter(user=user).exists())
    def test_create_aws_clount_fails_with_same_user_same_name(
            self, mock_enable, mock_notify_sources):
        """Test create_aws_cloud_account fails with same name different platform IDs."""
        # The first call just creates the existing objects.
        util.create_aws_cloud_account(self.user, self.arn, self.name,
                                      self.auth_id, self.app_id,
                                      self.source_id)

        other_arn = util_helper.generate_dummy_arn()
        other_auth_id = _faker.pyint()
        other_app_id = _faker.pyint()
        other_source_id = _faker.pyint()

        with self.assertRaises(ValidationError) as raise_context:
            util.create_aws_cloud_account(
                self.user,
                other_arn,
                self.name,
                other_auth_id,
                other_app_id,
                other_source_id,
            )
        exception_detail = raise_context.exception.detail
        self.assertIn("name", exception_detail)
        self.assertIn("Could not set up cloud metering.",
                      exception_detail["name"])
        self.assertIn("CG1003", exception_detail["name"])
Exemple #19
0
    def test_save_instance_with_available_image(self):
        """Test that save instance events also writes image on instance."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = api_helper.generate_cloud_account(
            arn=arn, aws_account_id=aws_account_id)

        region = util_helper.get_random_region()
        instances_data = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running)
            ]
        }
        ami_id = instances_data[region][0]["ImageId"]

        mock_session = Mock()
        described_amis = util_helper.generate_dummy_describe_image(
            image_id=ami_id, owner_id=aws_account_id)

        with patch.object(util.aws, "describe_images") as mock_describe_images:
            mock_describe_images.return_value = [described_amis]
            util.create_new_machine_images(mock_session, instances_data)
            mock_describe_images.assert_called_with(mock_session, {ami_id},
                                                    region)
        awsinstance = util.save_instance(account, instances_data[region][0],
                                         region)
        instance = awsinstance.instance.get()
        self.assertEqual(instance.machine_image.content_object.ec2_ami_id,
                         ami_id)
        self.assertEqual(instance.machine_image.status, MachineImage.PENDING)
Exemple #20
0
    def test_create_fails_when_assume_role_fails_unexpectedly(self):
        """Test that account is not saved if assume_role fails unexpectedly."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        validated_data = {
            'account_arn': arn,
        }

        mock_request = Mock()
        mock_request.user = util_helper.generate_test_user()
        context = {'request': mock_request}

        client_error = ClientError(
            error_response=MagicMock(),
            operation_name=Mock(),
        )

        with patch.object(aws.sts, 'boto3') as mock_boto3:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.side_effect = client_error
            serializer = AwsAccountSerializer(context=context)

            with self.assertRaises(ClientError) as cm:
                serializer.create(validated_data)
            raised_exception = cm.exception
            self.assertEqual(raised_exception, client_error)
    def test_create_aws_clount_fails_same_aws_account_different_arn(
            self, mock_enable, mock_notify_sources):
        """
        Test create_aws_cloud_account fails with same ARN and different AWS Account.

        If we ever change cloudigrade to support multiple ARNs in the same AWS Account,
        this test and its underlying logic must be rewritten.
        """
        util.create_aws_cloud_account(self.user, self.arn, self.name,
                                      self.auth_id, self.app_id,
                                      self.source_id)

        other_name = self.name = _faker.word()
        other_arn = util_helper.generate_dummy_arn(
            account_id=self.aws_account_id, resource=_faker.word())
        self.assertNotEqual(self.arn, other_arn)

        with self.assertRaises(ValidationError) as raise_context:
            util.create_aws_cloud_account(
                self.user,
                other_arn,
                other_name,
                self.auth_id,
                self.app_id,
                self.source_id,
            )
        exception_detail = raise_context.exception.detail
        self.assertIn("account_arn", exception_detail)
        self.assertIn("Could not set up cloud metering.",
                      exception_detail["account_arn"])
        self.assertIn("CG1002", exception_detail["account_arn"])
Exemple #22
0
    def test_get_running_instances(self):
        """Assert we get expected instances in a dict keyed by regions."""
        mock_arn = helper.generate_dummy_arn()
        mock_regions = [f'region-{uuid.uuid4()}']
        mock_role = helper.generate_dummy_role()
        mock_running_instance = helper.generate_dummy_describe_instance(
            state=aws.InstanceState.running)
        mock_stopped_instance = helper.generate_dummy_describe_instance(
            state=aws.InstanceState.stopped)
        mock_described = {
            'Reservations': [
                {
                    'Instances': [
                        mock_running_instance,
                        mock_stopped_instance,
                    ],
                },
            ],
        }
        expected_found = {mock_regions[0]: [mock_running_instance]}

        with patch.object(aws, 'get_regions') as mock_get_regions, \
                patch.object(aws, 'boto3') as mock_boto3:
            mock_assume_role = mock_boto3.client.return_value.assume_role
            mock_assume_role.return_value = mock_role
            mock_get_regions.return_value = mock_regions
            mock_client = mock_boto3.Session.return_value.client.return_value
            mock_client.describe_instances.return_value = mock_described

            actual_found = aws.get_running_instances(aws.get_session(mock_arn))

        self.assertDictEqual(expected_found, actual_found)
Exemple #23
0
    def test_create_new_machine_images(self):
        """Test that new machine images are saved to the DB."""
        aws_account_id = util_helper.generate_dummy_aws_account_id()
        arn = util_helper.generate_dummy_arn(aws_account_id)
        account = AwsAccount(
            account_arn=arn,
            aws_account_id=aws_account_id,
            user=util_helper.generate_test_user(),
        )
        account.save()

        region = random.choice(util_helper.SOME_AWS_REGIONS)
        running_instances = {
            region: [
                util_helper.generate_dummy_describe_instance(
                    state=aws.InstanceState.running
                )
            ]
        }
        ami_id = running_instances[region][0]['ImageId']

        result = util.create_new_machine_images(account, running_instances)

        amis = AwsMachineImage.objects.filter(account=account).all()

        self.assertEqual(result, [ami_id])
        for ami in amis:
            self.assertEqual(ami.ec2_ami_id, ami_id)
Exemple #24
0
    def test_copy_ami_snapshot_success(self, mock_aws):
        """Assert that the snapshot copy task succeeds."""
        mock_arn = util_helper.generate_dummy_arn()
        mock_region = random.choice(util_helper.SOME_AWS_REGIONS)
        mock_image_id = util_helper.generate_dummy_image_id()
        mock_image = util_helper.generate_mock_image(mock_image_id)
        block_mapping = mock_image.block_device_mappings
        mock_snapshot_id = block_mapping[0]['Ebs']['SnapshotId']
        mock_snapshot = util_helper.generate_mock_snapshot(mock_snapshot_id)
        mock_new_snapshot_id = util_helper.generate_dummy_snapshot_id()
        mock_session = mock_aws.boto3.Session.return_value

        mock_aws.get_session.return_value = mock_session
        mock_aws.get_ami.return_value = mock_image
        mock_aws.get_ami_snapshot_id.return_value = mock_snapshot_id
        mock_aws.get_snapshot.return_value = mock_snapshot
        mock_aws.copy_snapshot.return_value = mock_new_snapshot_id

        with patch.object(tasks, 'create_volume') as mock_create_volume:
            copy_ami_snapshot(mock_arn, mock_image_id, mock_region)
            mock_create_volume.delay.assert_called_with(
                mock_image_id, mock_new_snapshot_id)

        mock_aws.get_session.assert_called_with(mock_arn)
        mock_aws.get_ami.assert_called_with(mock_session, mock_image_id,
                                            mock_region)
        mock_aws.get_ami_snapshot_id.assert_called_with(mock_image)
        mock_aws.add_snapshot_ownership.assert_called_with(mock_snapshot)
        mock_aws.copy_snapshot.assert_called_with(mock_snapshot_id,
                                                  mock_region)
Exemple #25
0
 def test_copy_ami_to_customer_account_missing_image(self, mock_aws):
     """Assert early return if the AwsMachineImage doesn't exist."""
     arn = util_helper.generate_dummy_arn()
     reference_ami_id = util_helper.generate_dummy_image_id()
     region = util_helper.get_random_region()
     tasks.copy_ami_to_customer_account(arn, reference_ami_id, region)
     mock_aws.get_session.assert_not_called()
Exemple #26
0
    def test_copy_ami_snapshot_encrypted(self, mock_aws):
        """Assert that the task marks the image as encrypted in the DB."""
        mock_account_id = util_helper.generate_dummy_aws_account_id()
        mock_region = random.choice(util_helper.SOME_AWS_REGIONS)
        mock_arn = util_helper.generate_dummy_arn(mock_account_id, mock_region)

        mock_image_id = util_helper.generate_dummy_image_id()
        mock_image = util_helper.generate_mock_image(mock_image_id)
        mock_snapshot_id = util_helper.generate_dummy_snapshot_id()
        mock_snapshot = util_helper.generate_mock_snapshot(mock_snapshot_id,
                                                           encrypted=True)
        mock_session = mock_aws.boto3.Session.return_value

        mock_aws.get_session.return_value = mock_session
        mock_aws.get_ami.return_value = mock_image
        mock_aws.get_ami_snapshot_id.return_value = mock_snapshot_id
        mock_aws.get_snapshot.return_value = mock_snapshot

        account = AwsAccount(
            aws_account_id=mock_account_id,
            account_arn=mock_arn,
            user=util_helper.generate_test_user(),
        )
        account.save()
        ami = AwsMachineImage.objects.create(account=account,
                                             is_windows=False,
                                             ec2_ami_id=mock_image_id)

        ami.save()

        with patch.object(tasks, 'create_volume') as mock_create_volume,\
                self.assertRaises(AwsSnapshotEncryptedError):
            copy_ami_snapshot(mock_arn, mock_image_id, mock_region)
            self.assertTrue(ami.is_encrypted)
            mock_create_volume.delay.assert_not_called()
Exemple #27
0
    def test_copy_ami_to_customer_account_not_marketplace(self, mock_aws):
        """Assert that the task fails when non-marketplace error occurs."""
        arn = util_helper.generate_dummy_arn()
        reference_ami_id = util_helper.generate_dummy_image_id()
        source_region = util_helper.get_random_region()

        api_helper.generate_image(ec2_ami_id=reference_ami_id)

        mock_aws.copy_ami.side_effect = ClientError(
            error_response={
                "Error": {
                    "Code": "ItIsAMystery",
                    "Message": "Mystery Error"
                }
            },
            operation_name=Mock(),
        )

        with self.assertRaises(RuntimeError) as e:
            tasks.copy_ami_to_customer_account(arn, reference_ami_id,
                                               source_region)

        self.assertIn("ClientError", e.exception.args[0])
        self.assertIn("ItIsAMystery", e.exception.args[0])
        self.assertIn("Mystery Error", e.exception.args[0])

        mock_aws.get_session.assert_called_with(arn)
        mock_aws.get_ami.assert_called_with(mock_aws.get_session.return_value,
                                            reference_ami_id, source_region)
Exemple #28
0
    def test_remove_snapshot_ownership_success(self, mock_aws, mock_boto3):
        """Assert that the remove snapshot ownership task succeeds."""
        mock_arn = util_helper.generate_dummy_arn()
        mock_customer_snapshot_id = util_helper.generate_dummy_snapshot_id()
        mock_customer_snapshot = util_helper.generate_mock_snapshot(
            mock_customer_snapshot_id)
        mock_snapshot_copy_id = util_helper.generate_dummy_snapshot_id()
        mock_snapshot_copy = util_helper.generate_mock_snapshot(
            mock_snapshot_copy_id)
        zone = settings.HOUNDIGRADE_AWS_AVAILABILITY_ZONE
        region = zone[:-1]

        resource = mock_boto3.resource.return_value
        resource.Snapshot.return_value = mock_snapshot_copy

        mock_aws.check_snapshot_state.return_value = None
        mock_aws.get_snapshot.return_value = mock_customer_snapshot

        mock_aws.get_region_from_availability_zone.return_value = region

        tasks.remove_snapshot_ownership(mock_arn, mock_customer_snapshot_id,
                                        region, mock_snapshot_copy_id)

        mock_aws.remove_snapshot_ownership.assert_called_with(
            mock_customer_snapshot)
Exemple #29
0
    def test_parse_arn_with_region_and_account(self):
        """Assert successful account ID parsing from a well-formed ARN."""
        mock_account_id = helper.generate_dummy_aws_account_id()
        mock_arn = helper.generate_dummy_arn(account_id=mock_account_id,
                                             region="test-region-1")

        arn_object = AwsArn(mock_arn)

        partition = arn_object.partition
        self.assertIsNotNone(partition)

        service = arn_object.service
        self.assertIsNotNone(service)

        region = arn_object.region
        self.assertIsNotNone(region)

        account_id = arn_object.account_id
        self.assertIsNotNone(account_id)

        resource_type = arn_object.resource_type
        self.assertIsNotNone(resource_type)

        resource_separator = arn_object.resource_separator
        self.assertIsNotNone(resource_separator)

        resource = arn_object.resource
        self.assertIsNotNone(resource)

        reconstructed_arn = ("arn:" + partition + ":" + service + ":" +
                             region + ":" + str(account_id) + ":" +
                             resource_type + resource_separator + resource)

        self.assertEqual(mock_account_id, account_id)
        self.assertEqual(mock_arn, reconstructed_arn)
Exemple #30
0
 def setUp(self):
     """Set up test models."""
     aws_account_id = util_helper.generate_dummy_aws_account_id()
     arn = util_helper.generate_dummy_arn(account_id=aws_account_id)
     self.role = util_helper.generate_dummy_role()
     self.account = helper.generate_cloud_account(
         arn=arn, aws_account_id=aws_account_id, name="test")