def get_statistics(stats_key=None): """ return a list of all available statistics keys in the database if no *stats_key* is specified. If a stats_key is specified it returns the data of this key. The parameters "start" and "end" can be used to specify a time window, from which the statistics data should be fetched. """ if stats_key is None: stats_keys = get_stats_keys() g.audit_object.log({"success": True}) return send_result(stats_keys) else: param = request.all_data start = getParam(param, "start") if start: start = parse_legacy_time(start, return_date=True) end = getParam(param, "end") if end: end = parse_legacy_time(end, return_date=True) values = get_values(stats_key=stats_key, start_timestamp=start, end_timestamp=end) # convert timestamps to strings values_w_string = [(s[0].strftime(AUTH_DATE_FORMAT), s[1]) for s in values] g.audit_object.log({"success": True}) return send_result(values_w_string)
def api_delete(application=None): """ Delete an existing subscription """ r = delete_subscription(application) g.audit_object.log({'success': True}) return send_result(r)
def api_request(): """ Create a subscription request. This request needs to be sent to NetKnights to create a subscription """ subscription_request = create_subscription_request() return send_result(subscription_request)
def list_taskmodules(): """ Return a list of task module identifiers. """ taskmodules = get_available_taskmodules() g.audit_object.log({"success": True}) return send_result(taskmodules)
def list_nodes(): """ Return a list of available nodes """ nodes = get_privacyidea_nodes() g.audit_object.log({"success": True}) return send_result(nodes)
def get_statistics_last(stats_key): """ Get the last value of the stats key """ last_value = get_last_value(stats_key) g.audit_object.log({"success": True}) return send_result(last_value)
def api_delete(application=None): """ Create a subscription request. This request needs to be sent to NetKnights to create a subscription """ r = delete_subscription(application) return send_result(r)
def list_periodic_tasks(): """ Return a list of objects of defined periodic tasks. """ ptasks = get_periodic_tasks() result = [convert_datetimes_to_string(ptask) for ptask in ptasks] g.audit_object.log({"success": True}) return send_result(result)
def api_delete(application=None): """ Create a subscription request. This request needs to be sent to NetKnights to create a subscription """ r = delete_subscription(application) g.audit_object.log({'success': True}) return send_result(r)
def api_set(): """ """ subscription_file = request.files['file'] file_contents = subscription_file.read() subscription = yaml.load(file_contents) set_subscription(subscription) return send_result(True)
def api_set(): """ """ subscription_file = request.files['file'] file_contents = subscription_file.read() subscription = yaml.safe_load(file_contents) r = save_subscription(subscription) g.audit_object.log({'success': True}) return send_result(r)
def get_periodic_task_api(ptaskid): """ Return the dictionary describing a periodic task. :param ptaskid: ID of the periodic task """ ptask = get_periodic_task_by_id(int(ptaskid)) g.audit_object.log({"success": True}) return send_result(convert_datetimes_to_string(ptask))
def api_set(): """ """ subscription_file = request.files['file'] file_contents = subscription_file.read() subscription = yaml.load(file_contents) r = save_subscription(subscription) g.audit_object.log({'success': True}) return send_result(r)
def disable_periodic_task_api(ptaskid): """ Disable a certain periodic task. :param ptaskid: ID of the periodic task :return: ID of the periodic task """ result = enable_periodic_task(int(ptaskid), False) g.audit_object.log({"success": True}) return send_result(result)
def api_get(application=None): """ Return the subscription object as JSON. """ subscription = get_subscription() for sub in subscription: # If subscription is valid, we have a negative timedelta sub["timedelta"] = (datetime.datetime.now() - sub.get("date_till")).days return send_result(subscription)
def get_taskmodule_options(taskmodule): """ Return the available options for the given taskmodule. :param taskmodule: Identifier of the task module :return: a dictionary mapping option keys to description dictionaries """ options = get_taskmodule(taskmodule).options g.audit_object.log({"success": True}) return send_result(options)
def delete_periodic_task_api(ptaskid): """ Delete a certain periodic task. :param ptaskid: ID of the periodic task :return: ID of the periodic task """ result = delete_periodic_task(int(ptaskid)) g.audit_object.log({"success": True, "info": result}) return send_result(result)
def get_rights(): """ This returns the rights of the logged in user. :reqheader Authorization: The authorization token acquired by /auth request """ enroll_types = g.policy_object.ui_get_enroll_tokentypes(g.client_ip, g.logged_in_user) g.audit_object.log({"success": True}) return send_result(enroll_types)
def get_rights(): """ This returns the rights of the logged in user. :reqheader Authorization: The authorization token acquired by /auth request """ enroll_types = g.policy_object.ui_get_enroll_tokentypes( g.client_ip, g.logged_in_user) g.audit_object.log({"success": True}) return send_result(enroll_types)
def api_get(application=None): """ Return the subscription object as JSON. """ subscription = get_subscription() active_tokens = get_tokens(count=True, active=True, assigned=True) for sub in subscription: # If subscription is valid, we have a negative timedelta sub["timedelta"] = (datetime.datetime.now() - sub.get("date_till")).days sub["active_tokens"] = active_tokens g.audit_object.log({'success': True}) return send_result(subscription)
def set_periodic_task_api(): """ Create or replace an existing periodic task definition. :param id: ID of an existing periodic task definition that should be updated :param name: Name of the periodic task :param active: true if the periodic task should be active :param retry_if_failed: privacyIDEA will retry to execute the task if failed :param interval: Interval at which the periodic task should run (in cron syntax) :param nodes: Comma-separated list of nodes on which the periodic task should run :param taskmodule: Task module name of the task :param ordering: Ordering of the task, must be a number >= 0. :param options: A dictionary (possibly JSON) of periodic task options, mapping unicodes to unicodes :return: ID of the periodic task """ param = request.all_data ptask_id = getParam(param, "id", optional=True) if ptask_id is not None: ptask_id = int(ptask_id) name = getParam(param, "name", optional=False) active = is_true(getParam(param, "active", default=True)) retry_if_failed = is_true(getParam(param, "retry_if_failed", default=True)) interval = getParam(param, "interval", optional=False) node_string = getParam(param, "nodes", optional=False) if node_string.strip(): node_list = [node.strip() for node in node_string.split(",")] else: raise ParameterError(u"nodes: expected at least one node") taskmodule = getParam(param, "taskmodule", optional=False) if taskmodule not in get_available_taskmodules(): raise ParameterError("Unknown task module: {!r}".format(taskmodule)) ordering = int(getParam(param, "ordering", optional=False)) options = getParam(param, "options", optional=True) if options is None: options = {} elif not isinstance(options, dict): options = json.loads(options) if not isinstance(options, dict): raise ParameterError(u"options: expected dictionary, got {!r}".format(options)) result = set_periodic_task(name, interval, node_list, taskmodule, ordering, options, active, ptask_id, retry_if_failed) g.audit_object.log({"success": True, "info": result}) return send_result(result)
def set_periodic_task_api(): """ Create or replace an existing periodic task definition. :param id: ID of an existing periodic task definition that should be updated :param name: Name of the periodic task :param active: true if the periodic task should be active :param interval: Interval at which the periodic task should run (in cron syntax) :param nodes: Comma-separated list of nodes on which the periodic task should run :param taskmodule: Task module name of the task :param ordering: Ordering of the task, must be a number >= 0. :param options: A dictionary (possibly JSON) of periodic task options, mapping unicodes to unicodes :return: ID of the periodic task """ param = request.all_data ptask_id = getParam(param, "id", optional=True) if ptask_id is not None: ptask_id = int(ptask_id) name = getParam(param, "name", optional=False) active = is_true(getParam(param, "active", default=True)) interval = getParam(param, "interval", optional=False) node_string = getParam(param, "nodes", optional=False) if node_string.strip(): node_list = [node.strip() for node in node_string.split(",")] else: raise ParameterError(u"nodes: expected at least one node") taskmodule = getParam(param, "taskmodule", optional=False) if taskmodule not in get_available_taskmodules(): raise ParameterError("Unknown task module: {!r}".format(taskmodule)) ordering = int(getParam(param, "ordering", optional=False)) options = getParam(param, "options", optional=True) if options is None: options = {} elif not isinstance(options, dict): options = json.loads(options) if not isinstance(options, dict): raise ParameterError(u"options: expected dictionary, got {!r}".format(options)) result = set_periodic_task(name, interval, node_list, taskmodule, ordering, options, active, ptask_id) g.audit_object.log({"success": True, "info": result}) return send_result(result)
def delete_statistics(stats_key): """ Delete the statistics data of a certain stats_key. You can specify the start date and the end date when to delete the monitoring data. You should specify the dates including the timezone. Otherwise your client could send its local time and the server would interpret it as its own local time which would result in deleting unexpected entries. You can specify the dates like 2010-12-31 22:00+0200 """ param = request.all_data start = getParam(param, "start") if start: start = parse_legacy_time(start, return_date=True) end = getParam(param, "end") if end: end = parse_legacy_time(end, return_date=True) r = delete_stats(stats_key, start, end) g.audit_object.log({"success": True}) return send_result(r)
def api_get(): """ Return the subscription object as JSON. """ subscription = get_subscription() return send_result(subscription)
def get_auth_token(): """ This call verifies the credentials of the user and issues an authentication token, that is used for the later API calls. The authentication token has a validity, that is usually 1 hour. :jsonparam username: The username of the user who wants to authenticate to the API. :jsonparam password: The password/credentials of the user who wants to authenticate to the API. :return: A json response with an authentication token, that needs to be used in any further request. :status 200: in case of success :status 401: if authentication fails **Example Authentication Request**: .. sourcecode:: http POST /auth HTTP/1.1 Host: example.com Accept: application/json username=admin password=topsecret **Example Authentication Response**: .. sourcecode:: http HTTP/1.0 200 OK Content-Length: 354 Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": { "token": "eyJhbGciOiJIUz....jdpn9kIjuGRnGejmbFbM" } }, "version": "privacyIDEA unknown" } **Response for failed authentication**: .. sourcecode:: http HTTP/1.1 401 UNAUTHORIZED Content-Type: application/json Content-Length: 203 { "id": 1, "jsonrpc": "2.0", "result": { "error": { "code": -401, "message": "missing Authorization header" }, "status": false }, "version": "privacyIDEA unknown", "config": { "logout_time": 30 } } """ validity = timedelta(hours=1) username = getParam(request.all_data, "username") password = getParam(request.all_data, "password") realm = getParam(request.all_data, "realm") details = {} if username is None: raise AuthError(_("Authentication failure. Missing Username"), id=ERROR.AUTHENTICATE_MISSING_USERNAME) if realm: username = username + "@" + realm # Failsafe to have the user attempt in the log, whatever happens # This can be overwritten later g.audit_object.log({"user": username, "realm": realm}) secret = current_app.secret_key superuser_realms = current_app.config.get("SUPERUSER_REALM", []) # This is the default role for the logged in user. # The role privileges may be risen to "admin" role = ROLE.USER # The way the user authenticated. This could be # "password" = The admin user DB or the user store # "pi" = The admin or the user is authenticated against privacyIDEA # "remote_user" = authenticated by webserver authtype = "password" # Verify the password admin_auth = False user_auth = False loginname, realm = split_user(username) realm = realm or get_default_realm() user_obj = User() # Check if the remote user is allowed if (request.remote_user == username) and is_remote_user_allowed(request): # Authenticated by the Web Server # Check if the username exists # 1. in local admins # 2. in a realm # 2a. is an admin realm authtype = "remote_user " if db_admin_exist(username): role = ROLE.ADMIN admin_auth = True g.audit_object.log({ "success": True, "user": "", "administrator": username, "info": "internal admin" }) else: # check, if the user exists user_obj = User(loginname, realm) g.audit_object.log({ "user": user_obj.login, "realm": user_obj.realm, "info": log_used_user(user_obj) }) if user_obj.exist(): user_auth = True if user_obj.realm in superuser_realms: role = ROLE.ADMIN admin_auth = True elif verify_db_admin(username, password): role = ROLE.ADMIN admin_auth = True # This admin is not in the default realm! realm = "" g.audit_object.log({ "success": True, "user": "", "administrator": username, "info": "internal admin" }) else: # The user could not be identified against the admin database, # so we do the rest of the check options = {"g": g, "clientip": g.client_ip} for key, value in request.all_data.items(): if value and key not in ["g", "clientip"]: options[key] = value user_obj = User(loginname, realm) user_auth, role, details = check_webui_user( user_obj, password, options=options, superuser_realms=superuser_realms) details = details or {} if role == ROLE.ADMIN: g.audit_object.log({ "user": "", "administrator": user_obj.login, "realm": user_obj.realm, "resolver": user_obj.resolver, "serial": details.get('serial', None), "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj), details.get("loginmode")) }) else: g.audit_object.log({ "user": user_obj.login, "realm": user_obj.realm, "resolver": user_obj.resolver, "serial": details.get('serial', None), "info": u"{0!s}|loginmode={1!s}".format(log_used_user(user_obj), details.get("loginmode")) }) if not admin_auth and not user_auth: raise AuthError(_("Authentication failure. Wrong credentials"), id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS, details=details or {}) else: g.audit_object.log({"success": True}) request.User = user_obj # If the HSM is not ready, we need to create the nonce in another way! hsm = init_hsm() if hsm.is_ready: nonce = geturandom(hex=True) # Add the role to the JWT, so that we can verify it internally # Add the authtype to the JWT, so that we could use it for access # definitions rights = g.policy_object.ui_get_rights(role, realm, loginname, g.client_ip) menus = g.policy_object.ui_get_main_menus( { "username": loginname, "role": role, "realm": realm }, g.client_ip) else: import os nonce = hexlify_and_unicode(os.urandom(20)) rights = [] menus = [] # What is the log level? log_level = current_app.config.get("PI_LOGLEVEL", 30) token = jwt.encode( { "username": loginname, "realm": realm, "nonce": nonce, "role": role, "authtype": authtype, "exp": datetime.utcnow() + validity, "rights": rights }, secret, algorithm='HS256').decode('utf8') # Add the role to the response, so that the WebUI can make decisions # based on this (only show selfservice, not the admin part) return send_result( { "token": token, "role": role, "username": loginname, "realm": realm, "log_level": log_level, "rights": rights, "menus": menus }, details=details)
def get_auth_token(): """ This call verifies the credentials of the user and issues an authentication token, that is used for the later API calls. The authentication token has a validity, that is usually 1 hour. :jsonparam username: The username of the user who wants to authenticate to the API. :jsonparam password: The password/credentials of the user who wants to authenticate to the API. :return: A json response with an authentication token, that needs to be used in any further request. :status 200: in case of success :status 401: if authentication fails **Example Authentication Request**: .. sourcecode:: http POST /auth HTTP/1.1 Host: example.com Accept: application/json username=admin password=topsecret **Example Authentication Response**: .. sourcecode:: http HTTP/1.0 200 OK Content-Length: 354 Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": { "token": "eyJhbGciOiJIUz....jdpn9kIjuGRnGejmbFbM" } }, "version": "privacyIDEA unknown" } **Response for failed authentication**: .. sourcecode:: http HTTP/1.1 401 UNAUTHORIZED Content-Type: application/json Content-Length: 203 { "id": 1, "jsonrpc": "2.0", "result": { "error": { "code": -401, "message": "missing Authorization header" }, "status": false }, "version": "privacyIDEA unknown", "config": { "logout_time": 30 } } """ validity = timedelta(hours=1) username = getParam(request.all_data, "username") password = getParam(request.all_data, "password") realm = getParam(request.all_data, "realm") details = {} if username is None: raise AuthError(_("Authentication failure. Missing Username"), id=ERROR.AUTHENTICATE_MISSING_USERNAME) if realm: username = username + "@" + realm # Failsafe to have the user attempt in the log, whatever happens # This can be overwritten later g.audit_object.log({"user": username, "realm": realm}) secret = current_app.secret_key superuser_realms = current_app.config.get("SUPERUSER_REALM", []) # This is the default role for the logged in user. # The role privileges may be risen to "admin" role = ROLE.USER # The way the user authenticated. This could be # "password" = The admin user DB or the user store # "pi" = The admin or the user is authenticated against privacyIDEA # "remote_user" = authenticated by webserver authtype = "password" # Verify the password admin_auth = False user_auth = False loginname, realm = split_user(username) realm = realm or get_default_realm() user_obj = User() # Check if the remote user is allowed if (request.remote_user == username) and is_remote_user_allowed(request): # Authenticated by the Web Server # Check if the username exists # 1. in local admins # 2. in a realm # 2a. is an admin realm authtype = "remote_user " if db_admin_exist(username): role = ROLE.ADMIN admin_auth = True g.audit_object.log({"success": True, "user": "", "administrator": username, "info": "internal admin"}) else: # check, if the user exists user_obj = User(loginname, realm) g.audit_object.log({"user": user_obj.login, "realm": user_obj.realm, "info": log_used_user(user_obj)}) if user_obj.exist(): user_auth = True if user_obj.realm in superuser_realms: role = ROLE.ADMIN admin_auth = True elif verify_db_admin(username, password): role = ROLE.ADMIN admin_auth = True # This admin is not in the default realm! realm = "" g.audit_object.log({"success": True, "user": "", "administrator": username, "info": "internal admin"}) else: # The user could not be identified against the admin database, # so we do the rest of the check options = {"g": g, "clientip": g.client_ip} for key, value in request.all_data.items(): if value and key not in ["g", "clientip"]: options[key] = value user_obj = User(loginname, realm) user_auth, role, details = check_webui_user(user_obj, password, options=options, superuser_realms= superuser_realms) if role == ROLE.ADMIN: g.audit_object.log({"user": "", "administrator": user_obj.login, "realm": user_obj.realm, "info": log_used_user(user_obj)}) else: g.audit_object.log({"user": user_obj.login, "realm": user_obj.realm, "info": log_used_user(user_obj)}) if not admin_auth and not user_auth: raise AuthError(_("Authentication failure. Wrong credentials"), id=ERROR.AUTHENTICATE_WRONG_CREDENTIALS, details=details or {}) else: g.audit_object.log({"success": True}) request.User = user_obj # If the HSM is not ready, we need to create the nonce in another way! hsm = init_hsm() if hsm.is_ready: nonce = geturandom(hex=True) # Add the role to the JWT, so that we can verify it internally # Add the authtype to the JWT, so that we could use it for access # definitions rights = g.policy_object.ui_get_rights(role, realm, loginname, g.client_ip) menus = g.policy_object.ui_get_main_menus({"username": loginname, "role": role, "realm": realm}, g.client_ip) else: import os nonce = hexlify_and_unicode(os.urandom(20)) rights = [] menus = [] # What is the log level? log_level = current_app.config.get("PI_LOGLEVEL", 30) token = jwt.encode({"username": loginname, "realm": realm, "nonce": nonce, "role": role, "authtype": authtype, "exp": datetime.utcnow() + validity, "rights": rights}, secret, algorithm='HS256').decode('utf8') # Add the role to the response, so that the WebUI can make decisions # based on this (only show selfservice, not the admin part) return send_result({"token": token, "role": role, "username": loginname, "realm": realm, "log_level": log_level, "rights": rights, "menus": menus}, details=details)