def test_02_create_modify_delete_smsgateway_configuration(self): identifier = "myGW" provider_module = "privacyidea.lib.smsprovider.HTTPSmsPrpvoder" id = set_smsgateway(identifier, provider_module, description="test", options={ "HTTP_METHOD": "POST", "URL": "example.com" }) self.assertTrue(id > 0) gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "test") # update the description set_smsgateway(identifier, provider_module, description="This is a sensible description") gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "This is a sensible description") # update some options set_smsgateway(identifier, provider_module, options={ "HTTP_METHOD": "POST", "URL": "example.com", "new key": "value" }) gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 3) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), "example.com") self.assertEqual(gw[0].option_dict.get("new key"), "value") # delete a single option r = delete_smsgateway_option(id, "URL") gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 2) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), None) self.assertEqual(gw[0].option_dict.get("new key"), "value") # finally delete the gateway definition r = delete_smsgateway(identifier) self.assertEqual(r, id) # delete successful? gw = get_smsgateway() self.assertEqual(len(gw), 0)
def get_init_detail(self, params=None, user=None): """ This returns the init details during enrollment. In the 1st step the QR Code is returned. """ response_detail = TokenClass.get_init_detail(self, params, user) if "otpkey" in response_detail: del response_detail["otpkey"] params = params or {} user = user or User() tokenlabel = params.get("tokenlabel", "<s>") tokenissuer = params.get("tokenissuer", "privacyIDEA") sslverify = getParam(params, PUSH_ACTION.SSL_VERIFY, allowed_values=["0", "1"], default="1") # Add rollout state the response response_detail['rollout_state'] = self.token.rollout_state extra_data = {"enrollment_credential": self.get_tokeninfo("enrollment_credential")} imageurl = params.get("appimageurl") if imageurl: extra_data.update({"image": imageurl}) if self.token.rollout_state == "clientwait": # Get the values from the configured PUSH config fb_identifier = params.get(PUSH_ACTION.FIREBASE_CONFIG) firebase_configs = get_smsgateway(identifier=fb_identifier, gwtype=GWTYPE) if len(firebase_configs) != 1: raise ParameterError("Unknown Firebase configuration!") fb_options = firebase_configs[0].option_dict for k in [FIREBASE_CONFIG.PROJECT_NUMBER, FIREBASE_CONFIG.PROJECT_ID, FIREBASE_CONFIG.APP_ID, FIREBASE_CONFIG.API_KEY, FIREBASE_CONFIG.APP_ID_IOS, FIREBASE_CONFIG.API_KEY_IOS]: extra_data[k] = fb_options.get(k) # this allows to upgrade our crypto extra_data["v"] = 1 extra_data["serial"] = self.get_serial() extra_data["sslverify"] = sslverify # We display this during the first enrollment step! qr_url = create_push_token_url(url=fb_options.get(FIREBASE_CONFIG.REGISTRATION_URL), user=user.login, realm=user.realm, serial=self.get_serial(), tokenlabel=tokenlabel, issuer=tokenissuer, user_obj=user, extra_data=extra_data, ttl=fb_options.get(FIREBASE_CONFIG.TTL)) response_detail["pushurl"] = {"description": _("URL for privacyIDEA Push Token"), "value": qr_url, "img": create_img(qr_url, width=250) } self.add_tokeninfo(FIREBASE_CONFIG.PROJECT_ID, fb_options.get(FIREBASE_CONFIG.PROJECT_ID)) response_detail["enrollment_credential"] = self.get_tokeninfo("enrollment_credential") elif self.token.rollout_state == "enrolled": # in the second enrollment step we return the public key of the server to the smartphone. pubkey = strip_key(self.get_tokeninfo(PUBLIC_KEY_SERVER)) response_detail["public_key"] = pubkey return response_detail
def get_gateway(gwid=None): """ returns a json list of the gateway definitions Or returns a list of available sms providers with their configuration /smsgateway/providers """ res = {} # TODO: if the gateway definitions contains a password normal users should # not be allowed to read the configuration. Normal users should only be # allowed to read the identifier of the definitions! if gwid == "providers": for classname in SMS_PROVIDERS: smsclass = get_sms_provider_class( classname.rsplit(".", 1)[0], classname.rsplit(".", 1)[1]) res[classname] = smsclass.parameters() else: res = [gw.as_dict() for gw in get_smsgateway(id=gwid)] g.audit_object.log({"success": True}) return send_result(res)
def test_02_create_modify_delete_smsgateway_configuration(self): identifier = "myGW" provider_module = "privacyidea.lib.smsprovider.HTTPSmsPrpvoder" id = set_smsgateway(identifier, provider_module, description="test", options={"HTTP_METHOD": "POST", "URL": "example.com"}) self.assertTrue(id > 0) gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "test") # update the description set_smsgateway(identifier, provider_module, description="This is a sensible description") gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "This is a sensible description") # update some options set_smsgateway(identifier, provider_module, options={"HTTP_METHOD": "POST", "URL": "example.com", "new key": "value"}) gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 3) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), "example.com") self.assertEqual(gw[0].option_dict.get("new key"), "value") # delete a single option r = delete_smsgateway_option(id, "URL") gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 2) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), None) self.assertEqual(gw[0].option_dict.get("new key"), "value") # finally delete the gateway definition r = delete_smsgateway(identifier) self.assertEqual(r, id) # delete successful? gw = get_smsgateway() self.assertEqual(len(gw), 0)
def test_02_fail(self): # The script returns a failing rcode identifier = "myScriptSMS" config = {"background": SCRIPT_WAIT, "script": "fail.sh"} provider_module = "privacyidea.lib.smsprovider.ScriptSMSProvider" \ ".ScriptSMSProvider" id = set_smsgateway(identifier, provider_module, description="test", options=config) self.assertTrue(id > 0) sms = ScriptSMSProvider(smsgateway=get_smsgateway(identifier)[0], directory=self.directory) self.assertRaises(SMSError, sms.submit_message, "123456", "Hello") delete_smsgateway(identifier)
def test_02_success(self): # the script runs successfully identifier = "myScriptSMS" config = {"background": SCRIPT_WAIT, "script": "success.sh"} provider_module = "privacyidea.lib.smsprovider.ScriptSMSProvider" \ ".ScriptSMSProvider" id = set_smsgateway(identifier, provider_module, description="test", options=config) self.assertTrue(id > 0) sms = ScriptSMSProvider(smsgateway=get_smsgateway(identifier)[0], directory=self.directory) r = sms.submit_message("123456", "Hello") self.assertTrue(r) delete_smsgateway(identifier)
def upgrade(): # 1. Read the push_registration_url and ttl from the Firebase Config fb_gateways = get_smsgateway(gwtype=GWTYPE) print(fb_gateways) # 2. Check which policy contains this Firebase Config P = PolicyClass() pols = P.list_policies(scope=SCOPE.ENROLL, action="{0!s}".format(PUSH_ACTION.FIREBASE_CONFIG)) # iterate through all enrollment policies for pol in pols: # Check for all firebase gateways, if this policy needs to be modified for fbgw in fb_gateways: if pol.get("action").get( PUSH_ACTION.FIREBASE_CONFIG) == fbgw.identifier: print("Modifying policy {0!s}".format(pol.get("name"))) # This is an enrollment policy, that references this very firebase config # 3. Add the push_registration_url and ttl to this policy registration_url = fbgw.option_dict.get("registration URL") ttl = fbgw.option_dict.get("time to live") # We can leave most of the parameters None, since it will update the policy. # We still need to pass the original "active" and "check_all_resolvers" params # and we need to update the action action = pol.get("action") # Only add registration_url and ttl to the policy, if these values actually exist, # to avoid deleting (setting an empty value) in the policy. if registration_url: action[PUSH_ACTION.REGISTRATION_URL] = registration_url if ttl: action[PUSH_ACTION.TTL] = ttl r = set_policy( name=pol.get("name"), scope=SCOPE.ENROLL, active=pol.get("active"), check_all_resolvers=pol.get("check_all_resolvers"), action=action) print("+- Updated policy {0!s}: {1!s}".format( pol.get("name"), r)) # 4. Delete push_registration_url and ttl from the Firebase Config # Note: If we had a firebase config, that would not be used in a policy, # the url and ttl would not be deleted from the firebase config. But this # does not matter. I like to keep it in this for-loop to avoid side unknown side effects. print("Deleting URL and TTL from the Firebase Gateway config.") if registration_url: delete_smsgateway_option(fbgw.id, "registration URL") if ttl: delete_smsgateway_option(fbgw.id, "time to live")
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ smtpserver_objs = get_smtpservers() smsgateway_dicts = get_smsgateway() smsgateways = [sms.identifier for sms in smsgateway_dicts] smtpservers = [s.config.identifier for s in smtpserver_objs] actions = {"sendmail": {"emailconfig": {"type": "str", "required": True, "description": _("Send notification " "email via this " "email server."), "value": smtpservers}, "subject": {"type": "str", "required": False, "description": _("The subject of " "the mail that " "is sent.") }, "body": {"type": "text", "required": False, "description": _("The body of the " "mail that is sent.")} }, "sendsms": {"smsconfig": {"type": "str", "required": True, "description": _("Send the user " "notification via a " "predefined SMS " "gateway."), "value": smsgateways}, "body": {"type": "text", "required": False, "description": _("The text of the SMS.")} } } return actions
def test_01_fail_no_script(self): # The script does not exist identifier = "myScriptSMS" config = { "background": SCRIPT_WAIT, "script": "sms-script-does-not-exist.sh" } provider_module = "privacyidea.lib.smsprovider.ScriptSMSProvider" \ ".ScriptSMSProvider" id = set_smsgateway(identifier, provider_module, description="test", options=config) self.assertTrue(id > 0) sms = ScriptSMSProvider(smsgateway=get_smsgateway(identifier)[0], directory=self.directory) self.assertRaises(SMSError, sms.submit_message, "123456", "Hello") delete_smsgateway(identifier) # We bail out, fi no smsgateway definition is given! sms = ScriptSMSProvider(directory=self.directory) self.assertRaises(SMSError, sms.submit_message, "123456", "Hello")
def get_gateway(gwid=None): """ returns a json list of the gateway definitions Or returns a list of available sms providers with their configuration /smsgateway/providers """ res = {} # TODO: if the gateway definitions contains a password normal users should # not be allowed to read the configuration. Normal users should only be # allowed to read the identifier of the definitions! if gwid == "providers": for classname in SMS_PROVIDERS: smsclass = get_sms_provider_class(classname.rsplit(".", 1)[0], classname.rsplit(".", 1)[1]) res[classname] = smsclass.parameters() else: res = [gw.as_dict() for gw in get_smsgateway(id=gwid)] g.audit_object.log({"success": True}) return send_result(res)
def test_02_create_modify_delete_smsgateway_configuration(self): identifier = "myGW" provider_module = "privacyidea.lib.smsprovider.HttpSMSProvider.HttpSMSProvider" id = set_smsgateway(identifier, provider_module, description="test", options={ "HTTP_METHOD": "POST", "URL": "example.com" }, headers={ "Authorization": "QWERTZ", "BANANA": "will be eaten" }) self.assertTrue(id > 0) gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "test") # update the description set_smsgateway(identifier, provider_module, description="This is a sensible description") gw = get_smsgateway(id=id) self.assertEqual(gw[0].description, "This is a sensible description") # update some options set_smsgateway(identifier, provider_module, options={ "HTTP_METHOD": "POST", "URL": "example.com", "IDENTICAL_KEY": "new option" }, headers={ "Authorization": "ValueChanged", "IDENTICAL_KEY": "new header", "URL": "URL_in_headers" }) gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 3) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), "example.com") self.assertEqual(gw[0].option_dict.get("IDENTICAL_KEY"), "new option") self.assertEqual(gw[0].header_dict.get("Authorization"), "ValueChanged") self.assertEqual(gw[0].header_dict.get("BANANA"), None) self.assertEqual(gw[0].header_dict.get("IDENTICAL_KEY"), "new header") self.assertEqual(gw[0].header_dict.get("URL"), "URL_in_headers") # delete a single option r = delete_smsgateway_option(id, "URL") gw = get_smsgateway(id=id) self.assertEqual(len(gw[0].option_dict), 2) self.assertEqual(gw[0].option_dict.get("HTTP_METHOD"), "POST") self.assertEqual(gw[0].option_dict.get("URL"), None) self.assertEqual(gw[0].option_dict.get("IDENTICAL_KEY"), "new option") # delete a single header r = delete_smsgateway_header(id, "IDENTICAL_KEY") gw = get_smsgateway(id=id) self.assertEqual(gw[0].header_dict.get("IDENTICAL_KEY"), None) # delete a single header via generic function r = delete_smsgateway_key_generic(id, "URL", Type="header") gw = get_smsgateway(id=id) self.assertEqual(gw[0].header_dict.get("URL"), None) # finally delete the gateway definition r = delete_smsgateway(identifier) self.assertEqual(r, id) # delete successful? gw = get_smsgateway() self.assertEqual(len(gw), 0)
def get_class_info(key=None, ret='all'): """ returns all or a subtree of the token definition :param key: subsection identifier :type key: str :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype : s.o. """ gws = get_smsgateway(gwtype=GWTYPE) res = { 'type': 'push', 'title': _('PUSH Token'), 'description': _('PUSH: Send a push notification to a smartphone.'), 'user': ['enroll'], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin", "user"], 'policy': { SCOPE.ENROLL: { PUSH_ACTION.FIREBASE_CONFIG: { 'type': 'str', 'desc': _('The configuration of your Firebase application.'), 'group': "PUSH", 'value': [gw.identifier for gw in gws] }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during the enrollment. (default 1)' ), 'group': "PUSH", 'value': ["0", "1"] } }, SCOPE.AUTH: { PUSH_ACTION.MOBILE_TEXT: { 'type': 'str', 'desc': _('The question the user sees on his mobile phone.'), 'group': 'PUSH' }, PUSH_ACTION.MOBILE_TITLE: { 'type': 'str', 'desc': _('The title of the notification, the user sees on his mobile phone.' ), 'group': 'PUSH' }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during authentication. (default 1)' ), 'group': "PUSH", 'value': ["0", "1"] } } }, } if key: ret = res.get(key, {}) else: if ret == 'all': ret = res return ret
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ smtpserver_objs = get_smtpservers() smsgateway_dicts = get_smsgateway() smsgateways = [sms.identifier for sms in smsgateway_dicts] smtpservers = [s.config.identifier for s in smtpserver_objs] actions = {"sendmail": {"emailconfig": {"type": "str", "required": True, "description": _("Send notification " "email via this " "email server."), "value": smtpservers}, "subject": {"type": "str", "required": False, "description": _("The subject of " "the mail that " "is sent.") }, "body": {"type": "text", "required": False, "description": _("The body of the " "mail that is " "sent.")}, "To": {"type": "str", "required": True, "description": _("Send notification to " "this user."), "value": [ NOTIFY_TYPE.TOKENOWNER, NOTIFY_TYPE.LOGGED_IN_USER, NOTIFY_TYPE.INTERNAL_ADMIN, NOTIFY_TYPE.ADMIN_REALM, NOTIFY_TYPE.EMAIL]}, "To "+NOTIFY_TYPE.ADMIN_REALM: { "type": "str", "value": current_app.config.get( "SUPERUSER_REALM", []), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.ADMIN_REALM}, "To "+NOTIFY_TYPE.INTERNAL_ADMIN: { "type": "str", "value": [a.username for a in get_db_admins()], "visibleIf": "To", "visibleValue": NOTIFY_TYPE.INTERNAL_ADMIN}, "To "+NOTIFY_TYPE.EMAIL: { "type": "str", "description": _("Any email address, to " "which the notification " "should be sent."), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.EMAIL} }, "sendsms": {"smsconfig": {"type": "str", "required": True, "description": _("Send the user " "notification via a " "predefined SMS " "gateway."), "value": smsgateways}, "body": {"type": "text", "required": False, "description": _("The text of the " "SMS.")}, "To": {"type": "str", "required": True, "description": _("Send notification to " "this user."), "value": [NOTIFY_TYPE.TOKENOWNER]} } } return actions
def get_class_info(key=None, ret='all'): """ returns all or a subtree of the token definition :param key: subsection identifier :type key: str :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype : s.o. """ gws = get_smsgateway(gwtype=GWTYPE) res = {'type': 'push', 'title': _('PUSH Token'), 'description': _('PUSH: Send a push notification to a smartphone.'), 'user': ['enroll'], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin", "user"], 'policy': { SCOPE.ENROLL: { PUSH_ACTION.FIREBASE_CONFIG: { 'type': 'str', 'desc': _('The configuration of your Firebase application.'), 'group': "PUSH", 'value': [gw.identifier for gw in gws] }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during the enrollment. (default 1)'), 'group': "PUSH", 'value': ["0", "1"] } }, SCOPE.AUTH: { PUSH_ACTION.MOBILE_TEXT: { 'type': 'str', 'desc': _('The question the user sees on his mobile phone.'), 'group': 'PUSH' }, PUSH_ACTION.MOBILE_TITLE: { 'type': 'str', 'desc': _('The title of the notification, the user sees on his mobile phone.'), 'group': 'PUSH' }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during authentication. (default 1)'), 'group': "PUSH", 'value': ["0", "1"] } } }, } if key: ret = res.get(key, {}) else: if ret == 'all': ret = res return ret
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ smtpserver_objs = get_smtpservers() smsgateway_dicts = get_smsgateway() smsgateways = [sms.identifier for sms in smsgateway_dicts] smtpservers = [s.config.identifier for s in smtpserver_objs] actions = { "sendmail": { "emailconfig": { "type": "str", "required": True, "description": _("Send notification email via this email server."), "value": smtpservers }, "mimetype": { "type": "str", "description": _("Either send email as plain text or HTML."), "value": ["plain", "html"] }, "attach_qrcode": { "type": "bool", "description": _("Send QR-Code image as an attachment " "(cid URL: token_image)") }, "subject": { "type": "str", "required": False, "description": _("The subject of the mail that is sent.") }, "reply_to": { "type": "str", "required": False, "description": _("The Reply-To header in the sent email."), "value": [ NOTIFY_TYPE.NO_REPLY_TO, NOTIFY_TYPE.TOKENOWNER, NOTIFY_TYPE.LOGGED_IN_USER, NOTIFY_TYPE.INTERNAL_ADMIN, NOTIFY_TYPE.ADMIN_REALM, NOTIFY_TYPE.EMAIL ] }, "reply_to " + NOTIFY_TYPE.ADMIN_REALM: { "type": "str", "value": get_app_config_value("SUPERUSER_REALM", []), "visibleIf": "reply_to", "visibleValue": NOTIFY_TYPE.ADMIN_REALM }, "reply_to " + NOTIFY_TYPE.INTERNAL_ADMIN: { "type": "str", "value": [a.username for a in get_db_admins()], "visibleIf": "reply_to", "visibleValue": NOTIFY_TYPE.INTERNAL_ADMIN }, "reply_to " + NOTIFY_TYPE.EMAIL: { "type": "str", "description": _("Any email address, to which the notification " "should be sent."), "visibleIf": "reply_to", "visibleValue": NOTIFY_TYPE.EMAIL }, "body": { "type": "text", "required": False, "description": _("The body of the mail that is sent.") }, "To": { "type": "str", "required": True, "description": _("Send notification to this user."), "value": [ NOTIFY_TYPE.TOKENOWNER, NOTIFY_TYPE.LOGGED_IN_USER, NOTIFY_TYPE.INTERNAL_ADMIN, NOTIFY_TYPE.ADMIN_REALM, NOTIFY_TYPE.EMAIL ] }, "To " + NOTIFY_TYPE.ADMIN_REALM: { "type": "str", "value": get_app_config_value("SUPERUSER_REALM", []), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.ADMIN_REALM }, "To " + NOTIFY_TYPE.INTERNAL_ADMIN: { "type": "str", "value": [a.username for a in get_db_admins()], "visibleIf": "To", "visibleValue": NOTIFY_TYPE.INTERNAL_ADMIN }, "To " + NOTIFY_TYPE.EMAIL: { "type": "str", "description": _("Any email address, to which the notification " "should be sent."), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.EMAIL } }, "sendsms": { "smsconfig": { "type": "str", "required": True, "description": _("Send the user notification via a " "predefined SMS gateway."), "value": smsgateways }, "body": { "type": "text", "required": False, "description": _("The text of the SMS.") }, "To": { "type": "str", "required": True, "description": _("Send notification to this user."), "value": [NOTIFY_TYPE.TOKENOWNER] } }, "savefile": { "body": { "type": "text", "required": True, "description": _("This is the template content of " "the new file. Can contain the tags " "as specified in the documentation.") }, "filename": { "type": "str", "required": True, "description": _("The filename of the notification. Existing files " "are overwritten. The name can contain tags as specified " "in the documentation and can also contain the tag {random}." ) } } } return actions
def get_class_info(key=None, ret='all'): """ returns all or a subtree of the token definition :param key: subsection identifier :type key: string :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype : s.o. """ sms_gateways = [gw.identifier for gw in get_smsgateway()] res = {'type': 'sms', 'title': _('SMS Token'), 'description': _('SMS: Send a One Time Password to the users mobile ' 'phone.'), 'user': ['enroll'], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin", "user"], 'policy': { SCOPE.AUTH: { SMSACTION.SMSTEXT: { 'type': 'str', 'desc': _('The text that will be send via SMS for' ' an SMS token. Use <otp> and <serial> ' 'as parameters.')}, SMSACTION.SMSAUTO: { 'type': 'bool', 'desc': _('If set, a new SMS OTP will be sent ' 'after successful authentication with ' 'one SMS OTP.')}, ACTION.CHALLENGETEXT: { 'type': 'str', 'desc': _('Use an alternate challenge text for telling the ' 'user to enter the code from the SMS.') } }, SCOPE.ADMIN: { SMSACTION.GATEWAYS: { 'type': 'str', 'desc': u"{0!s} ({1!s})".format( _('Choose the gateways the administrator is allowed to set.'), " ".join(sms_gateways)) } }, SCOPE.USER: { SMSACTION.GATEWAYS: { 'type': 'str', 'desc': u"{0!s} ({1!s})".format( _('Choose the gateways the user is allowed to set.'), " ".join(sms_gateways)) } }, }, } if key: ret = res.get(key, {}) else: if ret == 'all': ret = res return ret
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ smtpserver_objs = get_smtpservers() smsgateway_dicts = get_smsgateway() smsgateways = [sms.identifier for sms in smsgateway_dicts] smtpservers = [s.config.identifier for s in smtpserver_objs] actions = { "sendmail": { "emailconfig": { "type": "str", "required": True, "description": _("Send notification " "email via this " "email server."), "value": smtpservers }, "subject": { "type": "str", "required": False, "description": _("The subject of " "the mail that " "is sent.") }, "body": { "type": "text", "required": False, "description": _("The body of the " "mail that is sent.") } }, "sendsms": { "smsconfig": { "type": "str", "required": True, "description": _("Send the user " "notification via a " "predefined SMS " "gateway."), "value": smsgateways }, "body": { "type": "text", "required": False, "description": _("The text of the SMS.") } } } return actions
def get_class_info(key=None, ret='all'): """ returns all or a subtree of the token definition :param key: subsection identifier :type key: str :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype: dict """ gws = get_smsgateway(gwtype=GWTYPE) res = { 'type': 'push', 'title': _('PUSH Token'), 'description': _('PUSH: Send a push notification to a smartphone.'), 'user': ['enroll'], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin", "user"], 'policy': { SCOPE.ENROLL: { PUSH_ACTION.FIREBASE_CONFIG: { 'type': 'str', 'desc': _('The configuration of your Firebase application.'), 'group': "PUSH", 'value': [POLL_ONLY] + [gw.identifier for gw in gws] }, PUSH_ACTION.REGISTRATION_URL: { "required": True, 'type': 'str', 'group': "PUSH", 'desc': _('The URL the Push App should contact in the second enrollment step.' ' Usually it is the endpoint /ttype/push of the privacyIDEA server.' ) }, PUSH_ACTION.TTL: { 'type': 'int', 'group': "PUSH", 'desc': _('The second enrollment step must be completed within this time (in minutes).' ) }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during the enrollment. (default 1)' ), 'group': "PUSH", 'value': ["0", "1"] }, ACTION.MAXTOKENUSER: { 'type': 'int', 'desc': _("The user may only have this maximum number of Push tokens assigned." ), 'group': GROUP.TOKEN }, ACTION.MAXACTIVETOKENUSER: { 'type': 'int', 'desc': _("The user may only have this maximum number of active Push tokens assigned." ), 'group': GROUP.TOKEN } }, SCOPE.AUTH: { PUSH_ACTION.MOBILE_TEXT: { 'type': 'str', 'desc': _('The question the user sees on his mobile phone.'), 'group': 'PUSH' }, PUSH_ACTION.MOBILE_TITLE: { 'type': 'str', 'desc': _('The title of the notification, the user sees on his mobile phone.' ), 'group': 'PUSH' }, PUSH_ACTION.SSL_VERIFY: { 'type': 'str', 'desc': _('The smartphone needs to verify SSL during authentication. (default 1)' ), 'group': "PUSH", 'value': ["0", "1"] }, PUSH_ACTION.WAIT: { 'type': 'int', 'desc': _('Wait for number of seconds for the user ' 'to confirm the challenge in the first request.'), 'group': "PUSH" }, PUSH_ACTION.ALLOW_POLLING: { 'type': 'str', 'desc': _('Configure whether to allow push tokens to poll for ' 'challenges'), 'group': 'PUSH', 'value': [ PushAllowPolling.ALLOW, PushAllowPolling.DENY, PushAllowPolling.TOKEN ], 'default': PushAllowPolling.ALLOW } } }, } if key: ret = res.get(key, {}) else: if ret == 'all': ret = res return ret
def get_class_info(key=None, ret='all'): """ returns all or a subtree of the token definition :param key: subsection identifier :type key: string :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype : s.o. """ sms_gateways = [gw.identifier for gw in get_smsgateway()] res = { 'type': 'sms', 'title': _('SMS Token'), 'description': _('SMS: Send a One Time Password to the users mobile ' 'phone.'), 'user': ['enroll'], # This tokentype is enrollable in the UI for... 'ui_enroll': ["admin", "user"], 'policy': { SCOPE.AUTH: { SMSACTION.SMSTEXT: { 'type': 'str', 'desc': _('The text that will be send via SMS for' ' an SMS token. Use <otp> and <serial> ' 'as parameters.') }, SMSACTION.SMSAUTO: { 'type': 'bool', 'desc': _('If set, a new SMS OTP will be sent ' 'after successful authentication with ' 'one SMS OTP.') }, ACTION.CHALLENGETEXT: { 'type': 'str', 'desc': _('Use an alternate challenge text for telling the ' 'user to enter the code from the SMS.') } }, SCOPE.ADMIN: { SMSACTION.GATEWAYS: { 'type': 'str', 'desc': u"{0!s} ({1!s})".format( _('Choose the gateways the administrator is allowed to set.' ), " ".join(sms_gateways)) } }, SCOPE.USER: { SMSACTION.GATEWAYS: { 'type': 'str', 'desc': u"{0!s} ({1!s})".format( _('Choose the gateways the user is allowed to set.' ), " ".join(sms_gateways)) } }, SCOPE.ENROLL: { ACTION.MAXTOKENUSER: { 'type': 'int', 'desc': _("The user may only have this maximum number of SMS tokens assigned." ), 'group': GROUP.TOKEN }, ACTION.MAXACTIVETOKENUSER: { 'type': 'int', 'desc': _("The user may only have this maximum number of active SMS tokens assigned." ), 'group': GROUP.TOKEN } } }, } if key: ret = res.get(key, {}) else: if ret == 'all': ret = res return ret
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ realm_list = list(get_realms()) actions = {ACTION_TYPE.SET_TOKENREALM: {"realm": {"type": "str", "required": True, "description": _("set a new realm of the token"), "value": realm_list}, "only_realm": {"type": "bool", "description": _("The new realm will be the only " "realm of the token. I.e. all " "other realms will be removed " "from this token. Otherwise the " "realm will be added to the token.") } }, ACTION_TYPE.DELETE: {}, ACTION_TYPE.UNASSIGN: {}, ACTION_TYPE.DISABLE: {}, ACTION_TYPE.ENABLE: {}, ACTION_TYPE.SET_RANDOM_PIN: { "length": {"type": "int", "required": True, "description": _("set the PIN of the token to a random PIN of this length."), "value": list(range(1,32))} }, ACTION_TYPE.INIT: {"tokentype": {"type": "str", "required": True, "description": _("Token type to create"), "value": get_token_types() }, "user": {"type": "bool", "description": _("Assign token to user in " "request or to tokenowner.")}, "realm": {"type": "str", "required": False, "description": _("Set the realm of the newly " "created token."), "value": realm_list}, "dynamic_phone": { "type": "bool", "visibleIf": "tokentype", "visibleValue": "sms", "description": _("Dynamically read the mobile number " "from the user store.") }, "dynamic_email": { "type": "bool", "visibleIf": "tokentype", "visibleValue": "email", "description": _("Dynamically read the email address " "from the user store.") }, "smtp_identifier": { "type": "str", "visibleIf": "tokentype", "visibleValue": "email", "description": _("Use a specific SMTP server configuration for this token."), "value": [server.config.identifier for server in get_smtpservers()] }, "sms_identifier": { "type": "str", "visibleIf": "tokentype", "visibleValue": "sms", "description": _("Use a specific SMS gateway configuration for this token."), "value": [gateway.identifier for gateway in get_smsgateway()] }, "additional_params": { "type": "str", "description": _("A dictionary of additional init parameters.") }, "motppin": { "type": "str", "visibleIf": "tokentype", "visibleValue": "motp", "description": _("Set the MOTP PIN of the MOTP " "token during enrollment. This " "is a required value for " "enrolling MOTP tokens.")} }, ACTION_TYPE.SET_DESCRIPTION: {"description": { "type": "str", "description": _("The new description of the " "token.") } }, ACTION_TYPE.SET_VALIDITY: {VALIDITY.START: { "type": "str", "description": _("The token will be valid starting " "at the given date. Can be a fixed " "date or an offset like +10m, " "+24h, +7d.") }, VALIDITY.END: { "type": "str", "description": _("The token will be valid until " "the given date. Can be a fixed " "date or an offset like +10m, " "+24h, +7d.") } }, ACTION_TYPE.SET_COUNTWINDOW: {"count window": { # TODO: should be "int" but we do not support # this at the moment. "type": "str", "required": True, "description": _("Set the new count window of " "the token.") } }, ACTION_TYPE.SET_FAILCOUNTER: { "fail counter": { "type": "str", "required": True, "description": _("Set the failcounter of " "the token.") } }, ACTION_TYPE.CHANGE_FAILCOUNTER: { "change fail counter": { "type": "str", "required": True, "description": _("Increase or decrease the fail counter of the token. " "Values of +n, -n with n being an integer are accepted.") } }, ACTION_TYPE.SET_TOKENINFO: {"key": { "type": "str", "required": True, "description": _("Set this tokeninfo key.") }, "value": { "type": "str", "description": _("Set the above key the this " "value.") } }, ACTION_TYPE.DELETE_TOKENINFO: {"key": { "type": "str", "required": True, "description": _("Delete this tokeninfo key.") } } } return actions
def actions(cls): """ This method returns a dictionary of allowed actions and possible options in this handler module. :return: dict with actions """ smtpserver_objs = get_smtpservers() smsgateway_dicts = get_smsgateway() smsgateways = [sms.identifier for sms in smsgateway_dicts] smtpservers = [s.config.identifier for s in smtpserver_objs] actions = {"sendmail": {"emailconfig": {"type": "str", "required": True, "description": _("Send notification " "email via this " "email server."), "value": smtpservers}, "mimetype": {"type": "str", "description": _("Either send " "email as plain text or HTML."), "value": ["plain", "html"]}, "subject": {"type": "str", "required": False, "description": _("The subject of " "the mail that " "is sent.")}, "reply_to": {"type": "str", "required": False, "description": _("The Reply-To " "header in the " "sent email.")}, "body": {"type": "text", "required": False, "description": _("The body of the " "mail that is " "sent.")}, "To": {"type": "str", "required": True, "description": _("Send notification to " "this user."), "value": [ NOTIFY_TYPE.TOKENOWNER, NOTIFY_TYPE.LOGGED_IN_USER, NOTIFY_TYPE.INTERNAL_ADMIN, NOTIFY_TYPE.ADMIN_REALM, NOTIFY_TYPE.EMAIL]}, "To "+NOTIFY_TYPE.ADMIN_REALM: { "type": "str", "value": get_app_config_value("SUPERUSER_REALM", []), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.ADMIN_REALM}, "To "+NOTIFY_TYPE.INTERNAL_ADMIN: { "type": "str", "value": [a.username for a in get_db_admins()], "visibleIf": "To", "visibleValue": NOTIFY_TYPE.INTERNAL_ADMIN}, "To "+NOTIFY_TYPE.EMAIL: { "type": "str", "description": _("Any email address, to " "which the notification " "should be sent."), "visibleIf": "To", "visibleValue": NOTIFY_TYPE.EMAIL} }, "sendsms": {"smsconfig": {"type": "str", "required": True, "description": _("Send the user " "notification via a " "predefined SMS " "gateway."), "value": smsgateways}, "body": {"type": "text", "required": False, "description": _("The text of the " "SMS.")}, "To": {"type": "str", "required": True, "description": _("Send notification to " "this user."), "value": [NOTIFY_TYPE.TOKENOWNER]} } } return actions