Example #1
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)
Example #2
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())
Example #3
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()
Example #4
0
    def test_copy_ami_snapshot_marketplace(self, mock_aws):
        """Assert that a suspected marketplace image is checked."""
        mock_account_id = util_helper.generate_dummy_aws_account_id()
        mock_session = mock_aws.boto3.Session.return_value
        mock_aws.get_session_account_id.return_value = mock_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_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.side_effect = ClientError(
            error_response={'Error': {
                'Code': 'InvalidSnapshot.NotFound'
            }},
            operation_name=Mock(),
        )

        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,
                                             ec2_ami_id=mock_image_id)

        ami.save()

        with patch.object(tasks, 'create_volume') as mock_create_volume, \
                patch.object(tasks, 'copy_ami_to_customer_account') as \
                mock_copy_ami_to_customer_account:
            copy_ami_snapshot(mock_arn, mock_image_id, mock_region)
            mock_create_volume.delay.assert_not_called()
            mock_copy_ami_to_customer_account.delay.assert_called_with(
                mock_arn, mock_image_id, mock_region, maybe_marketplace=True)
Example #5
0
    def test_copy_ami_snapshot_private_shared(self, mock_aws):
        """Assert that the task copies the image when it is private/shared."""
        mock_account_id = util_helper.generate_dummy_aws_account_id()
        mock_session = mock_aws.boto3.Session.return_value
        mock_aws.get_session_account_id.return_value = mock_account_id

        # the account id to use as the private shared image owner
        other_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=False, owner_id=other_account_id)

        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,
                                             ec2_ami_id=mock_image_id)

        ami.save()

        with patch.object(tasks, 'create_volume') as mock_create_volume, \
                patch.object(tasks, 'copy_ami_to_customer_account') as \
                mock_copy_ami_to_customer_account:
            copy_ami_snapshot(mock_arn, mock_image_id, mock_region)
            mock_create_volume.delay.assert_not_called()
            mock_copy_ami_to_customer_account.delay.assert_called_with(
                mock_arn, mock_image_id, mock_region)
Example #6
0
 def test_create_404s_missing_account(self):
     """Test report 404s when requesting an account that doesn't exist."""
     mock_request = Mock()
     mock_request.data = {
         'cloud_provider': AWS_PROVIDER_STRING,
         'cloud_account_id': helper.generate_dummy_aws_account_id(),
         'start': '2018-01-01T00:00:00',
         'end': '2018-02-01T00:00:00',
     }
     view = ReportViewSet()
     with patch.object(view, 'serializer_class') as mock_serializer_class:
         mock_serializer_class.return_value.generate = \
             Mock(side_effect=AwsAccount.DoesNotExist())
         with self.assertRaises(exceptions.NotFound):
             view.list(mock_request)
Example #7
0
 def create(self, validated_data):
     """Create an AwsAccount."""
     arn = validated_data['account_arn']
     aws_account_id = aws.extract_account_id_from_arn(arn)
     account = AwsAccount(account_arn=arn, aws_account_id=aws_account_id)
     session = aws.get_session(arn)
     if aws.verify_account_access(session):
         instances_data = aws.get_running_instances(session)
         with transaction.atomic():
             account.save()
             create_initial_aws_instance_events(account, instances_data)
     else:
         raise serializers.ValidationError(
             _('AwsAccount verification failed. ARN Info Not Stored'))
     return account
Example #8
0
 def create(self, validated_data):
     """Create an AwsAccount."""
     arn = aws.AwsArn(validated_data['account_arn'])
     aws_account_id = arn.account_id
     user = self.context['request'].user
     account = AwsAccount(
         account_arn=str(arn),
         aws_account_id=aws_account_id,
         user=user,
     )
     try:
         session = aws.get_session(str(arn))
     except ClientError as error:
         if error.response.get('Error', {}).get('Code') == 'AccessDenied':
             raise serializers.ValidationError(
                 detail={
                     'account_arn':
                     [_('Permission denied for ARN "{0}"').format(arn)]
                 })
         raise
     account_verified, failed_actions = aws.verify_account_access(session)
     if account_verified:
         instances_data = aws.get_running_instances(session)
         with transaction.atomic():
             account.save()
             new_amis = create_new_machine_images(account, instances_data)
             create_initial_aws_instance_events(account, instances_data)
         messages = generate_aws_ami_messages(instances_data, new_amis)
         for message in messages:
             copy_ami_snapshot.delay(str(arn), message['image_id'],
                                     message['region'])
     else:
         failure_details = [_('Account verification failed.')]
         failure_details += [
             _('Access denied for policy action "{0}".').format(action)
             for action in failed_actions
         ]
         raise serializers.ValidationError(
             detail={'account_arn': failure_details})
     return account
Example #9
0
    def create(self, validated_data):
        """Create an AwsAccount."""
        arn = aws.AwsArn(validated_data['account_arn'])
        aws_account_id = arn.account_id

        account = AwsAccount.objects.filter(
            aws_account_id=aws_account_id).first()
        if account is not None:
            raise serializers.ValidationError(
                detail={
                    'account_arn': [
                        _('An ARN already exists for account "{0}"').format(
                            aws_account_id)
                    ]
                })

        user = self.context['request'].user
        name = validated_data.get('name')
        account = AwsAccount(
            account_arn=str(arn),
            aws_account_id=aws_account_id,
            name=name,
            user=user,
        )
        try:
            session = aws.get_session(str(arn))
        except ClientError as error:
            if error.response.get('Error', {}).get('Code') == 'AccessDenied':
                raise serializers.ValidationError(
                    detail={
                        'account_arn':
                        [_('Permission denied for ARN "{0}"').format(arn)]
                    })
            raise
        account_verified, failed_actions = aws.verify_account_access(session)
        if account_verified:
            instances_data = aws.get_running_instances(session)
            with transaction.atomic():
                account.save()
                try:
                    aws.configure_cloudtrail(session, aws_account_id)
                except ClientError as error:
                    if error.response.get('Error', {}).get('Code') == \
                            'AccessDeniedException':
                        raise serializers.ValidationError(
                            detail={
                                'account_arn': [
                                    _('Access denied to create CloudTrail for '
                                      'ARN "{0}"').format(arn)
                                ]
                            })
                    raise
                new_amis = create_new_machine_images(account, instances_data)
                create_initial_aws_instance_events(account, instances_data)
            messages = generate_aws_ami_messages(instances_data, new_amis)
            for message in messages:
                image = start_image_inspection(str(arn), message['image_id'],
                                               message['region'])
                self.add_openshift_tag(session, message['image_id'],
                                       message['region'], image)
        else:
            failure_details = [_('Account verification failed.')]
            failure_details += [
                _('Access denied for policy action "{0}".').format(action)
                for action in failed_actions
            ]
            raise serializers.ValidationError(
                detail={'account_arn': failure_details})
        return account
Example #10
0
 def assert_account_exists(self):
     """Assert that the AWS account ID exists in cloudigrade."""
     if not AwsAccount.objects.filter(
             aws_account_id=self.cloud_account_id).exists():
         raise AwsAccount.DoesNotExist()
Example #11
0
    def test_ami_tags_removed_success(self, mock_receive, mock_s3, mock_del):
        """Test processing a CloudTrail log for ami tags removed."""
        mock_user = util_helper.generate_test_user()
        mock_arn = util_helper.generate_dummy_arn()
        aws_account = AwsAccount(user=mock_user,
                                 name='test',
                                 aws_account_id='1234',
                                 account_arn=mock_arn)
        aws_account.save()

        mock_ec2_ami_id = util_helper.generate_dummy_image_id()
        aws_machine_image = AwsMachineImage(account=aws_account,
                                            ec2_ami_id=mock_ec2_ami_id)
        aws_machine_image.save()

        openshift_tag = ImageTag.objects.filter(
            description=tasks.OPENSHIFT_MODEL_TAG).first()
        aws_machine_image.tags.add(openshift_tag)

        mock_sqs_message_body = {
            'Records': [{
                's3': {
                    'bucket': {
                        'name': 'test-bucket',
                    },
                    'object': {
                        'key': 'path/to/log/log.json.gz',
                    },
                },
            }]
        }

        mock_queue_url = 'https://sqs.queue.url'
        mock_receipt_handle = str(uuid.uuid4())
        mock_region = random.choice(util_helper.SOME_AWS_REGIONS)

        now = datetime.datetime.utcnow()
        mock_occurred_at = datetime.datetime(year=now.year,
                                             month=now.month,
                                             day=now.day,
                                             hour=now.hour,
                                             minute=now.minute,
                                             second=now.second,
                                             tzinfo=tz.tzutc())

        mock_message = util_helper.generate_mock_sqs_message(
            mock_queue_url, json.dumps(mock_sqs_message_body),
            mock_receipt_handle)

        mock_cloudtrail_log = {
            'Records': [{
                'eventTime':
                mock_occurred_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
                'eventSource':
                'ec2.amazonaws.com',
                'awsRegion':
                mock_region,
                'eventName':
                tasks.DELETE_TAG,
                'requestParameters': {
                    'resourcesSet': {
                        'items': [{
                            'resourceId': mock_ec2_ami_id
                        }]
                    },
                    'tagSet': {
                        'items': [{
                            'key': tasks.AWS_OPENSHIFT_TAG,
                            'value': tasks.AWS_OPENSHIFT_TAG
                        }]
                    }
                }
            }]
        }

        mock_receive.return_value = [mock_message]
        mock_s3.return_value = json.dumps(mock_cloudtrail_log)

        tasks.analyze_log()

        self.assertEqual(
            None,
            aws_machine_image.tags.filter(
                description=tasks.OPENSHIFT_MODEL_TAG).first())