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 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 test_security(): passwd = get_random_password() p_hash = get_password_hash(passwd) assert verify_password(passwd, p_hash)
def set_user_account(username, **kwargs): """ Save the user account information. Variables: username => Name of the user to get the account info 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 } """ try: data = request.json new_pass = data.pop('new_pass', None) old_user = STORAGE.user.get(username, as_obj=False) if not old_user: return make_api_response({"success": False}, "User %s does not exists" % username, 404) if not data['name']: return make_api_response({"success": False}, "Full name of the user cannot be empty", 400) data['apikeys'] = old_user.get('apikeys', []) data['otp_sk'] = old_user.get('otp_sk', None) data['security_tokens'] = old_user.get('security_tokens', {}) or {} 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) data.pop('new_pass_confirm', None) else: data['password'] = old_user.get('password', "__NO_PASSWORD__") or "__NO_PASSWORD__" # Apply dynamic classification data['classification'] = get_dynamic_classification(data['classification'], data['email']) ret_val = save_user_account(username, data, kwargs['user']) if ret_val and \ not old_user['is_active'] \ and data['is_active'] \ and config.ui.tos_lockout \ and config.ui.tos_lockout_notify: try: email = data['email'] or "" for adr in config.ui.tos_lockout_notify: send_activated_email(adr, username, email, kwargs['user']['uname']) if email: send_activated_email(email, username, email, kwargs['user']['uname']) except Exception as e: # We can't send confirmation email, Rollback user change and mark this a failure STORAGE.user.save(username, old_user) LOGGER.error(f"An error occured while sending confirmation emails: {str(e)}") return make_api_response({"success": False}, "The system was unable to send confirmation emails. " "Retry again later...", 404) return make_api_response({"success": ret_val}) except AccessDeniedException as e: return make_api_response({"success": False}, str(e), 403) except InvalidDataException as e: return make_api_response({"success": False}, str(e), 400)
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 signup(**_): """ Signup a new user into the system Variables: None Arguments: None Data Block: { "user": <UID>, "password": <DESIRED_PASSWORD>, "password_confirm": <DESIRED_PASSWORD_CONFIRMATION>, "email": <EMAIL_ADDRESS> } 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 uname = data.get('user', None) password = data.get('password', None) password_confirm = data.get('password_confirm', None) email = data.get('email', None) if not uname or not password or not password_confirm or not email: return make_api_response( {"success": False}, "Not enough information to proceed with user creation", 400) if STORAGE.user.get(uname) or len(uname) < 3: return make_api_response( {"success": False}, "There is already a user registered with this name", 460) else: for c in uname: if not 97 <= ord(c) <= 122 and not ord(c) == 45: return make_api_response( {"success": False}, "Invalid username. [Lowercase letters and dashes " "only with at least 3 letters]", 460) if password_confirm != password: return make_api_response("", "Passwords do not match", 469) password_requirements = config.auth.internal.password_requirements.as_primitives( ) if not check_password_requirements(password, **password_requirements): error_msg = get_password_requirement_message(**password_requirements) return make_api_response({"success": False}, error_msg, 469) if STORAGE.user.search(f"email:{email.lower()}").get('total', 0) != 0: return make_api_response( {"success": False}, "There is already a user registered with this email address", 466) # Normalize email address email = email.lower() email_valid = False for r in config.auth.internal.signup.valid_email_patterns: matcher = re.compile(r) if matcher.findall(email): email_valid = True break if not email_valid: extra = "" if config.ui.email: extra = f". Contact {config.ui.email} for more information." return make_api_response({"success": False}, f"Invalid email address{extra}", 466) password = get_password_hash(password) key = hashlib.sha256( get_random_password(length=512).encode('utf-8')).hexdigest() try: send_signup_email(email, key) get_signup_queue(key).add({ "uname": uname, "password": password, "email": email, "groups": ['USERS'], "name": uname }) except Exception: return make_api_response( {"success": False}, "The system failed to send signup confirmation link.", 400) return make_api_response({"success": True})
def reset_pwd(**_): """ Reset the password for the specified reset ID Variables: None Arguments: None Data Block: { "reset_id": <RESET_HASH>, "password": <PASSWORD TO RESET TO>, "password_confirm": <CONFIRMATION OF PASSWORD TO RESET TO> } 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 reset_id = data.get('reset_id', None) password = data.get('password', None) password_confirm = data.get('password_confirm', None) if reset_id and password and password_confirm: if password != password_confirm: return make_api_response({"success": False}, err="Password mismatch", status_code=469) password_requirements = config.auth.internal.password_requirements.as_primitives( ) if not check_password_requirements(password, **password_requirements): error_msg = get_password_requirement_message( **password_requirements) return make_api_response({"success": False}, error_msg, 469) try: reset_queue = get_reset_queue(reset_id) members = reset_queue.members() reset_queue.delete() if members: email = members[0] res = STORAGE.user.search(f"email:{email}") if res.get('total', 0) == 1: user = STORAGE.user.get(res['items'][0].uname) user.password = get_password_hash(password) STORAGE.user.save(user.uname, user) return make_api_response({"success": True}) except Exception: pass return make_api_response({"success": False}, err="Invalid parameters passed", status_code=400)
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.")