def test_ssh_fail(self): """AUTHENTICATION (REST): SSH RSA public key exchange (wrong credentials).""" root = InternalAccount('root', **self.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') options = [] headers = { 'X-Rucio-Account': 'root', 'X-Rucio-SSH-Signature': signature } headers.update(self.vo_header) result = TestApp(APP.wsgifunc(*options)).get('/ssh', headers=headers, expect_errors=True) assert result.status == 401 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 import_identities(identities, account_name, old_identities, old_identity_account, account_email, session=None): for identity in identities: identity['type'] = IdentityType[identity['type'].upper()] missing_identities = [identity for identity in identities if (identity['identity'], identity['type']) not in old_identities] missing_identity_account = [identity for identity in identities if (identity['identity'], identity['type'], account_name) not in old_identity_account] to_be_removed_identity_account = [old_identity for old_identity in old_identity_account if (old_identity[0], old_identity[1], old_identity[2]) not in [(identity['identity'], identity['type'], account_name) for identity in identities] and old_identity[2] == account_name] # add missing identities for identity in missing_identities: identity_type = identity['type'] password = identity.get('password') identity = identity['identity'] if identity_type == IdentityType.USERPASS: identity_module.add_identity(identity=identity, password=password, email=account_email, type_=identity_type, session=session) elif identity_type == IdentityType.GSS or identity_type == IdentityType.SSH or identity_type == IdentityType.X509: identity_module.add_identity(identity=identity, email=account_email, type_=identity_type, session=session) # add missing identity-account association for identity in missing_identity_account: identity_module.add_account_identity(identity['identity'], identity['type'], account_name, email=account_email, session=session) # remove identities from account-identity association for identity in to_be_removed_identity_account: identity_module.del_account_identity(identity=identity[0], type_=identity[1], account=identity[2], session=session)
def test_ssh_success(self): """AUTHENTICATION (REST): SSH RSA public key exchange (correct credentials).""" try: add_account_identity(PUBLIC_KEY, IdentityType.SSH, 'root', email='*****@*****.**') except Duplicate: pass # might already exist, can skip options = [] headers = {'X-Rucio-Account': 'root'} result = TestApp(APP.wsgifunc(*options)).get('/ssh_challenge_token', headers=headers, expect_errors=True) assert_equal(result.status, 200) assert_in('challenge-', result.header('X-Rucio-SSH-Challenge-Token')) signature = ssh_sign(PRIVATE_KEY, result.header('X-Rucio-SSH-Challenge-Token')) headers = { 'X-Rucio-Account': 'root', 'X-Rucio-SSH-Signature': signature } result = TestApp(APP.wsgifunc(*options)).get('/ssh', headers=headers, expect_errors=True) assert_equal(result.status, 200) assert_greater(len(result.header('X-Rucio-Auth-Token')), 32) del_account_identity(PUBLIC_KEY, IdentityType.SSH, 'root')
def test_invalid_padding(self): """AUTHENTICATION (CORE): SSH RSA public key exchange (public key with invalid padding).""" root = InternalAccount('root', **self.vo) try: add_account_identity(INVALID_PADDED_PUBLIC_KEY, IdentityType.SSH, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip challenge_token = get_ssh_challenge_token(account='root', appid='test', ip='127.0.0.1', **self.vo).get('token') ssh_sign_string = ssh_sign(PRIVATE_KEY, challenge_token) signature = base64.b64decode(ssh_sign_string) result = get_auth_token_ssh(account='root', signature=signature, appid='test', ip='127.0.0.1', **self.vo) assert result is not None del_account_identity(INVALID_PADDED_PUBLIC_KEY, IdentityType.SSH, root)
def test_get_auth_token_ssh_success(self): """AUTHENTICATION (CORE): SSH RSA public key exchange (good signature).""" try: add_account_identity(PUBLIC_KEY, IdentityType.SSH, 'root', email='*****@*****.**') except Duplicate: pass # might already exist, can skip challenge_token = get_ssh_challenge_token(account='root', appid='test', ip='127.0.0.1').token signature = base64.b64decode(ssh_sign(PRIVATE_KEY, challenge_token)) result = get_auth_token_ssh(account='root', signature=signature, appid='test', ip='127.0.0.1') assert_is_not_none(result) del_account_identity(PUBLIC_KEY, IdentityType.SSH, 'root')
def sync_oidc(self, iam_users): for user in iam_users: username = user['userName'] email = user['emails'][0]['value'] user_subject = user['id'] if not user['active']: logging.debug( 'Skipped OIDC identity for User {} [not active]'.format( username)) continue # Rucio DB schema restriction if len(username) > 25: logging.debug( 'Skipped OIDC identity for User {} [len(username) > 25]'. format(username)) continue try: internal_account = InternalAccount(username) user_identity = "SUB={}, ISS={}".format( user_subject, self.iam_server) if not identity.exist_identity_account( user_identity, IdentityType.OIDC, internal_account): identity.add_account_identity(user_identity, IdentityType.OIDC, internal_account, email) logging.debug( 'Added OIDC identity for User {}'.format(username)) except Exception as e: logging.debug(e)
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(self): """ ACCOUNT (REST): send a DELETE to remove an identity of an account.""" mw = [] account = account_name_generator() identity = uuid() password = '******' add_account(account, 'USER', '*****@*****.**', 'root', **self.vo) add_identity(identity, IdentityType.USERPASS, '*****@*****.**', password) add_account_identity(identity, IdentityType.USERPASS, InternalAccount(account, **self.vo), '*****@*****.**') headers1 = {'X-Rucio-Account': account, 'X-Rucio-Username': identity, 'X-Rucio-Password': password} headers1.update(self.vo_header) res1 = TestApp(auth_app.wsgifunc(*mw)).get('/userpass', headers=headers1, expect_errors=True) token = str(res1.header('X-Rucio-Auth-Token')) # normal deletion headers2 = {'X-Rucio-Auth-Token': str(token)} data = dumps({'authtype': 'USERPASS', 'identity': identity}) res2 = TestApp(account_app.wsgifunc(*mw)).delete('/' + account + '/identities', headers=headers2, params=data, expect_errors=True) assert_equal(res2.status, 200) # unauthorized deletion other_account = account_name_generator() headers2 = {'X-Rucio-Auth-Token': str(token)} data = dumps({'authtype': 'USERPASS', 'identity': identity}) res2 = TestApp(account_app.wsgifunc(*mw)).delete('/' + other_account + '/identities', headers=headers2, params=data, expect_errors=True) assert_equal(res2.status, 401)
def test_list_account_identities(self): """ ACCOUNT (CORE): Test listing of account identities """ email = 'email' identity = uuid() identity_type = IdentityType.USERPASS account = InternalAccount('root', **self.vo) add_account_identity(identity, identity_type, account, email, password='******') identities = list_identities(account) assert {'type': identity_type, 'identity': identity, 'email': email} in identities
def test_ssh(self): """ IDENTITY (CORE): Test adding and removing SSH public key authentication """ add_identity(self.account.external, IdentityType.SSH, email='*****@*****.**') add_account_identity('my_public_key', IdentityType.SSH, self.account, email='*****@*****.**') list_identities() del_account_identity('my_public_key', IdentityType.SSH, self.account) del_identity(self.account.external, IdentityType.SSH)
def test_get_auth_token_saml_fail(self): """AUTHENTICATION (CORE): SAML NameID (wrong credentials).""" root = InternalAccount('root', **self.vo) try: add_account_identity('ddmlab', IdentityType.SAML, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip with assert_raises(AccessDenied): get_auth_token_saml(account='root', saml_nameid='not_ddmlab', appid='test', ip='127.0.0.1', **self.vo) del_account_identity('ddmlab', IdentityType.SAML, root)
def add_vo(vo, description, email, session=None): """ Add a VO and setup a new root user. New root user will have account name 'root' and a userpass identity with username: '******' and password: '******' :param vo: 3-letter unique tag for a VO. :param descrition: Descriptive string for the VO (e.g. Full name). :param email: Contact email for the VO. :param session: The db session in use. """ if not config_get_bool( 'common', 'multi_vo', raise_exception=False, default=False): raise exception.UnsupportedOperation( 'VO operations cannot be performed in single VO mode.') if len(vo) != 3: raise exception.RucioException('Invalid VO tag, must be 3 chars.') new_vo = models.VO(vo=vo, description=description, email=email) try: new_vo.save(session=session) except IntegrityError: raise exception.Duplicate('VO {} already exists!'.format(vo)) except DatabaseError as error: raise exception.RucioException(error.args) from rucio.core.account import add_account, list_identities from rucio.core.identity import add_account_identity new_root = InternalAccount('root', vo=vo) add_account(account=new_root, type_=AccountType['SERVICE'], email=email, session=session) add_account_identity(identity='root@{}'.format(vo), type_=IdentityType['USERPASS'], account=new_root, email=email, default=False, password='******', session=session) for ident in list_identities(account=InternalAccount('super_root', vo='def'), session=session): add_account_identity(identity=ident['identity'], type_=ident['type'], account=new_root, email='', session=session)
def test_get_auth_token_ssh_fail(self): """AUTHENTICATION (CORE): SSH RSA public key exchange (wrong signature).""" root = InternalAccount('root', **self.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') result = get_auth_token_ssh(account='root', signature=signature, appid='test', ip='127.0.0.1', **self.vo) assert_is_none(result) del_account_identity(PUBLIC_KEY, IdentityType.SSH, root)
def add_account_identity(identity_key, id_type, account, email, issuer, default=False, password=None, vo='def'): """ Adds a membership association between identity and account. :param identity_key: The identity key name. For example x509 DN, or a username. :param id_type: The type of the authentication (x509, gss, userpass, ssh, saml). :param account: The account name. :param email: The Email address associated with the identity. :param issuer: The issuer account. :param default: If True, the account should be used by default with the provided identity. :param password: Password if id_type is userpass. :param vo: the VO to act on. """ kwargs = {'identity': identity_key, 'type': id_type, 'account': account} if not permission.has_permission( issuer=issuer, vo=vo, action='add_account_identity', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not add account identity' % (issuer)) account = InternalAccount(account, vo=vo) return identity.add_account_identity(identity=identity_key, type=IdentityType.from_sym(id_type), default=default, email=email, account=account, password=password)
def recover_vo_root_identity(root_vo, identity_key, id_type, email, issuer, default=False, password=None, vo='def'): """ Adds a membership association between identity and the root account for given VO. :param root_vo: The VO whose root needs recovery :param identity_key: The identity key name. For example x509 DN, or a username. :param id_type: The type of the authentication (x509, gss, userpass, ssh, saml). :param email: The Email address associated with the identity. :param issuer: The issuer account. :param default: If True, the account should be used by default with the provided identity. :param password: Password if id_type is userpass. :param vo: the VO to act on. """ kwargs = {} if not has_permission( issuer=issuer, vo=vo, action='recover_vo_root_identity', kwargs=kwargs): raise exception.AccessDenied( 'Account %s can not recover root identity' % (issuer)) account = InternalAccount('root', vo=root_vo) return identity.add_account_identity(identity=identity_key, type=IdentityType[id_type.upper()], default=default, email=email, account=account, password=password)
def test_get_auth_token_saml_success(self): """AUTHENTICATION (CORE): SAML NameID (correct credentials).""" root = InternalAccount('root', **self.vo) try: add_account_identity('ddmlab', IdentityType.SAML, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip try: result = get_auth_token_saml(account='root', saml_nameid='ddmlab', appid='test', ip='127.0.0.1', **self.vo) assert_is_not_none(result) except: # FIXME: The WebUI isn't linked to CERN SSO yet so this needs to be fixed once it is linked pass del_account_identity('ddmlab', IdentityType.SAML, root)
def add_vo(vo, description, password, email, session=None): """ Add a VO and setup a new root user. New root user will have account name 'root' and a userpass identity with username: '******' and password from the rootpass parameter :param vo: 3-letter unique tag for a VO. :param descrition: Descriptive string for the VO (e.g. Full name). :param email: Contact email for the VO. :param password: The password to set for the root user of the new VO :param session: The db session in use. """ if len(vo) != 3: raise exception.RucioException('Invalid VO tag, must be 3 chars.') new_vo = models.VO(vo=vo, description=description, email=email) try: new_vo.save(session=session) except IntegrityError: raise exception.Duplicate('VO {} already exists!'.format(vo)) except DatabaseError as error: raise exception.RucioException(error.args) from rucio.core.account import add_account, list_identities from rucio.core.identity import add_account_identity new_root = InternalAccount('root', vo=vo) add_account(account=new_root, type=AccountType.from_sym('SERVICE'), email=email, session=session) add_account_identity(identity='root@{}'.format(vo), type=IdentityType.from_sym('userpass'), account=new_root, email=email, default=False, password=password, session=session) for ident in list_identities(account=InternalAccount('super_root', vo='def'), session=session): add_account_identity(identity=ident['identity'], type=ident['type'], account=new_root, email='', session=session)
def test_get_auth_token_saml_success(self): """AUTHENTICATION (CORE): SAML NameID (correct credentials).""" root = InternalAccount('root', **self.vo) try: add_account_identity('ddmlab', IdentityType.SAML, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip result = get_auth_token_saml(account='root', saml_nameid='ddmlab', appid='test', ip='127.0.0.1', **self.vo) assert result is not None del_account_identity('ddmlab', IdentityType.SAML, root)
def sync_x509(self, iam_users): for user in iam_users: username = user['userName'] email = user['emails'][0]['value'] if not user['active']: logging.debug( 'Skipped X509 identity for User {} [not active]'.format( username)) continue # Rucio DB schema restriction if len(username) > 25: logging.debug( 'Skipped X509 identity for User {} [len(username) > 25]'. format(username)) continue if 'urn:indigo-dc:scim:schemas:IndigoUser' in user: indigo_user = user['urn:indigo-dc:scim:schemas:IndigoUser'] if 'certificates' in indigo_user: for certificate in indigo_user['certificates']: if 'subjectDn' in certificate: subjectDn = self.make_gridmap_compatible( certificate['subjectDn']) try: internal_account = InternalAccount(username) if not identity.exist_identity_account( subjectDn, IdentityType.X509, internal_account): identity.add_account_identity( subjectDn, IdentityType.X509, internal_account, email) logging.debug( 'Added X509 identity for User {}'. format(username)) except Exception as e: logging.debug(e)
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)
def test_ssh_success(self): """AUTHENTICATION (REST): SSH RSA public key exchange (correct credentials).""" root = InternalAccount('root', **self.vo) try: add_account_identity(PUBLIC_KEY, IdentityType.SSH, root, email='*****@*****.**') except Duplicate: pass # might already exist, can skip options = [] headers = {'X-Rucio-Account': 'root'} headers.update(self.vo_header) result = TestApp(APP.wsgifunc(*options)).get('/ssh_challenge_token', headers=headers, expect_errors=True) assert result.status == 200 assert 'challenge-' in result.header('X-Rucio-SSH-Challenge-Token') signature = ssh_sign(PRIVATE_KEY, result.header('X-Rucio-SSH-Challenge-Token')) headers = { 'X-Rucio-Account': 'root', 'X-Rucio-SSH-Signature': signature } headers.update(self.vo_header) result = TestApp(APP.wsgifunc(*options)).get('/ssh', headers=headers, expect_errors=True) assert result.status == 200 assert len(result.header('X-Rucio-Auth-Token')) > 32 del_account_identity(PUBLIC_KEY, IdentityType.SSH, root)
def add_account_identity(identity_key, type, account, email, issuer, default=False): """ Adds a membership association between identity and account. :param identity_key: The identity key name. For example x509 DN, or a username. :param type: The type of the authentication (x509, gss, userpass). :param account: The account name. :param email: The Email address associated with the identity. :param issuer: The issuer account. :param default: If True, the account should be used by default with the provided identity. """ kwargs = {'identity': identity_key, 'type': type, 'account': account} if not permission.has_permission(issuer=issuer, action='add_account_identity', kwargs=kwargs): raise exception.AccessDenied('Account %s can not add account identity' % (issuer)) return identity.add_account_identity(identity=identity_key, type=IdentityType.from_sym(type), default=default, email=email, account=account)
def test_userpass(self): """ IDENTITY (CORE): Test adding and removing username/password authentication """ add_identity(self.account.external, IdentityType.USERPASS, email='*****@*****.**', password='******') add_account_identity('ddmlab_%s' % self.account, IdentityType.USERPASS, self.account, email='*****@*****.**', password='******') add_identity('/ch/cern/rucio/ddmlab_%s' % self.account, IdentityType.X509, email='*****@*****.**') add_account_identity('/ch/cern/rucio/ddmlab_%s' % self.account, IdentityType.X509, self.account, email='*****@*****.**') add_identity('ddmlab_%s' % self.account, IdentityType.GSS, email='*****@*****.**') add_account_identity('ddmlab_%s' % self.account, IdentityType.GSS, self.account, email='*****@*****.**') list_identities() del_account_identity('ddmlab_%s' % self.account, IdentityType.USERPASS, self.account) del_account_identity('/ch/cern/rucio/ddmlab_%s' % self.account, IdentityType.X509, self.account) del_account_identity('ddmlab_%s' % self.account, IdentityType.GSS, self.account) del_identity('ddmlab_%s' % self.account, IdentityType.USERPASS)
def test_userpass(self): """ IDENTITY (CORE): Test adding and removing username/password authentication """ add_identity(self.account, IdentityType.USERPASS, email="*****@*****.**", password="******") add_account_identity( "ddmlab_%s" % self.account, IdentityType.USERPASS, self.account, email="*****@*****.**" ) add_identity("/ch/cern/rucio/ddmlab_%s" % self.account, IdentityType.X509, email="*****@*****.**") add_account_identity( "/ch/cern/rucio/ddmlab_%s" % self.account, IdentityType.X509, self.account, email="*****@*****.**" ) add_identity("ddmlab_%s" % self.account, IdentityType.GSS, email="*****@*****.**") add_account_identity("ddmlab_%s" % self.account, IdentityType.GSS, self.account, email="*****@*****.**") list_identities() del_account_identity("ddmlab_%s" % self.account, IdentityType.USERPASS, self.account) del_account_identity("/ch/cern/rucio/ddmlab_%s" % self.account, IdentityType.X509, self.account) del_account_identity("ddmlab_%s" % self.account, IdentityType.GSS, self.account) del_identity("ddmlab_%s" % self.account, IdentityType.USERPASS)
def setup(self): # New RSE self.new_rse = rse_name_generator() # RSE 1 that already exists self.old_rse_1 = rse_name_generator() self.old_rse_id_1 = add_rse(self.old_rse_1, availability=1, region_code='DE', country_name='DE', deterministic=True, volatile=True, staging_area=True, time_zone='Europe', latitude='1', longitude='2') add_protocol( self.old_rse_id_1, { 'scheme': 'scheme1', 'hostname': 'hostname1', 'port': 1000, 'impl': 'TODO' }) add_protocol( self.old_rse_id_1, { 'scheme': 'scheme3', 'hostname': 'hostname3', 'port': 1000, 'impl': 'TODO' }) set_rse_limits(rse_id=self.old_rse_id_1, name='MaxBeingDeletedFiles', value='10') set_rse_limits(rse_id=self.old_rse_id_1, name='MinFreeSpace', value='10') add_rse_attribute(rse_id=self.old_rse_id_1, key='attr1', value='test10') add_rse_attribute(rse_id=self.old_rse_id_1, key='lfn2pfn_algorithm', value='test10') add_rse_attribute(rse_id=self.old_rse_id_1, key='verify_checksum', value=True) # RSE 2 that already exists self.old_rse_2 = rse_name_generator() self.old_rse_id_2 = add_rse(self.old_rse_2) # RSE 3 that already exists self.old_rse_3 = rse_name_generator() self.old_rse_id_3 = add_rse(self.old_rse_3) # RSE 4 that already exists self.old_rse_4 = rse_name_generator() self.old_rse_id_4 = add_rse(self.old_rse_4) # RSE 4 that already exists self.old_rse_4 = rse_name_generator() add_rse(self.old_rse_4) self.old_rse_id_4 = get_rse_id(self.old_rse_4) # Distance that already exists add_distance(self.old_rse_id_1, self.old_rse_id_2) # Account 1 that already exists self.old_account_1 = InternalAccount(rse_name_generator()) add_account(self.old_account_1, AccountType.USER, email='test') # Account 2 that already exists self.old_account_2 = InternalAccount(rse_name_generator()) add_account(self.old_account_2, AccountType.USER, email='test') # Identity that should be removed self.identity_to_be_removed = rse_name_generator() add_identity(self.identity_to_be_removed, IdentityType.X509, email='email') add_account_identity(self.identity_to_be_removed, IdentityType.X509, self.old_account_2, 'email') # Identity that already exsits but should be added to the account self.identity_to_be_added_to_account = rse_name_generator() add_identity(self.identity_to_be_added_to_account, IdentityType.X509, email='email') self.data1 = { 'rses': { self.new_rse: { 'rse_type': RSEType.TAPE, 'availability': 3, 'city': 'NewCity', 'region_code': 'CH', 'country_name': 'switzerland', 'staging_area': False, 'time_zone': 'Europe', 'latitude': 1, 'longitude': 2, 'deterministic': True, 'volatile': False, 'protocols': [{ 'scheme': 'scheme', 'hostname': 'hostname', 'port': 1000, 'impl': 'impl' }], 'attributes': { 'attr1': 'test' }, 'MinFreeSpace': 20000, 'lfn2pfn_algorithm': 'hash2', 'verify_checksum': False, 'availability_delete': True, 'availability_read': False, 'availability_write': True }, self.old_rse_1: { 'rse_type': RSEType.TAPE, 'deterministic': False, 'volatile': False, 'region_code': 'US', 'country_name': 'US', 'staging_area': False, 'time_zone': 'Asia', 'longitude': 5, 'city': 'City', 'availability': 2, 'latitude': 10, 'protocols': [{ 'scheme': 'scheme1', 'hostname': 'hostname1', 'port': 1000, 'prefix': 'prefix', 'impl': 'impl1' }, { 'scheme': 'scheme2', 'hostname': 'hostname2', 'port': 1001, 'impl': 'impl' }], 'attributes': { 'attr1': 'test1', 'attr2': 'test2' }, 'MinFreeSpace': 10000, 'MaxBeingDeletedFiles': 1000, 'verify_checksum': False, 'lfn2pfn_algorithm': 'hash3', 'availability_delete': False, 'availability_read': False, 'availability_write': True }, self.old_rse_2: {}, self.old_rse_3: {} }, 'distances': { self.old_rse_1: { self.old_rse_2: { 'src_rse': self.old_rse_1, 'dest_rse': self.old_rse_2, 'ranking': 10 }, self.old_rse_3: { 'src_rse': self.old_rse_1, 'dest_rse': self.old_rse_3, 'ranking': 4 } } }, 'accounts': [{ 'account': InternalAccount('new_account'), 'email': 'email', 'identities': [{ 'type': 'userpass', 'identity': 'username', 'password': '******' }] }, { 'account': InternalAccount('new_account2'), 'email': 'email' }, { 'account': self.old_account_2, 'email': 'new_email', 'identities': [{ 'identity': self.identity_to_be_added_to_account, 'type': 'x509' }, { 'type': 'userpass', 'identity': 'username2', 'password': '******' }] }, { 'account': InternalAccount('jdoe'), 'email': 'email' }] } self.data2 = {'rses': {self.new_rse: {'rse': self.new_rse}}} self.data3 = {'distances': {}}