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"""
import re
from django.core.validators import URLValidator
from django.db import models
from django.utils.regex_helper import _lazy_re_compile
from model_utils.managers import InheritanceManager
from rest_framework.serializers import BaseSerializer
@ -48,3 +52,21 @@ class InheritanceForeignKey(models.ForeignKey):
"""Custom ForeignKey that uses 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 urllib.parse import urljoin
from django.core.validators import URLValidator
from django.db import models
from django.forms import ModelForm
from django.utils.translation import gettext as _
from passbook.crypto.models import CertificateKeyPair
from passbook.lib.models import DomainlessURLValidator
from passbook.outposts.models import OutpostModel
from passbook.providers.oauth2.constants import (
SCOPE_OPENID,
@ -41,10 +41,10 @@ class ProxyProvider(OutpostModel, OAuth2Provider):
Protocols by using a Reverse-Proxy."""
internal_host = models.TextField(
validators=[URLValidator(schemes=("http", "https"))]
validators=[DomainlessURLValidator(schemes=("http", "https"))]
)
external_host = models.TextField(
validators=[URLValidator(schemes=("http", "https"))]
validators=[DomainlessURLValidator(schemes=("http", "https"))]
)
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"""
from typing import Optional, Type
from django.core.validators import URLValidator
from django.db import models
from django.forms import ModelForm
from django.utils.translation import gettext_lazy as _
from ldap3 import Connection, Server
from passbook.core.models import Group, PropertyMapping, Source
from passbook.lib.models import DomainlessURLValidator
class LDAPSource(Source):
"""Federate LDAP Directory with passbook, or create new accounts in LDAP."""
server_uri = models.TextField(
validators=[URLValidator(schemes=["ldap", "ldaps"])],
validators=[DomainlessURLValidator(schemes=["ldap", "ldaps"])],
verbose_name=_("Server URI"),
)
bind_cn = models.TextField(verbose_name=_("Bind CN"))