This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
authentik/passbook/providers/proxy/models.py

102 lines
3 KiB
Python
Raw Normal View History

2020-08-19 08:32:44 +00:00
"""passbook proxy models"""
2020-09-02 22:04:12 +00:00
import string
from random import SystemRandom
from typing import Iterable, Type
from urllib.parse import urljoin
2020-08-19 08:32:44 +00:00
from django.db import models
from django.forms import ModelForm
from django.utils.translation import gettext as _
2020-09-02 22:04:12 +00:00
from passbook.crypto.models import CertificateKeyPair
from passbook.lib.models import DomainlessURLValidator
2020-09-02 22:04:12 +00:00
from passbook.outposts.models import OutpostModel
2020-08-19 08:32:44 +00:00
from passbook.providers.oauth2.constants import (
SCOPE_OPENID,
SCOPE_OPENID_EMAIL,
SCOPE_OPENID_PROFILE,
)
from passbook.providers.oauth2.models import (
ClientTypes,
JWTAlgorithms,
OAuth2Provider,
ResponseTypes,
ScopeMapping,
)
2020-09-02 22:04:12 +00:00
def get_cookie_secret():
"""Generate random 32-character string for cookie-secret"""
return "".join(
SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(32)
)
def _get_callback_url(uri: str) -> str:
return urljoin(uri, "/pbprox/callback")
class ProxyProvider(OutpostModel, OAuth2Provider):
2020-08-19 08:32:44 +00:00
"""Protect applications that don't support any of the other
Protocols by using a Reverse-Proxy."""
internal_host = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))]
2020-08-19 08:32:44 +00:00
)
external_host = models.TextField(
validators=[DomainlessURLValidator(schemes=("http", "https"))]
2020-08-19 08:32:44 +00:00
)
2020-09-02 22:04:12 +00:00
cookie_secret = models.TextField(default=get_cookie_secret)
skip_path_regex = models.TextField(
default="",
blank=True,
2020-09-19 10:21:31 +00:00
help_text=_(
(
"Regular expression for which authentication is not required. "
"Each new line is interpreted as a new Regular Expression."
)
),
)
2020-09-02 22:04:12 +00:00
certificate = models.ForeignKey(
CertificateKeyPair, on_delete=models.SET_NULL, null=True, blank=True,
2020-09-02 22:04:12 +00:00
)
2020-08-19 08:32:44 +00:00
def form(self) -> Type[ModelForm]:
from passbook.providers.proxy.forms import ProxyProviderForm
return ProxyProviderForm
def set_oauth_defaults(self):
"""Ensure all OAuth2-related settings are correct"""
self.client_type = ClientTypes.CONFIDENTIAL
self.response_type = ResponseTypes.CODE
2020-09-02 22:04:12 +00:00
self.jwt_alg = JWTAlgorithms.RS256
self.rsa_key = CertificateKeyPair.objects.first()
2020-08-19 08:32:44 +00:00
scopes = ScopeMapping.objects.filter(
scope_name__in=[SCOPE_OPENID, SCOPE_OPENID_PROFILE, SCOPE_OPENID_EMAIL]
)
self.property_mappings.set(scopes)
self.redirect_uris = "\n".join(
[
2020-09-02 22:04:12 +00:00
_get_callback_url(self.external_host),
_get_callback_url(self.internal_host),
2020-08-19 08:32:44 +00:00
]
)
def __str__(self):
2020-09-02 22:04:12 +00:00
return f"Proxy Provider {self.name}"
def get_required_objects(self) -> Iterable[models.Model]:
required_models = [self]
if self.certificate is not None:
required_models.append(self.certificate)
return required_models
2020-08-19 08:32:44 +00:00
class Meta:
verbose_name = _("Proxy Provider")
verbose_name_plural = _("Proxy Providers")