def manage_other_instance(): """ This server will try to login to other 'Universal Login' server and act as its manager. If failed, nothing will happen but it shall return an error message. If success, this server will change its state as a manager. This instance will now act as a manager for the target. :return: """ # Gets manager token that is to be saved in the 'Client manager' res = requests.post('%s/api/v1/admin/login' % request.values.get('url'), data={"password": request.values.get('key')}) if res.status_code != 200: return Response(json.dumps({ "type": "error", "msg": "Login to other instance did not succeed." }), mimetype='application/json'), 403 # Locks /init route config('UL_LOCK_INIT', 'true') # Saves jws token returned by the server config('UL_INSTANCE_TOKEN', res.json().get('jws')) return Response(json.dumps({ "type": "success", "msg": "Login to other instance succeeds. Please redirect to /manage", "redirect": res.json().get('redirect') }), mimetype='application/json'), 200
def conn(): if Mongo.__conn__ is None: conn = mongo_client(host=config('UL_DB_HOST')) conn[config('UL_DB_NAME')].authenticate( name=config('UL_DB_USER'), password=config('UL_DB_PASS')) Mongo.__conn__ = conn return Mongo.__conn__
def post(): user = db()['users'].find_one( {"username": request.values.get('username').lower()}) if user is not None: valid_username = request.values.get( 'username').lower() == user['username'].lower() valid_password = bcrypt.hashpw( request.values.get('password').encode('utf-8'), user['password']) == user['password'] if valid_username and valid_password: token = jwt.JWT(header={'alg': 'HS256'}, claims={ 'usr': user['username'], 'iat': int(time.time()), 'exp': int(time.time() + 900) }) token.make_signed_token( jwk.JWK(**json.loads(config('UL_KEY')))) return Response(json.dumps({ "type": "success", "msg": "Login success.", "jws": token.serialize() }), mimetype='application/json'), 200 return Response(json.dumps({"msg": "Invalid username and/or password"}), mimetype='application/json'), 403
def generate_new_token(): """ Generates admin token needed for other 'Universal Login' instance to authenticate themselves :return: """ token = random_str(32) config( 'UL_ADMIN_PASSWORD', str( bcrypt.hashpw(token.encode('utf-8'), bcrypt.gensalt()).decode())) return Response( json.dumps({ "type": "success", "msg": "Token has been generated successfully. Please do not lose this token, as we only store the hash " "in the server.", "token": token })), 200
def admin_login(): """ Checks if password submitted by client is correct. If it is, the server will return a signed JWT claim that proves the admin that it is an admin in this server. Login is only one time. Once someone claimed that they are the admin, this method shall be rendered useless. :return: """ req_pass = request.values.get('password').encode('utf-8') adm_pass = config('UL_ADMIN_PASSWORD').encode('utf-8') admin_is_logged_in = config('UL_ADMIN_LOGGED_IN') is not None password_is_invalid = bcrypt.checkpw(req_pass, adm_pass) is False # Checks if someone already logged in to the server, or checks invalidity of password if admin_is_logged_in or password_is_invalid: return Response(json.dumps({ "type": "error", "msg": "Request forbidden." }), mimetype='application/json'), 403 # Locks the admin_login() config('UL_ADMIN_LOGGED_IN', 'true') # Generates JWK config('UL_ADMIN_KEY', jwk.JWK.generate(kty='oct', size=256).export()) # Claim token = jwt.JWT(header={'alg': 'HS256'}, claims={'administrator': True}) # Signs the JWT using the newly generated key token.make_signed_token(jwk.JWK(**json.loads(config('UL_ADMIN_KEY')))) # Returns successful response, and the jws token. return Response(json.dumps({ "type": "success", "msg": "Login succeed.", "jws": token.serialize(), "redirect": "/manage" }), mimetype='application/json'), 200
def setup_get_environment(): if config('UL_ENV_SHOWN') == 'true': return Response(json.dumps({ "type": "error", "msg": "You are not authorized to view this page." }), mimetype='application/json'), 403 # Mark UL_ENV_SHOWN so that server won't be allowed to show the info again. config('UL_ENV_SHOWN', 'true') return Response(json.dumps({ "type": "success", "msg": "Environment variable retrieval succeed. Please look at env variable.", "env": { "UL_KEY": config('UL_KEY'), "UL_DB_HOST": config('UL_DB_HOST'), "UL_DB_ROOT_USER": config('UL_DB_ROOT_USER'), "UL_DB_ROOT_PASS": config('UL_DB_ROOT_PASS'), "UL_DB_NAME_PREFIX": config('UL_DB_NAME_PREFIX'), "UL_DB_USER": config('UL_DB_USER'), "UL_DB_PASS": config('UL_DB_PASS'), "UL_DB_NAME": config('UL_DB_NAME'), "UL_TP_CHECK": config('UL_TP_CHECK'), "UL_TP_URL": config('UL_TP_URL'), "UL_TP_REQUEST_FORMAT": config('UL_TP_REQUEST_FORMAT') } }), mimetype='application/json'), 200
def set_environment(): """ Deprecated :return: """ # Check all essential environment variable if essential_env_present(): # Redirects to /login page return redirect('/login') essential_env = { "UL_DB_HOST": request.values.get('UL_DB_HOST'), "UL_DB_ROOT_USER": request.values.get('UL_DB_ROOT_USER'), "UL_DB_ROOT_PASS": request.values.get('UL_DB_ROOT_PASS'), "UL_DB_NAME_PREFIX": request.values.get('UL_DB_NAME_PREFIX'), "UL_TP_CHECK": request.values.get('UL_TP_CHECK'), "UL_TP_URL": request.values.get('UL_TP_URL'), "UL_TP_REQUEST_FORMAT": request.values.get('UL_TP_REQUEST_FORMAT') } # Sets essential env setting for key in essential_env: if essential_env[key] is None: config(key, '') else: config(key, essential_env[key]) # Create a client instance (mongodb) client = mongo_client(host=config('UL_DB_HOST'), username=config('UL_DB_ROOT_USER'), password=config('UL_DB_ROOT_PASS')) # Assigns database name from prefix config('UL_DB_NAME', config('UL_DB_NAME_PREFIX') + 'ul_db') # Creates an initial user: admin:admin # Note that this will have issue if we have third party authentication server. # I will make a separate setup for this, but for now, the implementation would be # just this simple. I will not handle third party auth for now... client[config('UL_DB_NAME')].users.insert_one({ "username": "******", "password": bcrypt.hashpw(b'admin', bcrypt.gensalt()) }) # Assign a random username and password for universal login user account config('UL_DB_USER', 'ul_user_' + random_str(5)) config('UL_DB_PASS', random_str(16)) # Creates a user dedicated for universal login only client[config('UL_DB_NAME')].command("createUser", config('UL_DB_USER'), pwd=config('UL_DB_PASS'), roles=["readWrite"]) # Generate a symmetric key # Note: I wish to use asymmetric key, but I have issues with EC or RSA. # Errors: TypeError: object of type '_RSAPrivateKey' has no len() or # TypeError: object of type '_EllipticCurvePrivateKey' has no len() config('UL_KEY', jwk.JWK.generate(kty='oct', size=256).export()) # Set environment from submitted form with open('/html/setup-done.html', 'r') as html_file: # index.html file html = html_file.read() # Check all essential environment variable if essential_env_present(): # Perform re-setup. return Response(html), 200 # Perform URL redirection return redirect('/')
def set_environment_new(): # Check all essential environment variable if essential_env_present(): # Returns an access denied response return Response(json.dumps({ "type": "error", "msg": "Access is denied." }), mimetype='application/json'), 403 essential_env = { "UL_DB_HOST": request.values.get('UL_DB_HOST'), "UL_DB_ROOT_USER": request.values.get('UL_DB_ROOT_USER'), "UL_DB_ROOT_PASS": request.values.get('UL_DB_ROOT_PASS'), "UL_DB_NAME_PREFIX": request.values.get('UL_DB_NAME_PREFIX'), "UL_TP_CHECK": request.values.get('UL_TP_CHECK'), "UL_TP_URL": request.values.get('UL_TP_URL'), "UL_TP_REQUEST_FORMAT": request.values.get('UL_TP_REQUEST_FORMAT') } # Perform validation status = MongoSetupController.validate() if status.get('type') == 'error': return Response(json.dumps(status), mimetype='application/json'), 403 # Sets essential env setting for key in essential_env: if essential_env[key] is None: config(key, '') else: config(key, essential_env[key]) # Create a client instance (mongodb) client = mongo_client(host=config('UL_DB_HOST'), username=config('UL_DB_ROOT_USER'), password=config('UL_DB_ROOT_PASS')) # Assigns database name from prefix config('UL_DB_NAME', config('UL_DB_NAME_PREFIX') + 'ul_db') # Creates an initial user: admin:admin # Note that this will have issue if we have third party authentication server. # I will make a separate setup for this, but for now, the implementation would be # just this simple. I will not handle third party auth for now... client[config('UL_DB_NAME')].users.insert_one({ "username": "******", "password": bcrypt.hashpw(b'admin', bcrypt.gensalt()) }) # Assign a random username and password for universal login user account config('UL_DB_USER', 'ul_user_' + random_str(5)) config('UL_DB_PASS', random_str(16)) # Creates a user dedicated for universal login only client[config('UL_DB_NAME')].command("createUser", config('UL_DB_USER'), pwd=config('UL_DB_PASS'), roles=["readWrite"]) # Generate a symmetric key # Note: I wish to use asymmetric key, but I have issues with EC or RSA. # Errors: TypeError: object of type '_RSAPrivateKey' has no len() or # TypeError: object of type '_EllipticCurvePrivateKey' has no len() config('UL_KEY', jwk.JWK.generate(kty='oct', size=256).export()) return Response(json.dumps({ "type": "success", "msg": "Environment has been successfuly set." }), mimetype='application/json'), 200
def db(): return Mongo.conn()[config('UL_DB_NAME')]
def generate_new_token(): if (config('UL_LOCK_INIT')) is not None: return init_is_locked() return AdminController.generate_new_token()
def init(): if (config('UL_LOCK_INIT')) is not None: return redirect('/manage') return InitController().index()
def manage_other_instance(): if (config('UL_LOCK_INIT')) is not None: return init_is_locked() return AdminController.manage_other_instance()