"""Methods for operating against Auth0 environments.""" import json from sync_env import config from sync_env.connectors import logging from sync_env.models import auth0_client logger = logging.get_current_logger() def delete_all_users( auth0_domain, auth0_api_url, auth0_machine_client_id, auth0_machine_client_secret, auth0_connection, skip_user_ids ): """Delete all users in specified target Auth0 environment. Args: auth0_domain: (str) Auth0 domain (whatever.auth0.com). auth0_api_url: (str) Auth0 API url. auth0_machine_client_id: (str) Machine client id. auth0_machine_client_secret: (str) Machine client secret. auth0_connection: (str) Auth0 db connection (art-relations). skip_user_ids: (str) Do not delete these users. """ # get a management token token_response = auth0_client.get_auth0_management_token( auth0_domain, auth0_api_url, auth0_machine_client_id, auth0_machine_client_secret ) if token_response.status != 200: return token_response page = 0 users_response = auth0_client.get_auth0_users_paginated( auth0_domain, token_response.message.get('access_token'), auth0_connection, page, config.USERS_PER_PAGE) if users_response.status != 200: raise Exception('Call to auth0 GET USERS resulted in {}'.format( users_response.status)) users = users_response.message while len(users): for user in users: if user.get('user_id').replace('auth0|', '') not in skip_user_ids: logger.info(msg=json.dumps( {'action': 'delete_auth0_user', 'user': user})) delete_response = auth0_client.delete_auth0_user( auth0_domain, token_response.message.get('access_token'), user.get('user_id')) if delete_response.status != 200: logger.error( msg='Call to auth0 DELETE USER resulted in {}'.format( delete_response.status)) raise Exception( 'Call to auth0 DELETE USER resulted in {}'.format( delete_response.status)) else: logger.info(msg=json.dumps( {'action': 'skip_delete_auth0_user', 'user': user})) page += 1 users_response = auth0_client.get_auth0_users_paginated( auth0_domain, token_response.message.get('access_token'), auth0_connection, page, config.USERS_PER_PAGE) if users_response.status != 200: raise Exception( 'Call to auth0 GET USERS resulted in {}'.format( users_response.status)) users = users_response.message def transform_user(user, auth0_connection): """Transform certain user metadata befor syncing. Params: user: (dict) The user dict to transform. auth0_connection: (string) The connection to add the user to. Returns: dict: The transformed user. """ email = config.SYNC_EMAIL_TEMPLATE.format( user.get('user_id')) user_metadata = user.get('user_metadata', {}) user_metadata['source_email'] = user.get('email') user_metadata['bypass_mfa'] = True new_user = { 'connection': auth0_connection, 'name': email, 'email': email, 'password': config.SYNC_PASSWORD, 'user_metadata': user_metadata, 'email_verified': True, 'verify_email': False, 'app_metadata': user.get('app_metadata', {}) } return new_user def sync_users_across_env( source_auth0_domain, source_auth0_api_url, source_auth0_machine_client_id, source_auth0_machine_client_secret, source_auth0_connection, target_auth0_domain, target_auth0_api_url, target_auth0_machine_client_id, target_auth0_machine_client_secret, target_auth0_connection ): """Sync all users from source to target Auth0 env. Args: source_auth0_domain: (str) Auth0 domain (whatever.auth0.com). source_auth0_api_url: (str) Auth0 API url. source_auth0_machine_client_id: (str) Machine client id. source_auth0_machine_client_secret: (str) Machine client secret. source_auth0_connection: (str) Auth0 db connection (art-relations). target_auth0_domain: (str) Auth0 domain (whatever.auth0.com). target_auth0_api_url: (str) Auth0 API url. target_auth0_machine_client_id: (str) Machine client id. target_auth0_machine_client_secret: (str) Machine client secret. target_auth0_connection: (str) Auth0 db connection (art-relations). """ source_token_response = auth0_client.get_auth0_management_token( source_auth0_domain, source_auth0_api_url, source_auth0_machine_client_id, source_auth0_machine_client_secret ) if source_token_response.status != 200: logger.error( msg='Call to auth0 GET MANAGEMENT TOKEN resulted an error') return source_token_response target_token_response = auth0_client.get_auth0_management_token( target_auth0_domain, target_auth0_api_url, target_auth0_machine_client_id, target_auth0_machine_client_secret ) if target_token_response.status != 200: return target_token_response page = 0 users_response = auth0_client.get_auth0_users_paginated( source_auth0_domain, source_token_response.message.get('access_token'), source_auth0_connection, page, config.USERS_PER_PAGE) if users_response.status != 200: raise Exception('Call to auth0 GET USERS resulted in {}'.format( users_response.status)) users = users_response.message while len(users): for user in users: new_user = transform_user( user, target_auth0_connection) logger.info(msg=json.dumps( {'action': 'create_auth0_user', 'user': new_user})) create_response = auth0_client.create_auth0_user( target_auth0_domain, target_token_response.message.get('access_token'), new_user) if create_response.status != 200: logger.error( msg='Call to auth0 CREATE USER resulted in {}: {}'.format( create_response.status, create_response.errors.get('message'))) print( 'Call to auth0 CREATE USER resulted in {}: {}'.format( create_response.status, create_response.errors.get('message'))) page += 1 users_response = auth0_client.get_auth0_users_paginated( source_auth0_domain, source_token_response.message.get('access_token'), source_auth0_connection, page, config.USERS_PER_PAGE) if users_response.status != 200: raise Exception( 'Call to auth0 GET USERS resulted in {}'.format( users_response.status)) users = users_response.message def sync_specific_users_across_env( source_user_ids, source_auth0_domain, source_auth0_api_url, source_auth0_machine_client_id, source_auth0_machine_client_secret, source_auth0_connection, target_auth0_domain, target_auth0_api_url, target_auth0_machine_client_id, target_auth0_machine_client_secret, target_auth0_connection ): """Sync all users from source to target Auth0 env. Args: source_user_ids: (list) auth0 user ids from source tenant to sync. source_auth0_domain: (str) Auth0 domain (whatever.auth0.com). source_auth0_api_url: (str) Auth0 API url. source_auth0_machine_client_id: (str) Machine client id. source_auth0_machine_client_secret: (str) Machine client secret. source_auth0_connection: (str) Auth0 db connection (art-relations). target_auth0_domain: (str) Auth0 domain (whatever.auth0.com). target_auth0_api_url: (str) Auth0 API url. target_auth0_machine_client_id: (str) Machine client id. target_auth0_machine_client_secret: (str) Machine client secret. target_auth0_connection: (str) Auth0 db connection (art-relations). """ if target_auth0_domain == 'workstation': raise Exception('Do not overwrite production workstation domain users') source_token_response = auth0_client.get_auth0_management_token( source_auth0_domain, source_auth0_api_url, source_auth0_machine_client_id, source_auth0_machine_client_secret ) if source_token_response.status != 200: logger.error( msg='Call to auth0 GET MANAGEMENT TOKEN resulted an error') return source_token_response target_token_response = auth0_client.get_auth0_management_token( target_auth0_domain, target_auth0_api_url, target_auth0_machine_client_id, target_auth0_machine_client_secret ) if target_token_response.status != 200: logger.error( msg='Call to auth0 GET MANAGEMENT TOKEN resulted an error') return target_token_response for user in source_user_ids: auth0_user_id = 'auth0|{}'.format(user.get('id')) # try to locate the user by email in the TARGET tenant email_search_response = auth0_client.search_auth0_users_by_email( target_auth0_domain, target_token_response.message.get('access_token'), config.SYNC_EMAIL_TEMPLATE.format(auth0_user_id)) existing_target_user = None if email_search_response.status == 200: if len(email_search_response.message): existing_target_user = email_search_response.message[0] # if we are forcing a sync, delete the target user if existing_target_user and user.get('force_delete') is True: auth0_client.delete_auth0_user( target_auth0_domain, target_token_response.message.get('access_token'), existing_target_user.get('user_id')) logger.info(msg=json.dumps( {'action': 'force_delete_user', 'user': existing_target_user})) if existing_target_user is None or user.get('force_delete') is True: user_response = auth0_client.get_auth0_user( source_auth0_domain, source_token_response.message.get('access_token'), 'auth0|{}'.format(user.get('id'))) if user_response.status == 200: new_user = transform_user( user_response.message, target_auth0_connection) auth0_client.create_auth0_user( target_auth0_domain, target_token_response.message.get('access_token'), new_user) logger.info(msg=json.dumps( {'action': 'create_user', 'user': new_user})) else: logger.info(msg=json.dumps( {'action': 'skip_user', 'user': user})) return True