def create_users(ds, log=None): admin_pass = os.getenv("DEV_ADMIN_PASS", 'admin') or 'admin' user_pass = os.getenv("DEV_USER_PASS", 'user') or 'user' user_data = User({ "agrees_with_tos": "NOW", "apikeys": {'devkey': {'acl': ["R", "W"], "password": get_password_hash(admin_pass)}}, "classification": classification.RESTRICTED, "name": "Administrator", "email": "*****@*****.**", "password": get_password_hash(admin_pass), "uname": "admin", "type": ["admin", "user", "signature_importer"]}) ds.user.save('admin', user_data) ds.user_settings.save('admin', UserSettings({"ignore_cache": True, "deep_scan": True})) if log: log.info(f"\tU:{user_data.uname} P:{admin_pass}") user_data = User({ "name": "User", "email": "*****@*****.**", "apikeys": {'devkey': {'acl': ["R", "W"], "password": get_password_hash(user_pass)}}, "password": get_password_hash(user_pass), "uname": "user"}) ds.user.save('user', user_data) ds.user_settings.save('user', UserSettings()) if log: log.info(f"\tU:{user_data.uname} P:{user_pass}") ds.user.commit()
def signup_validate(**_): """ Validate a user's signup request Variables: None Arguments: None Data Block: { "registration_key": "234234...ADFCB" # Key used to validate the user's signup process } Result example: { "success": true } """ if not config.auth.internal.signup.enabled: return make_api_response({"success": False}, "Signup process has been disabled", 403) try: data = request.json except BadRequest: data = request.values registration_key = data.get('registration_key', None) if registration_key: try: signup_queue = get_signup_queue(registration_key) members = signup_queue.members() signup_queue.delete() if members: user_info = members[0] # Add dynamic classification group user_info['classification'] = get_dynamic_classification( user_info.get('classification', Classification.UNRESTRICTED), user_info['email']) user = User(user_info) username = user.uname STORAGE.user.save(username, user) return make_api_response({"success": True}) except (KeyError, ValueError) as e: LOGGER.warning(f"Fail to signup user: {str(e)}") pass else: return make_api_response( {"success": False}, "Not enough information to proceed with user creation", 400) return make_api_response({"success": False}, "Invalid registration key", 400)
def signup_validate(**_): """ Validate a user's signup request Variables: None Arguments: None Data Block: { "registration_key": "234234...ADFCB" # Key used to validate the user's signup process } Result example: { "success": true } """ if not config.auth.internal.signup.enabled: return make_api_response({"success": False}, "Signup process has been disabled", 403) data = request.json if not data: data = request.values registration_key = data.get('registration_key', None) if registration_key: try: signup_queue = get_signup_queue(registration_key) members = signup_queue.members() signup_queue.delete() if members: user_info = members[0] user = User(user_info) username = user.uname STORAGE.user.save(username, user) return make_api_response({"success": True}) except (KeyError, ValueError): pass else: return make_api_response( {"success": False}, "Not enough information to proceed with user creation", 400) return make_api_response({"success": False}, "Invalid registration key", 400)
def ensure_service_account(self): """Check that the update service account exists, if it doesn't, create it.""" uname = 'update_service_account' if self.datastore.user.get_if_exists(uname): return uname user_data = User({ "agrees_with_tos": "NOW", "classification": "RESTRICTED", "name": "Update Account", "password": get_password_hash(''.join(random.choices(string.ascii_letters, k=20))), "uname": uname, "type": ["signature_importer"] }) self.datastore.user.save(uname, user_data) self.datastore.user_settings.save(uname, UserSettings()) return uname
def save_user_account(username, data, user): # Clear non user account data avatar = data.pop('avatar', None) data.pop('2fa_enabled', None) data.pop('security_token_enabled', None) data.pop('has_password', None) data = User(data).as_primitives() if username != data['uname']: raise AccessDeniedException( "You are not allowed to change the username.") if username != user['uname'] and 'admin' not in user['type']: raise AccessDeniedException( "You are not allowed to change another user then yourself.") current = STORAGE.user.get(username, as_obj=False) if current: if 'admin' not in user['type']: for key in current.keys(): if data[key] != current[ key] and key not in ACCOUNT_USER_MODIFIABLE: raise AccessDeniedException( "Only Administrators can change the value of the field [%s]." % key) else: raise InvalidDataException( "You cannot save a user that does not exists [%s]." % username) if avatar is None: STORAGE.user_avatar.delete(username) else: STORAGE.user_avatar.save(username, avatar) return STORAGE.user.save(username, data)
def add_user_account(username, **_): """ Add a user to the system Variables: username => Name of the user to add Arguments: None Data Block: { "name": "Test user", # Name of the user "is_active": true, # Is the user active? "classification": "", # Max classification for user "uname": "usertest", # Username "type": ['user'], # List of all types the user is member of "avatar": null, # Avatar of the user "groups": ["TEST"] # Groups the user is member of } Result example: { "success": true # Saving the user info succeded } """ data = request.json if "{" in username or "}" in username: return make_api_response({"success": False}, "You can't use '{}' in the username", 412) if not STORAGE.user.get(username): new_pass = data.pop('new_pass', None) if new_pass: password_requirements = config.auth.internal.password_requirements.as_primitives() if not check_password_requirements(new_pass, **password_requirements): error_msg = get_password_requirement_message(**password_requirements) return make_api_response({"success": False}, error_msg, 469) data['password'] = get_password_hash(new_pass) else: data['password'] = data.get('password', "__NO_PASSWORD__") or "__NO_PASSWORD__" # Data's username as to match the API call username data['uname'] = username if not data['name']: data['name'] = data['uname'] # Add add dynamic classification group data['classification'] = get_dynamic_classification(data['classification'], data['email']) # Clear non user account data avatar = data.pop('avatar', None) if avatar is not None: STORAGE.user_avatar.save(username, avatar) try: return make_api_response({"success": STORAGE.user.save(username, User(data))}) except ValueError as e: return make_api_response({"success": False}, str(e), 400) else: return make_api_response({"success": False}, "The username you are trying to add already exists.", 400)
def login(): ui4_path = request.cookies.get('ui4_path', None) if ui4_path is not None: resp = redirect( redirect_helper(f"{ui4_path}?{request.query_string.decode()}")) resp.delete_cookie("ui4_path") return resp registration_key = request.args.get('registration_key', None) avatar = None oauth_token = '' oauth_error = '' username = '' oauth_validation = config.auth.oauth.enabled and 'code' in request.args and 'state' in request.args oauth_provider = request.args.get('provider', None) up_login = config.auth.internal.enabled or config.auth.ldap.enabled next_url = angular_safe( request.args.get('next', request.cookies.get('next_url', "/"))) if "login.html" in next_url or "logout.html" in next_url: next_url = "/" if registration_key and config.auth.internal.signup.enabled: try: signup_queue = get_signup_queue(registration_key) members = signup_queue.members() signup_queue.delete() if members: user_info = members[0] user = User(user_info) username = user.uname STORAGE.user.save(username, user) except (KeyError, ValueError): pass if config.auth.oauth.enabled: providers = str([ name for name, p in config.auth.oauth.providers.items() if p['client_id'] and p['client_secret'] ]) if oauth_validation: oauth = current_app.extensions.get( 'authlib.integrations.flask_client') provider = oauth.create_client(oauth_provider) if provider: # noinspection PyBroadException try: # Test oauth access token token = provider.authorize_access_token() oauth_provider_config = config.auth.oauth.providers[ oauth_provider] # Get user data resp = provider.get(oauth_provider_config.user_get) if resp.ok: user_data = resp.json() # Add group data if API is configured for it if oauth_provider_config.user_groups: resp_grp = provider.get( oauth_provider_config.user_groups) if resp_grp.ok: groups = resp_grp.json() if oauth_provider_config.user_groups_data_field: groups = groups[oauth_provider_config. user_groups_data_field] if oauth_provider_config.user_groups_name_field: groups = [ x[oauth_provider_config. user_groups_name_field] for x in groups ] user_data['groups'] = groups data = parse_profile(user_data, oauth_provider_config) has_access = data.pop('access', False) if has_access: oauth_avatar = data.pop('avatar', None) # Find if user already exists users = STORAGE.user.search( f"email:{data['email']}", fl="uname", as_obj=False)['items'] if users: cur_user = STORAGE.user.get( users[0]['uname'], as_obj=False) or {} # Do not update username and password from the current user data['uname'] = cur_user.get( 'uname', data['uname']) data['password'] = cur_user.get( 'password', data['password']) else: if data['uname'] != data['email']: # Username was computed using a regular expression, lets make sure we don't # assign the same username to two users res = STORAGE.user.search( f"uname:{data['uname']}", rows=0, as_obj=False) if res['total'] > 0: cnt = res['total'] new_uname = f"{data['uname']}{cnt}" while STORAGE.user.get( new_uname) is not None: cnt += 1 new_uname = f"{data['uname']}{cnt}" data['uname'] = new_uname cur_user = {} username = data['uname'] # Make sure the user exists in AL and is in sync if (not cur_user and oauth_provider_config.auto_create) or \ (cur_user and oauth_provider_config.auto_sync): # Update the current user cur_user.update(data) # Save avatar if oauth_avatar: avatar = fetch_avatar( oauth_avatar, provider, oauth_provider_config) if avatar: STORAGE.user_avatar.save( username, avatar) # Save updated user STORAGE.user.save(username, cur_user) if cur_user: if avatar is None: avatar = STORAGE.user_avatar.get( username ) or "/static/images/user_default.png" oauth_token = hashlib.sha256( str(token).encode( "utf-8", errors='replace')).hexdigest() get_token_store(username).add(oauth_token) else: oauth_validation = False avatar = None username = '' oauth_error = "User auto-creation is disabled" else: oauth_validation = False oauth_error = "This user is not allowed access to the system" except Exception as _: oauth_validation = False oauth_error = "Invalid oAuth2 token, try again" else: providers = str([]) return custom_render("login.html", next=next_url, avatar=avatar, username=username, oauth_error=oauth_error, oauth_token=oauth_token, providers=providers, signup=config.auth.internal.enabled and config.auth.internal.signup.enabled, oauth_validation=str(oauth_validation).lower(), up_login=str(up_login).lower())
import os from assemblyline.odm.models.user_settings import UserSettings from assemblyline.common.security import get_password_hash from assemblyline.odm.models.user import User from assemblyline.common import forge ADMIN_USER = os.environ.get("AL_ADMIN_USER", "admin") INITIAL_ADMIN_PASSWORD = os.environ.get("AL_ADMIN_PASSWORD", "admin") if __name__ == '__main__': ds = forge.get_datastore() if not ds.user.get_if_exists(ADMIN_USER): user_data = User({ "agrees_with_tos": "NOW", "classification": "RESTRICTED", "name": "Admin user", "password": get_password_hash(INITIAL_ADMIN_PASSWORD), "uname": ADMIN_USER, "type": ["admin", "user", "signature_importer"]}) ds.user.save(ADMIN_USER, user_data) ds.user_settings.save(ADMIN_USER, UserSettings()) print("Initial user setup finished.") else: print(f"User {ADMIN_USER} already found, system is already setup.")