move common saml code

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer
2024-08-18 15:43:45 +02:00
parent 0611eea0e7
commit 7f4fbf354e
29 changed files with 105 additions and 101 deletions

View File

View File

View File

@ -0,0 +1,10 @@
from rest_framework.fields import CharField
from authentik.core.api.utils import PassiveSerializer
class SAMLMetadataSerializer(PassiveSerializer):
"""SAML Provider Metadata serializer"""
metadata = CharField(read_only=True)
download_url = CharField(read_only=True, required=False)

View File

@ -23,6 +23,8 @@ from rest_framework.serializers import PrimaryKeyRelatedField, ValidationError
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
from authentik.common.saml.api import SAMLMetadataSerializer
from authentik.common.saml.constants import SAML_BINDING_POST, SAML_BINDING_REDIRECT
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, PropertyMappingPreviewSerializer
@ -34,7 +36,6 @@ from authentik.providers.saml.processors.authn_request_parser import AuthNReques
from authentik.providers.saml.processors.metadata import MetadataProcessor
from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
from authentik.rbac.decorators import permission_required
from authentik.sources.saml.processors.constants import SAML_BINDING_POST, SAML_BINDING_REDIRECT
LOGGER = get_logger()
@ -200,13 +201,6 @@ class SAMLProviderSerializer(ProviderSerializer):
extra_kwargs = ProviderSerializer.Meta.extra_kwargs
class SAMLMetadataSerializer(PassiveSerializer):
"""SAML Provider Metadata serializer"""
metadata = CharField(read_only=True)
download_url = CharField(read_only=True, required=False)
class SAMLProviderImportSerializer(PassiveSerializer):
"""Import saml provider from XML Metadata"""

View File

@ -4,7 +4,7 @@ from django.apps.registry import Apps
from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from authentik.sources.saml.processors import constants
from authentik.common.saml import constants
def update_algorithms(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):

View File

@ -7,12 +7,7 @@ from django.utils.translation import gettext_lazy as _
from rest_framework.serializers import Serializer
from structlog.stdlib import get_logger
from authentik.core.api.object_types import CreatableType
from authentik.core.models import PropertyMapping, Provider
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DSA_SHA1,
ECDSA_SHA1,
ECDSA_SHA256,
@ -27,6 +22,11 @@ from authentik.sources.saml.processors.constants import (
SHA384,
SHA512,
)
from authentik.core.api.object_types import CreatableType
from authentik.core.models import PropertyMapping, Provider
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
LOGGER = get_logger()

View File

@ -10,21 +10,7 @@ from lxml import etree # nosec
from lxml.etree import Element, SubElement # nosec
from structlog.stdlib import get_logger
from authentik.core.expression.exceptions import PropertyMappingExpressionException
from authentik.events.models import Event, EventAction
from authentik.events.signals import get_login_event
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import AuthNRequest
from authentik.providers.saml.utils import get_random_id
from authentik.providers.saml.utils.time import get_time_string
from authentik.sources.ldap.auth import LDAP_DISTINGUISHED_NAME
from authentik.sources.saml.exceptions import (
InvalidEncryption,
InvalidSignature,
UnsupportedNameIDFormat,
)
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DIGEST_ALGORITHM_TRANSLATION_MAP,
NS_MAP,
NS_SAML_ASSERTION,
@ -37,6 +23,20 @@ from authentik.sources.saml.processors.constants import (
SAML_NAME_ID_FORMAT_X509,
SIGN_ALGORITHM_TRANSFORM_MAP,
)
from authentik.common.saml.exceptions import (
InvalidEncryption,
InvalidSignature,
UnsupportedNameIDFormat,
)
from authentik.common.saml.id import get_random_id
from authentik.common.saml.time import get_time_string
from authentik.core.expression.exceptions import PropertyMappingExpressionException
from authentik.events.models import Event, EventAction
from authentik.events.signals import get_login_event
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import AuthNRequest
from authentik.sources.ldap.auth import LDAP_DISTINGUISHED_NAME
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
LOGGER = get_logger()

View File

@ -9,11 +9,7 @@ import xmlsec
from defusedxml import ElementTree
from structlog.stdlib import get_logger
from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLProvider
from authentik.providers.saml.utils.encoding import decode_base64_and_inflate
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DSA_SHA1,
NS_MAP,
NS_SAML_PROTOCOL,
@ -23,6 +19,10 @@ from authentik.sources.saml.processors.constants import (
RSA_SHA512,
SAML_NAME_ID_FORMAT_UNSPECIFIED,
)
from authentik.common.saml.encoding import decode_base64_and_inflate
from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLProvider
ERROR_CANNOT_DECODE_REQUEST = "Cannot decode SAML request."
ERROR_SIGNATURE_REQUIRED_BUT_ABSENT = (

View File

@ -5,11 +5,11 @@ from dataclasses import dataclass
from defusedxml import ElementTree
from authentik.common.saml.constants import NS_SAML_PROTOCOL
from authentik.common.saml.encoding import decode_base64_and_inflate
from authentik.providers.saml.exceptions import CannotHandleAssertion
from authentik.providers.saml.models import SAMLProvider
from authentik.providers.saml.processors.authn_request_parser import ERROR_CANNOT_DECODE_REQUEST
from authentik.providers.saml.utils.encoding import decode_base64_and_inflate
from authentik.sources.saml.processors.constants import NS_SAML_PROTOCOL
@dataclass(slots=True)

View File

@ -9,9 +9,7 @@ from django.http import HttpRequest
from django.urls import reverse
from lxml.etree import Element, SubElement, tostring # nosec
from authentik.providers.saml.models import SAMLProvider
from authentik.providers.saml.utils.encoding import strip_pem_header
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DIGEST_ALGORITHM_TRANSLATION_MAP,
NS_MAP,
NS_SAML_METADATA,
@ -25,6 +23,8 @@ from authentik.sources.saml.processors.constants import (
SAML_NAME_ID_FORMAT_X509,
SIGN_ALGORITHM_TRANSFORM_MAP,
)
from authentik.common.saml.encoding import strip_pem_header
from authentik.providers.saml.models import SAMLProvider
class MetadataProcessor:

View File

@ -9,16 +9,16 @@ from defusedxml.lxml import fromstring
from lxml import etree # nosec
from structlog.stdlib import get_logger
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.utils.encoding import PEM_FOOTER, PEM_HEADER
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
NS_MAP,
NS_SAML_METADATA,
SAML_BINDING_POST,
SAML_BINDING_REDIRECT,
)
from authentik.common.saml.encoding import PEM_FOOTER, PEM_HEADER
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
LOGGER = get_logger()

View File

@ -8,6 +8,13 @@ from django.test import TestCase
from lxml import etree # nosec
from authentik.blueprints.tests import apply_blueprint
from authentik.common.saml.constants import (
NS_MAP,
SAML_BINDING_REDIRECT,
SAML_NAME_ID_FORMAT_EMAIL,
SAML_NAME_ID_FORMAT_UNSPECIFIED,
)
from authentik.common.saml.exceptions import MismatchedRequestID
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction
@ -17,14 +24,7 @@ from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.assertion import AssertionProcessor
from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser
from authentik.sources.saml.exceptions import MismatchedRequestID
from authentik.sources.saml.models import SAMLSource
from authentik.sources.saml.processors.constants import (
NS_MAP,
SAML_BINDING_REDIRECT,
SAML_NAME_ID_FORMAT_EMAIL,
SAML_NAME_ID_FORMAT_UNSPECIFIED,
)
from authentik.sources.saml.processors.request import SESSION_KEY_REQUEST_ID, RequestProcessor
from authentik.sources.saml.processors.response import ResponseProcessor

View File

@ -5,6 +5,7 @@ from defusedxml.lxml import fromstring
from django.test import RequestFactory, TestCase
from lxml import etree # nosec
from authentik.common.saml.constants import ECDSA_SHA256, NS_MAP, NS_SAML_METADATA
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.crypto.builder import PrivateKeyAlg
@ -14,7 +15,6 @@ from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor
from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
from authentik.sources.saml.processors.constants import ECDSA_SHA256, NS_MAP, NS_SAML_METADATA
class TestServiceProviderMetadataParser(TestCase):

View File

@ -8,6 +8,8 @@ from django.utils.http import urlencode
from django.utils.translation import gettext as _
from structlog.stdlib import get_logger
from authentik.common.saml.encoding import deflate_and_base64_encode, nice64
from authentik.common.saml.exceptions import SAMLException
from authentik.core.models import Application
from authentik.events.models import Event, EventAction
from authentik.flows.challenge import (
@ -24,8 +26,6 @@ from authentik.policies.utils import delete_none_values
from authentik.providers.saml.models import SAMLBindings, SAMLProvider
from authentik.providers.saml.processors.assertion import AssertionProcessor
from authentik.providers.saml.processors.authn_request_parser import AuthNRequest
from authentik.providers.saml.utils.encoding import deflate_and_base64_encode, nice64
from authentik.sources.saml.exceptions import SAMLException
LOGGER = get_logger()
URL_VALIDATOR = URLValidator(schemes=("http", "https"))

View File

@ -7,9 +7,9 @@ from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from authentik.common.saml.api import SAMLMetadataSerializer
from authentik.core.api.sources import SourceSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.providers.saml.api.providers import SAMLMetadataSerializer
from authentik.sources.saml.models import SAMLSource
from authentik.sources.saml.processors.metadata import MetadataProcessor

View File

@ -6,7 +6,7 @@ from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
import authentik.lib.utils.time
from authentik.sources.saml.processors import constants
from authentik.common.saml import constants
def update_algorithms(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):

View File

@ -9,20 +9,7 @@ from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from rest_framework.serializers import Serializer
from authentik.core.models import (
GroupSourceConnection,
PropertyMapping,
Source,
UserSourceConnection,
)
from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import RedirectChallenge
from authentik.flows.models import Flow
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DSA_SHA1,
ECDSA_SHA1,
ECDSA_SHA256,
@ -46,6 +33,19 @@ from authentik.sources.saml.processors.constants import (
SHA384,
SHA512,
)
from authentik.core.models import (
GroupSourceConnection,
PropertyMapping,
Source,
UserSourceConnection,
)
from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.challenge import RedirectChallenge
from authentik.flows.models import Flow
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.utils.time import timedelta_string_validator
class SAMLBindingTypes(models.TextChoices):

View File

@ -5,14 +5,14 @@ from typing import Optional
from django.http import HttpRequest
from lxml.etree import Element, SubElement, tostring # nosec
from authentik.providers.saml.utils.encoding import strip_pem_header
from authentik.sources.saml.models import SAMLSource
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
NS_MAP,
NS_SAML_METADATA,
NS_SIGNATURE,
SAML_BINDING_POST,
)
from authentik.common.saml.encoding import strip_pem_header
from authentik.sources.saml.models import SAMLSource
class MetadataProcessor:

View File

@ -8,17 +8,17 @@ from django.http import HttpRequest
from lxml import etree # nosec
from lxml.etree import Element # nosec
from authentik.providers.saml.utils import get_random_id
from authentik.providers.saml.utils.encoding import deflate_and_base64_encode
from authentik.providers.saml.utils.time import get_time_string
from authentik.sources.saml.models import SAMLBindingTypes, SAMLSource
from authentik.sources.saml.processors.constants import (
from authentik.common.saml.constants import (
DIGEST_ALGORITHM_TRANSLATION_MAP,
NS_MAP,
NS_SAML_ASSERTION,
NS_SAML_PROTOCOL,
SIGN_ALGORITHM_TRANSFORM_MAP,
)
from authentik.common.saml.encoding import deflate_and_base64_encode
from authentik.common.saml.id import get_random_id
from authentik.common.saml.time import get_time_string
from authentik.sources.saml.models import SAMLBindingTypes, SAMLSource
SESSION_KEY_REQUEST_ID = "authentik/sources/saml/request_id"

View File

@ -13,6 +13,23 @@ from django.utils.timezone import now
from lxml import etree # nosec
from structlog.stdlib import get_logger
from authentik.common.saml.constants import (
NS_MAP,
NS_SAML_ASSERTION,
NS_SAML_PROTOCOL,
SAML_NAME_ID_FORMAT_EMAIL,
SAML_NAME_ID_FORMAT_PERSISTENT,
SAML_NAME_ID_FORMAT_TRANSIENT,
SAML_NAME_ID_FORMAT_WINDOWS,
SAML_NAME_ID_FORMAT_X509,
)
from authentik.common.saml.exceptions import (
InvalidEncryption,
InvalidSignature,
MismatchedRequestID,
MissingSAMLResponse,
UnsupportedNameIDFormat,
)
from authentik.core.models import (
USER_ATTRIBUTE_DELETE_ON_LOGOUT,
USER_ATTRIBUTE_EXPIRES,
@ -22,28 +39,11 @@ from authentik.core.models import (
)
from authentik.core.sources.flow_manager import SourceFlowManager
from authentik.lib.utils.time import timedelta_from_string
from authentik.sources.saml.exceptions import (
InvalidEncryption,
InvalidSignature,
MismatchedRequestID,
MissingSAMLResponse,
UnsupportedNameIDFormat,
)
from authentik.sources.saml.models import (
GroupSAMLSourceConnection,
SAMLSource,
UserSAMLSourceConnection,
)
from authentik.sources.saml.processors.constants import (
NS_MAP,
NS_SAML_ASSERTION,
NS_SAML_PROTOCOL,
SAML_NAME_ID_FORMAT_EMAIL,
SAML_NAME_ID_FORMAT_PERSISTENT,
SAML_NAME_ID_FORMAT_TRANSIENT,
SAML_NAME_ID_FORMAT_WINDOWS,
SAML_NAME_ID_FORMAT_X509,
)
from authentik.sources.saml.processors.request import SESSION_KEY_REQUEST_ID
LOGGER = get_logger()

View File

@ -6,11 +6,11 @@ from defusedxml.lxml import fromstring
from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory, TestCase
from authentik.common.saml.constants import NS_SAML_ASSERTION
from authentik.core.tests.utils import create_test_flow
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response, load_fixture
from authentik.sources.saml.models import SAMLSource, SAMLSourcePropertyMapping
from authentik.sources.saml.processors.constants import NS_SAML_ASSERTION
from authentik.sources.saml.processors.response import ResponseProcessor
ROOT = fromstring(load_fixture("fixtures/response_success.xml").encode())

View File

@ -5,11 +5,11 @@ from base64 import b64encode
from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory, TestCase
from authentik.common.saml.exceptions import InvalidEncryption
from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import dummy_get_response, load_fixture
from authentik.sources.saml.exceptions import InvalidEncryption
from authentik.sources.saml.models import SAMLSource
from authentik.sources.saml.processors.response import ResponseProcessor

View File

@ -14,6 +14,8 @@ from django.views.decorators.csrf import csrf_exempt
from structlog.stdlib import get_logger
from xmlsec import InternalError, VerificationError
from authentik.common.saml.encoding import nice64
from authentik.common.saml.exceptions import MissingSAMLResponse, UnsupportedNameIDFormat
from authentik.flows.challenge import (
PLAN_CONTEXT_ATTRS,
PLAN_CONTEXT_TITLE,
@ -34,8 +36,6 @@ from authentik.flows.planner import (
from authentik.flows.stage import ChallengeStageView
from authentik.flows.views.executor import NEXT_ARG_NAME, SESSION_KEY_GET, SESSION_KEY_PLAN
from authentik.lib.views import bad_request_message
from authentik.providers.saml.utils.encoding import nice64
from authentik.sources.saml.exceptions import MissingSAMLResponse, UnsupportedNameIDFormat
from authentik.sources.saml.models import SAMLBindingTypes, SAMLSource
from authentik.sources.saml.processors.metadata import MetadataProcessor
from authentik.sources.saml.processors.request import RequestProcessor

View File

@ -7,13 +7,13 @@ from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from authentik.blueprints.tests import apply_blueprint, reconcile_app
from authentik.common.saml.constants import SAML_BINDING_POST
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert
from authentik.flows.models import Flow
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.sources.saml.processors.constants import SAML_BINDING_POST
from tests.e2e.utils import SeleniumTestCase, retry