Example #1
0
def ui_user(user_info):
    """Create a user for use in a UI test."""
    user = create_user_account(user_info)
    get_auth(user)
    logger.debug('user: %s / %s', user['username'], user['password'])

    return user
Example #2
0
def create_user_account():
    """Create a factory to create user accounts.

    This fixture creates a factory (a function) which will create a user
    account. Repeated calls will create return new users. All users created
    with this factory will delete any cloud accounts associated with the users
    after the test has run.

    Optional arguments can be passed as a dictionary:
        {'username': '******', 'password': '******', 'email': 'str'}

    If none are provided, values will be generated and returned.
    """
    users = []

    def factory(**kwargs):
        """Create a user, add it to our list of users, and return it."""
        user = utils.create_user_account(**kwargs)
        users.append(user)
        return user

    yield factory

    client = api.Client()

    for user in users:
        auth = utils.get_auth(user)
        while client.get(urls.CLOUD_ACCOUNT, auth=auth).json()['results']:
            account = client.get(
                urls.CLOUD_ACCOUNT, auth=auth).json()['results'][0]
            client.delete(urljoin(urls.CLOUD_ACCOUNT, str(account['id'])))
Example #3
0
def cloud_account(drop_account_data, cloudtrails_to_delete):
    """Create a cloud account, return the auth object and account details."""
    assert direct_count_images() == 0
    auth = get_auth()
    create_response = create_cloud_account(
        auth, 0, cloudtrails_to_delete=cloudtrails_to_delete)
    return (auth, create_response)
def test_negative_create_cloud_account_missing(drop_account_data,
                                               field_to_delete):
    """Ensure attempts to create cloud accounts missing data are rejected.

    :id: a93821ba-4181-47e7-b685-dbe642c1441e
    :description: Ensure an user cannot register a cloud account missing data.
    :steps: 1) Create a user and authenticate with their password
        2) Send a POST with the incomplete cloud account information to
            'api/v1/account/'
    :expectedresults: The server rejects the incomplete request.
    """
    auth = get_auth()
    client = api.Client(authenticate=False, response_handler=api.echo_handler)
    cfg = config.get_config()
    aws_profile = cfg['aws_profiles'][0]
    profile_name = aws_profile['name']
    acct_arn = aws_profile['arn']

    cloud_account = {
        'account_arn': acct_arn,
        'resourcetype': 'AwsAccount',
        'name': profile_name,
    }
    # remove one field
    cloud_account.pop(field_to_delete)
    create_response = client.post(urls.CLOUD_ACCOUNT,
                                  payload=cloud_account,
                                  auth=auth)
    missing_fields = create_response.json().keys()
    assert create_response.status_code == 400, create_response.json()
    assert field_to_delete in missing_fields, create_response.json()
Example #5
0
def accounts_report_data():
    """Create cloud account data for the accounts report tests.

    Create three cloud accounts and create some instance data.
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    first_account = inject_aws_cloud_account(
        user['id'],
        name='a greatest account ever',
    )
    second_account = inject_aws_cloud_account(
        user['id'],
        name='b just another account',
    )
    third_account = inject_aws_cloud_account(
        user['id'],
        name='c my awesome account',
    )

    # Make first account have one RHEL instance and image that was running for
    # 3 days
    inject_instance_data(first_account['id'], 'rhel', [5, 2])

    # Make second account have one RHEL and one OpenShift instance and image
    # that was running for 5 days
    inject_instance_data(second_account['id'], 'rhel,openshift', [12, 7])

    # Make third account have one OpenShift instance and image that was running
    # for 10 days
    inject_instance_data(third_account['id'], 'openshift', [13, 3])

    return auth, first_account, second_account, third_account
Example #6
0
def test_image_report_empty():
    """Test accounts without any instance or image report has empty summary.

    :id: 2a152ef6-fcd8-491c-b3cc-bda81699453a
    :description: Test that an account without any instances or images shows up
        in the results with 0 counts.
    :steps:
        1) Add a cloud account
        2) GET from the image report endpoint
    :expectedresults:
        - An empty list is returned
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    client = api.Client(authenticate=False)

    report_start, report_end = utils.get_time_range()
    params = {
        'start': report_start,
        'end': report_end,
        'account_id': acct['id'],
    }
    response = client.get(urls.REPORT_IMAGES, params=params, auth=auth)

    images = response.json()['images']

    assert images == [], repr(images)
Example #7
0
def test_list_accounts_empty(create_user_account):
    """Test accounts without any instance or image history have empty summaries.

    :id: 2a152ef6-fcd8-491c-b3cc-bda81699453a
    :description: Test that an account without any instances or images shows up
        in the results with 0 counts.
    :steps:
        1) Add a cloud account
        2) GET from the account report endpoint
    :expectedresults:
        - The account is in the response and matches the created account
        - Instances, images, RHEL, and Openshift all have 0 counts
    """
    user = create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    client = api.Client(authenticate=False)

    start, end = utils.get_time_range()
    params = {
        'start': start,
        'end': end,
    }
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    account = response.json()['cloud_account_overviews'][0]

    assert account['cloud_account_id'] == acct['aws_account_id']
    assert account['images'] == 0, repr(account)
    assert account['instances'] == 0, repr(account)
    assert account['rhel_instances'] == 0, repr(account)
    assert account['openshift_instances'] == 0, repr(account)
Example #8
0
def test_runtime_requests_from_future():
    """Test future start and end times for empty set result.

    :id: 133A04EE-55C3-4948-B2F9-D89A6A84C9FC
    :description: Test events that start/end in the future ensuring
        that results are empty [].
    :steps:
        1) Add a cloud account
        2) Insert past instance, image, and event data
        3) Insert future instance, image, and event data
        4) GET from the image report endpoint
    :expectedresults:
        - When start/end times are in the future OR when start>end
            expect runtine_seconds to be empty.
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type = 'openshift'
    instance_start = 2
    instance_end = 1
    client = api.Client(authenticate=False, response_handler=api.echo_handler)
    events = [instance_start]
    if instance_end:
        events.append(instance_end)
    inject_instance_data(acct['id'], image_type, events)

    report_start, report_end = utils.get_time_range(180)
    params = {
        'start': report_start,
        'end': report_end,
        'account_id': acct['id'],
    }
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)
    response_data = response.json()['cloud_account_overviews'][0]
    rhel_instances = response_data['rhel_instances']
    openshift_instances = response_data['openshift_instances']
    rhel_runtime_seconds = response_data['rhel_runtime_seconds']
    openshift_runtime_seconds = response_data['openshift_runtime_seconds']

    assert rhel_instances is None
    assert openshift_instances is None
    assert rhel_runtime_seconds is None
    assert openshift_runtime_seconds is None
    past_date = datetime.datetime.now() + datetime.timedelta(-30)
    backwards_params = {
        'start': report_start,
        'end': past_date,
        'account_id': acct['id'],
    }
    response = client.get(
        urls.REPORT_ACCOUNTS,
        params=backwards_params,
        auth=auth,
    )
    response_error = response.json()['non_field_errors'][0]
    assert response_error == 'End date must be after start date.'
Example #9
0
def ui_user():
    """Create a user for use in a UI test."""
    global USER
    if USER:
        return USER
    else:
        username = uuid4() + '@example.com'
        password = gen_password()
        user = create_user_account({
            'username': username,
            'email': username,
            'password': password,
        })
        get_auth(user)
        logger.debug('user: %s / %s', username, password)

        USER = user
        return user
def test_create_cloud_account_duplicate_names_different_users(
        cloudtrails_to_delete):
    """Ensure cloud accounts can be registered to a user.

    :id: 7bf483b7-f0d0-40db-9c18-396dc4a58792
    :description: Ensure an user can register a cloud account by specifying
        the role ARN.
    :steps: 1) Create a user and authenticate with their password
        2) Send a POST with the cloud account information to 'api/v1/account/'
        3) Send a GET to 'api/v1/account/' to get a list of the cloud accounts
        4) Attempt to create a duplicate and expect it to be rejected
        5) Attempt to delete the account and expect to be rejected
    :expectedresults:
        1) The server returns a 201 response with the information
            of the created account.
        2) The account cannot be duplicated, and attempts to do so receive a
            400 status code.
        3) The account cannot be deleted and attempts to do so receive a 405
            response.
    """
    # TODO: refactor inject_aws_cloud_account to use seed data
    user = ''  # create_user_account()
    auth = get_auth(user)
    client = api.Client(authenticate=False, response_handler=api.echo_handler)
    cfg = config.get_config()
    aws_profile = cfg['aws_profiles'][0]
    # TODO: refactor inject_aws_cloud_account to use seed data
    profile_name = ''  # aws_profile['name']
    # inject_aws_cloud_account(user['id'], name=profile_name)

    # Now try to reuse the name
    auth = get_auth()
    aws_profile = cfg['aws_profiles'][1]
    acct_arn = aws_profile['arn']
    cloud_account = {
        'account_arn': acct_arn,
        'name': profile_name,
        'resourcetype': 'AwsAccount'
    }
    create_response = client.post(urls.CLOUD_ACCOUNT,
                                  payload=cloud_account,
                                  auth=auth)
    assert create_response.status_code == 201, create_response.json()
Example #11
0
def test_future_instances(param):
    """Test instance events generate usage summary results for correct tags.

    :id: f3c84697-a40c-40d9-846d-117e2647e9d3
    :description: Test combinations of image tags, start/end events, and the
        resulting counts from the summary report API.
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the account report endpoint
    :expectedresults:
        - The instance, image, RHEL, and Openshift counts match the expectation
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'], acct_age=param.acct_age)
    start, end = 0, None

    client = api.Client(authenticate=False)

    events = [start]
    if end:
        events.append(end)
    inject_instance_data(acct['id'], '', events)

    # Set date range for 30 days in the past
    start, end = utils.get_time_range(-30)
    params = {
        'start': start,
        'end': end,
    }
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    account = response.json()['cloud_account_overviews'][0]
    acct_creation = datetime.today() - timedelta(days=param.acct_age)

    start, end = utils.get_time_range(-30, formatted=False)
    if acct_creation < start:
        info = 'Account created before start of window'
    elif acct_creation > end:
        info = 'Account newer than window'
    else:
        info = 'Account created during window'

    assert account['cloud_account_id'] == acct['aws_account_id']

    if param.unknown:
        exp = None
    else:
        exp = 0
    assert account['images'] == exp, info
    assert account['instances'] == exp, info
    assert account['rhel_instances'] == exp, info
    assert account['openshift_instances'] == exp, info
Example #12
0
def test_list_account_while_impersonating(impersonate):
    """Test account data fetched via impersonating a user as a superuser.

    :id: 5f99c7ec-a4d3-4040-868f-9340015e4c9c
    :description: Test that the same assertions can be made for fetching data
        as a regular user and fetching data impersonating that same user
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the account report endpoint as regular user
        3) GET from the account report endpoint as super user impersonating
    :expectedresults:
        - The instance, image, RHEL, and Openshift counts match the expectation
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type = 'rhel'
    exp_inst = 1
    exp_images = 1
    exp_rhel = 1
    exp_openshift = 0
    start = 0
    end = None
    offset = 0

    # authenticate (as superuser) if we are impersonating
    client = api.Client(authenticate=impersonate)

    events = [start]
    if end:
        events.append(end)
    inject_instance_data(acct['id'], image_type, events)

    start, end = utils.get_time_range(offset)
    params = {
        'start': start,
        'end': end,
    }
    if impersonate:
        params['user_id'] = user['id']
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    account = response.json()['cloud_account_overviews'][0]

    assert account['cloud_account_id'] == acct['aws_account_id']
    assert account['images'] == exp_images, repr(account)
    assert account['instances'] == exp_inst, repr(account)
    assert account['rhel_instances'] == exp_rhel, repr(account)
    assert account['openshift_instances'] == exp_openshift, repr(account)
Example #13
0
def test_list_images_while_impersonating(impersonate):
    """Test account data fetched via impersonating a user as a superuser.

    :id: 5f99c7ec-a4d3-4040-868f-9340015e4c9c
    :description: Test that the same assertions can be made for fetching data
        as a regular user and fetching data impersonating that same user
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the image report endpoint as regular user
        3) GET from the image report endpoint as super user impersonating
    :expectedresults:
        - The images are returned for the user and a super user, but
            no one else.
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type = 'rhel'
    exp_rhel = True
    exp_openshift = False
    start = 12
    end = 10
    offset = 0
    # start and end values indicate number of days in the past
    # so their difference is the whole number of days of runtime
    expected_runtime = (start - end) * 24 * 60 * 60

    # authenticate (as superuser) if we are impersonating
    client = api.Client(authenticate=impersonate)

    events = [start]
    if end:
        events.append(end)
    inject_instance_data(acct['id'], image_type, events)

    report_start, report_end = utils.get_time_range(offset)
    params = {
        'start': report_start,
        'end': report_end,
        'account_id': acct['id'],
    }
    response = client.get(urls.REPORT_IMAGES, params=params, auth=auth)

    image = response.json()['images'][0]
    assert image['rhel'] == exp_rhel, repr(image)
    assert image['openshift'] == exp_openshift, repr(image)
    assert int(image['runtime_seconds']) == int(expected_runtime), repr(image)
Example #14
0
def test_multiple_runs_counted_once():
    """Test instances being run a different times in the same period count once.

    :id: 0e8d0475-54d9-43af-9c2b-23f84865c6b4
    :description: Within any single period of reporting an instance which has
        been started and stopped multiple times still counts just once.
    :steps:
        1) Add a cloud account
        2) Insert event data with more than one start and stop in the last 30
           day period
        3) GET from the account report endpoint
    :expectedresults:
        - The instance and image should only be counted once
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type = ''
    exp_inst = 1
    exp_images = 1
    exp_rhel = 0
    exp_openshift = 0

    client = api.Client(authenticate=False)

    start, end = utils.get_time_range()
    params = {
        'start': start,
        'end': end,
    }

    events = [
        20,
        15,
        10,
        5,
    ]
    inject_instance_data(acct['id'], image_type, events)

    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    account = response.json()['cloud_account_overviews'][0]

    assert account['cloud_account_id'] == acct['aws_account_id']
    assert account['images'] == exp_images, repr(account)
    assert account['instances'] == exp_inst, repr(account)
    assert account['rhel_instances'] == exp_rhel, repr(account)
    assert account['openshift_instances'] == exp_openshift, repr(account)
Example #15
0
def test_list_account_with_multiple():
    """Test that a user with multiple accounts can list all.

    :id: 1f16a664-a4ea-410e-9ff8-0a6e42cb4df2
    :description: Test that the same assertions can be made for fetching data
        with just one account works with multiple.
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the account report endpoint as regular user
    :expectedresults:
        - The instance, image, RHEL, and Openshift counts match the expectation
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type = 'rhel'
    exp_inst = 1
    exp_images = 1
    exp_rhel = 1
    exp_openshift = 0
    time = 0
    offset = 0

    acct2 = inject_aws_cloud_account(user['id'])

    client = api.Client(authenticate=False)

    inject_instance_data(acct['id'], image_type, [time])

    start, end = utils.get_time_range(offset)
    params = {
        'start': start,
        'end': end,
    }
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    accounts = response.json()['cloud_account_overviews']
    account = accounts[0]
    account2 = accounts[1]

    assert account['cloud_account_id'] == acct['aws_account_id']
    assert account2['cloud_account_id'] == acct2['aws_account_id']
    assert account['images'] == exp_images, repr(account)
    assert account['instances'] == exp_inst, repr(account)
    assert account['rhel_instances'] == exp_rhel, repr(account)
    assert account['openshift_instances'] == exp_openshift, repr(account)
Example #16
0
def test_past_without_instances():
    """Test accounts with instances only after the filter period.

    :id: 72aaa6e2-2c60-4e71-bb47-3644bd6beb71
    :description: Test that an account with instances that were created prior
        to the current report end date.
    :steps:
        1) Add a cloud account
        2) Inject instance data for today
        3) GET from the account report endpoint for 30 days ago
    :expectedresults:
        - The account is in the response and matches the created account
        - Instances, images, RHEL, and Openshift all have None counts
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    # TODO: refactor inject_aws_cloud_account to use seed data
    acct = ''  # inject_aws_cloud_account(user['id'])
    client = api.Client(authenticate=False)

    # ask for last 30 days
    report_start, report_end = utils.get_time_range()
    params = {
        'start': report_start,
        'end': report_end,
        'account_id': acct['id'],
    }

    response = client.get(urls.REPORT_IMAGES, params=params, auth=auth)
    images = response.json()['images']

    assert images == [], repr(images)

    # No tagged images, started 60 days ago and stopped 45 days ago
    # image_type = ''
    instance_start = 60
    instance_end = 45
    events = [instance_start, instance_end]
    print(events)
    # inject_instance_data(acct['id'], image_type, events)

    # test that still have no images in report
    response = client.get(urls.REPORT_IMAGES, params=params, auth=auth)
    images = response.json()['images']

    assert images == [], repr(images)
Example #17
0
def test_sysconfig():
    """Ensure sysconfig returns expected configuration information.

    :id: 984b1e7c-597f-419c-8c73-8d84ce4417ff
    :description: Ensure sysconfig returns expected configuration information.
    :steps: Do an authenticated GET requests to /api/v1/sysconfig/ and check
        the response.
    :expectedresults: The server returns a 201 response with the expected
        configuration information.
    """
    auth = get_auth()
    client = api.Client(response_handler=api.json_handler)
    response = client.get(urls.SYSCONFIG, auth=auth)
    assert set(response.keys()) == set((
        'aws_account_id',
        'aws_policies',
        'version',
    ))
    assert re.match(r'\d+', response['aws_account_id'])
Example #18
0
def test_user_list(drop_account_data):
    """Super users can request lists of created user accounts.

    :id: 52567e92-2b6a-43b0-bdc0-5a347b9dd4bc
    :description: Super users, and only super users, are able to request a user
        list.
    :steps:
        1) Authenticate with a super user account and request the user list
            end point contains yourself and a created non-super user account.
        2) Authenticate with a non-super user account and request the user list
            to verify a 4xx error
    :expectedresults: The super user can get the list, but not the regular user
        account.
    """
    client = api.Client()
    response = client.get(urls.USER_LIST)
    pre_user_list = response.json()
    usernames = [user['username'] for user in pre_user_list]
    assert get_config()['super_user_name'] in usernames

    new_user = create_user_account()
    account_number = random.randint(2, 5)
    for _ in range(account_number):
        inject_aws_cloud_account(new_user['id'])
    response = client.get(urls.USER_LIST).json()

    for user in response:
        assert 'accounts' in user, user
        assert 'challenged_images' in user, user

        if user['id'] == new_user['id']:
            assert user['accounts'] == account_number
            assert user['challenged_images'] == 0

    new_user_list = [user for user in response if user not in pre_user_list]
    new_user_ids = [user['id'] for user in new_user_list]

    assert new_user['id'] in new_user_ids

    auth = get_auth(new_user)
    client = api.Client(authenticate=False, response_handler=api.echo_handler)
    response = client.get(urls.USER_LIST, auth=auth)
    assert response.status_code == 403
Example #19
0
def test_cancel(browser_session, ui_addacct_page3, u1_user):
    """The user can add a new account using a valid current ARN.

    :id: fa01c0a2-86da-11e8-af5f-8c1645548902
    :description: The user can create and name a new cloud account.
    :steps:
        1) Open the dashboard and click the "Add Account"
        2) Enter a name for the account
        3) Proceed to page 3
        4) Enter an ARN which is valid ARN for a resource we are granted
           permission to
        5) Click the "Cancel" button to cancel attempt to create the account
    :expectedresults: The Account is not created and can't be fetched by the
        account list API for verification with the given name and ARN.
    """
    selenium = browser_session
    if find_element_by_text(selenium, 'Different Name', timeout=0.5):
        clean_slate(selenium)
        back_to_addacct_wizard(selenium)
    else:
        back_to_addacct_wizard(selenium)
    acct_arn = config.get_config()['aws_profiles'][0]['arn']
    dialog = selenium.find_element_by_xpath('//div[@role="dialog"]')
    fill_input_by_label(selenium, dialog, 'Account Name', 'My Account')
    find_element_by_text(selenium, 'Next').click()
    find_element_by_text(selenium, 'Next').click()

    fill_input_by_label(selenium, dialog, 'ARN', acct_arn)
    find_element_by_text(dialog, 'Cancel').click()
    find_element_by_text(selenium, 'Yes').click()

    pytest.raises(
        NoSuchElementException,
        selenium.find_element_by_tag_name,
        'dialog',
    )

    client = api.Client(authenticate=False)
    auth = get_auth(user=u1_user)
    sleep(0.25)
    response = client.get(urls.CLOUD_ACCOUNT, auth=auth)
    res = response.json()['results']
    assert res[0]['account_arn'] != acct_arn
Example #20
0
def test_aws_policy(new_session, browser_session, ui_addacct_page1, u1_user):
    """Test the shared policy between UI and API.

    :id: 82c82a98-4e03-4459-8944-9cca03b59955
    :description: The UI should use the currently single policy from the API.
    :steps:
        1) Open the Add Account dialog and view the policy
        2) Get the policy from the API directly
    :expectedresults: The policy named traditional_inspection from the API
        should match the policy contents in the UI precisely.
    """
    el = browser_session.find_element_by_class_name('cloudmeter-copy-input')
    ui_policy = json.loads(el.get_attribute('value'))
    sleep(1)
    client = api.Client(authenticate=False, response_handler=api.json_handler)
    auth = get_auth(user=u1_user)
    response = client.get(urls.SYSCONFIG, auth=auth)
    api_policy = response['aws_policies']['traditional_inspection']
    assert api_policy == ui_policy, \
        f'ui_policy seen: {ui_policy}' \
        f'api_policy seen: {api_policy}'
Example #21
0
def test_list_account_tagging(conf):
    """Test instance events generate usage summary results for correct tags.

    :id: f3c84697-a40c-40d9-846d-117e2647e9d3
    :description: Test combinations of image tags, start/end events, and the
        resulting counts from the summary report API.
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the account report endpoint
    :expectedresults:
        - The instance, image, RHEL, and Openshift counts match the expectation
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type, exp_inst, exp_images, exp_rhel, exp_openshift, \
        start, end, offset = conf[1:]

    client = api.Client(authenticate=False)

    events = [start]
    if end:
        events.append(end)
    inject_instance_data(acct['id'], image_type, events)

    start, end = utils.get_time_range(offset)
    params = {
        'start': start,
        'end': end,
    }
    response = client.get(urls.REPORT_ACCOUNTS, params=params, auth=auth)

    account = response.json()['cloud_account_overviews'][0]

    assert account['cloud_account_id'] == acct['aws_account_id']
    assert account['images'] == exp_images, repr(account)
    assert account['instances'] == exp_inst, repr(account)
    assert account['rhel_instances'] == exp_rhel, repr(account)
    assert account['openshift_instances'] == exp_openshift, repr(account)
Example #22
0
def test_image_tagging(conf):
    """Test instance events generate image usage results with correct tags.

    :id: f3c84697-a40c-40d9-846d-117e2647e9d3
    :description: Test combinations of image tags, start/end events, and the
        resulting counts from the summary report API.
    :steps:
        1) Add a cloud account
        2) Insert instance, image, and event data
        3) GET from the image report endpoint
    :expectedresults:
        - The images have correct tags and usage amounts
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])
    image_type, exp_inst, exp_images, exp_rhel, exp_openshift, \
        instance_start, instance_end, offset = conf
    # start and end values indicate number of days in the past
    # so their difference is the whole number of days of runtime
    expected_runtime = (instance_start - instance_end) * 24 * 60 * 60
    client = api.Client(authenticate=False)

    events = [instance_start]
    if instance_end:
        events.append(instance_end)
    inject_instance_data(acct['id'], image_type, events)

    report_start, report_end = utils.get_time_range(offset)
    params = {
        'start': report_start,
        'end': report_end,
        'account_id': acct['id'],
    }
    response = client.get(urls.REPORT_IMAGES, params=params, auth=auth)

    image = response.json()['images'][0]
    assert image['rhel'] == exp_rhel, repr(image)
    assert image['openshift'] == exp_openshift, repr(image)
    assert int(image['runtime_seconds']) == int(expected_runtime), repr(image)
Example #23
0
def test_create_multiple_cloud_accounts(drop_account_data,
                                        cloudtrails_to_delete):
    """Ensure cloud accounts can be registered to a user.

    :id: f1db2617-fd15-4270-b9d3-595db001e1e7
    :description: Ensure an user can register multiple cloud accounts as long
        as each ARN is associated with unique cloud accounts.
    :steps: 1) Create a user and authenticate with their password
        2) Send POSTS with each of the cloud account's information to
            'api/v1/account/'
        3) Send a GET to 'api/v1/account/' to get a list of the cloud accounts
    :expectedresults: The server returns a 201 response with the information of
        the created accounts.
    """
    client = api.Client(authenticate=False)
    auth = get_auth()
    cfg = config.get_config()
    accts = []
    for profile in cfg['aws_profiles']:
        arn = profile['arn']
        cloud_account = {
            'account_arn': arn,
            'name': uuid4(),
            'resourcetype': 'AwsAccount'
        }
        create_response = client.post(urls.CLOUD_ACCOUNT,
                                      payload=cloud_account,
                                      auth=auth)
        assert create_response.status_code == 201
        cloudtrails_to_delete.append(
            (profile['name'], profile['cloudtrail_name']))

        accts.append(create_response.json())

    # list cloud accounts associated with this user
    list_response = client.get(urls.CLOUD_ACCOUNT, auth=auth)
    for acct in accts:
        assert acct in list_response.json()['results']
Example #24
0
def test_sysconfig():
    """Ensure sysconfig returns expected configuration information.

    :id: 984b1e7c-597f-419c-8c73-8d84ce4417ff
    :description: Ensure sysconfig returns expected configuration information.
    :steps: Do an authenticated GET requests to /api/v1/sysconfig/ and check
        the response.
    :expectedresults: The server returns a 201 response with the expected
        configuration information. The api.json_handler will raise an error if
        the response_code isn't a successful one - ie 2XX OK, 4XX or 5XX NOK.
    """
    user = {
        'username': '******',
        'password': '******',
    }
    auth = get_auth(user)
    client = api.Client(response_handler=api.json_handler, token=auth)
    response = client.get(urls.SYSCONFIG, auth=auth)
    assert set(response.keys()) == set((
        'aws_account_id',
        'aws_policies',
        'version',
    ))
    assert re.match(r'\d+', response['aws_account_id'])
Example #25
0
def test_create_cloud_account_duplicate_names(drop_account_data,
                                              cloudtrails_to_delete):
    """Ensure cloud accounts can be registered to a user.

    :id: 47b6b382-092a-420f-a8b0-63e6578e4857
    :description: Ensure an user can register a cloud account by specifying
        the role ARN.
    :steps: 1) Create a user and authenticate with their password
        2) Send a POST with the cloud account information to 'api/v1/account/'
        3) Send a GET to 'api/v1/account/' to get a list of the cloud accounts
        4) Attempt to create a duplicate and expect it to be rejected
        5) Attempt to delete the account and expect to be rejected
    :expectedresults:
        1) The server returns a 201 response with the information
            of the created account.
        2) The account cannot be duplicated, and attempts to do so receive a
            400 status code.
        3) The account cannot be deleted and attempts to do so receive a 405
            response.
    """
    user = create_user_account()
    auth = get_auth(user)
    client = api.Client(authenticate=False, response_handler=api.echo_handler)
    cfg = config.get_config()
    inject_aws_cloud_account(user['id'], name=cfg['aws_profiles'][0]['name'])

    # Now try to reuse the name
    cloud_account = {
        'account_arn': cfg['aws_profiles'][0]['arn'],
        'name': cfg['aws_profiles'][0]['name'],
        'resourcetype': 'AwsAccount'
    }
    create_response = client.post(urls.CLOUD_ACCOUNT,
                                  payload=cloud_account,
                                  auth=auth)
    assert create_response.status_code == 400
Example #26
0
def test_flagged_account_numbers():
    """Test the number of flagged images in accounts.

    :id: BBD687F5-0B78-4E86-8368-C5C8EEBD9263
    :description: Test that the number of images reported as flagged matches
    the flagged/challenged images in accounts.

    :steps:
        1) Add a cloud account
        2) Insert RHEL and RHOCP image
        3) Check number of challenged/flagged RHEL/RHOCP images
        4) Challenge images
        5) Check number of challenged/flagged RHEL/RHOCP images
    :expectedresults:
        - Challenged RHEL images = 0 when none are challenged
        - Challenged RHEL images > 0 when one or more are challenged
        - Challenged RHOCP images = 0 when none are challenged
        - Challenged RHOCP images > 0 when one or more are challenged
    """
    user = utils.create_user_account()
    auth = utils.get_auth(user)
    acct = inject_aws_cloud_account(user['id'])

    images = {}
    for tag in ('rhel', 'openshift'):
        image_type = tag
        events = [1, 2]
        client = api.Client(authenticate=False,
                            response_handler=api.echo_handler)
        images[tag] = inject_instance_data(
            acct['id'],
            image_type,
            events,
        )

        report_start, report_end = utils.get_time_range()
        params = {
            'start': report_start,
            'end': report_end,
            'account_id': acct['id'],
        }
    response = client.get(urls.REPORT_ACCOUNTS, params=params,
                          auth=auth).json()['cloud_account_overviews'][0]
    assert response['rhel_instances'] == 1
    assert response['openshift_instances'] == 1
    assert response['rhel_images_challenged'] == 0
    assert response['openshift_images_challenged'] == 0

    rhel_image = images.get('rhel')
    openshift_image = images.get('openshift')
    images = [rhel_image, openshift_image]
    # Shuffle images to be sure that each is called first, to ensure that
    # order doesn't matter
    shuffle(images)
    first_image_url = urljoin(urls.IMAGE, str(images[0]['image_id'])) + '/'
    second_image_url = urljoin(urls.IMAGE, str(images[1]['image_id'])) + '/'
    first_image_response = client.get(first_image_url, auth=auth).json()
    second_image = ''
    challenged_image = ''
    unchallenged_image = ''

    # Challenge first image
    if first_image_response['rhel']:
        first_image_response['rhel_challenged'] = True
        client.put(first_image_url, first_image_response, auth=auth)
        first_image = 'rhel'
        second_image = 'openshift'
        challenged_image = 'rhel_images_challenged'
        unchallenged_image = 'openshift_images_challenged'
    else:
        first_image_response['openshift_challenged'] = True
        client.put(first_image_url, first_image_response, auth=auth)
        first_image = 'openshift'
        second_image = 'rhel'
        challenged_image = 'openshift_images_challenged'
        unchallenged_image = 'rhel_images_challenged'
    first_response = client.get(urls.REPORT_ACCOUNTS, params=params,
                                auth=auth).json()['cloud_account_overviews'][0]

    assert first_response[challenged_image] == 1
    assert first_response[unchallenged_image] == 0
    assert first_response[f'{second_image}_instances'] == 1
    assert first_response[f'{first_image}_instances'] == 0

    # Challenge second image
    second_image_response = client.get(second_image_url, auth=auth).json()
    second_image_response[f'{second_image}_challenged'] = True

    client.put(second_image_url, second_image_response, auth=auth)
    second_response = client.get(
        urls.REPORT_ACCOUNTS, params=params,
        auth=auth).json()['cloud_account_overviews'][0]

    assert second_response[challenged_image] == 1
    assert second_response[unchallenged_image] == 1
    assert second_response[f'{second_image}_instances'] == 0
    assert second_response[f'{first_image}_instances'] == 0
Example #27
0
def test_cloudtrail_updated(drop_account_data,
                            cloudtrails_and_buckets_to_delete):
    """Ensure the cloudtrail is updated if a pre-existing one is found.

    :id: f4a93a35-41e5-490d-bc3f-7c0df9ea805b
    :description: Ensure that at cloud account creation, if a pre-existing
        cloudigrade cloudtrail is found, it is updated.
    :steps: 1) Create a user and authenticate with their password
        2) Create a cloudtrail with the same name that cloudigrade uses but
            a different s3 bucket.
        3) Create a cloud account using this same AWS account.
        4) Assert that the cloudtrail is updated and now uses correct s3
            bucket.
    :expectedresults:
        1) The server returns a 201 response with the information
            of the created account.
        2) The cloudtrail is updated to use the correct s3 bucket.
    """
    auth = get_auth()
    cfg = config.get_config()
    aws_profile = cfg['aws_profiles'][0]
    profile_name = aws_profile['name']
    acct_arn = aws_profile['arn']
    client = api.Client(authenticate=False)
    cloudtrail_client = aws_utils.aws_session(profile_name).client(
        'cloudtrail')

    # create our own cloud trail with a different s3 bucket
    bucket_name = aws_utils.create_bucket_for_cloudtrail(profile_name)
    # Queue the bucket for cleanup
    cloudtrails_and_buckets_to_delete.append((profile_name, None, bucket_name))
    if cloudtrail_client.describe_trails(
            trailNameList=[aws_profile['cloudtrail_name']]).get('trailList'):
        cloudtrail_client.update_trail(Name=aws_profile['cloudtrail_name'],
                                       S3BucketName=bucket_name)
    else:
        cloudtrail_client.create_trail(Name=aws_profile['cloudtrail_name'],
                                       S3BucketName=bucket_name)
    # Queue the cloudtrail for cleanup
    cloudtrails_and_buckets_to_delete.append(
        (profile_name, aws_profile['cloudtrail_name'], None))
    cloud_account = {
        'account_arn': acct_arn,
        'resourcetype': 'AwsAccount',
        'name': 'name',
    }
    create_response = client.post(urls.CLOUD_ACCOUNT,
                                  payload=cloud_account,
                                  auth=auth)
    assert create_response.status_code == 201, create_response.json()

    acct = create_response.json()

    # get specific account
    get_response = client.get(urljoin(urls.CLOUD_ACCOUNT,
                                      '{}/'.format(acct['id'])),
                              auth=auth)
    assert acct == get_response.json()

    # Assert that a cloudtrail has been set up in the customer's account
    trails = [
        trail for trail in cloudtrail_client.describe_trails()['trailList']
    ]
    trail_names = [trail['Name'] for trail in trails]
    assert aws_profile['cloudtrail_name'] in trail_names
    the_trail = [
        trail for trail in trails
        if trail['Name'] == aws_profile['cloudtrail_name']
    ][0]
    assert the_trail['S3BucketName'].endswith('-cloudigrade-s3')
    assert bucket_name not in the_trail['S3BucketName']
Example #28
0
def test_create_cloud_account(drop_account_data, cloudtrails_to_delete):
    """Ensure cloud accounts can be registered to a user.

    :id: f7a9225b-83af-4567-b59a-a8bb62d612c9
    :description: Ensure an user can register a cloud account by specifying
        the role ARN.
    :steps: 1) Create a user and authenticate with their password
        2) Send a POST with the cloud account information to 'api/v1/account/'
        3) Send a GET to 'api/v1/account/' to get a list of the cloud accounts
        4) Attempt to create a duplicate and expect it to be rejected
        5) Attempt to delete the account and expect to succeed
    :expectedresults:
        1) The server returns a 201 response with the information
            of the created account.
        2) The account cannot be duplicated, and attempts to do so receive a
            400 status code.
        3) The account can be deleted and we get a 200 response.
    """
    auth = get_auth()
    client = api.Client(authenticate=False)
    cfg = config.get_config()
    aws_profile = cfg['aws_profiles'][0]
    profile_name = aws_profile['name']
    acct_arn = aws_profile['arn']
    cloud_account = {
        'account_arn': acct_arn,
        'name': uuid4(),
        'resourcetype': 'AwsAccount'
    }
    start = time()
    create_response = client.post(urls.CLOUD_ACCOUNT,
                                  payload=cloud_account,
                                  auth=auth)
    end = time()
    create_data = create_response.json()
    assert end - start < 7
    assert create_response.status_code == 201
    assert create_data['account_arn'] == acct_arn
    assert create_data['aws_account_id'] == aws_profile['account_number']

    # Assert that a cloudtrail has been set up in the customer's account
    cloudtrail_client = aws_utils.aws_session(profile_name).client(
        'cloudtrail')
    trail_names = [
        trail['Name']
        for trail in cloudtrail_client.describe_trails()['trailList']
    ]
    assert aws_profile['cloudtrail_name'] in trail_names
    # since account was created, add trail to cleanup
    cloudtrails_to_delete.append(
        (profile_name, aws_profile['cloudtrail_name']))

    acct = create_response.json()

    # get specific account
    account_url = urljoin(urls.CLOUD_ACCOUNT, '{}/'.format(acct['id']))
    get_response = client.get(account_url, auth=auth)
    assert acct == get_response.json()

    # list cloud accounts associated with this user
    list_response = client.get(urls.CLOUD_ACCOUNT, auth=auth)
    assert acct in list_response.json()['results']

    # Check if account name can be patched
    payload = {
        'name': 'new_name',
        'resourcetype': 'AwsAccount',
    }
    response = client.patch(account_url, payload=payload, auth=auth)
    response = client.get(account_url, auth=auth)
    assert response.json()['name'] == 'new_name'

    # Check if an account can be updated
    payload = {
        'account_arn': acct_arn,
        'name': 'new_name2',
        'resourcetype': 'AwsAccount',
    }
    response = client.put(account_url, payload=payload, auth=auth)
    response = client.get(account_url, auth=auth)
    assert response.json()['name'] == 'new_name2'

    # assert we cannot create duplicate
    client.response_handler = api.echo_handler
    response = client.post(urls.CLOUD_ACCOUNT,
                           payload=cloud_account,
                           auth=auth)
    assert response.status_code == 400
    assert 'account_arn' in response.json().keys()
    assert 'already exists' in response.json()['account_arn'][0]

    # attempt to delete the specific account
    delete_response = client.delete(urljoin(urls.CLOUD_ACCOUNT,
                                            '{}/'.format(acct['id'])),
                                    auth=auth)
    assert delete_response.status_code == 204
Example #29
0
def test_negative_read_other_cloud_account(drop_account_data,
                                           cloudtrails_to_delete):
    """Ensure users cannot access eachother's cloud accounts.

    :id: b500d301-dd46-41b0-af3b-0145f9404784
    :description: Ensure one user is not allowed to read another user's cloud
        account data.
    :steps: 1) Create two users and authenticate with their passwords
        2) For each user, send a POST with the cloud account information to
            'api/v1/account/'
        3) For each, send a GET to 'api/v1/account/' to get a list of the
           cloud accounts
        4) Ensure a super user sees all accounts.
    :expectedresults: The server only returns cloud accounts related to the
        user making the request, except the super user, who sees all accounts.
    """
    client = api.Client(authenticate=False)
    user1 = create_user_account()
    user2 = create_user_account()
    auth1 = get_auth(user1)
    auth2 = get_auth(user2)

    # create cloud account for 1st user
    acct1 = inject_aws_cloud_account(user1['id'])
    # create account for 2nd user
    acct2 = inject_aws_cloud_account(user2['id'])

    # list cloud accounts associated with each user
    list_response = client.get(urls.CLOUD_ACCOUNT, auth=auth1)
    acct_ids_found = [
        acct['aws_account_id'] for acct in list_response.json()['results']
    ]
    assert acct1['aws_account_id'] in acct_ids_found
    assert acct2['aws_account_id'] not in acct_ids_found

    list_response = client.get(urls.CLOUD_ACCOUNT, auth=auth2)
    acct_ids_found = [
        acct['aws_account_id'] for acct in list_response.json()['results']
    ]
    assert acct2['aws_account_id'] in acct_ids_found
    assert acct1['aws_account_id'] not in acct_ids_found

    # use super user token to see all
    superclient = api.Client()
    list_response = superclient.get(urls.CLOUD_ACCOUNT)
    acct_ids_found = [
        acct['aws_account_id'] for acct in list_response.json()['results']
    ]
    assert acct2['aws_account_id'] in acct_ids_found
    assert acct1['aws_account_id'] in acct_ids_found

    # create cloud account with super user
    # update cloud account to differnt ARN
    # FIXME: clumsy way to get super user id
    all_users = superclient.get(urls.USER_LIST).json()
    super_user_id = [user['id'] for user in all_users
                     if user['is_superuser']][0]
    acct3 = inject_aws_cloud_account(super_user_id)
    list_response = superclient.get(urls.CLOUD_ACCOUNT)
    acct_ids_found = [
        acct['aws_account_id'] for acct in list_response.json()['results']
    ]
    assert acct3['aws_account_id'] in acct_ids_found
    assert list_response.json()['count'] == 3

    # make sure user1 still just see theirs
    list_response = client.get(urls.CLOUD_ACCOUNT, auth=auth1)
    acct_ids_found = [
        acct['aws_account_id'] for acct in list_response.json()['results']
    ]
    assert acct1['aws_account_id'] in acct_ids_found
    assert acct2['aws_account_id'] not in acct_ids_found
    assert acct3['aws_account_id'] not in acct_ids_found
def test_broken_image(
        aws_profile,
        cloudtrails_to_delete,
        image_fixture,
):
    """Ensure Houndigrade handles broken image inspection gracefully.

    :id: 723A10AB-A729-41DE-93B2-966DCC6AD71D
    :description: When an instance is created from an image that is flawed
        (ie- garbled files -> yum.conf, /var/lib/rpm), it still gets
        inspected.
    :steps: 1) Create a user and authenticate with their password
        2) Create instances based off of a broken image
        3) Send a POST with the cloud account information to 'api/v1/account/'
        4) Send a GET to 'api/v1/instance/' and expect to get the instances we
            created
        5) Send a GET to 'api/v1/image/' and expect to get the image that
            the instances were based off of.
        6) Keep checking to see that the images progress from "pending",
            "preparing", "inspecting", to "inspected"
    :expectedresults:
        1) The server returns a 201 response with the information
            of the created account.
        2) We get 200 responses for our GET requests and information about
            the images includes inspection state information.
        3) The images are eventually inspected.
    """
    image_type, image_name, expected_state = broken_image
    image_fixture = image_fixture[2]
    source_image = image_fixture.source_image
    source_image_id = source_image['image_id']
    instance_id = image_fixture.instance_id

    auth = get_auth()
    client = api.Client(authenticate=False, response_handler=api.json_handler)
    aws_profile_name = aws_profile['name']
    aws_utils.delete_cloudtrail(
        (aws_profile_name, aws_profile['cloudtrail_name']))
    aws_utils.clean_cloudigrade_queues()

    # Create cloud account on cloudigrade
    cloud_account = {
        'name': aws_profile['name'],
        'account_arn': aws_profile['arn'],
        'resourcetype': AWS_ACCOUNT_TYPE
    }
    client.post(
        urls.CLOUD_ACCOUNT,
        payload=cloud_account,
        auth=auth
    )

    # Cleanup cloudtrail after test so events
    # don't keep coming into the cloudigrade s3 bucket
    cloudtrails_to_delete.append(
        (aws_profile['name'], aws_profile['cloudtrail_name'])
    )

    # Look for instances that should have been discovered
    # upon account creation.
    found_instances = wait_for_cloudigrade_instance(instance_id, auth)
    assert instance_id in found_instances

    # Look for images that should have been discovered
    # upon account creation.
    list_images = client.get(urls.IMAGE, auth=auth)
    found_images = [image['ec2_ami_id'] for image in list_images['results']]
    assert source_image_id in found_images
    wait_for_inspection(source_image, expected_state, auth)