providers/proxy: add domainless URL Validator

This commit is contained in:
Jens Langhammer 2020-09-13 21:52:34 +02:00
parent 696aa7e5f6
commit 7fe9b8f0b4
5 changed files with 91 additions and 5 deletions

View File

@ -1,5 +1,9 @@
"""Generic models""" """Generic models"""
import re
from django.core.validators import URLValidator
from django.db import models from django.db import models
from django.utils.regex_helper import _lazy_re_compile
from model_utils.managers import InheritanceManager from model_utils.managers import InheritanceManager
from rest_framework.serializers import BaseSerializer from rest_framework.serializers import BaseSerializer
@ -48,3 +52,21 @@ class InheritanceForeignKey(models.ForeignKey):
"""Custom ForeignKey that uses InheritanceForwardManyToOneDescriptor""" """Custom ForeignKey that uses InheritanceForwardManyToOneDescriptor"""
forward_related_accessor_class = InheritanceForwardManyToOneDescriptor forward_related_accessor_class = InheritanceForwardManyToOneDescriptor
class DomainlessURLValidator(URLValidator):
"""Subclass of URLValidator which doesn't check the domain
(to allow hostnames without domain)"""
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.host_re = "(" + self.hostname_re + self.domain_re + "|localhost)"
self.regex = _lazy_re_compile(
r"^(?:[a-z0-9.+-]*)://" # scheme is validated separately
r"(?:[^\s:@/]+(?::[^\s:@/]*)?@)?" # user:pass authentication
r"(?:" + self.ipv4_re + "|" + self.ipv6_re + "|" + self.host_re + ")"
r"(?::\d{2,5})?" # port
r"(?:[/?#][^\s]*)?" # resource path
r"\Z",
re.IGNORECASE,
)

View File

@ -0,0 +1,37 @@
# Generated by Django 3.1.1 on 2020-09-13 19:47
from django.db import migrations, models
import passbook.lib.models
class Migration(migrations.Migration):
dependencies = [
("passbook_providers_proxy", "0003_proxyprovider_certificate"),
]
operations = [
migrations.AlterField(
model_name="proxyprovider",
name="external_host",
field=models.TextField(
validators=[
passbook.lib.models.DomainlessURLValidator(
schemes=("http", "https")
)
]
),
),
migrations.AlterField(
model_name="proxyprovider",
name="internal_host",
field=models.TextField(
validators=[
passbook.lib.models.DomainlessURLValidator(
schemes=("http", "https")
)
]
),
),
]

View File

@ -4,12 +4,12 @@ from random import SystemRandom
from typing import Iterable, Type from typing import Iterable, Type
from urllib.parse import urljoin from urllib.parse import urljoin
from django.core.validators import URLValidator
from django.db import models from django.db import models
from django.forms import ModelForm from django.forms import ModelForm
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from passbook.crypto.models import CertificateKeyPair from passbook.crypto.models import CertificateKeyPair
from passbook.lib.models import DomainlessURLValidator
from passbook.outposts.models import OutpostModel from passbook.outposts.models import OutpostModel
from passbook.providers.oauth2.constants import ( from passbook.providers.oauth2.constants import (
SCOPE_OPENID, SCOPE_OPENID,
@ -41,10 +41,10 @@ class ProxyProvider(OutpostModel, OAuth2Provider):
Protocols by using a Reverse-Proxy.""" Protocols by using a Reverse-Proxy."""
internal_host = models.TextField( internal_host = models.TextField(
validators=[URLValidator(schemes=("http", "https"))] validators=[DomainlessURLValidator(schemes=("http", "https"))]
) )
external_host = models.TextField( external_host = models.TextField(
validators=[URLValidator(schemes=("http", "https"))] validators=[DomainlessURLValidator(schemes=("http", "https"))]
) )
cookie_secret = models.TextField(default=get_cookie_secret) cookie_secret = models.TextField(default=get_cookie_secret)

View File

@ -0,0 +1,27 @@
# Generated by Django 3.1.1 on 2020-09-13 19:47
from django.db import migrations, models
import passbook.lib.models
class Migration(migrations.Migration):
dependencies = [
("passbook_sources_ldap", "0004_auto_20200524_1146"),
]
operations = [
migrations.AlterField(
model_name="ldapsource",
name="server_uri",
field=models.TextField(
validators=[
passbook.lib.models.DomainlessURLValidator(
schemes=["ldap", "ldaps"]
)
],
verbose_name="Server URI",
),
),
]

View File

@ -1,20 +1,20 @@
"""passbook LDAP Models""" """passbook LDAP Models"""
from typing import Optional, Type from typing import Optional, Type
from django.core.validators import URLValidator
from django.db import models from django.db import models
from django.forms import ModelForm from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ldap3 import Connection, Server from ldap3 import Connection, Server
from passbook.core.models import Group, PropertyMapping, Source from passbook.core.models import Group, PropertyMapping, Source
from passbook.lib.models import DomainlessURLValidator
class LDAPSource(Source): class LDAPSource(Source):
"""Federate LDAP Directory with passbook, or create new accounts in LDAP.""" """Federate LDAP Directory with passbook, or create new accounts in LDAP."""
server_uri = models.TextField( server_uri = models.TextField(
validators=[URLValidator(schemes=["ldap", "ldaps"])], validators=[DomainlessURLValidator(schemes=["ldap", "ldaps"])],
verbose_name=_("Server URI"), verbose_name=_("Server URI"),
) )
bind_cn = models.TextField(verbose_name=_("Bind CN")) bind_cn = models.TextField(verbose_name=_("Bind CN"))