def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = get_all_params(request.values, request.data) g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.event_config = EventConfiguration() # access_route contains the ip adresses of all clients, hops and proxies. g.client_ip = request.access_route[0] if request.access_route else \ request.remote_addr privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") user_loginname = "" if "blueprint_token" in request.endpoint: # In case of token endpoint we evaluate the user in the request. # Note: In policy-endpoint "user" is part of the policy configuration # and will cause an exception user = get_user_from_param(request.all_data) user_loginname = user.login realm = user.realm or realm g.audit_object.log({"success": False, "serial": serial, "user": user_loginname, "realm": realm, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": ""}) if g.logged_in_user.get("role") == "user": # A user is calling this API # In case the token API is called by the user and not by the admin we # need to restrict the token view. CurrentUser = get_user_from_param({"user": g.logged_in_user.get( "username"), "realm": g.logged_in_user.get( "realm")}) request.all_data["user"] = CurrentUser.login request.all_data["resolver"] = CurrentUser.resolver request.all_data["realm"] = CurrentUser.realm g.audit_object.log({"user": CurrentUser.login, "realm": CurrentUser.realm}) else: # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def create_user_api(): """ Create a new user in the given resolver. **Example request**: .. sourcecode:: http POST /user user=new_user resolver=<resolvername> surname=... givenname=... email=... mobile=... phone=... password=... description=... Host: example.com Accept: application/json """ # We can not use "get_user_from_param", since this checks the existence # of the user. attributes = _get_attributes_from_param(request.all_data) username = getParam(request.all_data, "user", optional=False) resolvername = getParam(request.all_data, "resolver", optional=False) r = create_user(resolvername, attributes) g.audit_object.log({ "success": True, "info": "%s: %s/%s" % (r, username, resolvername) }) return send_result(r)
def resync_api(serial=None): """ Resync the OTP token by providing two consecutive OTP values. You can call the function like this: POST /token/resync?serial=<serial>&otp1=<otp1>&otp2=<otp2> POST /token/resync/<serial>?otp1=<otp1>&otp2=<otp2> :param serial: the serial number of the single token to reset :type serial: basestring :param otp1: First OTP value :type otp1: basestring :param otp2: Second OTP value :type otp2: basestring :return: In case of success it returns "value"=True :rtype: json object """ if not serial: serial = getParam(request.all_data, "serial", required) otp1 = getParam(request.all_data, "otp1", required) otp2 = getParam(request.all_data, "otp2", required) res = resync_token(serial, otp1, otp2) g.audit_object.log({"success": True}) return send_result(res)
def create(identifier=None): """ This call creates or updates a RADIUS server definition. :param identifier: The unique name of the RADIUS server definition :param server: The FQDN or IP of the RADIUS server :param port: The port of the RADIUS server :param secret: The RADIUS secret of the RADIUS server :param description: A description for the definition """ param = request.all_data identifier = identifier.replace(" ", "_") server = getParam(param, "server", required) port = int(getParam(param, "port", default=1812)) secret = getParam(param, "secret", required) description = getParam(param, "description", default="") dictionary = getParam(param, "dictionary", default="/etc/privacyidea/dictionary") r = add_radius(identifier, server, secret, port=port, description=description, dictionary=dictionary) g.audit_object.log({'success': r > 0, 'info': r}) return send_result(r > 0)
def create_user_api(): """ Create a new user in the given resolver. **Example request**: .. sourcecode:: http POST /user user=new_user resolver=<resolvername> surname=... givenname=... email=... mobile=... phone=... password=... description=... Host: example.com Accept: application/json """ # We can not use "get_user_from_param", since this checks the existence # of the user. attributes = _get_attributes_from_param(request.all_data) username = getParam(request.all_data, "user", optional=False) resolvername = getParam(request.all_data, "resolver", optional=False) r = create_user(resolvername, attributes) g.audit_object.log({"success": True, "info": "%s: %s/%s" % (r, username, resolvername)}) return send_result(r)
def before_request(): """ This is executed before the request It is checked, if a user of role admin is logged in. Checks for either user OR admin are performed in api/token.py. """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = remove_session_from_param(request.values, request.data) # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) g.audit_object.log({"success": False, "serial": serial, "realm": realm, "client": request.remote_addr, "client_user_agent": request.user_agent.browser, "privacyidea_server": request.host, "action": "%s %s" % (request.method, request.url_rule), "administrator": g.logged_in_user.get("username"), "action_detail": "", "info": ""}) g.Policy = PolicyClass()
def list_machinetokens_api(): """ Return a list of MachineTokens either for a given machine or for a given token. :param serial: Return the MachineTokens for a the given Token :param hostname: Identify the machine by the hostname :param machineid: Identify the machine by the machine ID and the resolver name :param resolver: Identify the machine by the machine ID and the resolver name :return: """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial") application = getParam(request.all_data, "application") res = [] if not hostname and not machineid and not resolver: # We return the list of the machines for the given serial res = list_token_machines(serial) else: res = list_machine_tokens(hostname=hostname, machine_id=machineid, resolver_name=resolver) g.audit_object.log({'success': True, 'info': "serial: %s, hostname: %s" % (serial, hostname)}) return send_result(res)
def get_serial_by_otp_api(otp=None): """ Get the serial number for a given OTP value. If the administrator has a token, he does not know to whom it belongs, he can type in the OTP value and gets the serial number of the token, that generates this very OTP value. :query otp: The given OTP value :query type: Limit the search to this token type :query unassigned: If set=1, only search in unassigned tokens :query assigned: If set=1, only search in assigned tokens :query serial: This can be a substring of serial numbers to search in. :query window: The number of OTP look ahead (default=10) :return: The serial number of the token found """ ttype = getParam(request.all_data, "type") unassigned_param = getParam(request.all_data, "unassigned") assigned_param = getParam(request.all_data, "assigned") serial_substr = getParam(request.all_data, "serial") window = int(getParam(request.all_data, "window", default=10)) serial_substr = serial_substr or "" assigned = None if unassigned_param: assigned = False if assigned_param: assigned = True tokenobj_list = get_tokens(tokentype=ttype, serial="*%s*" % serial_substr, assigned=assigned) serial = get_serial_by_otp(tokenobj_list, otp=otp, window=window) g.audit_object.log({"success": True, "info": "get %s by OTP" % serial}) return send_result({"serial": serial})
def attach_token_api(): """ Attach an existing token to a machine with a certain application. :param hostname: identify the machine by the hostname :param machineid: identify the machine by the machine ID and the resolver name :param resolver: identify the machine by the machine ID and the resolver name :param serial: identify the token by the serial number :param application: the name of the application like "luks" or "ssh". Parameters not listed will be treated as additional options. :return: json result with "result": true and the machine list in "value". **Example request**: .. sourcecode:: http POST /token HTTP/1.1 Host: example.com Accept: application/json { "hostname": "puckel.example.com", "machienid": "12313098", "resolver": "machineresolver1", "serial": "tok123", "application": "luks" } """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial", optional=False) application = getParam(request.all_data, "application", optional=False) # get additional options: options = {} for key in request.all_data.keys(): if key not in [ "hostname", "machineid", "resolver", "serial", "application" ]: # We use the key as additional option options[key] = request.all_data.get(key) mt_object = attach_token(serial, application, hostname=hostname, machine_id=machineid, resolver_name=resolver, options=options) g.audit_object.log({ 'success': True, 'info': "serial: %s, application: %s" % (serial, application) }) return send_result(mt_object.id)
def set_gateway(): """ This creates a new SMS gateway definition or updates an existing one. :jsonparam name: The unique identifier of the SMS gateway definition :jsonparam module: The providermodule name :jsonparam description: An optional description of the definition :jsonparam options.*: Additional options for the provider module (module specific) """ param = request.all_data identifier = getParam(param, "name", optional=False) providermodule = getParam(param, "module", optional=False) description = getParam(param, "description", optional=True) options = {} for k, v in param.iteritems(): if k.startswith("option."): options[k[7:]] = v res = set_smsgateway(identifier, providermodule, description, options=options) g.audit_object.log({"success": True, "info": res}) return send_result(res)
def list_machinetokens_api(): """ Return a list of MachineTokens either for a given machine or for a given token. :param serial: Return the MachineTokens for a the given Token :param hostname: Identify the machine by the hostname :param machineid: Identify the machine by the machine ID and the resolver name :param resolver: Identify the machine by the machine ID and the resolver name :return: """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial") application = getParam(request.all_data, "application") res = [] if not hostname and not machineid and not resolver: # We return the list of the machines for the given serial res = list_token_machines(serial) else: res = list_machine_tokens(hostname=hostname, machine_id=machineid, resolver_name=resolver) g.audit_object.log({ 'success': True, 'info': "serial: %s, hostname: %s" % (serial, hostname) }) return send_result(res)
def get_challenges_api(serial=None): """ This endpoint returns the active challenges in the database or returns the challenges for a single token by its serial number :query serial: The optional serial number of the token for which the challenges should be returned :query sortby: sort the output by column :query sortdir: asc/desc :query page: request a certain page :query pagesize: limit the number of returned tokens :return: json """ param = request.all_data page = int(getParam(param, "page", optional, default=1)) sort = getParam(param, "sortby", optional, default="timestamp") sdir = getParam(param, "sortdir", optional, default="asc") psize = int(getParam(param, "pagesize", optional, default=15)) challenges = get_challenges_paginate(serial=serial, sortby=sort, sortdir=sdir, page=page, psize=psize) g.audit_object.log({"success": True}) return send_result(challenges)
def set_config(): """ set a configuration key or a set of configuration entries parameter are generic keyname=value pairs. *remark: In case of key-value pairs the type information could be provided by an additional parameter with same keyname with the postfix ".type". Value could then be 'password' to trigger the storing of the value in an encrypted form :param key: configuration entry name :param value: configuration value :param type: type of the value: int or string/text or password password will trigger to store the encrypted value :param description: additional information for this config entry * or :param key-value pairs: pair of &keyname=value pairs :return: a json result with a boolean "result": true """ param = request.all_data result = {} for key in param: if key.split(".")[-1] not in ["type", "desc"]: # Only store base values, not type or desc value = getParam(param, key, optional) typ = getParam(param, key + ".type", optional) desc = getParam(param, key + ".desc", optional) res = set_privacyidea_config(key, value, typ, desc) result[key] = res g.audit_object.log({"success": True}) g.audit_object.add_to_log({"info": "%s=%s, " % (key, value)}) return send_result(result)
def set_option_api(): """ This sets a Machine Token option or deletes it, if the value is empty. :param hostname: identify the machine by the hostname :param machineid: identify the machine by the machine ID and the resolver name :param resolver: identify the machine by the machine ID and the resolver name :param serial: identify the token by the serial number :param application: the name of the application like "luks" or "ssh". Parameters not listed will be treated as additional options. :return: """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial", optional=False) application = getParam(request.all_data, "application", optional=False) # get additional options: options_add = {} options_del = [] for key in request.all_data.keys(): if key not in [ "hostname", "machineid", "resolver", "serial", "application" ]: # We use the key as additional option value = request.all_data.get(key) if value: options_add[key] = request.all_data.get(key) else: options_del.append(key) o_add = add_option(serial=serial, application=application, hostname=hostname, machine_id=machineid, resolver_name=resolver, options=options_add) o_del = len(options_del) for k in options_del: delete_option(serial=serial, application=application, hostname=hostname, machine_id=machineid, resolver_name=resolver, key=k) g.audit_object.log({ 'success': True, 'info': "serial: %s, application: %s" % (serial, application) }) return send_result({"added": o_add, "deleted": o_del})
def get_auth_items_api(application=None): """ This fetches the authentication items for a given application and the given client machine. :param challenge: A challenge for which the authentication item is calculated. In case of the Yubikey this can be a challenge that produces a response. The authentication item is the combination of the challenge and the response. :type challenge: basestring :param hostname: The hostname of the machine :type hostname: basestring :return: dictionary with lists of authentication items **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": { "ssh": [ { "username": "******", "sshkey": "...." } ], "luks": [ { "slot": ".....", "challenge": "...", "response": "...", "partition": "..." ] } }, "version": "privacyIDEA unknown" } """ challenge = getParam(request.all_data, "challenge") hostname = getParam(request.all_data, "hostname", optional=False) # Get optional additional filter parameters filter_param = request.all_data for key in ["challenge", "hostname"]: if key in filter_param: del(filter_param[key]) ret = get_auth_items(hostname, ip=g.client_ip, application=application, challenge=challenge, filter_param=filter_param) g.audit_object.log({'success': True, 'info': "host: {0!s}, application: {1!s}".format(hostname, application)}) return send_result(ret)
def get_auth_items_api(application=None): """ This fetches the authentication items for a given application and the given client machine. :param challenge: A challenge for which the authentication item is calculated. In case of the Yubikey this can be a challenge that produces a response. The authentication item is the combination of the challenge and the response. :type challenge: basestring :param hostname: The hostname of the machine :type hostname: basestring :return: dictionary with lists of authentication items **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": { "ssh": [ { "username": "******", "sshkey": "...." } ], "luks": [ { "slot": ".....", "challenge": "...", "response": "...", "partition": "..." ] } }, "version": "privacyIDEA unknown" } """ challenge = getParam(request.all_data, "challenge") hostname = getParam(request.all_data, "hostname", optional=False) # Get optional additional filter parameters filter_param = request.all_data for key in ["challenge", "hostname"]: if key in filter_param: del(filter_param[key]) ret = get_auth_items(hostname, ip=request.remote_addr, application=application, challenge=challenge, filter_param=filter_param) g.audit_object.log({'success': True, 'info': "host: %s, application: %s" % (hostname, application)}) return send_result(ret)
def attach_token_api(): """ Attach an existing token to a machine with a certain application. :param hostname: identify the machine by the hostname :param machineid: identify the machine by the machine ID and the resolver name :param resolver: identify the machine by the machine ID and the resolver name :param serial: identify the token by the serial number :param application: the name of the application like "luks" or "ssh". Parameters not listed will be treated as additional options. :return: json result with "result": true and the machine list in "value". **Example request**: .. sourcecode:: http POST /token HTTP/1.1 Host: example.com Accept: application/json { "hostname": "puckel.example.com", "machienid": "12313098", "resolver": "machineresolver1", "serial": "tok123", "application": "luks" } """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial", optional=False) application = getParam(request.all_data, "application", optional=False) # get additional options: options = {} for key in request.all_data.keys(): if key not in ["hostname", "machineid", "resolver", "serial", "application"]: # We use the key as additional option options[key] = request.all_data.get(key) mt_object = attach_token(serial, application, hostname=hostname, machine_id=machineid, resolver_name=resolver, options=options) g.audit_object.log({'success': True, 'info': "serial: %s, application: %s" % (serial, application)}) return send_result(mt_object.id)
def _get_attributes_from_param(param): from privacyidea.lib.resolver import get_resolver_object map = get_resolver_object(getParam(param, "resolver", optional=False)).map username = getParam(param, "user", optional=False) # Add attributes attributes = {"username": username} for attribute in map.keys(): value = getParam(param, attribute) if value: attributes[attribute] = getParam(param, attribute) return attributes
def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = get_all_params(request.values, request.data) g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # We can add logic to use X-Forwarded-For g.client_ip = request.remote_addr privacyidea_server = current_app.config.get("PI_AUDIT_SERVERNAME") or \ request.host # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") user = get_user_from_param(request.all_data) # log it g.audit_object.log({"success": False, "serial": serial, "user": user.login, "realm": user.realm or realm, "client": g.client_ip, "client_user_agent": request.user_agent.browser, "privacyidea_server": privacyidea_server, "action": "{0!s} {1!s}".format(request.method, request.url_rule), "action_detail": "", "info": ""}) if g.logged_in_user.get("role") == "user": # A user is calling this API # In case the token API is called by the user and not by the admin we # need to restrict the token view. CurrentUser = get_user_from_param({"user": g.logged_in_user.get( "username"), "realm": g.logged_in_user.get( "realm")}) request.all_data["user"] = CurrentUser.login request.all_data["resolver"] = CurrentUser.resolver request.all_data["realm"] = CurrentUser.realm g.audit_object.log({"user": CurrentUser.login, "realm": CurrentUser.realm}) else: # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def before_request(): """ This is executed before the request. user_required checks if there is a logged in admin or user The checks for ONLY admin are preformed in api/system.py """ # remove session from param and gather all parameters, either # from the Form data or from JSON in the request body. request.all_data = get_all_params(request.values, request.data) g.policy_object = PolicyClass() g.audit_object = getAudit(current_app.config) # Already get some typical parameters to log serial = getParam(request.all_data, "serial") realm = getParam(request.all_data, "realm") # log it g.audit_object.log({ "success": False, "serial": serial, "realm": realm, "client": request.remote_addr, "client_user_agent": request.user_agent.browser, "privacyidea_server": request.host, "action": "%s %s" % (request.method, request.url_rule), "action_detail": "", "info": "" }) if g.logged_in_user.get("role") == "user": # A user is calling this API # In case the token API is called by the user and not by the admin we # need to restrict the token view. CurrentUser = get_user_from_param({ "user": g.logged_in_user.get("username"), "realm": g.logged_in_user.get("realm") }) request.all_data["user"] = CurrentUser.login request.all_data["resolver"] = CurrentUser.resolver request.all_data["realm"] = CurrentUser.realm g.audit_object.log({ "user": CurrentUser.login, "realm": CurrentUser.realm }) else: # An administrator is calling this API g.audit_object.log({"administrator": g.logged_in_user.get("username")})
def set_option_api(): """ This sets a Machine Token option or deletes it, if the value is empty. :param hostname: identify the machine by the hostname :param machineid: identify the machine by the machine ID and the resolver name :param resolver: identify the machine by the machine ID and the resolver name :param serial: identify the token by the serial number :param application: the name of the application like "luks" or "ssh". Parameters not listed will be treated as additional options. :return: """ hostname = getParam(request.all_data, "hostname") machineid = getParam(request.all_data, "machineid") resolver = getParam(request.all_data, "resolver") serial = getParam(request.all_data, "serial", optional=False) application = getParam(request.all_data, "application", optional=False) # get additional options: options_add = {} options_del = [] for key in request.all_data.keys(): if key not in ["hostname", "machineid", "resolver", "serial", "application"]: # We use the key as additional option value = request.all_data.get(key) if value: options_add[key] = request.all_data.get(key) else: options_del.append(key) o_add = add_option(serial=serial, application=application, hostname=hostname, machine_id=machineid, resolver_name=resolver, options=options_add) o_del = len(options_del) for k in options_del: delete_option(serial=serial, application=application, hostname=hostname, machine_id=machineid, resolver_name=resolver, key=k) g.audit_object.log({'success': True, 'info': "serial: %s, application: %s" % (serial, application)}) return send_result({"added": o_add, "deleted": o_del})
def assign_api(): """ Assign a token to a user. The required arguments are serial, user and realm. :return: In case of success it returns "value": True. :rtype: json object """ user = get_user_from_param(request.all_data, required) serial = getParam(request.all_data, "serial", required) pin = getParam(request.all_data, "pin") encrypt_pin = getParam(request.all_data, "encryptpin") res = assign_token(serial, user, pin=pin, encrypt_pin=encrypt_pin) g.audit_object.log({"success": True}) return send_result(res)
def _get_attributes_from_param(param): username = getParam(param, "user", optional=False) surname = getParam(param, "surname") givenname = getParam(param, "givenname") email = getParam(param, "email") phone = getParam(param, "phone") mobile = getParam(param, "mobile") password = getParam(param, "password") description = getParam(param, "description") # Add attributes attributes = {"username": username} if surname: attributes["surname"] = surname if givenname: attributes["givenname"] = givenname if email: attributes["email"] = email if phone: attributes["phone"] = phone if mobile: attributes["mobile"] = mobile if password: attributes["password"] = password if description: attributes["description"] = description return attributes
def test(): """ Test the email configuration :return: """ param = request.all_data identifier = getParam(param, "identifier", required) server = getParam(param, "server", required) port = int(getParam(param, "port", default=25)) username = getParam(param, "username", default="") password = getParam(param, "password", default="") sender = getParam(param, "sender", default="") tls = bool(getParam(param, "tls")) recipient = getParam(param, "recipient", required) s = SMTPServerDB( identifier=identifier, server=server, port=port, username=username, password=password, sender=sender, tls=tls ) r = SMTPServer.test_email( s, recipient, "Test Email from privacyIDEA", "This is a test email from privacyIDEA. " "The configuration %s is working." % identifier, ) g.audit_object.log({"success": r > 0, "info": r}) return send_result(r > 0)
def test(): """ Test the email configuration :return: """ param = request.all_data identifier = getParam(param, "identifier", required) server = getParam(param, "server", required) port = int(getParam(param, "port", default=25)) username = getParam(param, "username", default="") password = getParam(param, "password", default="") sender = getParam(param, "sender", default="") tls = getParam(param, "tls", default=False) tls = tls in [True, "True", "true", "1"] recipient = getParam(param, "recipient", required) s = SMTPServerDB(identifier=identifier, server=server, port=port, username=username, password=password, sender=sender, tls=tls) r = SMTPServer.test_email( s, recipient, "Test Email from privacyIDEA", "This is a test email from privacyIDEA. " "The configuration %s is working." % identifier) g.audit_object.log({'success': r > 0, 'info': r}) return send_result(r > 0)
def copyuser_api(): """ Copy the token user from one token to the other. :jsonparam basestring from: the serial number of the token, from where you want to copy the pin. :jsonparam basestring to: the serial number of the token, from where you want to copy the pin. :return: returns value=True in case of success :rtype: bool """ serial_from = getParam(request.all_data, "from", required) serial_to = getParam(request.all_data, "to", required) res = copy_token_user(serial_from, serial_to) g.audit_object.log({"success": True}) return send_result(res)
def disable_api(serial=None): """ Disable a single token or all the tokens of a user. Disabled tokens can not be used to authenticate but can be enabled again. You can call the function like this: POST /token/disable?serial=<serial> POST /token/disable?user=<user>&realm=<realm> POST /token/disable/<serial> :param serial: the serial number of the single token to disable :type serial: basestring :param user: The login name of the user :type user: basestring :param realm: the realm name of the user :type realm: basestring :return: In case of success it returns the number of disabled tokens in "value". :rtype: json object """ user = get_user_from_param(request.all_data, optional) if not serial: serial = getParam(request.all_data, "serial", optional) res = enable_token(serial, enable=False, user=user) g.audit_object.log({"success": res > 0}) return send_result(res)
def reset_api(serial=None): """ Reset the failcounter of a single token or of all tokens of a user. You can call the function like this: POST /token/reset?serial=<serial> POST /token/reset?user=<user>&realm=<realm> POST /token/reset/<serial> :param serial: the serial number of the single token to reset :type serial: basestring :param user: The login name of the user :type user: basestring :param realm: the realm name of the user :type realm: basestring :return: In case of success it returns "value"=True :rtype: json object """ user = get_user_from_param(request.all_data, optional) if not serial: serial = getParam(request.all_data, "serial", optional) res = reset_token(serial, user=user) g.audit_object.log({"success": True}) return send_result(res)
def token(ttype=None): """ This is a special token function. Each token type can define an additional API call, that does not need authentication on the REST API level. :return: Token Type dependent """ tokenc = get_token_class(ttype) res = tokenc.api_endpoint(request, g) serial = getParam(request.all_data, "serial") user = get_user_from_param(request.all_data) g.audit_object.log({ "success": 1, "user": user, "serial": serial, "tokentype": ttype }) if res[0] == "json": return jsonify(res[1]) elif res[0] in ["html", "plain"]: return Response(res[1], mimetype="text/{0!s}".format(res[0])) else: return Response(res[1], mimetype="application/octet-binary", headers=res[2])
def revoke_api(serial=None): """ Revoke a single token or all the tokens of a user. A revoked token will usually be locked. A locked token can not be used anymore. For certain token types additional actions might occur when revoking a token. :param serial: the serial number of the single token to revoke :type serial: basestring :param user: The login name of the user :type user: basestring :param realm: the realm name of the user :type realm: basestring :return: In case of success it returns the number of revoked tokens in "value". :rtype: json object """ user = get_user_from_param(request.all_data, optional) if not serial: serial = getParam(request.all_data, "serial", optional) res = revoke_token(serial, user=user) g.audit_object.log({"success": res > 0}) return send_result(res)
def tokenrealm_api(serial=None): """ Set the realms of a token. The token is identified by the unique serial number You can call the function like this: POST /token/realm?serial=<serial>&realms=<something> POST /token/realm/<serial>?realms=<hash> :jsonparam basestring serial: the serial number of the single token to reset :jsonparam basestring realms: The realms the token should be assigned to. Comma separated :return: returns value=True in case of success :rtype: bool """ realms = getParam(request.all_data, "realms", required) if type(realms) == list: realm_list = realms else: realm_list = [r.strip() for r in realms.split(",")] res = set_realms(serial, realms=realm_list) g.audit_object.log({"success": True}) return send_result(res == 1)
def tokenrealm_api(serial=None): """ Set the realms of a token. The token is identified by the unique serial number You can call the function like this: POST /token/realm?serial=<serial>&realms=<something> POST /token/realm/<serial>?realms=<hash> :param serial: the serial number of the single token to reset :type serial: basestring :param realms: The realms the token should be assigned to. Comma seperated :type realms: basestring :return: returns value=True in case of success :rtype: bool """ realms = getParam(request.all_data, "realms", required) if type(realms) == list: realm_list = realms else: realm_list = [r.strip() for r in realms.split(",")] res = set_realms(serial, realms=realm_list) g.audit_object.log({"success": True}) return send_result(res == 1)
def setpin_api(serial=None): """ Set the the user pin or the SO PIN of the specific token. Usually these are smartcard or token specific PINs. E.g. the userpin is used with mOTP tokens to store the mOTP PIN. The token is identified by the unique serial number. You can call the function like this: POST /token/setpin?serial=<serial>&userpin=<userpin>&sopin=<sopin> POST /token/setpin/<serial>?userpin=<userpin>&sopin=<sopin> :param serial: the serial number of the single token to reset :type serial: basestring :param userpin: The user PIN of a smartcard :type userpin: basestring :param sopin: The SO PIN of a smartcard :type sopin: basestring :param otppin: The OTP PIN of a token :type otppin: basestring :return: In "value" returns the number of PINs set. :rtype: json object """ if not serial: serial = getParam(request.all_data, "serial", required) userpin = getParam(request.all_data, "userpin") sopin = getParam(request.all_data, "sopin") otppin = getParam(request.all_data, "otppin") user = get_user_from_param(request.all_data) encrypt_pin = getParam(request.all_data, "encryptpin") res = 0 if userpin: g.audit_object.add_to_log({'action_detail': "userpin, "}) res += set_pin_user(serial, userpin) if sopin: g.audit_object.add_to_log({'action_detail': "sopin, "}) res += set_pin_so(serial, sopin) if otppin: g.audit_object.add_to_log({'action_detail': "otppin, "}) res += set_pin(serial, otppin, user=user, encrypt_pin=encrypt_pin) g.audit_object.log({"success": True}) return send_result(res)
def assign_api(): """ Assign a token to a user. :param serial: The token, which should be assigned to a user :param user: The username of the user :param realm: The realm of the user :return: In case of success it returns "value": True. :rtype: json object """ user = get_user_from_param(request.all_data, required) serial = getParam(request.all_data, "serial", required) pin = getParam(request.all_data, "pin") encrypt_pin = getParam(request.all_data, "encryptpin") res = assign_token(serial, user, pin=pin, encrypt_pin=encrypt_pin) g.audit_object.log({"success": True}) return send_result(res)
def update_user(): """ Edit a user in the user store. The resolver must have the flag editable, so that the user can be deleted. Only administrators are allowed to edit users. **Example request**: .. sourcecode:: http PUT /user user=existing_user resolver=<resolvername> surname=... givenname=... email=... mobile=... phone=... password=... description=... Host: example.com Accept: application/json .. note:: Also a user can call this function to e.g. change his password. But in this case the parameter "user" and "resolver" get overwritten by the values of the authenticated user, even if he specifies another username. """ attributes = _get_attributes_from_param(request.all_data) username = getParam(request.all_data, "user", optional=False) resolvername = getParam(request.all_data, "resolver", optional=False) user_obj = User(login=username, resolver=resolvername) # Remove the password from the attributes, so that we can hide it in the # logs password = attributes.get("password") if password: del attributes["password"] r = user_obj.update_user_info(attributes, password=password) g.audit_object.log({ "success": True, "info": "{0!s}: {1!s}/{2!s}".format(r, username, resolvername) }) return send_result(r)
def assign_api(): """ Assign a token to a user. :jsonparam serial: The token, which should be assigned to a user :jsonparam user: The username of the user :jsonparam realm: The realm of the user :return: In case of success it returns "value": True. :rtype: json object """ user = get_user_from_param(request.all_data, required) serial = getParam(request.all_data, "serial", required) pin = getParam(request.all_data, "pin") encrypt_pin = getParam(request.all_data, "encryptpin") res = assign_token(serial, user, pin=pin, encrypt_pin=encrypt_pin) g.audit_object.log({"success": True}) return send_result(res)
def get_users(): """ list the users in a realm A normal user can call this endpoint and will get information about his own account. :param realm: a realm that contains several resolvers. Only show users from this realm :param resolver: a distinct resolvername :param <searchexpr>: a search expression, that depends on the ResolverClass :return: json result with "result": true and the userlist in "value". **Example request**: .. sourcecode:: http GET /user?realm=realm1 HTTP/1.1 Host: example.com Accept: application/json **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "jsonrpc": "2.0", "result": { "status": true, "value": [ { "description": "Cornelius K\u00f6lbel,,+49 151 2960 1417,+49 561 3166797,[email protected]", "email": "*****@*****.**", "givenname": "Cornelius", "mobile": "+49 151 2960 1417", "phone": "+49 561 3166797", "surname": "K\u00f6lbel", "userid": "1009", "username": "******", "resolver": "name-of-resolver" } ] }, "version": "privacyIDEA unknown" } """ realm = getParam(request.all_data, "realm") users = get_user_list(request.all_data) g.audit_object.log({'success': True, 'info': "realm: {0!s}".format(realm)}) return send_result(users)
def test(): """ Test the RADIUS definition :return: """ param = request.all_data identifier = getParam(param, "identifier", required) server = getParam(param, "server", required) port = int(getParam(param, "port", default=1812)) secret = getParam(param, "secret", required) user = getParam(param, "username", required) password = getParam(param, "password", required) dictionary = getParam(param, "dictionary", default="/etc/privacyidea/dictinoary") s = RADIUSServerDB(identifier=identifier, server=server, port=port, secret=secret, dictionary=dictionary) r = RADIUSServer.request(s, user, password) g.audit_object.log({'success': r > 0, 'info': r}) return send_result(r > 0)
def create(identifier=None): """ This call creates or updates an SMTP server definition. :param identifier: The unique name of the SMTP server definition :param server: The FQDN or IP of the mail server :param port: The port of the mail server :param username: The mail username for authentication at the SMTP server :param password: The password for authentication at the SMTP server :param tls: If the server should do TLS :param description: A description for the definition """ param = request.all_data server = getParam(param, "server", required) port = int(getParam(param, "port", default=25)) username = getParam(param, "username", default="") password = getParam(param, "password", default="") sender = getParam(param, "sender", default="") tls = getParam(param, "tls", default=False) tls = tls in ["True", True, "true", "1"] description = getParam(param, "description", default="") r = add_smtpserver(identifier, server, port=port, username=username, password=password, tls=tls, description=description, sender=sender) g.audit_object.log({'success': r > 0, 'info': r}) return send_result(r > 0)
def create(identifier=None): """ This call creates or updates an SMTP server definition. :param identifier: The unique name of the SMTP server definition :param server: The FQDN or IP of the mail server :param port: The port of the mail server :param username: The mail username for authentication at the SMTP server :param password: The password for authentication at the SMTP server :param tls: If the server should do TLS :param description: A description for the definition """ param = request.all_data server = getParam(param, "server", required) port = int(getParam(param, "port", default=25)) username = getParam(param, "username", default="") password = getParam(param, "password", default="") sender = getParam(param, "sender", default="") tls = bool(getParam(param, "tls")) description = getParam(param, "description", default="") r = add_smtpserver( identifier, server, port=port, username=username, password=password, tls=tls, description=description, sender=sender, ) g.audit_object.log({"success": r > 0, "info": r}) return send_result(r > 0)
def get_resolvers(): """ returns a json list of all resolver. :param type: Only return resolvers of type (like passwdresolver..) :type type: basestring :param editable: Set to "1" if only editable resolvers should be returned. :type editable: basestring """ typ = getParam(request.all_data, "type", optional) editable = getParam(request.all_data, "editable", optional) if editable == "1": editable = True elif editable == "0": editable = False res = get_resolver_list(filter_resolver_type=typ, editable=editable) g.audit_object.log({"success": True}) return send_result(res)
def test_resolver(): """ :return: a json result with True, if the given values can create a working resolver and a description. """ param = request.all_data rtype = getParam(param, "type", required) success, desc = pretestresolver(rtype, param) return send_result(success, details={"description": desc})
def get_resolvers(): """ returns a json list of all machine resolver. :param type: Only return resolvers of type (like "hosts"...) """ typ = getParam(request.all_data, "type", optional) res = get_resolver_list(filter_resolver_type=typ) g.audit_object.log({"success": True}) return send_result(res)
def resync_api(serial=None): """ Resync the OTP token by providing two consecutive OTP values. :jsonparam basestring serial: the serial number of the single token to reset :jsonparam basestring otp1: First OTP value :jsonparam basestring otp2: Second OTP value :return: In case of success it returns "value"=True :rtype: json object """ user = get_user_from_param(request.all_data, optional) if not serial: serial = getParam(request.all_data, "serial", required) otp1 = getParam(request.all_data, "otp1", required) otp2 = getParam(request.all_data, "otp2", required) res = resync_token(serial, otp1, otp2, user=user) g.audit_object.log({"success": True}) return send_result(res)
def set_default(): """ method: system/set description: define default settings for tokens. These default settings are used when new tokens are generated. The default settings will not affect already enrolled tokens. arguments: DefaultMaxFailCount - Default value for the maximum allowed authentication failures DefaultSyncWindow - Default value for the synchronization window DefaultCountWindow - Default value for the coutner window DefaultOtpLen - Default value for the OTP value length -- usually 6 or 8 DefaultResetFailCount - Default value, if the FailCounter should be reset on successful authentication [True|False] returns: a json result with a boolean "result": true exception: if an error occurs an exception is serialized and returned """ keys = ["DefaultMaxFailCount", "DefaultSyncWindow", "DefaultCountWindow", "DefaultOtpLen", "DefaultResetFailCount"] description = "parameters are: %s" % ", ".join(keys) param = getLowerParams(request.all_data) result = {} for k in keys: if k.lower() in param: value = getParam(param, k.lower(), required) res = set_privacyidea_config(k, value) result[k] = res g.audit_object.log({"success": True}) g.audit_object.add_to_log({"info": "%s=%s, " % (k, value)}) if len(result) == 0: log.warning("Failed saving config. Could not find any " "known parameter. %s" % description) raise ParameterError("Usage: %s" % description, id=77) return send_result(result)
def reset_password(): """ reset the password with a given recovery code. The recovery code was sent by get_recover_code and is bound to a certain user. :jsonparam recoverycode: The recoverycode sent the the user :jsonparam password: The new password of the user :return: a json result with a boolean "result": true """ r = False user_obj = get_user_from_param(request.all_data, required) recoverycode = getParam(request.all_data, "recoverycode", required) password = getParam(request.all_data, "password", required) if check_recoverycode(user_obj, recoverycode): # set password r = user_obj.update_user_info({"password": password}) g.audit_object.log({"success": r, "info": "{0!s}".format(user_obj)}) return send_result(r)
def test_resolver(): """ This function tests, if the given parameter will create a working machine resolver. The Machine Resolver Class itself verifies the functionality. This can also be network connectivity to a Machine Store. :return: a json result with bool """ param = request.all_data rtype = getParam(param, "type", required) success, desc = pretestresolver(rtype, param) return send_result(success, details={"description": desc})
def get_serial_by_otp_api(otp=None): """ Get the serial number for a given OTP value. If the administrator has a token, he does not know to whom it belongs, he can type in the OTP value and gets the serial number of the token, that generates this very OTP value. :query otp: The given OTP value :query type: Limit the search to this token type :query unassigned: If set=1, only search in unassigned tokens :query assigned: If set=1, only search in assigned tokens :query serial: This can be a substring of serial numbers to search in. :query window: The number of OTP look ahead (default=10) :return: The serial number of the token found """ ttype = getParam(request.all_data, "type") unassigned_param = getParam(request.all_data, "unassigned") assigned_param = getParam(request.all_data, "assigned") serial_substr = getParam(request.all_data, "serial") window = int(getParam(request.all_data, "window", default=10)) serial_substr = serial_substr or "" assigned = None if unassigned_param: assigned = False if assigned_param: assigned = True tokenobj_list = get_tokens(tokentype=ttype, serial="*{0!s}*".format(serial_substr), assigned=assigned) serial = get_serial_by_otp(tokenobj_list, otp=otp, window=window) g.audit_object.log({ "success": True, "info": "get {0!s} by OTP".format(serial) }) return send_result({"serial": serial})
def setpin_api(serial=None): """ Set the the user pin or the SO PIN of the specific token. Usually these are smartcard or token specific PINs. E.g. the userpin is used with mOTP tokens to store the mOTP PIN. The token is identified by the unique serial number. :jsonparam basestring serial: the serial number of the single token to reset :jsonparam basestring userpin: The user PIN of a smartcard :jsonparam basestring sopin: The SO PIN of a smartcard :jsonparam basestring otppin: The OTP PIN of a token :return: In "value" returns the number of PINs set. :rtype: json object """ if not serial: serial = getParam(request.all_data, "serial", required) g.audit_object.log({"serial": serial}) userpin = getParam(request.all_data, "userpin") sopin = getParam(request.all_data, "sopin") otppin = getParam(request.all_data, "otppin") user = get_user_from_param(request.all_data) encrypt_pin = getParam(request.all_data, "encryptpin") res = 0 if userpin is not None: g.audit_object.add_to_log({'action_detail': "userpin, "}) res += set_pin_user(serial, userpin, user=user) if sopin is not None: g.audit_object.add_to_log({'action_detail': "sopin, "}) res += set_pin_so(serial, sopin, user=user) if otppin is not None: g.audit_object.add_to_log({'action_detail': "otppin, "}) res += set_pin(serial, otppin, user=user, encrypt_pin=encrypt_pin) g.audit_object.log({"success": True}) return send_result(res)
def create_user_api(): """ Create a new user in the given resolver. **Example request**: .. sourcecode:: http POST /user user=new_user resolver=<resolvername> surname=... givenname=... email=... mobile=... phone=... password=... description=... Host: example.com Accept: application/json """ # We can not use "get_user_from_param", since this checks the existence # of the user. attributes = _get_attributes_from_param(request.all_data) username = getParam(request.all_data, "user", optional=False) resolvername = getParam(request.all_data, "resolver", optional=False) # Remove the password from the attributes, so that we can hide it in the # logs password = attributes.get("password") del attributes["password"] r = create_user(resolvername, attributes, password=password) g.audit_object.log({ "success": True, "info": "{0!s}: {1!s}/{2!s}".format(r, username, resolvername) }) return send_result(r)
def trigger_challenge(): """ An administrator can call this endpoint if he has the right of ``triggerchallenge`` (scope: admin). He can pass a ``user`` name and or a ``serial`` number. privacyIDEA will trigger challenges for all native challenges response tokens, possessed by this user or only for the given serial number. The request needs to contain a valid PI-Authorization header. :param user: The loginname/username of the user, who tries to authenticate. :param realm: The realm of the user, who tries to authenticate. If the realm is omitted, the user is looked up in the default realm. :param serial: The serial number of the token. :return: a json result with a "result" of the number of matching challenge response tokens **Example response** for a successful authentication: .. sourcecode:: http {"jsonrpc": "2.0", "signature": "1939...146964", "detail": {"transaction_ids": ["03921966357577766962"], "messages": ["Enter the OTP from the SMS:"], "threadid": 140422378276608}, "versionnumber": "unknown", "version": "privacyIDEA unknown", "result": {"status": true, "value": 1}, "time": 1482223663.517212, "id": 1} """ user = request.User serial = getParam(request.all_data, "serial") result_obj = 0 details = {"messages": [], "transaction_ids": []} token_objs = get_tokens(serial=serial, user=user) for token_obj in token_objs: if "challenge" in token_obj.mode: # If this is a challenge response token, we create a challenge success, return_message, transactionid, attributes = \ token_obj.create_challenge() if success: result_obj += 1 details.get("transaction_ids").append(transactionid) details.get("messages").append(return_message) return send_result(result_obj, details=details)