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
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'])))
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()
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
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)
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)
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.'
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()
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
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)
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)
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)
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)
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)
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'])
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
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
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}'
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)
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)
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']
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'])
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
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
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']
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
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)