1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

Refactor MFA classes and add network restrictions

This commit is contained in:
Adolfo Gómez García 2024-01-26 23:24:05 +01:00
parent f2c5ca2e92
commit 01e765a1db
No known key found for this signature in database
GPG Key ID: DD1ABF20724CDA23
2 changed files with 37 additions and 6 deletions

View File

@ -65,16 +65,18 @@ class LoginAllowed(enum.StrEnum):
ALLOWED_IF_IN_NETWORKS = '2'
DENIED_IF_IN_NETWORKS = '3'
@staticmethod
def check_ip_allowed(request: 'ExtendedHttpRequest', networks: typing.Optional[collections.abc.Iterable[str]] = None) -> bool:
if networks is None:
return True # No network restrictions, so we allow
return any(i.contains(request.ip) for i in Network.objects.filter(uuid__in=list(networks)))
@staticmethod
def check_action(
action: 'LoginAllowed|str',
request: 'ExtendedHttpRequest',
networks: typing.Optional[collections.abc.Iterable[str]] = None,
) -> bool:
def checkIp() -> bool:
if networks is None:
return True # No network restrictions, so we allow
return any(i.contains(request.ip) for i in Network.objects.filter(uuid__in=list(networks)))
if isinstance(action, str):
action = LoginAllowed(action)
@ -82,8 +84,8 @@ class LoginAllowed(enum.StrEnum):
return {
LoginAllowed.ALLOWED: True,
LoginAllowed.DENIED: False,
LoginAllowed.ALLOWED_IF_IN_NETWORKS: checkIp(),
LoginAllowed.DENIED_IF_IN_NETWORKS: not checkIp(),
LoginAllowed.ALLOWED_IF_IN_NETWORKS: LoginAllowed.check_ip_allowed(request, networks),
LoginAllowed.DENIED_IF_IN_NETWORKS: not LoginAllowed.check_ip_allowed(request, networks)
}.get(action, False)
@staticmethod

View File

@ -41,6 +41,8 @@ from django.utils.translation import gettext_noop as _, gettext
from uds import models
from uds.core import mfas, exceptions
from uds.core.mfas.mfa import MFA
from uds.core.types.requests import ExtendedHttpRequest
from uds.core.ui import gui
from uds.core.util import validators, decorators
@ -142,6 +144,20 @@ class EmailMFA(mfas.MFA):
old_field_name='allowLoginWithoutMFA',
)
allow_skip_mfa_from_networks = gui.MultiChoiceField(
label=_('Allow skip MFA from networks'),
readonly=False,
rows=5,
order=32,
tooltip=_('Users within these networks will not be asked for OTP'),
required=False,
choices=lambda: [
gui.choice_item(v.uuid, v.name) # type: ignore
for v in models.Network.objects.all().order_by('name')
],
tab=_('Config'),
)
networks = gui.MultiChoiceField(
label=_('Mail OTP Networks'),
readonly=False,
@ -306,3 +322,16 @@ class EmailMFA(mfas.MFA):
smtp.login(self.username.value, self.password.value)
return smtp
def process(
self,
request: ExtendedHttpRequest,
userId: str,
username: str,
identifier: str,
validity: int | None = None,
) -> mfas.MFA.RESULT:
# if ip allowed to skip mfa, return allowed
if mfas.LoginAllowed.check_ip_allowed(request, self.allow_skip_mfa_from_networks.value):
return mfas.MFA.RESULT.ALLOWED
return super().process(request, userId, username, identifier, validity)