feat(2fa): added 2fa for more auth plugins and moved 2fa forced functionality to ee edition. Fixes: RCCE-68
This commit is contained in:
parent
aea08fa1b2
commit
d069311e52
9 changed files with 33 additions and 27 deletions
|
|
@ -176,9 +176,6 @@ class BaseAppView(object):
|
|||
if not user_obj:
|
||||
return
|
||||
|
||||
if user_obj.has_forced_2fa and user_obj.extern_type != 'rhodecode':
|
||||
return
|
||||
|
||||
if user_obj.needs_2fa_configure and view_name != self.SETUP_2FA_VIEW:
|
||||
h.flash(
|
||||
"You are required to configure 2FA",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import urllib.parse
|
|||
from rhodecode.translation import _
|
||||
from rhodecode.authentication.base import (
|
||||
RhodeCodeExternalAuthPlugin, hybrid_property)
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
|
||||
from rhodecode.authentication.routes import AuthnPluginResourceBase
|
||||
from rhodecode.lib.colander_utils import strip_whitespace
|
||||
from rhodecode.lib.ext_json import json, formatted_json
|
||||
|
|
@ -53,7 +53,7 @@ class CrowdAuthnResource(AuthnPluginResourceBase):
|
|||
pass
|
||||
|
||||
|
||||
class CrowdSettingsSchema(AuthnPluginSettingsSchemaBase):
|
||||
class CrowdSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
|
||||
host = colander.SchemaNode(
|
||||
colander.String(),
|
||||
default='127.0.0.1',
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import urllib.error
|
|||
from rhodecode.translation import _
|
||||
from rhodecode.authentication.base import (
|
||||
RhodeCodeExternalAuthPlugin, hybrid_property)
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
|
||||
from rhodecode.authentication.routes import AuthnPluginResourceBase
|
||||
from rhodecode.lib.colander_utils import strip_whitespace
|
||||
from rhodecode.model.db import User
|
||||
|
|
@ -55,7 +55,7 @@ class JasigCasAuthnResource(AuthnPluginResourceBase):
|
|||
pass
|
||||
|
||||
|
||||
class JasigCasSettingsSchema(AuthnPluginSettingsSchemaBase):
|
||||
class JasigCasSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
|
||||
service_url = colander.SchemaNode(
|
||||
colander.String(),
|
||||
default='https://domain.com/cas/v1/tickets',
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import colander
|
|||
from rhodecode.translation import _
|
||||
from rhodecode.authentication.base import (
|
||||
RhodeCodeExternalAuthPlugin, AuthLdapBase, hybrid_property)
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
|
||||
from rhodecode.authentication.routes import AuthnPluginResourceBase
|
||||
from rhodecode.lib.colander_utils import strip_whitespace
|
||||
from rhodecode.lib.exceptions import (
|
||||
|
|
@ -245,7 +245,7 @@ class AuthLdap(AuthLdapBase):
|
|||
return dn, user_attrs
|
||||
|
||||
|
||||
class LdapSettingsSchema(AuthnPluginSettingsSchemaBase):
|
||||
class LdapSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
|
||||
tls_kind_choices = ['PLAIN', 'LDAPS', 'START_TLS']
|
||||
tls_reqcert_choices = ['NEVER', 'ALLOW', 'TRY', 'DEMAND', 'HARD']
|
||||
search_scope_choices = ['BASE', 'ONELEVEL', 'SUBTREE']
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import socket
|
|||
from rhodecode.translation import _
|
||||
from rhodecode.authentication.base import (
|
||||
RhodeCodeExternalAuthPlugin, hybrid_property)
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
|
||||
from rhodecode.authentication.routes import AuthnPluginResourceBase
|
||||
from rhodecode.lib.colander_utils import strip_whitespace
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ class PamAuthnResource(AuthnPluginResourceBase):
|
|||
pass
|
||||
|
||||
|
||||
class PamSettingsSchema(AuthnPluginSettingsSchemaBase):
|
||||
class PamSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
|
||||
service = colander.SchemaNode(
|
||||
colander.String(),
|
||||
default='login',
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import colander
|
|||
from rhodecode.translation import _
|
||||
from rhodecode.lib.utils2 import safe_bytes
|
||||
from rhodecode.model.db import User
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase
|
||||
from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase, TwoFactorAuthnPluginSettingsSchemaMixin
|
||||
from rhodecode.authentication.base import (
|
||||
RhodeCodeAuthPluginBase, hybrid_property, HTTP_TYPE, VCS_TYPE)
|
||||
from rhodecode.authentication.routes import AuthnPluginResourceBase
|
||||
|
|
@ -182,16 +182,7 @@ class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase):
|
|||
return None
|
||||
|
||||
|
||||
class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase):
|
||||
global_2fa = colander.SchemaNode(
|
||||
colander.Bool(),
|
||||
default=False,
|
||||
description=_('Force all users to use two factor authentication by enabling this.'),
|
||||
missing=False,
|
||||
title=_('Global 2FA'),
|
||||
widget='bool',
|
||||
)
|
||||
|
||||
class RhodeCodeSettingsSchema(TwoFactorAuthnPluginSettingsSchemaMixin, AuthnPluginSettingsSchemaBase):
|
||||
auth_restriction_choices = [
|
||||
(RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE, 'All users'),
|
||||
(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN, 'Super admins only'),
|
||||
|
|
|
|||
|
|
@ -48,3 +48,17 @@ class AuthnPluginSettingsSchemaBase(colander.MappingSchema):
|
|||
validator=colander.Range(min=0, max=None),
|
||||
widget='int',
|
||||
)
|
||||
|
||||
|
||||
class TwoFactorAuthnPluginSettingsSchemaMixin(colander.MappingSchema):
|
||||
"""
|
||||
Mixin for extending plugins with two-factor authentication option.
|
||||
"""
|
||||
global_2fa = colander.SchemaNode(
|
||||
colander.Bool(),
|
||||
default=False,
|
||||
description=_('Force all users to use two factor authentication with this plugin.'),
|
||||
missing=False,
|
||||
title=_('enforce 2FA for users'),
|
||||
widget='bool',
|
||||
)
|
||||
|
|
|
|||
|
|
@ -810,11 +810,10 @@ class User(Base, BaseModel):
|
|||
@hybrid_property
|
||||
def has_forced_2fa(self):
|
||||
"""
|
||||
Checks if 2fa was forced for ALL users (including current one)
|
||||
Checks if 2fa was forced for current user
|
||||
"""
|
||||
from rhodecode.model.settings import SettingsModel
|
||||
# So now we're supporting only auth_rhodecode_global_2fa
|
||||
if value := SettingsModel().get_setting_by_name('auth_rhodecode_global_2fa'):
|
||||
if value := SettingsModel().get_setting_by_name(f'{self.extern_type}_global_2fa'):
|
||||
return value.app_settings_value
|
||||
return False
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,12 @@
|
|||
%elif node.widget == "password":
|
||||
${h.password(node.name, defaults.get(node.name), class_="large")}
|
||||
%elif node.widget == "bool":
|
||||
<div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div>
|
||||
%if node.name == "global_2fa" and c.rhodecode_edition_id != "EE":
|
||||
<input type="checkbox" disabled/>
|
||||
<%node.description = _('This feature is available in RhodeCode EE edition only. Contact {sales_email} to obtain a trial license.').format(sales_email='<a href="mailto:sales@rhodecode.com">sales@rhodecode.com</a>')%>
|
||||
%else:
|
||||
<div class="checkbox" >${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div>
|
||||
%endif
|
||||
%elif node.widget == "select":
|
||||
${h.select(node.name, defaults.get(node.name), node.validator.choices, class_="select2AuthSetting")}
|
||||
%elif node.widget == "select_with_labels":
|
||||
|
|
@ -80,7 +85,7 @@
|
|||
<span class="error-message">${errors.get(node.name)}</span>
|
||||
<br />
|
||||
%endif
|
||||
<p class="help-block pre-formatting">${node.description}</p>
|
||||
<p class="help-block pre-formatting">${node.description | n}</p>
|
||||
</div>
|
||||
</div>
|
||||
%endfor
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue