def test_add_attribute(rest_client, auth_token): """ ACCOUNT (REST): add/get/delete attribute.""" acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 key = account_name_generator() value = "true" data = {'key': key, 'value': value} response = rest_client.post('/accounts/{0}/attr/{1}'.format(acntusr, key), headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.get('/accounts/' + acntusr + '/attr/', headers=headers(auth(auth_token))) assert response.status_code == 200 response = rest_client.delete('/accounts/{0}/attr/{1}'.format( acntusr, key), headers=headers(auth(auth_token)), json=data) assert response.status_code == 200
def test_list_scope(rest_client, auth_token): """ SCOPE (REST): send a GET list all scopes for one account """ tmp_val = account_name_generator() headers_dict = {'Rucio-Type': 'user', 'X-Rucio-Account': 'root'} data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/%s' % tmp_val, headers=headers(auth(auth_token), hdrdict(headers_dict)), json=data) assert response.status_code == 201 scopes = [scope_name_generator() for _ in range(5)] for scope in scopes: response = rest_client.post('/accounts/%s/scopes/%s' % (tmp_val, scope), headers=headers(auth(auth_token)), json={}) assert response.status_code == 201 response = rest_client.get('/accounts/%s/scopes/' % tmp_val, headers=headers(auth(auth_token))) assert response.status_code == 200 svr_list = loads(response.get_data(as_text=True)) for scope in scopes: assert scope in svr_list
def test_create_user_failure(rest_client, auth_token): """ ACCOUNT (REST): send a POST with an existing user to test the error case """ data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/jdoe', headers=headers(auth(auth_token)), json=data) assert response.status_code in (201, 409) response = rest_client.post('/accounts/jdoe', headers=headers(auth(auth_token)), json=data) assert response.status_code == 409
def test_ssh_success(vo, rest_client): """AUTHENTICATION (REST): SSH RSA public key exchange (correct credentials).""" root = InternalAccount('root', vo=vo) try: add_account_identity(PUBLIC_KEY, IdentityType.SSH, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip headers_dict = {'X-Rucio-Account': 'root'} response = rest_client.get('/auth/ssh_challenge_token', headers=headers(hdrdict(headers_dict), vohdr(vo))) assert response.status_code == 200 assert 'challenge-' in response.headers.get('X-Rucio-SSH-Challenge-Token') signature = ssh_sign(PRIVATE_KEY, response.headers.get('X-Rucio-SSH-Challenge-Token')) headers_dict = { 'X-Rucio-Account': 'root', 'X-Rucio-SSH-Signature': signature } response = rest_client.get('/auth/ssh', headers=headers(hdrdict(headers_dict), vohdr(vo))) assert response.status_code == 200 assert len(response.headers.get('X-Rucio-Auth-Token')) > 32 del_account_identity(PUBLIC_KEY, IdentityType.SSH, root)
def test_delete_identity_of_account(vo, rest_client): """ ACCOUNT (REST): send a DELETE to remove an identity of an account.""" account = account_name_generator() identity = uuid() password = '******' add_account(account, 'USER', '*****@*****.**', 'root', vo=vo) add_identity(identity, IdentityType.USERPASS, '*****@*****.**', password) add_account_identity(identity, IdentityType.USERPASS, InternalAccount(account, vo=vo), '*****@*****.**') auth_response = rest_client.get('/auth/userpass', headers=headers( loginhdr(account, identity, password), vohdr(vo))) assert auth_response.status_code == 200 assert 'X-Rucio-Auth-Token' in auth_response.headers token = str(auth_response.headers.get('X-Rucio-Auth-Token')) assert len(token) != 0 # normal deletion data = {'authtype': 'USERPASS', 'identity': identity} response = rest_client.delete('/accounts/' + account + '/identities', headers=headers(auth(token)), json=data) assert response.status_code == 200 # unauthorized deletion other_account = account_name_generator() data = {'authtype': 'USERPASS', 'identity': identity} response = rest_client.delete('/accounts/' + other_account + '/identities', headers=headers(auth(token)), json=data) assert response.status_code == 401
def test_add_identity_to_account(rest_client, auth_token): """ ACCOUNT (REST): send a POST to add an identity to an account.""" identity = uuid() # normal addition data = { 'authtype': 'USERPASS', 'email': '*****@*****.**', 'password': '******', 'identity': identity } response = rest_client.post('/accounts/root/identities', headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 # duplicate identity response = rest_client.post('/accounts/root/identities', headers=headers(auth(auth_token)), json=data) assert response.status_code == 409 # missing password identity = uuid() data = { 'authtype': 'USERPASS', 'email': '*****@*****.**', 'identity': identity } response = rest_client.post('/accounts/root/identities', headers=headers(auth(auth_token)), json=data) assert response.status_code == 400
def test_create_and_update_and_list_subscription(rest_client, auth_token): """ SUBSCRIPTION (REST): Test the creation of a new subscription, update it, list it """ subscription_name = uuid() projects = ['data12_900GeV', 'data12_8TeV', 'data13_900GeV', 'data13_8TeV'] pattern1 = r'(_tid|physics_(Muons|JetTauEtmiss|Egamma)\..*\.ESD|express_express(?!.*NTUP|.*\.ESD|.*RAW)|(physics|express)(?!.*NTUP).* \ \.x|physics_WarmStart|calibration(?!_PixelBeam.merge.(NTUP_IDVTXLUMI|AOD))|merge.HIST|NTUP_MUONCALIB|NTUP_TRIG)' data = { 'options': { 'filter': { 'project': projects, 'datatype': [ 'AOD', ], 'excluded_pattern': pattern1, 'account': [ 'tier0', ] }, 'replication_rules': [{ 'lifetime': 86400, 'rse_expression': 'MOCK|MOCK2', 'copies': 2, 'activity': 'Data Brokering' }], 'lifetime': 100000, 'retroactive': 0, 'dry_run': 0, 'comments': 'blahblah' } } response = rest_client.post('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 data = { 'options': { 'filter': { 'project': [ 'toto', ] } } } response = rest_client.put('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.get('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token))) assert response.status_code == 200 assert loads(loads( response.get_data(as_text=True))['filter'])['project'][0] == 'toto'
def test_get_user_success(rest_client, auth_token): """ ACCOUNT (REST): send a GET to retrieve the infos of the new user """ acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.get('/accounts/' + acntusr, headers=headers(auth(auth_token))) assert response.status_code == 200 body = loads(response.get_data(as_text=True)) assert body['account'] == acntusr
def test_list_scope_no_scopes(rest_client, auth_token): """ SCOPE (REST): send a GET list all scopes for one account without scopes """ acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.get('/accounts/%s/scopes/' % acntusr, headers=headers(auth(auth_token))) assert response.status_code == 404 assert response.headers.get('ExceptionClass') == 'ScopeNotFound'
def test_scope_success(rest_client, auth_token): """ SCOPE (REST): send a POST to create a new account and scope """ acntusr = account_name_generator() data = {'type': 'USER', 'email': 'rucio.email.com'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 scopeusr = scope_name_generator() response = rest_client.post('/accounts/%s/scopes/%s' % (acntusr, scopeusr), headers=headers(auth(auth_token))) assert response.status_code == 201
def test_create_existing_subscription(rse_factory, rest_client, auth_token): """ SUBSCRIPTION (REST): Test the creation of a existing subscription """ subscription_name = uuid() rse1, _ = rse_factory.make_mock_rse() rse2, _ = rse_factory.make_mock_rse() rse_expression = '%s|%s' % (rse1, rse2) projects = ['data12_900GeV', 'data12_8TeV', 'data13_900GeV', 'data13_8TeV'] pattern1 = r'(_tid|physics_(Muons|JetTauEtmiss|Egamma)\..*\.ESD|express_express(?!.*NTUP|.*\.ESD|.*RAW)|(physics|express)(?!.*NTUP).* \ \.x|physics_WarmStart|calibration(?!_PixelBeam.merge.(NTUP_IDVTXLUMI|AOD))|merge.HIST|NTUP_MUONCALIB|NTUP_TRIG)' data = { 'options': { 'name': subscription_name, 'filter': { 'project': projects, 'datatype': [ 'AOD', ], 'excluded_pattern': pattern1, 'account': [ 'tier0', ] }, 'replication_rules': [{ 'lifetime': 86400, 'rse_expression': rse_expression, 'copies': 2, 'activity': 'Data Brokering' }], 'lifetime': 100000, 'retroactive': 0, 'dry_run': 0, 'comments': 'We are the knights who say Ni !' } } response = rest_client.post('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.post('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token)), json=data) assert response.status_code == 409 assert response.headers.get('ExceptionClass') == 'SubscriptionDuplicate'
def test_del_user_success(rest_client, auth_token): """ ACCOUNT (REST): send a DELETE to disable the new user """ acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 response = rest_client.delete('/accounts/' + acntusr, headers=headers(auth(auth_token))) assert response.status_code == 200 response = rest_client.get('/accounts/' + acntusr, headers=headers(auth(auth_token))) assert response.status_code == 200 body = loads(response.get_data(as_text=True)) assert body['status'] == AccountStatus.DELETED.name
def test_update_account(rest_client, auth_token): """ ACCOUNT (REST): send a PUT to update an account.""" acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 data = {'status': 'SUSPENDED', 'email': 'test'} response = rest_client.put('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 200 response = rest_client.get('/accounts/' + acntusr, headers=headers(auth(auth_token))) assert response.status_code == 200 body = loads(response.get_data(as_text=True)) assert body['status'] == 'SUSPENDED' assert body['email'] == 'test'
def test_create_user_not_json_dict(rest_client, auth_token): """ ACCOUNT (REST): send a POST with a non dictionary json body""" data = ('account', 'account') response = rest_client.post('/accounts/testaccount', headers=headers(auth(auth_token)), json=data) assert response.status_code == 400 assert response.headers.get('ExceptionClass') == 'TypeError' assert loads(response.get_data(as_text=True)) == {"ExceptionMessage": "body must be a json dictionary", "ExceptionClass": "TypeError"}
def test_update_nonexisting_subscription(rest_client, auth_token): """ SUBSCRIPTION (REST): Test the update of a non-existing subscription """ subscription_name = uuid() data = {'options': {'filter': {'project': ['toto', ]}}} response = rest_client.put('/subscriptions/root/' + subscription_name, headers=headers(auth(auth_token)), json=data) assert response.status_code == 404 assert response.headers.get('ExceptionClass') == 'SubscriptionNotFound'
def test_scope_duplicate(rest_client, auth_token): """ SCOPE (REST): send a POST to create a already existing scope to test the error""" acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201 scopeusr = scope_name_generator() response = rest_client.post('/accounts/%s/scopes/%s' % (acntusr, scopeusr), headers=headers(auth(auth_token))) assert response.status_code == 201 response = rest_client.post('/accounts/%s/scopes/%s' % (acntusr, scopeusr), headers=headers(auth(auth_token))) assert response.status_code == 409
def test_userpass_fail(vo, rest_client): """AUTHENTICATION (REST): Username and password (wrong credentials).""" response = rest_client.get('/auth/userpass', headers=headers( loginhdr('wrong', 'wrong', 'wrong'), vohdr(vo))) assert response.status_code == 401
def check_error_api(params, exception_class, exception_message, code): headers_dict = {'X-Rucio-Type': 'user', 'X-Rucio-Account': 'root'} response = rest_client.get('/requests/list', query_string=params, headers=headers(auth(auth_token), vohdr(vo), hdrdict(headers_dict))) assert response.status_code == code body = parse_response(response.get_data(as_text=True)) assert body['ExceptionClass'] == exception_class assert body['ExceptionMessage'] == exception_message
def get_replicas(): return parse_replicas_from_string( rest_client.get( '/replicas/%s/%s?select=geoip' % (mock_scope.external, protocols_setup['files'][0]['name']), headers=headers(auth(auth_token), vohdr(vo), accept( Mime.JSON_STREAM))).get_data(as_text=True))
def test_userpass_success(vo, rest_client): """AUTHENTICATION (REST): Username and password (correct credentials).""" response = rest_client.get('/auth/userpass', headers=headers( loginhdr('root', 'ddmlab', 'secret'), vohdr(vo))) assert response.status_code == 200 assert len(response.headers.get('X-Rucio-Auth-Token')) > 32
def test_userpass(rest_client, auth_token): """ ACCOUNT (REST): send a POST to add an identity to an account.""" username = uuid() # normal addition headers_dict = {'X-Rucio-Username': username, 'X-Rucio-Password': '******', 'X-Rucio-Email': 'email'} response = rest_client.put('/identities/root/userpass', headers=headers(auth(auth_token), hdrdict(headers_dict))) assert response.status_code == 201
def auth_token(rest_client, vo): from rucio.tests.common import vohdr, headers, loginhdr auth_response = rest_client.get('/auth/userpass', headers=headers(loginhdr('root', 'ddmlab', 'secret'), vohdr(vo))) assert auth_response.status_code == 200 token = auth_response.headers.get('X-Rucio-Auth-Token') assert token return str(token)
def test_scope_failure(rest_client, auth_token): """ SCOPE (REST): send a POST to create a new scope for a not existing account to test the error""" scopeusr = scope_name_generator() account_name_generator() response = rest_client.post('/accounts/%s/scopes/%s' % (scopeusr, scopeusr), headers=headers(auth(auth_token))) assert response.status_code == 404
def test_create_user_success(rest_client, auth_token): """ ACCOUNT (REST): send a POST to create a new user """ acntusr = account_name_generator() data = {'type': 'USER', 'email': '*****@*****.**'} response = rest_client.post('/accounts/' + acntusr, headers=headers(auth(auth_token)), json=data) assert response.status_code == 201
def test_saml_fail(vo, rest_client): """AUTHENTICATION (REST): SAML Username and password (wrong credentials).""" headers_dict = {'X-Rucio-Account': 'root'} userpass = {'username': '******', 'password': '******'} response = rest_client.get('/auth/saml', headers=headers(hdrdict(headers_dict), vohdr(vo))) if not response.headers.get('X-Rucio-Auth-Token'): SAML_auth_url = response.headers.get('X-Rucio-SAML-Auth-URL') response = session().post(SAML_auth_url, data=userpass, verify=False, allow_redirects=True) response = rest_client.get('/auth/saml', headers=headers(hdrdict(headers_dict))) assert response.status_code == 401
def check_correct_api(params, expected_requests): headers_dict = {'X-Rucio-Type': 'user', 'X-Rucio-Account': 'root'} response = rest_client.get('/requests/list', query_string=params, headers=headers(auth(auth_token), vohdr(vo), hdrdict(headers_dict))) assert response.status_code == 200 requests = set() for request in response.get_data(as_text=True).split('\n')[:-1]: request = parse_response(request) requests.add((request['state'], request['source_rse_id'], request['dest_rse_id'], request['name'])) assert requests == expected_requests
def test_create_user_non_json_body(rest_client, auth_token): """ ACCOUNT (REST): send a POST with a non json body""" response = rest_client.post('/accounts/testuser', headers=headers(auth(auth_token)), data="unfug") assert response.status_code == 400 assert response.headers.get('ExceptionClass') == 'ValueError' assert loads(response.get_data(as_text=True)) == { "ExceptionMessage": "cannot decode json parameter dictionary", "ExceptionClass": "ValueError" }
def test_create_user_missing_parameter(rest_client, auth_token): """ ACCOUNT (REST): send a POST with a missing parameter""" response = rest_client.post('/accounts/account', headers=headers(auth(auth_token)), json={}) assert response.status_code == 400 assert response.headers.get('ExceptionClass') == 'KeyError' assert loads(response.get_data(as_text=True)) == { "ExceptionMessage": "\'type\' not defined", "ExceptionClass": "KeyError" }
def test_sort_geoip_address_not_found_error(vo, rest_client, auth_token, protocols_setup, content_type): """Replicas: test sorting via geoip with ignoring geoip errors.""" class MockedGeoIPError(Exception): def __init__(self, *args): super(MockedGeoIPError, self).__init__(*args) def fake_get_geoip_db(*args, **kwargs): raise MockedGeoIPError() data = { 'dids': [{ 'scope': f['scope'].external, 'name': f['name'], 'type': 'FILE' } for f in protocols_setup['files']], 'schemes': schemes, 'sort': 'geoip', } # invalidate cache for __get_distance so that __get_geoip_db is called replica_sorter.REGION.invalidate() with mock.patch('rucio.core.replica_sorter.__get_geoip_db', side_effect=fake_get_geoip_db) as get_geoip_db_mock: response = rest_client.post('/replicas/list', headers=headers(auth(auth_token), vohdr(vo), accept(content_type)), json=data) assert response.status_code == 200 replicas_response = response.get_data(as_text=True) assert replicas_response get_geoip_db_mock.assert_called()
def test_ssh_fail(vo, rest_client): """AUTHENTICATION (REST): SSH RSA public key exchange (wrong credentials).""" root = InternalAccount('root', vo=vo) try: add_account_identity(PUBLIC_KEY, IdentityType.SSH, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip signature = ssh_sign(PRIVATE_KEY, 'sign_something_else') headers_dict = { 'X-Rucio-Account': 'root', 'X-Rucio-SSH-Signature': signature } response = rest_client.get('/auth/ssh', headers=headers(hdrdict(headers_dict), vohdr(vo))) assert response.status_code == 401 del_account_identity(PUBLIC_KEY, IdentityType.SSH, root)