def client(datastore): user = datastore.user.get('admin') random_pass = get_random_password(length=48) key_name = "key_%s" % get_random_id().lower() user.apikeys[key_name] = { "password": bcrypt.hash(random_pass), "acl": ["R", "W"] } datastore.user.save('admin', user) api_key = "%s:%s" % (key_name, random_pass) c = get_client(UI_HOST, apikey=('admin', api_key), verify=False) return c
def get_reset_link(**_): """ Send a reset link via email to the email address specified Variables: None Arguments: None Data Block: { "email": <EMAIL ADDRESS TO RESET PASSWORD> } 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 email = data.get('email', None) if email and STORAGE.user.search(f"email:{email.lower()}").get('total', 0) == 1: key = hashlib.sha256( get_random_password(length=512).encode('utf-8')).hexdigest() # noinspection PyBroadException try: send_reset_email(email, key) get_reset_queue(key).add(email) return make_api_response({"success": True}) except Exception: make_api_response( {"success": False}, "The system failed to send the password reset link.", 400) return make_api_response( {"success": False}, "We have no record of this email address in our system.", 400)
def temporary_api_key(ds: AssemblylineDatastore, user_name: str, permissions=('R', 'W')): """Creates a context where a temporary API key is available.""" with Lock(f'user-{user_name}', timeout=10): name = ''.join(random.choices(string.ascii_lowercase, k=20)) random_pass = get_random_password(length=48) user = ds.user.get(user_name) user.apikeys[name] = { "password": bcrypt.hash(random_pass), "acl": permissions } ds.user.save(user_name, user) try: yield f"{name}:{random_pass}" finally: with Lock(f'user-{user_name}', timeout=10): user = ds.user.get(user_name) user.apikeys.pop(name) ds.user.save(user_name, user)
def add_apikey(name, priv, **kwargs): """ Add an API Key for the currently logged in user with given privileges Variables: name => Name of the API key priv => Requested privileges Arguments: None Data Block: None Result example: {"apikey": <ramdomly_generated_password>} """ user = kwargs['user'] user_data = STORAGE.user.get(user['uname']) if name in user_data.apikeys: return make_api_response("", err=f"APIKey '{name}' already exist", status_code=400) if priv not in API_PRIV_MAP: return make_api_response( "", err= f"Invalid APIKey privilege '{priv}'. Choose between: {API_PRIV_MAP.keys()}", status_code=400) random_pass = get_random_password(length=48) user_data.apikeys[name] = { "password": bcrypt.encrypt(random_pass), "acl": API_PRIV_MAP[priv] } STORAGE.user.save(user['uname'], user_data) return make_api_response({"apikey": f"{name}:{random_pass}"})
def test_security(): passwd = get_random_password() p_hash = get_password_hash(passwd) assert verify_password(passwd, p_hash)
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})