diff --git a/apps/authentication/const.py b/apps/authentication/const.py index d85afed75..d7e0690db 100644 --- a/apps/authentication/const.py +++ b/apps/authentication/const.py @@ -2,7 +2,7 @@ from django.db.models import TextChoices from authentication.confirm import CONFIRM_BACKENDS from .confirm import ConfirmMFA, ConfirmPassword, ConfirmReLogin -from .mfa import MFAOtp, MFASms, MFARadius +from .mfa import MFAOtp, MFASms, MFARadius, MFACustom RSA_PRIVATE_KEY = 'rsa_private_key' RSA_PUBLIC_KEY = 'rsa_public_key' @@ -35,3 +35,4 @@ class MFAType(TextChoices): OTP = MFAOtp.name, MFAOtp.display_name SMS = MFASms.name, MFASms.display_name Radius = MFARadius.name, MFARadius.display_name + Custom = MFACustom.name, MFACustom.display_name diff --git a/apps/authentication/mfa/__init__.py b/apps/authentication/mfa/__init__.py index 16279eb0d..077b6c12c 100644 --- a/apps/authentication/mfa/__init__.py +++ b/apps/authentication/mfa/__init__.py @@ -1,5 +1,4 @@ from .otp import MFAOtp, otp_failed_msg from .sms import MFASms from .radius import MFARadius - -MFA_BACKENDS = [MFAOtp, MFASms, MFARadius] +from .custom import MFACustom diff --git a/apps/authentication/mfa/custom.py b/apps/authentication/mfa/custom.py new file mode 100644 index 000000000..3b671f709 --- /dev/null +++ b/apps/authentication/mfa/custom.py @@ -0,0 +1,59 @@ +from django.conf import settings +from django.utils.module_loading import import_string +from django.utils.translation import ugettext_lazy as _ + +from common.utils import get_logger +from .base import BaseMFA + +logger = get_logger(__file__) + +mfa_custom_method = None + +if settings.MFA_CUSTOM: + """ 保证自定义认证方法在服务运行时不能被更改,只在第一次调用时加载一次 """ + try: + mfa_custom_method_path = 'data.mfa.main.check_code' + mfa_custom_method = import_string(mfa_custom_method_path) + except Exception as e: + logger.warning('Import custom auth method failed: {}, Maybe not enabled'.format(e)) + +custom_failed_msg = _("MFA Custom code invalid") + + +class MFACustom(BaseMFA): + name = 'mfa_custom' + display_name = 'Custom' + placeholder = _("MFA custom verification code") + + def check_code(self, code): + assert self.is_authenticated() + ok = False + try: + ok = mfa_custom_method(user=self.user, code=code) + except Exception as exc: + logger.error('Custom authenticate error: {}'.format(exc)) + msg = '' if ok else custom_failed_msg + return ok, msg + + def is_active(self): + return True + + @staticmethod + def global_enabled(): + return settings.MFA_CUSTOM and callable(mfa_custom_method) + + def get_enable_url(self) -> str: + return '' + + def can_disable(self): + return False + + def disable(self): + return '' + + @staticmethod + def help_text_of_disable(): + return _("MFA custom global enabled, cannot disable") + + def get_disable_url(self) -> str: + return '' diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index d7e4aee14..0bde002ea 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -227,6 +227,10 @@ class Config(dict): 'AUTH_CUSTOM': False, 'AUTH_CUSTOM_FILE_MD5': '', + # Custom Config + 'MFA_CUSTOM': False, + 'MFA_CUSTOM_FILE_MD5': '', + # Auth LDAP settings 'AUTH_LDAP': False, 'AUTH_LDAP_SERVER_URI': 'ldap://localhost:389', diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py index 2cf47e9fe..b4f1d3f9f 100644 --- a/apps/jumpserver/settings/auth.py +++ b/apps/jumpserver/settings/auth.py @@ -51,7 +51,6 @@ AUTH_LDAP_SYNC_CRONTAB = CONFIG.AUTH_LDAP_SYNC_CRONTAB AUTH_LDAP_SYNC_ORG_ID = CONFIG.AUTH_LDAP_SYNC_ORG_ID AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS = CONFIG.AUTH_LDAP_USER_LOGIN_ONLY_IN_USERS - # ============================================================================== # 认证 OpenID 配置参数 # 参考: https://django-oidc-rp.readthedocs.io/en/stable/settings.html @@ -180,7 +179,6 @@ if CONNECTION_TOKEN_EXPIRATION < 5 * 60: # 最少5分钟 CONNECTION_TOKEN_EXPIRATION = 5 * 60 - RBAC_BACKEND = 'rbac.backends.RBACBackend' AUTH_BACKEND_MODEL = 'authentication.backends.base.JMSModelBackend' AUTH_BACKEND_PUBKEY = 'authentication.backends.pubkey.PublicKeyAuthBackend' @@ -203,7 +201,7 @@ AUTHENTICATION_BACKENDS = [ # 只做权限校验 RBAC_BACKEND, # 密码形式 - AUTH_BACKEND_MODEL, AUTH_BACKEND_PUBKEY, AUTH_BACKEND_LDAP, AUTH_BACKEND_RADIUS, + AUTH_BACKEND_MODEL, AUTH_BACKEND_PUBKEY, AUTH_BACKEND_LDAP, AUTH_BACKEND_RADIUS, # 跳转形式 AUTH_BACKEND_CAS, AUTH_BACKEND_OIDC_PASSWORD, AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_SAML2, AUTH_BACKEND_OAUTH2, @@ -236,7 +234,22 @@ if AUTH_CUSTOM and AUTH_CUSTOM_FILE_MD5 == get_file_md5(AUTH_CUSTOM_FILE_PATH): # 自定义认证模块 AUTHENTICATION_BACKENDS.append(AUTH_BACKEND_CUSTOM) -AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2, AUTH_BACKEND_OAUTH2] +MFA_BACKEND_OTP = 'authentication.mfa.otp.MFAOtp' +MFA_BACKEND_RADIUS = 'authentication.mfa.radius.MFARadius' +MFA_BACKEND_SMS = 'authentication.mfa.sms.MFASms' +MFA_BACKEND_CUSTOM = 'authentication.mfa.custom.MFACustom' + +MFA_BACKENDS = [MFA_BACKEND_OTP, MFA_BACKEND_RADIUS, MFA_BACKEND_SMS] + +MFA_CUSTOM = CONFIG.MFA_CUSTOM +MFA_CUSTOM_FILE_MD5 = CONFIG.MFA_CUSTOM_FILE_MD5 +MFA_CUSTOM_FILE_PATH = os.path.join(PROJECT_DIR, 'data', 'mfa', 'main.py') +if MFA_CUSTOM and MFA_CUSTOM_FILE_MD5 == get_file_md5(MFA_CUSTOM_FILE_PATH): + # 自定义多因子认证模块 + MFA_BACKENDS.append(MFA_BACKEND_CUSTOM) + +AUTHENTICATION_BACKENDS_THIRD_PARTY = [AUTH_BACKEND_OIDC_CODE, AUTH_BACKEND_CAS, AUTH_BACKEND_SAML2, + AUTH_BACKEND_OAUTH2] ONLY_ALLOW_EXIST_USER_AUTH = CONFIG.ONLY_ALLOW_EXIST_USER_AUTH ONLY_ALLOW_AUTH_FROM_SOURCE = CONFIG.ONLY_ALLOW_AUTH_FROM_SOURCE diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 978aa3137..cd92cc294 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,4 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7522cd9a7e7853d078c81006cea7f6dbe4fb9d51ae7c6dddd50e8471536d4c0d -size 133026 +oid sha256:057dff28011cd49805396d87bd8dd17745f8f44d23bb5f26d7a29f581ffe206c +size 132904 + diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index efd3e1163..6c5eb1ee8 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -30,9 +30,9 @@ msgstr "Acls" #: orgs/models.py:70 perms/models/base.py:83 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/endpoint.py:14 terminal/models/endpoint.py:87 -#: terminal/models/storage.py:27 terminal/models/task.py:16 -#: terminal/models/terminal.py:101 users/forms/profile.py:33 -#: users/models/group.py:15 users/models/user.py:669 +#: terminal/models/storage.py:26 terminal/models/task.py:16 +#: terminal/models/terminal.py:100 users/forms/profile.py:33 +#: users/models/group.py:15 users/models/user.py:673 #: xpack/plugins/cloud/models.py:28 msgid "Name" msgstr "名前" @@ -64,7 +64,6 @@ msgstr "アクティブ" #: terminal/models/endpoint.py:22 terminal/models/endpoint.py:97 #: terminal/models/storage.py:30 terminal/models/terminal.py:115 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 -#: users/models/group.py:16 users/models/user.py:708 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/gathered_user/models.py:26 @@ -93,9 +92,6 @@ msgstr "ログイン確認" #: orgs/models.py:220 perms/models/base.py:84 rbac/builtin.py:120 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 -#: terminal/models/sharing.py:33 terminal/notifications.py:94 -#: terminal/notifications.py:142 tickets/models/comment.py:21 users/const.py:14 -#: users/models/user.py:901 users/models/user.py:932 #: users/serializers/group.py:19 msgid "User" msgstr "ユーザー" @@ -161,10 +157,6 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: authentication/models.py:260 authentication/serializers/password_mfa.py:25 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 -#: ops/models/adhoc.py:159 users/forms/profile.py:32 users/forms/profile.py:102 -#: users/models/user.py:667 users/templates/users/_msg_user_created.html:12 -#: users/templates/users/forgot_password.html:51 -#: users/templates/users/forgot_password.html:98 #: xpack/plugins/change_auth_plan/models/asset.py:34 #: xpack/plugins/change_auth_plan/models/asset.py:195 #: xpack/plugins/cloud/serializers/account_attrs.py:26 @@ -363,8 +355,6 @@ msgstr "タイプ表示" #: authentication/models.py:22 common/db/models.py:116 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 #: orgs/models.py:72 orgs/models.py:223 perms/models/base.py:92 -#: users/models/group.py:18 users/models/user.py:933 -#: xpack/plugins/change_auth_plan/models/base.py:45 #: xpack/plugins/cloud/models.py:125 msgid "Date created" msgstr "作成された日付" @@ -644,10 +634,6 @@ msgid "Labels" msgstr "ラベル" #: assets/models/asset.py:229 assets/models/base.py:183 -#: assets/models/cluster.py:28 assets/models/cmd_filter.py:56 -#: assets/models/cmd_filter.py:103 assets/models/group.py:21 -#: common/db/models.py:114 common/mixins/models.py:49 orgs/models.py:71 -#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:716 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -872,7 +858,7 @@ msgid "Default" msgstr "デフォルト" #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 -#: users/models/user.py:918 +#: users/models/user.py:920 msgid "System" msgstr "システム" @@ -881,7 +867,7 @@ msgid "Default Cluster" msgstr "デフォルトクラスター" #: assets/models/cmd_filter.py:34 perms/models/base.py:86 -#: users/models/group.py:31 users/models/user.py:675 +#: users/models/group.py:31 users/models/user.py:679 msgid "User group" msgstr "ユーザーグループ" @@ -1180,7 +1166,7 @@ msgstr "定期的なパフォーマンス" msgid "Currently only mail sending is supported" msgstr "現在、メール送信のみがサポートされています" -#: assets/serializers/base.py:16 users/models/user.py:699 +#: assets/serializers/base.py:16 users/models/user.py:701 msgid "Private key" msgstr "ssh秘密鍵" @@ -1574,7 +1560,7 @@ msgstr "ユーザーエージェント" #: audits/models.py:144 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:692 +#: users/forms/profile.py:65 users/models/user.py:696 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -1653,20 +1639,19 @@ msgstr "認証トークン" #: audits/signal_handlers.py:61 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:178 -#: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 -#: users/models/user.py:730 +#: notifications/backends/__init__.py:11 users/models/user.py:732 msgid "WeCom" msgstr "企業微信" #: audits/signal_handlers.py:62 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 -#: settings/serializers/auth/feishu.py:10 users/models/user.py:732 +#: users/models/user.py:734 msgid "FeiShu" msgstr "本を飛ばす" #: audits/signal_handlers.py:63 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 -#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:731 +#: users/models/user.py:733 msgid "DingTalk" msgstr "DingTalk" @@ -1969,6 +1954,18 @@ msgstr "動的コード" msgid "Please input security code" msgstr "セキュリティコードを入力してください" +#: authentication/mfa/custom.py:20 +msgid "MFA Custom code invalid" +msgstr "カスタム MFA 検証コードの検証に失敗しました" + +#: authentication/mfa/custom.py:26 +msgid "MFA custom verification code" +msgstr "カスタム MFA 検証コード" + +#: authentication/mfa/custom.py:56 +msgid "MFA custom global enabled, cannot disable" +msgstr "カスタム MFA はグローバルに有効になっており、無効にすることはできません" + #: authentication/mfa/otp.py:7 msgid "OTP code invalid, or server time error" msgstr "OTPコードが無効、またはサーバー時間エラー" @@ -2053,7 +2050,7 @@ msgstr "ひみつ" #: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 -#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:713 +#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:715 msgid "Date expired" msgstr "期限切れの日付" @@ -2183,14 +2180,14 @@ msgid "Show" msgstr "表示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: settings/serializers/security.py:39 users/models/user.py:556 +#: settings/serializers/security.py:39 users/models/user.py:557 #: users/serializers/profile.py:116 users/templates/users/mfa_setting.html:61 #: users/templates/users/user_verify_mfa.html:36 msgid "Disable" msgstr "無効化" #: authentication/templates/authentication/_access_key_modal.html:67 -#: users/models/user.py:557 users/serializers/profile.py:117 +#: users/models/user.py:558 users/serializers/profile.py:117 #: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:68 msgid "Enable" @@ -2239,7 +2236,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:402 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:406 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2723,11 +2720,11 @@ msgstr "特殊文字を含むべきではない" msgid "The mobile phone number format is incorrect" msgstr "携帯電話番号の形式が正しくありません" -#: jumpserver/conf.py:401 +#: jumpserver/conf.py:405 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:403 +#: jumpserver/conf.py:407 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -2771,9 +2768,8 @@ msgstr "" msgid "Notifications" msgstr "通知" -#: notifications/backends/__init__.py:10 settings/serializers/email.py:19 -#: settings/serializers/email.py:50 users/forms/profile.py:102 -#: users/models/user.py:671 +#: notifications/backends/__init__.py:10 users/forms/profile.py:102 +#: users/models/user.py:675 msgid "Email" msgstr "メール" @@ -3023,7 +3019,7 @@ msgid "Can view all joined org" msgstr "参加しているすべての組織を表示できます" #: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 -#: users/models/user.py:679 +#: users/models/user.py:683 msgid "Role" msgstr "ロール" @@ -5781,27 +5777,27 @@ msgstr "公開鍵は古いものと同じであってはなりません。" msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" -#: users/forms/profile.py:161 users/models/user.py:702 +#: users/forms/profile.py:161 users/models/user.py:704 msgid "Public key" msgstr "公開キー" -#: users/models/user.py:558 +#: users/models/user.py:559 msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:625 +#: users/models/user.py:629 msgid "Local" msgstr "ローカル" -#: users/models/user.py:681 users/serializers/user.py:149 +#: users/models/user.py:685 users/serializers/user.py:149 msgid "Is service account" msgstr "サービスアカウントです" -#: users/models/user.py:683 +#: users/models/user.py:687 msgid "Avatar" msgstr "アバター" -#: users/models/user.py:686 +#: users/models/user.py:690 msgid "Wechat" msgstr "微信" @@ -5831,6 +5827,8 @@ msgid "Need update password" msgstr "更新パスワードが必要" #: users/models/user.py:903 + + msgid "Can invite user" msgstr "ユーザーを招待できます" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 2529242ac..a33425cb5 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a1e0b5e70491c6228017987091e46d14ccde03b6e56bfb330d1604240c6b3d09 -size 109554 +oid sha256:8bc04011b7295eb6f5a7557e581a430b29013756ec872c71b1812d40f64853e8 +size 109464 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index c71cb52d0..7bfe4f19d 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-11-02 10:13+0800\n" +"POT-Creation-Date: 2022-09-23 15:38+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -63,7 +63,7 @@ msgstr "激活中" #: terminal/models/endpoint.py:22 terminal/models/endpoint.py:97 #: terminal/models/storage.py:30 terminal/models/terminal.py:115 #: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 -#: users/models/group.py:16 users/models/user.py:708 +#: users/models/group.py:16 users/models/user.py:710 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/gathered_user/models.py:26 @@ -91,9 +91,9 @@ msgstr "登录复核" #: perms/models/base.py:84 rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 -#: terminal/models/sharing.py:33 terminal/notifications.py:94 -#: terminal/notifications.py:142 tickets/models/comment.py:21 users/const.py:14 -#: users/models/user.py:901 users/models/user.py:932 +#: terminal/models/sharing.py:33 terminal/notifications.py:91 +#: terminal/notifications.py:139 tickets/models/comment.py:21 users/const.py:14 +#: users/models/user.py:903 users/models/user.py:934 #: users/serializers/group.py:19 msgid "User" msgstr "用户" @@ -159,10 +159,8 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: authentication/models.py:260 authentication/serializers/password_mfa.py:25 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 -#: ops/models/adhoc.py:159 users/forms/profile.py:32 users/forms/profile.py:102 -#: users/models/user.py:667 users/templates/users/_msg_user_created.html:12 -#: users/templates/users/forgot_password.html:51 -#: users/templates/users/forgot_password.html:98 +#: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:671 +#: users/templates/users/_msg_user_created.html:12 #: xpack/plugins/change_auth_plan/models/asset.py:34 #: xpack/plugins/change_auth_plan/models/asset.py:195 #: xpack/plugins/cloud/serializers/account_attrs.py:26 @@ -350,14 +348,13 @@ msgstr "类型名称" #: applications/serializers/application.py:105 assets/models/asset.py:230 #: assets/models/base.py:181 assets/models/cluster.py:26 -#: assets/models/cmd_filter.py:53 assets/models/domain.py:26 -#: assets/models/gathered_user.py:19 assets/models/group.py:22 -#: assets/models/label.py:25 assets/serializers/account.py:18 -#: assets/serializers/cmd_filter.py:28 assets/serializers/cmd_filter.py:48 -#: common/db/models.py:116 common/mixins/models.py:50 ops/models/adhoc.py:39 -#: ops/models/command.py:30 orgs/models.py:72 orgs/models.py:223 -#: perms/models/base.py:92 users/models/group.py:18 users/models/user.py:933 -#: xpack/plugins/change_auth_plan/models/base.py:45 +#: assets/models/domain.py:26 assets/models/gathered_user.py:19 +#: assets/models/group.py:22 assets/models/label.py:25 +#: assets/serializers/account.py:18 assets/serializers/cmd_filter.py:28 +#: assets/serializers/cmd_filter.py:48 common/db/models.py:114 +#: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 +#: orgs/models.py:72 orgs/models.py:223 perms/models/base.py:92 +#: users/models/group.py:18 users/models/user.py:935 #: xpack/plugins/cloud/models.py:125 msgid "Date created" msgstr "创建日期" @@ -637,10 +634,10 @@ msgid "Labels" msgstr "标签管理" #: assets/models/asset.py:229 assets/models/base.py:183 -#: assets/models/cluster.py:28 assets/models/cmd_filter.py:56 -#: assets/models/cmd_filter.py:103 assets/models/group.py:21 -#: common/db/models.py:114 common/mixins/models.py:49 orgs/models.py:71 -#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:716 +#: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 +#: assets/models/cmd_filter.py:99 assets/models/group.py:21 +#: common/db/models.py:112 common/mixins/models.py:49 orgs/models.py:71 +#: orgs/models.py:225 perms/models/base.py:91 users/models/user.py:718 #: users/serializers/group.py:33 #: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 @@ -865,7 +862,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 -#: users/models/user.py:918 +#: users/models/user.py:920 msgid "System" msgstr "系统" @@ -874,7 +871,7 @@ msgid "Default Cluster" msgstr "默认Cluster" #: assets/models/cmd_filter.py:34 perms/models/base.py:86 -#: users/models/group.py:31 users/models/user.py:675 +#: users/models/group.py:31 users/models/user.py:679 msgid "User group" msgstr "用户组" @@ -1170,7 +1167,7 @@ msgstr "定时执行" msgid "Currently only mail sending is supported" msgstr "当前只支持邮件发送" -#: assets/serializers/base.py:16 users/models/user.py:699 +#: assets/serializers/base.py:16 users/models/user.py:701 msgid "Private key" msgstr "ssh私钥" @@ -1560,7 +1557,7 @@ msgstr "用户代理" #: audits/models.py:144 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:692 +#: users/forms/profile.py:65 users/models/user.py:696 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -1652,7 +1649,7 @@ msgstr "飞书" #: audits/signal_handlers.py:63 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 -#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:731 +#: users/models/user.py:733 msgid "DingTalk" msgstr "钉钉" @@ -1944,6 +1941,18 @@ msgstr "动态码" msgid "Please input security code" msgstr "请输入动态安全码" +#: authentication/mfa/custom.py:20 +msgid "MFA Custom code invalid" +msgstr "自定义 MFA 验证码校验失败" + +#: authentication/mfa/custom.py:26 +msgid "MFA custom verification code" +msgstr "自定义 MFA 验证码" + +#: authentication/mfa/custom.py:56 +msgid "MFA custom global enabled, cannot disable" +msgstr "自定义 MFA 全局开启,无法被禁用" + #: authentication/mfa/otp.py:7 msgid "OTP code invalid, or server time error" msgstr "虚拟 MFA 验证码错误,或者服务器端时间不对" @@ -2028,7 +2037,7 @@ msgstr "密钥" #: authentication/models.py:74 authentication/models.py:264 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:30 -#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:713 +#: tickets/models/ticket/apply_asset.py:24 users/models/user.py:715 msgid "Date expired" msgstr "失效日期" @@ -2154,14 +2163,14 @@ msgid "Show" msgstr "显示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: settings/serializers/security.py:39 users/models/user.py:556 +#: settings/serializers/security.py:39 users/models/user.py:557 #: users/serializers/profile.py:116 users/templates/users/mfa_setting.html:61 #: users/templates/users/user_verify_mfa.html:36 msgid "Disable" msgstr "禁用" #: authentication/templates/authentication/_access_key_modal.html:67 -#: users/models/user.py:557 users/serializers/profile.py:117 +#: users/models/user.py:558 users/serializers/profile.py:117 #: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:68 msgid "Enable" @@ -2210,7 +2219,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:402 ops/tasks.py:145 ops/tasks.py:148 +#: jumpserver/conf.py:406 ops/tasks.py:145 ops/tasks.py:148 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2685,11 +2694,11 @@ msgstr "不能包含特殊字符" msgid "The mobile phone number format is incorrect" msgstr "手机号格式不正确" -#: jumpserver/conf.py:401 +#: jumpserver/conf.py:405 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:403 +#: jumpserver/conf.py:407 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -2979,7 +2988,7 @@ msgid "Can view all joined org" msgstr "可以查看所有加入的组织" #: orgs/models.py:222 rbac/models/role.py:46 rbac/models/rolebinding.py:44 -#: users/models/user.py:679 +#: users/models/user.py:683 msgid "Role" msgstr "角色" @@ -5691,27 +5700,27 @@ msgstr "不能和原来的密钥相同" msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" -#: users/forms/profile.py:161 users/models/user.py:702 +#: users/forms/profile.py:161 users/models/user.py:704 msgid "Public key" msgstr "SSH公钥" -#: users/models/user.py:558 +#: users/models/user.py:559 msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:625 +#: users/models/user.py:629 msgid "Local" msgstr "数据库" -#: users/models/user.py:681 users/serializers/user.py:149 +#: users/models/user.py:685 users/serializers/user.py:149 msgid "Is service account" msgstr "服务账号" -#: users/models/user.py:683 +#: users/models/user.py:687 msgid "Avatar" msgstr "头像" -#: users/models/user.py:686 +#: users/models/user.py:690 msgid "Wechat" msgstr "微信" diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 6158e9572..f08a487c2 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -16,6 +16,7 @@ from django.contrib.auth.models import AbstractUser from django.contrib.auth.hashers import check_password from django.utils.translation import ugettext_lazy as _ from django.shortcuts import reverse +from django.utils.module_loading import import_string from orgs.utils import current_org from orgs.models import Organization @@ -602,8 +603,11 @@ class MFAMixin: @staticmethod def get_user_mfa_backends(user): - from authentication.mfa import MFA_BACKENDS - backends = [cls(user) for cls in MFA_BACKENDS if cls.global_enabled()] + backends = [] + for cls in settings.MFA_BACKENDS: + cls = import_string(cls) + if cls.global_enabled(): + backends.append(cls(user)) return backends def get_active_mfa_backend_by_type(self, mfa_type):