def check(self, *args, **kwargs): auth = request.get_header('Authorization') if auth: (user, password) = parse_auth(auth) if user == self.username and password == self.password: return fn(self, *args, **kwargs) self._raise(401, 'Requires auth')
def call_api(func, args=""): add_header(response) s = request.environ.get('beaker.session') auth = parse_auth(request.get_header('Authorization', '')) # TODO: session as GET if 'session' in request.POST: # removes "' so it works on json strings s = s.get_by_id(remove_chars(request.POST['session'], "'\"")) elif auth: user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None)) # if auth is correct create a pseudo session if user: s = {'uid': user.uid} api = get_user_api(s) if not api: return HTTPError(403, dumps("Forbidden")) if not PYLOAD.isAuthorized(func, api.user): return HTTPError(401, dumps("Unauthorized")) args = args.split("/")[1:] kwargs = {} for x, y in chain(request.GET.iteritems(), request.POST.iteritems()): if x == "session": continue kwargs[x] = unquote(y) try: return callApi(api, func, *args, **kwargs) except ExceptionObject, e: return HTTPError(400, dumps(e))
def get_token(): credentials = request.headers.get("Authorization", "") username, password = parse_auth(credentials) or ("", "") username = username.strip().lower() password = hashlib.sha1(password).hexdigest() participant = participant_data.get(username) if not participant or participant["password"] != password: response.status = 401 return {"status": 401, "error": "bad user credentials"} token = hashlib.sha256(os.urandom(1024)).hexdigest() if participant["token"]: # ...invalidate previous token. del access_tokens[participant["token"]] participant["token"] = token access_tokens[token] = { "username": username, "uid": participant["uid"], "expires": int(time.time() + ACCESS_TOKEN_LIFETIME) } save_participants() response.status = 200 return { "status": 200, "token": token, "uid": participant["uid"], "expires": access_tokens[token]["expires"] }
def api_vnf_init_config(vnf_id): if auth_method == 'gatekeeper': if not gatekeeper_authentication(request.get_header('X-Auth-Token')): abort(401) elif auth_method == 'basic': user, passwd = parse_auth(request.get_header('Authorization')) if not check_credentials(user, passwd): abort(401) print "\n######## VNF INITIAL CONFIGURATION ########\n" print "VNF Validation: " if validate_VNF(vnf_id): print "Ok" print "\nRetrieving VNF Configuration: \n" try: vnfm_request = loads(request.body.getvalue()) print vnfm_request except: print "Fail: Unable to retrieve VNF Configuration" print "\n############## END ##############\n" abort(400) finally: print "\nStarting VNF initial configuration workflow\n" response = initial_configuration(vnf_id, vnfm_request) if not response: print "Fail: Unable to configure VNF" print "\n############## END ##############\n" abort(500) else: print "Fail: VNF not found" print "\n############## END ##############\n" abort(404)
def api_get_vnf_config(vnf_id): if auth_method == 'gatekeeper': if not gatekeeper_authentication(request.get_header('X-Auth-Token')): abort(401) elif auth_method == 'basic': user, passwd = parse_auth(request.get_header('Authorization')) if not check_credentials(user, passwd): abort(401) print "\n######## RETRIEVE VNF CURRENT CONFIGURATION ########\n" print "VNF Validation: " if validate_VNF(vnf_id): print "Ok" print "\nRetrieve Configuration workflow \n" conf_obj = get_current_configuration(vnf_id) if not conf_obj: print "\nThe VNF has not been configured\n" print "\n############## END ##############\n" abort(404) else: print "\n############## END ##############\n" return conf_obj else: print "Fail: VNF not found" print "\n############## END ##############\n" abort(404)
def api_delete_vnf(vnf_id): if auth_method == 'gatekeeper': if not gatekeeper_authentication(request.get_header('X-Auth-Token')): abort(401) if auth_method == 'basic': print "basic authentication" user, passwd = parse_auth(request.get_header('Authorization')) if not check_credentials(user, passwd): abort(401) print "\n######## DELETE VNF CONFIGURATION API ########\n" print "VNF Validation: " if validate_VNF(vnf_id): print "Ok\n" try: vnfm_request = loads(request.body.getvalue()) except: vnfm_request = None finally: print "\nStarting VNF removal workflow\n" response = delete_vnf(vnf_id, vnfm_request) if not response: print "Fail: the VNF could not be removed\n" print "\n############## END ##############\n" abort(500) print "\n############## END ##############\n" else: print "Fail: VNF not found" print "\n############## END ##############\n" abort(404)
def check_basic_auth(): auth = request.headers.get('Authorization') print "auth--> ", auth username, password = parse_auth(auth) print "basic auth:", username, ",", password hashed = ''.join(API_TOKEN) print "hashed:", hashed return sha256_crypt.verify(password, hashed)
def check_basic_auth(): auth = request.headers.get('Authorization') print "auth--> ", auth username, password = parse_auth(auth) print "basic auth:", username, "," , password hashed = ''.join(API_TOKEN) print "hashed:" ,hashed return sha256_crypt.verify(password, hashed)
def login_basic(self): auth = request.headers.get('Authorization') email, p = parse_auth(auth) response.set_cookie(self.COOKIE_NAME_ACCOUNT, email, secret=self.COOKIE_SECRET) return self.send("<html><script>window.close();</script></html>", ct="text/html")
def must_authenticate() -> User: global config, users auth = request.get_header("Authorization") username, password = parse_auth(auth) conf = authenticate(config, username, password) if conf == None: raise StatusError(403, "Unrecognized login") return users[username]
def check_pass(): auth = request.headers.get('Authorization') username, password = parse_auth(auth) auth_pass = False print "checking" if username == 'thioden': auth_pass = True cleared = True return auth_pass
def cookie(self): auth = request.headers.get('Authorization') if not auth: return self.application.send("<html><script>window.close();</script></html>", ct="text/html", ); who, p = parse_auth(auth) origin = request.query.get('origin', '*') # who is an identity (the username) value = {'sub': who} self.set_cookie(value, origin, response) return self.application.send("<html><script>window.close();</script></html>", ct="text/html", );
def decorator(*args, **kwargs): if not self.users: self.users = args[0].users (username, password) = bottle.parse_auth(bottle.request.get_header('Authorization')) user = self.users.get(username) if user and 'is_admin' in user and user['is_admin']: return f(*args, **kwargs) else: bottle.abort(401, 'Access denied')
def call_api(func, args=""): add_json_header(response) s = request.environ.get('beaker.session') # Accepts standard http auth auth = parse_auth(request.get_header('Authorization', '')) if 'session' in request.POST or 'session' in request.GET: # removes "' so it works on json strings s = s.get_by_id(remove_chars(request.params.get('session'), "'\"")) elif auth: user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None)) # if auth is correct create a pseudo session if user: s = {'uid': user.uid} api = get_user_api(s) if not api: return error(401, "Unauthorized") if not PYLOAD.isAuthorized(func, api.user): return error(403, "Forbidden") if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"): print "Invalid API call", func return error(404, "Not Found") # TODO: possible encoding # TODO Better error codes on invalid input args = [loads(unquote(arg)) for arg in args.split("/")[1:]] kwargs = {} # accepts body as json dict if request.json: kwargs = request.json # file upload, reads whole file into memory for name, f in request.files.iteritems(): kwargs["filename"] = f.filename content = StringIO() f.save(content) kwargs[name] = content.getvalue() content.close() # convert arguments from json to obj separately for x, y in request.params.iteritems(): try: if not x or not y or x == "session": continue kwargs[x] = loads(unquote(y)) except Exception, e: # Unsupported input msg = "Invalid Input %s, %s : %s" % (x, y, e.message) print_exc() print msg return error(415, msg)
def dyndnsUpdate(): auth = request.headers.get('Authorization') username, password = parse_auth(auth) hostnames = request.query.hostname ipv4 = request.query.myip or "" ipv6 = request.query.myip6 or "" # FIXME we need a way to adapt the return codes to other interfaces... return doUpdate(username, hostnames, ipv4, ipv6)
def terminal(): auth = bottle.request.headers.get('Authorization') port = bottle.request.query.port command = bottle.request.forms.get("file") print command if auth: user, _ = bottle.parse_auth(auth) CONFIG['ports'][port]['user'] = user if command == "reset": cmd = CONFIG['ports'][port]["resetcmd"] os.system(cmd) return get_terminal_dict(port, user)
def call_api(func, args=""): add_header(response) s = request.environ.get("beaker.session") # Accepts standard http auth auth = parse_auth(request.get_header("Authorization", "")) if "session" in request.POST or "session" in request.GET: # removes "' so it works on json strings s = s.get_by_id(remove_chars(request.params.get("session"), "'\"")) elif auth: user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get("REMOTE_ADDR", None)) # if auth is correct create a pseudo session if user: s = {"uid": user.uid} api = get_user_api(s) if not api: return HTTPError(401, dumps("Unauthorized"), **response.headers) if not PYLOAD.isAuthorized(func, api.user): return HTTPError(403, dumps("Forbidden"), **response.headers) if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"): print "Invalid API call", func return HTTPError(404, dumps("Not Found"), **response.headers) # TODO: possible encoding # TODO Better error codes on invalid input args = [loads(unquote(arg)) for arg in args.split("/")[1:]] kwargs = {} # accepts body as json dict if request.json: kwargs = request.json # convert arguments from json to obj separately for x, y in chain(request.GET.iteritems(), request.POST.iteritems()): if not x or not y or x == "session": continue kwargs[x] = loads(unquote(y)) try: result = getattr(api, func)(*args, **kwargs) # null is invalid json response if result is None: result = True return dumps(result) except ExceptionObject, e: return HTTPError(400, dumps(e), **response.headers)
def call_api(func, args=""): add_header(response) s = request.environ.get('beaker.session') # Accepts standard http auth auth = parse_auth(request.get_header('Authorization', '')) if 'session' in request.POST or 'session' in request.GET: # removes "' so it works on json strings s = s.get_by_id(remove_chars(request.params.get('session'), "'\"")) elif auth: user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None)) # if auth is correct create a pseudo session if user: s = {'uid': user.uid} api = get_user_api(s) if not api: return HTTPError(401, dumps("Unauthorized"), **response.headers) if not PYLOAD.isAuthorized(func, api.user): return HTTPError(403, dumps("Forbidden"), **response.headers) if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"): print "Invalid API call", func return HTTPError(404, dumps("Not Found"), **response.headers) # TODO: possible encoding # TODO Better error codes on invalid input args = [loads(unquote(arg)) for arg in args.split("/")[1:]] kwargs = {} # accepts body as json dict if request.json: kwargs = request.json # convert arguments from json to obj separately for x, y in chain(request.GET.iteritems(), request.POST.iteritems()): if not x or not y or x == "session": continue kwargs[x] = loads(unquote(y)) try: result = getattr(api, func)(*args, **kwargs) # null is invalid json response if result is None: result = True return dumps(result) except ExceptionObject, e: return HTTPError(400, dumps(e), **response.headers)
def validate(*args, **kwargs): """ Validation function for checking the credentials. """ auth_header = request.headers.get('Authorization') if auth_header is None: abort(401, 'Access denied') credentials = parse_auth(auth_header) if (credentials[0] == settings['user'] and credentials[1] == settings['password']): return func(**kwargs) else: abort(401, 'Access denied')
def _is_authorized(vdc): """Check if the user is authorized through BasicAuth or API Keys. """ auth_header = request.headers.get("Authorization") if auth_header: # Get vdc name and password from request Authorization header with Basic type name, password = parse_auth(auth_header) if vdc.validate_password(password) and name == vdc.vdc_name: return True else: api_key_header = request.headers.get("X-API-KEY") for name in APIKeyFactory.list_all(): api_key = APIKeyFactory.find(name) if api_key_header == api_key.key: return True
def test_noforms_auth_user_password(self): """POSTed body is not a forms, so we need to decode authorization ourselves. """ self.request.content_type = self.request.headers["Content-Type"] = "text/html" self.request.body = "<html>" self.request.auth = ("foobar", "barsecret") _, _, body, headers = oauth2.extract_params(self.request) self.assertEqual(body, "<html>") self.assertIn("Authorization", headers) import bottle client_id, client_secret = bottle.parse_auth(headers["Authorization"]) self.assertEqual(client_id, "foobar") self.assertEqual(client_secret, "barsecret")
def wrapper(*args, **kwargs): auth = request.headers.get('Authorization') if not auth: raise HTTPError(status=401, x_blobber_msg='Authentication required!') req_user, req_passwd = parse_auth(auth) USER = os.environ.get("CLIENT_USERNAME") PASSWORD = os.environ.get("CLIENT_PASSWORD") if not USER or not PASSWORD: raise HTTPError( status=500, x_blobber_msg='Client credentials unset on server!') if (req_user, req_passwd) != (USER, PASSWORD): raise HTTPError(status=403, x_blobber_msg='Authentication failed!') return fn(**kwargs)
def wrapper(*args, **kwargs): auth = request.headers.get('Authorization') if not auth: raise HTTPError(status=401, x_blobber_msg='Authentication required!') req_user, req_passwd = parse_auth(auth) USER = os.environ.get("CLIENT_USERNAME") PASSWORD = os.environ.get("CLIENT_PASSWORD") if not USER or not PASSWORD: raise HTTPError(status=500, x_blobber_msg='Client credentials unset on server!') if (req_user, req_passwd) != (USER, PASSWORD): raise HTTPError(status=403, x_blobber_msg='Authentication failed!') return fn(**kwargs)
def is_auth_by_header(self): header = request.get_header('Authorization') if header is None: return False pair = parse_auth(header) if pair is None: return False user, passwd = pair userinfo = get_user_info(self.db.session, user) if userinfo is None: return False if authenticate(passwd, userinfo): beaker = request.environ.get('beaker.session') beaker['login_info'] = create_user_dict(userinfo) beaker.save() return userinfo return False
def is_auth_by_header(self): header = request.get_header('Authorization') if header is None: return False pair = parse_auth(header) if pair is None: return False user, passwd = pair userinfo = get_user_info(self.db.session, user) if userinfo is None: return False if authenticate(passwd, userinfo): beaker = request.environ.get('beaker.session') beaker['login_info'] = create_user_dict(userinfo) beaker.save() return True return False
def br(): a_token = request.headers.get('Authorization') try: credentials = parse_auth(a_token) except: raise HTTPResponse('Please provide a Basic Authentication header\n', 403) if not utils.is_authenticated(*credentials): raise HTTPResponse( 'Unauthenticated\n', 403) u_and_c = credentials[0].split('__') user = u_and_c[0] if len(u_and_c) >1: company = u_and_c[1] else: company = user request.creds = utils.LocalEnv() request.creds.user = user request.creds.company = company request.creds.password = credentials[1]
def br(): a_token = request.headers.get('Authorization') try: credentials = parse_auth(a_token) except: raise HTTPResponse('Please provide a Basic Authentication header\n', 403) if not utils.is_authenticated(*credentials): raise HTTPResponse('Unauthenticated\n', 403) u_and_c = credentials[0].split('__') user = u_and_c[0] if len(u_and_c) > 1: company = u_and_c[1] else: company = user request.creds = utils.LocalEnv() request.creds.user = user request.creds.company = company request.creds.password = credentials[1]
def api_registervnf(): if auth_method == 'gatekeeper': print 'gatekeeper' if not gatekeeper_authentication(request.get_header('X-Auth-Token')): abort(401) if auth_method == 'basic': print 'basic authentication method' user, passwd = parse_auth(request.get_header('Authorization')) if not check_credentials(user, passwd): abort(401) try: vnfm_req = loads(request.body.getvalue()) print "\n######## REGISTERING VNF ########\n" print "VNF Id: " + vnfm_req['id'] + '\n' print "VNF Descriptor: " print vnfm_req register_vnf(vnfm_req['id'], vnfm_req['vnfd']) print "\n############## END ##############\n" except: abort(400)
def login(): auth = request.get_header('Authorization') try: username, password = parse_auth(auth) except: response.content_type = 'application/json' response.status = 401 resp = {'error': 'Empty credentials'} return dumps(resp) if check_auth(username, password): response.content_type = 'application/json' response.status = 200 return dumps({'token': user_token(username)}) response.content_type = 'application/json' response.status = 401 response.headers['WWW-Authenticate'] = 'Basic realm="Login Required"' resp = {'message': 'Authentication failed'} return dumps(resp)
def decorator(*args, **kwargs): if not self.users: self.users = args[0].users if not self.__l: self.__l = args[0].logger (username, password) = bottle.parse_auth(bottle.request.get_header('Authorization')) self.__l.debug('username: %s' % username) self.__l.debug('password: %s' % password) """User/pass based auth""" user = self.users.get(username) server = None if not user: self.__l.error('No user found for %s' % username) bottle.abort(401, 'Access denied') if not self.users.validate_password(username, password): self.__l.error('Password mismatch') bottle.abort(401, 'Access denied') return f(*args, username=user['username'], user=user, server=server, **kwargs)
def login_basic(self): auth = request.headers.get('Authorization') email,p = parse_auth(auth) response.set_cookie("account", email, secret="abc-123-!@#") return self.send("<html><script>window.close();</script></html>", ct="text/html");
def external(widget_type, identifier, action=None): # pylint: disable=too-many-return-statements, unsupported-membership-test # pylint: disable=unsubscriptable-object """ Application external identifier Use internal authentication (if a user is logged-in) or external basic authentication provided by the requiring application. Search in the known 'widget_type' (widget or table) to find the element 'identifier'. Use the 'links' parameter to prefix the navigation URLs. """ session = request.environ['beaker.session'] if 'current_user' in session: current_user = session['current_user'] if not user_authentication(current_user.token, None): # Redirect to application login page logger.warning( "before_request, current_user in the session is not authenticated." " Redirecting to the login page...") redirect('/login') credentials = current_user.token + ':' else: # Authenticate external access... if 'Authorization' not in request.headers or not request.headers[ 'Authorization']: logger.warning("external application access denied") response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>To embed an Alignak WebUI widget or table, you must provide credentials.<br>' 'Log into the Alignak WebUI with your credentials, or make a request ' 'with a Basic-Authentication allowing access to Alignak backend.</p>' '</div>') # Get HTTP authentication authentication = request.headers.get('Authorization') username, password = parse_auth(authentication) if not user_authentication(username, password): logger.warning("external application access denied for %s", username) response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>The provided credentials do not grant you access to Alignak WebUI.<br>' 'Please provide proper credentials.</p>' '</div>') current_user = session['current_user'] credentials = current_user.token + ':' # Make session data available in the templates BaseTemplate.defaults['current_user'] = session['current_user'] BaseTemplate.defaults['target_user'] = session['target_user'] BaseTemplate.defaults['datamgr'] = session['datamanager'] logger.debug("External request, widget type: %s", widget_type) if widget_type not in ['widget', 'table', 'list', 'host']: logger.warning("External application requested unknown type: %s", widget_type) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required type: %s.</h1>' '<p>The required type is unknwown</p></div>' % widget_type) if widget_type == 'widget': found_widget = None for widget in get_app_webui().get_widgets_for('external'): if identifier == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", identifier) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % identifier) logger.debug("Found widget: %s", found_widget) embedded_element = found_widget['function'](embedded=True, identifier=identifier, credentials=credentials) if request.params.get('page', 'no') == 'no': return embedded_element return template('external_widget', {'embedded_element': embedded_element}) if widget_type == 'table': found_table = None for table in get_app_webui().get_tables_for('external'): if identifier == table['id']: found_table = table break else: logger.warning("External application requested unknown table: %s", identifier) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required table: %s.</h1>' '<p>The required table is not available.</p></div>' % identifier) logger.debug("Found table: %s", found_table) if action and action in found_table['actions']: logger.info("Required action: %s", action) return found_table['actions'][action]() if request.params.get('page', 'no') == 'no': return found_table['function'](embedded=True, identifier=identifier, credentials=credentials) return template( 'external_table', { 'embedded_element': found_table['function'](embedded=True, identifier=identifier, credentials=credentials) }) if widget_type == 'list': if identifier in get_app_webui().lists: return get_app_webui().lists[identifier]['function'](embedded=True) else: logger.warning("External application requested unknown list: %s", identifier) return WebUI.response_ko(_('Unknown required list')) if widget_type == 'host': if not action: logger.warning( "External application requested host widget without widget name" ) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Missing host widget name.</h1>' '<p>You must provide a widget name</p></div>') # Identifier is the host identifier, not the widget one ! found_widget = None for widget in get_app_webui().get_widgets_for('host'): if action == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", action) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % action) logger.debug("Found host widget: %s", found_widget) if request.params.get('page', 'no') == 'no': return found_widget['function'](host_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials) return template( 'external_widget', { 'embedded_element': found_widget['function'](host_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials) })
def external(widget_type, identifier, action=None): # pylint: disable=too-many-return-statements, unsupported-membership-test # pylint: disable=unsubscriptable-object, too-many-locals """Application external identifier Use internal authentication (if a user is logged-in) or external basic authentication provided by the requiring application. Search in the known 'widget_type' (widget or table) to find the element 'identifier'. Use the 'links' parameter to prefix the navigation URLs. """ logger.warning("external request, url: %s %s", request.method, request.urlparts.path) # Get the WebUI instance webui = request.app.config['webui'] # Get the server session (it always exist...) session = request.environ['beaker.session'] st = datetime.datetime.fromtimestamp( session['_creation_time']).strftime('%Y-%m-%d %H:%M:%S') origin = request.environ.get( 'HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR') logger.debug("client: %s, session: %s / %s / %s", origin, session.id, st, session) current_user = None if 'current_user' in session and session['current_user']: current_user = session['current_user'] # Get the application instance authentication logger.debug("webapp: %s, request app: %s", webapp, request.app) logger.debug("current_user: %s", current_user) if not webapp.user_authentication(current_user.token, None, session): # Redirect to application login page logger.warning( "External request. User in the session is not authenticated. " "Redirecting to the login page...") redirect('/login') credentials = current_user.token + ':' else: # Authenticate external access... if 'Authorization' not in request.headers or not request.headers[ 'Authorization']: logger.warning("external application access denied") response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>To embed an Alignak WebUI widget or table, you must provide credentials.<br>' 'Log into the Alignak WebUI with your credentials, or make a request ' 'with a Basic-Authentication allowing access to Alignak backend.</p>' '</div>') # Get HTTP authentication authentication = request.headers.get('Authorization') username, password = parse_auth(authentication) # Get the application instance authentication logger.debug("external application, checking authentication for %s", username) if not webapp.user_authentication(username, password, session): logger.warning("external application access denied for %s", username) response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>The provided credentials do not grant you access to Alignak WebUI.<br>' 'Please provide proper credentials.</p>' '</div>') current_user = session['current_user'] credentials = current_user.token + ':' # Make session data available in the templates BaseTemplate.defaults['current_user'] = session['current_user'] # Make data manager available in the request and in the templates request.app.datamgr = DataManager(webapp, session=session) request.app.datamgr.load() logger.warning("request.app.datamgr: %s", request.app.datamgr) BaseTemplate.defaults['datamgr'] = request.app.datamgr logger.info("External request, element type: %s", widget_type) if widget_type not in [ 'files', 'widget', 'table', 'list', 'host', 'service', 'user' ]: logger.warning("External application requested unknown type: %s", widget_type) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required type: %s.</h1>' '<p>The required type is unknwown</p></div>' % widget_type) if widget_type == 'files': if identifier == 'js_list': response.status = 200 response.content_type = 'application/json' return json.dumps({'status': 'ok', 'files': webui.js_list}) if identifier == 'css_list': response.status = 200 response.content_type = 'application/json' return json.dumps({'status': 'ok', 'files': webui.css_list}) logger.warning("External application requested unknown files: %s", identifier) response.status = 409 response.content_type = 'application/json' return json.dumps({ 'status': 'ko', 'message': "Unknown files list: %s" % identifier }) if widget_type == 'widget': found_widget = None for widget in webui.get_widgets_for('external'): if identifier == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", identifier) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % identifier) logger.debug("found widget: %s", found_widget) embedded_element = found_widget['function'](embedded=True, identifier=identifier, credentials=credentials) if request.params.get('page', 'no') == 'no': return embedded_element return template('external_widget', {'embedded_element': embedded_element}) if widget_type == 'table': found_table = None for table in webui.get_tables_for('external'): if identifier == table['id']: found_table = table break else: logger.warning("External application requested unknown table: %s", identifier) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required table: %s.</h1>' '<p>The required table is not available.</p></div>' % identifier) logger.info("Found table: %s", found_table) if action and action in found_table['actions']: logger.info("Required action: %s = %s", action, found_table['actions'][action]) return found_table['actions'][action]() if request.params.get('page', 'no') == 'no': return found_table['function'](embedded=True, identifier=identifier, credentials=credentials) return template( 'external_table', { 'embedded_element': found_table['function'](embedded=True, identifier=identifier, credentials=credentials) }) if widget_type == 'list': if identifier in webui.lists: return webui.lists[identifier]['function'](embedded=True) logger.warning("External application requested unknown list: %s", identifier) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required list: %s.</h1>' '<p>The required list is not available.</p></div>' % identifier) if widget_type in ['host', 'service', 'user']: if not action: logger.warning( "External application requested %s widget without widget name", widget_type) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Missing %s widget name.</h1>' '<p>You must provide a widget name</p></div>' % widget_type) # Identifier is the element identifier, not the widget one ! found_widget = None for widget in webui.get_widgets_for(widget_type): if action == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", action) response.status = 409 response.content_type = 'text/html' return _('<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % action) logger.debug("Found %s widget: %s", widget_type, found_widget) if request.params.get('page', 'no') == 'no': return found_widget['function'](element_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials) return template( 'external_widget', { 'embedded_element': found_widget['function'](element_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials) })
def login_basic(self): auth = request.headers.get('Authorization') email,p = parse_auth(auth) response.set_cookie(self.COOKIE_NAME_ACCOUNT, email, secret=self.COOKIE_SECRET) return self.send("<html><script>window.close();</script></html>", ct="text/html");
def register(self, username=None, password=None, user_info=None): ''' Register a new user. Parameters ---------- username : str Username to register. Must be unique in the application. It can also be passed as the value of key `Username` as part of the GET or POST request. password : str Plaintext password for this username. It can also be passed as the value of key `Password` as part of the GET or POST request. user_info : dict Dictionary containing any additional information about this user. The key `RemoteIpAddr` will be added to this dictionary with the value provided by `bottle.request.environ.get("REMOTE_ADDR")` prior to matching the user against the whitelist and blacklist parameters given to the constructor of this class. The parameters `username` and `password` can also be passed to this method as items in the `user_info` dictionary. Any key-value pairs not described above that are passed as part of the GET or POST request will be added to this dictionary. If the requested security level requires it, all user info including username and password must be serialized and signed/encrypted into a field named `Data` as a json string. In that case, the single-use `Token` provided by the key exchange must also be provided. Returns ------- response : bottle.HTTPResponse Status code and body will determine if the login was successful. If successful, the body will contain the user record in JSON format. Examples -------- >>> app = BottleShip() >>> app.register("john", "1234").body '{"Username": "******", "Password": "******", "__id__": "2c849965-251f-4b5d- 8a27-77f86fa9e0e3", "RemoteIpAddr": null}' ''' request_dict = PandasDatabase._request(bottle.request, request_fallback=user_info) # If data and token are provided, then this must be secure data transfer secure_data = False if 'Data' in request_dict and 'Token' in request_dict: secure_data = True request_dict, err_msg = self._read_secure_json(request_dict) if err_msg: self._print(err_msg) return bottle.HTTPResponse(status=400, body=err_msg) # Cleanup information from the request request_dict = {tos(req_k): tos(req_v) for req_k, req_v in request_dict.items() if re.match(PandasDatabase._colname_rgx, tos(req_k))} # Verify username and password username = username or request_dict.get('Username') password = password or request_dict.get('Password', '') auth_header = bottle.request.get_header('Authorization') if auth_header: # If auth is available in the headers, take that username, password = bottle.parse_auth(auth_header) error_msg = self._error_username_password(username, password) if error_msg: self._print(error_msg) return bottle.HTTPResponse(status=400, body=error_msg) # Look for existing user record and, if any, reject registration user_record = self.pddb.find_one( 'bottleship_users', where={'Username': username}, astype='dict') if user_record: msg = 'Register error: Provided username already exists in the database.' self._print(msg) return bottle.HTTPResponse(status=400, body=msg) # Get the user requested security level or default security_level = request_dict.get('SecurityLevel', self.allowed_security[0]) request_dict['SecurityLevel'] = security_level if security_level not in self.allowed_security: msg = 'Login error: Security level must be one of: %r' % list(self.allowed_security) self._print(msg) res = bottle.HTTPResponse(status=400, body=msg) return res elif not secure_data and ('hmac' in security_level or 'rsa' in security_level): msg = ('Login error: Security level requested requires secure data transfer but ' 'plaintext was used instead') self._print(msg) res = bottle.HTTPResponse(status=400, body=msg) return res # Get user's IP address from request request_dict['RemoteIpAddr'] = bottle.request.environ.get('REMOTE_ADDR', '') # Insert the hashed password into user's record if password is not None: request_dict['Password'] = str(hash(password)) # Validate the user against our rules if not self._check_user(request_dict): msg = 'User does not meet the requirements.' self._print(msg) return bottle.HTTPResponse(status=403, body=msg) # Insert or update the user record user_cond = {'Username': username} user_record = self.pddb.upsert('bottleship_users', record=request_dict, where=user_cond, astype='dict')[0] # Depending on the security level, we may need to encrypt or sign the data user_record_json = self._dump_user_record(security_level, user_record) # Return the inserted user record return bottle.HTTPResponse(status=200, body=user_record_json)
def external(widget_type, identifier, action=None): # pylint: disable=too-many-return-statements, unsupported-membership-test # pylint: disable=unsubscriptable-object, too-many-locals """Application external identifier Use internal authentication (if a user is logged-in) or external basic authentication provided by the requiring application. Search in the known 'widget_type' (widget or table) to find the element 'identifier'. Use the 'links' parameter to prefix the navigation URLs. """ logger.warning("external request, url: %s %s", request.method, request.urlparts.path) # Get the WebUI instance webui = request.app.config['webui'] # Get the server session (it always exist...) session = request.environ['beaker.session'] st = datetime.datetime.fromtimestamp(session['_creation_time']).strftime('%Y-%m-%d %H:%M:%S') origin = request.environ.get('HTTP_X_FORWARDED_FOR') or request.environ.get('REMOTE_ADDR') logger.debug("client: %s, session: %s / %s / %s", origin, session.id, st, session) current_user = None if 'current_user' in session and session['current_user']: current_user = session['current_user'] # Get the application instance authentication logger.debug("webapp: %s, request app: %s", webapp, request.app) logger.debug("current_user: %s", current_user) if not webapp.user_authentication(current_user.token, None, session): # Redirect to application login page logger.warning("External request. User in the session is not authenticated. " "Redirecting to the login page...") redirect('/login') credentials = current_user.token + ':' else: # Authenticate external access... if 'Authorization' not in request.headers or not request.headers['Authorization']: logger.warning("external application access denied") response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>To embed an Alignak WebUI widget or table, you must provide credentials.<br>' 'Log into the Alignak WebUI with your credentials, or make a request ' 'with a Basic-Authentication allowing access to Alignak backend.</p>' '</div>' ) # Get HTTP authentication authentication = request.headers.get('Authorization') username, password = parse_auth(authentication) # Get the application instance authentication logger.debug("external application, checking authentication for %s", username) if not webapp.user_authentication(username, password, session): logger.warning("external application access denied for %s", username) response.status = 401 response.content_type = 'text/html' return _( '<div>' '<h1>External access denied.</h1>' '<p>The provided credentials do not grant you access to Alignak WebUI.<br>' 'Please provide proper credentials.</p>' '</div>' ) current_user = session['current_user'] credentials = current_user.token + ':' # Make session data available in the templates BaseTemplate.defaults['current_user'] = session['current_user'] # Make data manager available in the request and in the templates request.app.datamgr = DataManager(webapp, session=session) request.app.datamgr.load() logger.warning("request.app.datamgr: %s", request.app.datamgr) BaseTemplate.defaults['datamgr'] = request.app.datamgr logger.info("External request, element type: %s", widget_type) if widget_type not in ['files', 'widget', 'table', 'list', 'host', 'service', 'user']: logger.warning("External application requested unknown type: %s", widget_type) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Unknown required type: %s.</h1>' '<p>The required type is unknwown</p></div>' % widget_type ) if widget_type == 'files': if identifier == 'js_list': response.status = 200 response.content_type = 'application/json' return json.dumps({'status': 'ok', 'files': webui.js_list}) if identifier == 'css_list': response.status = 200 response.content_type = 'application/json' return json.dumps({'status': 'ok', 'files': webui.css_list}) logger.warning("External application requested unknown files: %s", identifier) response.status = 409 response.content_type = 'application/json' return json.dumps({'status': 'ko', 'message': "Unknown files list: %s" % identifier}) if widget_type == 'widget': found_widget = None for widget in webui.get_widgets_for('external'): if identifier == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", identifier) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % identifier ) logger.debug("found widget: %s", found_widget) embedded_element = found_widget['function']( embedded=True, identifier=identifier, credentials=credentials ) if request.params.get('page', 'no') == 'no': return embedded_element return template('external_widget', { 'embedded_element': embedded_element }) if widget_type == 'table': found_table = None for table in webui.get_tables_for('external'): if identifier == table['id']: found_table = table break else: logger.warning("External application requested unknown table: %s", identifier) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Unknown required table: %s.</h1>' '<p>The required table is not available.</p></div>' % identifier ) logger.info("Found table: %s", found_table) if action and action in found_table['actions']: logger.info("Required action: %s = %s", action, found_table['actions'][action]) return found_table['actions'][action]() if request.params.get('page', 'no') == 'no': return found_table['function']( embedded=True, identifier=identifier, credentials=credentials ) return template('external_table', { 'embedded_element': found_table['function']( embedded=True, identifier=identifier, credentials=credentials ) }) if widget_type == 'list': if identifier in webui.lists: return webui.lists[identifier]['function'](embedded=True) logger.warning("External application requested unknown list: %s", identifier) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Unknown required list: %s.</h1>' '<p>The required list is not available.</p></div>' % identifier ) if widget_type in ['host', 'service', 'user']: if not action: logger.warning( "External application requested %s widget without widget name", widget_type ) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Missing %s widget name.</h1>' '<p>You must provide a widget name</p></div>' % widget_type ) # Identifier is the element identifier, not the widget one ! found_widget = None for widget in webui.get_widgets_for(widget_type): if action == widget['id']: found_widget = widget break else: logger.warning("External application requested unknown widget: %s", action) response.status = 409 response.content_type = 'text/html' return _( '<div><h1>Unknown required widget: %s.</h1>' '<p>The required widget is not available.</p></div>' % action ) logger.debug("Found %s widget: %s", widget_type, found_widget) if request.params.get('page', 'no') == 'no': return found_widget['function']( element_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials ) return template('external_widget', { 'embedded_element': found_widget['function']( element_id=identifier, widget_id=found_widget['id'], embedded=True, identifier=identifier, credentials=credentials ) })
def login(self, username=None, password=None, _request_fallback=None): ''' Log in an existing user. Parameters ---------- username : str Username to login. It can also be passed as the value of key `Username` as part of the GET or POST request. password : str Plaintext password for this username. It can also be passed as the value of key `Password` as part of the GET or POST request. If the requested security level requires it, password must be signed/encrypted. _request_fallback : dict Used for testing purposes. The parameters `Username` and `Password` can also be passed to this method as items in the `_request_fallback` dictionary. Returns ------- response : bottle.HTTPResponse Status code and body will determine if the login was successful. If successful, the body will contain the user record in JSON format. Examples -------- >>> app = BottleShip() >>> res = app.login("john", "1234") >>> print(res.status_code, res.body) 403 Login error: Provided password does not match records for that username or username does not exist. ''' request_dict = PandasDatabase._request(bottle.request, request_fallback=_request_fallback) # If data and token are provided, then this must be secure data transfer secure_data = False if 'Data' in request_dict and 'Token' in request_dict: secure_data = True request_dict, err_msg = self._read_secure_json(request_dict) if err_msg: self._print(err_msg) return bottle.HTTPResponse(status=400, body=err_msg) # Cleanup information from the request request_dict = {tos(req_k): tos(req_v) for req_k, req_v in request_dict.items() if re.match(PandasDatabase._colname_rgx, tos(req_k))} # Verify username and password username = username or request_dict.get('Username') password = password or request_dict.get('Password', '') auth_header = bottle.request.get_header('Authorization') if auth_header: # If auth is available in the headers, take that username, password = bottle.parse_auth(auth_header) error_msg = self._error_username_password(username, password) if error_msg: self._print(error_msg) return bottle.HTTPResponse(status=400, body=error_msg) # Look for existing user record user_record = self.pddb.find_one( 'bottleship_users', where={'Username': username}, astype='dict') if not user_record: msg = ('Login error: Provided password does not match records for that username or ' 'username does not exist.') self._print(msg) return bottle.HTTPResponse(status=403, body=msg) # Make sure that the security level is supported security_level = request_dict.get( 'SecurityLevel', user_record.get('SecurityLevel', self.allowed_security[0])) if 'ipaddr' in user_record.get('SecurityLevel') and 'ipaddr' not in security_level: security_level += '+ipaddr' # Force IP address verification if registration requests it user_record['SecurityLevel'] = security_level if security_level not in self.allowed_security: msg = 'Login error: Security level must be one of: %r' % list(self.allowed_security) self._print(msg) res = bottle.HTTPResponse(status=400, body=msg) return res elif not secure_data and ('hmac' in security_level or 'rsa' in security_level): msg = ('Login error: Security level requested requires secure data transfer but ' 'plaintext was used instead') self._print(msg) res = bottle.HTTPResponse(status=400, body=msg) return res # Verify user password if 'Password' in user_record and user_record.get('Password') != str(hash(password)): msg = ('Login error: Provided password does not match records for that username or ' 'username does not exist.') self._print(msg) return bottle.HTTPResponse(status=403, body=msg) # Get user's IP address from request ip_addr = bottle.request.environ.get('REMOTE_ADDR', '') if ip_addr != user_record.get('RemoteIpAddr'): if 'ipaddr' in security_level: msg = 'Login error: Registration IP address does not match login attempt.' self._print(msg) return bottle.HTTPResponse(status=403, body=msg) else: user_record['RemoteIpAddr'] = ip_addr # Provide user with a temporary token token_key = str(request_dict.get('Key') if secure_data else user_record.get('Key')) token_record = self._gen_token(username, security_level=security_level, key=token_key) user_record['Token'] = token_record['Token'] # Update the user record user_cond = {'Username': username} user_record['Key'] = token_record.get('Key') user_record['LastLogin'] = str(time.time()) user_record = self.pddb.upsert('bottleship_users', record=user_record, where=user_cond, astype='dict')[0] # Depending on the security level, we may need to encrypt or sign the data user_record_json = self._dump_user_record(security_level, user_record) res = bottle.HTTPResponse(status=200, body=user_record_json) res.set_cookie('Token', token_record['Token'], path='/', expires=int(float(token_record.get('Expiry')))) return res
def call_api(func, args=""): add_json_header(response) s = request.environ.get('beaker.session') # Accepts standard http auth auth = parse_auth(request.get_header('Authorization', '')) if 'session' in request.POST or 'session' in request.GET: # removes "' so it works on json strings s = s.get_by_id(purge.chars(request.params.get('session'), "'\"")) elif auth: user = API.check_auth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None)) # if auth is correct create a pseudo session if user: s = {'uid': user.uid} api = get_user_api(s) if not api: return error(401, "Unauthorized") if not API.is_authorized(func, api.user): return error(403, "Forbidden") if not hasattr(API.EXTERNAL, func) or func.startswith("_"): print("Invalid API call", func) return error(404, "Not Found") # TODO: possible encoding # TODO: Better error codes on invalid input args = [loads(unquote(arg)) for arg in args.split("/")[1:]] kwargs = {} # accepts body as json dict if request.json: kwargs = request.json # file upload, reads whole file into memory for name, f in request.files.items(): kwargs['filename'] = f.filename with closing(io.StringIO()) as content: f.save(content) kwargs[name] = content.getvalue() # convert arguments from json to obj separately for x, y in request.params.items(): try: if not x or not y or x == "session": continue kwargs[x] = loads(unquote(y)) except Exception as e: # Unsupported input msg = "Invalid Input {0}, {1} : {2}".format(x, y, e.message) print_exc() print(msg) return error(415, msg) try: result = getattr(api, func)(*args, **kwargs) # null is invalid json response if result is None: result = True return json_response(result) except ExceptionObject as e: return error(400, e.message) except Exception as e: print_exc() return error(500, {'error': e.message, 'traceback': format_exc()})
def __get_username(self): (username, password) = bottle.parse_auth(bottle.request.get_header('Authorization')) return username
def __check_auth(self): auth = request.headers.get('Authorization') credentials = parse_auth(auth) if self.__config.http_user != credentials[ 0] or self.__config.http_pass != credentials[1]: raise Exception('Request is not authorized')