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)
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())
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()
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)
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)
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)
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
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
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
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()
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())