def test_02_updateserver(self): r = add_privacyideaserver(identifier="myserver", url="https://pi/pi", tls=False) self.assertTrue(r > 0) server = get_privacyideaserver("myserver") self.assertEqual(server.config.url, "https://pi/pi") self.assertFalse(server.config.tls) r = add_privacyideaserver(identifier="myserver", url="https://pi/", tls=True, description="Hallo") self.assertTrue(r > 0) server = get_privacyideaserver("myserver") self.assertEqual(server.config.url, "https://pi/") self.assertEqual(server.config.tls, True) self.assertEqual(server.config.description, "Hallo")
def update(self, param): """ second phase of the init process - updates parameters :param param: the request parameters :return: - nothing - """ # if another OTP length would be specified in /admin/init this would # be overwritten by the parent class, which is ok. self.set_otplen(6) TokenClass.update(self, param) remote_server_id = getParam(param, "remote.server_id", optional) if remote_server_id is not None: if get_privacyideaserver(id=remote_server_id): self.add_tokeninfo("remote.server_id", remote_server_id) else: remoteServer = getParam(param, "remote.server", required) self.add_tokeninfo("remote.server", remoteServer) log.warning( "Using remote.server for remote tokens is deprecated. Use remote.server_id!" ) val = getParam(param, "remote.local_checkpin", optional) or 0 self.add_tokeninfo("remote.local_checkpin", val) for key in [ "remote.serial", "remote.user", "remote.path", "remote.realm", "remote.resolver" ]: val = getParam(param, key, optional) if val is not None: self.add_tokeninfo(key, val) self.add_tokeninfo("tokenkind", TOKENKIND.VIRTUAL)
def do(self, action, options=None): """ This method executes the defined action in the given event. :param action: :param options: Contains the flask parameters g, request, response and the handler_def configuration :type options: dict :return: """ g = options.get("g") request = options.get("request") handler_def = options.get("handler_def") handler_options = handler_def.get("options", {}) if action == ACTION_TYPE.FORWARD: server_def = handler_options.get("privacyIDEA") pi_server = get_privacyideaserver(server_def) # the new url is the configured server url and the original path url = pi_server.config.url + request.path # We use the original method method = request.method tls = pi_server.config.tls # We also transfer the original payload data = request.all_data if handler_options.get("forward_client_ip"): data["client"] = g.client_ip if handler_options.get("realm"): data["realm"] = handler_options.get("realm") if handler_options.get("resolver"): data["resolver"] = handler_options.get("resolver") log.info(u"Sending {0} request to {1!r}".format(method, url)) requestor = None params = None headers = {} # We need to pass an authorization header if we forward administrative requests if handler_options.get("forward_authorization_token"): auth_token = request.headers.get('PI-Authorization') if not auth_token: auth_token = request.headers.get('Authorization') headers["PI-Authorization"] = auth_token if method.upper() == "GET": params = data data = None requestor = requests.get elif method.upper() == "POST": requestor = requests.post elif method.upper() == "DELETE": requestor = requests.delete if requestor: r = requestor(url, params=params, data=data, headers=headers, verify=tls) # convert requests Response to werkzeug Response response_dict = json.loads(r.text) if "detail" in response_dict: if response_dict.get("detail") is None: # In case of exceptions we may not have a detail response_dict["detail"] = {"origin": url} else: response_dict.get("detail")["origin"] = url # We will modify the response! # We can not use flask.jsonify(response_dict) here, since we # would work outside of application context! options["response"] = Response() options["response"].status_code = r.status_code options["response"].content_type = "application/json" options["response"].data = json.dumps(response_dict) else: log.warning(u"Unsupported method: {0!r}".format(method)) return True
def check_otp(self, otpval, counter=None, window=None, options=None): """ run the http request against the remote host :param otpval: the OTP value :param counter: The counter for counter based otp values :type counter: int :param window: a counter window :type counter: int :param options: additional token specific options :type options: dict :return: counter of the matching OTP value. :rtype: int """ otp_count = -1 pi_server_obj = None remoteServer = None remote_server_id = self.get_tokeninfo("remote.server_id") if remote_server_id: pi_server_obj = get_privacyideaserver(id=int(remote_server_id)) else: # Deprecated remoteServer = self.get_tokeninfo("remote.server") or "" log.warning( "Using remote.server for remote tokens is deprecated. Use remote.server_id!" ) ssl_verify = get_from_config("remote.verify_ssl_certificate", False, return_bool=True) or False # in preparation of the ability to relocate privacyidea urls, # we introduce the remote url path remotePath = self.get_tokeninfo("remote.path") or "" remotePath = remotePath.strip() remotePath = remotePath or "/validate/check" remoteSerial = self.get_tokeninfo("remote.serial") or "" remoteUser = self.get_tokeninfo("remote.user") or "" remoteRealm = self.get_tokeninfo("remote.realm") or "" remoteResolver = self.get_tokeninfo("remote.resolver") or "" # here we also need to check for remote.user and so on.... log.debug("checking OTP len:%r remotely on server: %r," " serial: %r, user: %r" % (len(otpval), remoteServer, remoteSerial, remoteUser)) params = {} if remoteSerial: params['serial'] = remoteSerial elif remoteUser: params['user'] = remoteUser params['realm'] = remoteRealm params['resolver'] = remoteResolver else: log.warning("The remote token does neither contain a " "remote.serial nor a remote.user.") return otp_count try: if remoteServer: # Deprecated params['pass'] = otpval request_url = "{0!s}{1!s}".format(remoteServer, remotePath) r = requests.post(request_url, data=params, verify=ssl_verify) elif pi_server_obj: r = pi_server_obj.validate_check(remoteUser, otpval, serial=remoteSerial, realm=remoteRealm, resolver=remoteResolver) if r.status_code == requests.codes.ok: response = r.json() result = response.get("result") if result.get("value"): otp_count = 1 # Add the serial of the used remote token in the tokeninfo parameters self.add_tokeninfo( "last_matching_remote_serial", response.get("detail", {}).get("serial")) except Exception as exx: # pragma: no cover log.error("Error getting response from " "remote Server (%r): %r" % (request_url, exx)) log.debug("{0!s}".format(traceback.format_exc())) return otp_count
def test_04_privacyidea_request(self): responses.add(responses.POST, "https://privacyidea/pi/validate/check", body="""{ "jsonrpc": "2.0", "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348", "detail": null, "version": "privacyIDEA 2.20.dev2", "result": { "status": true, "value": true}, "time": 1503561105.028947, "id": 1 }""", content_type="application/json") responses.add(responses.POST, "https://privacyidea/pi2/validate/check", body="""{ "jsonrpc": "2.0", "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348", "detail": null, "version": "privacyIDEA 2.20.dev2", "result": { "status": false}, "time": 1503561105.028947, "id": 1 }""", content_type="application/json", status=404) responses.add(responses.POST, "https://privacyidea/pi3/validate/check", body="""{ "jsonrpc": "2.0", "signature": "8714492288983608958721372435263469282038130269793819687538718333085851022315074567013564786433032592569773009757668260857150988825993253128403096686276017572870299270974318705442428477018018734211619614135162719525545735285162164985627482472020309913143284756699606758573589339750891246114721488327919685939018812698986042837837048205963507243718362073386749929275433723467277740468538209437683755941724140343215877868596281187733952567488886126455218397004400817126119660003078762499546137083926344365458736163867631154552432520453852071998486914168310985851091111203094188983006153929089352703802214328258347608348", "detail": null, "version": "privacyIDEA 2.20.dev2", "result": { "status": true, "value": false}, "time": 1503561105.028947, "id": 1 }""", content_type="application/json", status=404) # successful authentication r = add_privacyideaserver(identifier="pi", url="https://privacyidea/pi", tls=False) self.assertTrue(r > 0) pi = get_privacyideaserver("pi") r = PrivacyIDEAServer.request(pi.config, "user", "password") self.assertTrue(r) # failed authentication 404 r = add_privacyideaserver(identifier="pi2", url="https://privacyidea/pi2", tls=False) self.assertTrue(r > 0) pi = get_privacyideaserver("pi2") r = PrivacyIDEAServer.request(pi.config, "user", "password") self.assertFalse(r) # failed authentication value=false r = add_privacyideaserver(identifier="pi3", url="https://privacyidea/pi3", tls=False) self.assertTrue(r > 0) pi = get_privacyideaserver("pi3") r = PrivacyIDEAServer.request(pi.config, "user", "password") self.assertFalse(r)