Merge branch 'main' into multi-tenant-django-tenants

This commit is contained in:
Marc 'risson' Schmitt 2024-01-16 05:05:18 +01:00
commit 3f9d1af617
No known key found for this signature in database
GPG Key ID: 9C3FA22FABF1AA8D
24 changed files with 603 additions and 455 deletions

View File

@ -35,7 +35,7 @@ from authentik.core.models import (
Source, Source,
UserSourceConnection, UserSourceConnection,
) )
from authentik.enterprise.models import LicenseUsage from authentik.enterprise.models import LicenseKey, LicenseUsage
from authentik.events.utils import cleanse_dict from authentik.events.utils import cleanse_dict
from authentik.flows.models import FlowToken, Stage from authentik.flows.models import FlowToken, Stage
from authentik.lib.models import SerializerModel from authentik.lib.models import SerializerModel
@ -110,12 +110,16 @@ class Importer:
self.__pk_map: dict[Any, Model] = {} self.__pk_map: dict[Any, Model] = {}
self._import = blueprint self._import = blueprint
self.logger = get_logger() self.logger = get_logger()
ctx = {} ctx = self.default_context()
always_merger.merge(ctx, self._import.context) always_merger.merge(ctx, self._import.context)
if context: if context:
always_merger.merge(ctx, context) always_merger.merge(ctx, context)
self._import.context = ctx self._import.context = ctx
def default_context(self):
"""Default context"""
return {"goauthentik.io/enterprise/licensed": LicenseKey.get_total().is_valid()}
@staticmethod @staticmethod
def from_string(yaml_input: str, context: dict | None = None) -> "Importer": def from_string(yaml_input: str, context: dict | None = None) -> "Importer":
"""Parse YAML string and create blueprint importer from it""" """Parse YAML string and create blueprint importer from it"""

View File

@ -1,15 +1,18 @@
"""RAC Provider API Views""" """RAC Provider API Views"""
from django_filters.filters import AllValuesMultipleFilter
from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from rest_framework.fields import CharField from rest_framework.fields import CharField
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField from authentik.core.api.utils import JSONDictField
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.models import RACPropertyMapping from authentik.enterprise.providers.rac.models import RACPropertyMapping
class RACPropertyMappingSerializer(EnterpriseRequiredMixin, PropertyMappingSerializer): class RACPropertyMappingSerializer(PropertyMappingSerializer):
"""RACPropertyMapping Serializer""" """RACPropertyMapping Serializer"""
static_settings = JSONDictField() static_settings = JSONDictField()
@ -26,6 +29,16 @@ class RACPropertyMappingSerializer(EnterpriseRequiredMixin, PropertyMappingSeria
fields = PropertyMappingSerializer.Meta.fields + ["static_settings"] fields = PropertyMappingSerializer.Meta.fields + ["static_settings"]
class RACPropertyMappingFilter(FilterSet):
"""Filter for RACPropertyMapping"""
managed = extend_schema_field(OpenApiTypes.STR)(AllValuesMultipleFilter(field_name="managed"))
class Meta:
model = RACPropertyMapping
fields = ["name", "managed"]
class RACPropertyMappingViewSet(UsedByMixin, ModelViewSet): class RACPropertyMappingViewSet(UsedByMixin, ModelViewSet):
"""RACPropertyMapping Viewset""" """RACPropertyMapping Viewset"""
@ -33,4 +46,4 @@ class RACPropertyMappingViewSet(UsedByMixin, ModelViewSet):
serializer_class = RACPropertyMappingSerializer serializer_class = RACPropertyMappingSerializer
search_fields = ["name"] search_fields = ["name"]
ordering = ["name"] ordering = ["name"]
filterset_fields = ["name", "managed"] filterset_class = RACPropertyMappingFilter

View File

@ -15,7 +15,7 @@ from authentik.events.models import Event, EventAction
from authentik.flows.challenge import RedirectChallenge from authentik.flows.challenge import RedirectChallenge
from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import in_memory_stage from authentik.flows.models import in_memory_stage
from authentik.flows.planner import FlowPlanner from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner
from authentik.flows.stage import RedirectStage from authentik.flows.stage import RedirectStage
from authentik.flows.views.executor import SESSION_KEY_PLAN from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.utils.time import timedelta_from_string from authentik.lib.utils.time import timedelta_from_string
@ -39,7 +39,12 @@ class RACStartView(EnterprisePolicyAccessView):
planner = FlowPlanner(self.provider.authorization_flow) planner = FlowPlanner(self.provider.authorization_flow)
planner.allow_empty_flows = True planner.allow_empty_flows = True
try: try:
plan = planner.plan(self.request) plan = planner.plan(
self.request,
{
PLAN_CONTEXT_APPLICATION: self.application,
},
)
except FlowNonApplicableException: except FlowNonApplicableException:
raise Http404 raise Http404
plan.insert_stage( plan.insert_stage(

View File

@ -56,6 +56,7 @@ class OAuthSourceSerializer(SourceSerializer):
"""Get source's type configuration""" """Get source's type configuration"""
return SourceTypeSerializer(instance.source_type).data return SourceTypeSerializer(instance.source_type).data
# pylint: disable=too-many-locals
def validate(self, attrs: dict) -> dict: def validate(self, attrs: dict) -> dict:
session = get_http_session() session = get_http_session()
source_type = registry.find_type(attrs["provider_type"]) source_type = registry.find_type(attrs["provider_type"])
@ -73,9 +74,17 @@ class OAuthSourceSerializer(SourceSerializer):
config = well_known_config.json() config = well_known_config.json()
if "issuer" not in config: if "issuer" not in config:
raise ValidationError({"oidc_well_known_url": "Invalid well-known configuration"}) raise ValidationError({"oidc_well_known_url": "Invalid well-known configuration"})
attrs["authorization_url"] = config.get("authorization_endpoint", "") field_map = {
attrs["access_token_url"] = config.get("token_endpoint", "") # authentik field to oidc field
attrs["profile_url"] = config.get("userinfo_endpoint", "") "authorization_url": "authorization_endpoint",
"access_token_url": "token_endpoint",
"profile_url": "userinfo_endpoint",
}
for ak_key, oidc_key in field_map.items():
# Don't overwrite user-set values
if ak_key in attrs and attrs[ak_key]:
continue
attrs[ak_key] = config.get(oidc_key, "")
inferred_oidc_jwks_url = config.get("jwks_uri", "") inferred_oidc_jwks_url = config.get("jwks_uri", "")
# Prefer user-entered URL to inferred URL to default URL # Prefer user-entered URL to inferred URL to default URL

View File

@ -44,3 +44,7 @@ class TestTypeAzureAD(TestCase):
self.assertEqual(ak_context["username"], AAD_USER["userPrincipalName"]) self.assertEqual(ak_context["username"], AAD_USER["userPrincipalName"])
self.assertEqual(ak_context["email"], AAD_USER["mail"]) self.assertEqual(ak_context["email"], AAD_USER["mail"])
self.assertEqual(ak_context["name"], AAD_USER["displayName"]) self.assertEqual(ak_context["name"], AAD_USER["displayName"])
def test_user_id(self):
"""Test azure AD user ID"""
self.assertEqual(AzureADOAuthCallback().get_user_id(AAD_USER), AAD_USER["id"])

View File

@ -83,9 +83,6 @@ class TestOAuthSource(APITestCase):
"provider_type": "openidconnect", "provider_type": "openidconnect",
"consumer_key": "foo", "consumer_key": "foo",
"consumer_secret": "foo", "consumer_secret": "foo",
"authorization_url": "http://foo",
"access_token_url": "http://foo",
"profile_url": "http://foo",
"oidc_well_known_url": url, "oidc_well_known_url": url,
"oidc_jwks_url": "", "oidc_jwks_url": "",
}, },

View File

@ -25,6 +25,11 @@ class AzureADOAuthCallback(OpenIDConnectOAuth2Callback):
client_class = UserprofileHeaderAuthClient client_class = UserprofileHeaderAuthClient
def get_user_id(self, info: dict[str, str]) -> str:
# Default try to get `id` for the Graph API endpoint
# fallback to OpenID logic in case the profile URL was changed
return info.get("id", super().get_user_id(info))
def get_user_enroll_context( def get_user_enroll_context(
self, self,
info: dict[str, Any], info: dict[str, Any],

2
go.mod
View File

@ -28,7 +28,7 @@ require (
github.com/spf13/cobra v1.8.0 github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/wwt/guac v1.3.2 github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2023106.1 goauthentik.io/api/v3 v3.2023106.3
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.16.0 golang.org/x/oauth2 v0.16.0
golang.org/x/sync v0.6.0 golang.org/x/sync v0.6.0

4
go.sum
View File

@ -316,8 +316,8 @@ go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYO
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2023106.1 h1:HHXiw11tZzhHq5kLf43/ZhsOj+BqaHzwqWYiEOF/UpE= goauthentik.io/api/v3 v3.2023106.3 h1:/ROBnDg6HBNOEyINKdI8pnwiu+ETQfB3MMdjgAoxJ/I=
goauthentik.io/api/v3 v3.2023106.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= goauthentik.io/api/v3 v3.2023106.3/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

60
poetry.lock generated
View File

@ -707,20 +707,20 @@ tests = ["async-timeout", "coverage (>=4.5,<5.0)", "pytest", "pytest-asyncio", "
[[package]] [[package]]
name = "channels-redis" name = "channels-redis"
version = "4.1.0" version = "4.2.0"
description = "Redis-backed ASGI channel layer implementation" description = "Redis-backed ASGI channel layer implementation"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
files = [ files = [
{file = "channels_redis-4.1.0-py3-none-any.whl", hash = "sha256:3696f5b9fe367ea495d402ba83d7c3c99e8ca0e1354ff8d913535976ed0abf73"}, {file = "channels_redis-4.2.0-py3-none-any.whl", hash = "sha256:2c5b944a39bd984b72aa8005a3ae11637bf29b5092adeb91c9aad4ab819a8ac4"},
{file = "channels_redis-4.1.0.tar.gz", hash = "sha256:6bd4f75f4ab4a7db17cee495593ace886d7e914c66f8214a1f247ff6659c073a"}, {file = "channels_redis-4.2.0.tar.gz", hash = "sha256:01c26c4d5d3a203f104bba9e5585c0305a70df390d21792386586068162027fd"},
] ]
[package.dependencies] [package.dependencies]
asgiref = ">=3.2.10,<4" asgiref = ">=3.2.10,<4"
channels = "*" channels = "*"
msgpack = ">=1.0,<2.0" msgpack = ">=1.0,<2.0"
redis = ">=4.5.3" redis = ">=4.6"
[package.extras] [package.extras]
cryptography = ["cryptography (>=1.3.0)"] cryptography = ["cryptography (>=1.3.0)"]
@ -3657,28 +3657,28 @@ pyasn1 = ">=0.1.3"
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.1.12" version = "0.1.13"
description = "An extremely fast Python linter and code formatter, written in Rust." description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "ruff-0.1.12-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:544038693543c11edc56bb94a9875df2dc249e3616f90c15964c720dcccf0745"}, {file = "ruff-0.1.13-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e3fd36e0d48aeac672aa850045e784673449ce619afc12823ea7868fcc41d8ba"},
{file = "ruff-0.1.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:8a0e3ef6299c4eab75a7740730e4b4bd4a36e0bd8102ded01553403cad088fd4"}, {file = "ruff-0.1.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9fb6b3b86450d4ec6a6732f9f60c4406061b6851c4b29f944f8c9d91c3611c7a"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47f6d939461e3273f10f4cd059fd0b83c249d73f1736032fffbac83a62939395"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b13ba5d7156daaf3fd08b6b993360a96060500aca7e307d95ecbc5bb47a69296"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25be18abc1fc3f3d3fb55855c41ed5d52063316defde202f413493bb3888218c"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9ebb40442f7b531e136d334ef0851412410061e65d61ca8ce90d894a094feb22"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d41e9f100b50526d80b076fc9c103c729387ff3f10f63606ed1038c30a372a40"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226b517f42d59a543d6383cfe03cccf0091e3e0ed1b856c6824be03d2a75d3b6"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:472a0548738d4711549c7874b43fab61aacafb1fede29c5232d4cfb8e2d13f69"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5f0312ba1061e9b8c724e9a702d3c8621e3c6e6c2c9bd862550ab2951ac75c16"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46685ef2f106b827705df876d38617741ed4f858bbdbc0817f94476c45ab6669"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2f59bcf5217c661254bd6bc42d65a6fd1a8b80c48763cb5c2293295babd945dd"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf6073749c70b616d7929897b14824ec6713a6c3a8195dfd2ffdcc66594d880c"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6894b00495e00c27b6ba61af1fc666f17de6140345e5ef27dd6e08fb987259d"},
{file = "ruff-0.1.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bdf26e5a2efab4c3aaf6b61648ea47a525dc12775810a85c285dc9ca03e5ac0"}, {file = "ruff-0.1.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1600942485c6e66119da294c6294856b5c86fd6df591ce293e4a4cc8e72989"},
{file = "ruff-0.1.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b631c6a95e4b6d5c4299e599067b5a89f5b18e2f2d9a6c22b879b3c4b077c96e"}, {file = "ruff-0.1.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ee3febce7863e231a467f90e681d3d89210b900d49ce88723ce052c8761be8c7"},
{file = "ruff-0.1.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f193f460e231e63af5fc7516897cf5ab257cbda72ae83cf9a654f1c80c3b758a"}, {file = "ruff-0.1.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dcaab50e278ff497ee4d1fe69b29ca0a9a47cd954bb17963628fa417933c6eb1"},
{file = "ruff-0.1.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:718523c3a0b787590511f212d30cc9b194228ef369c8bdd72acd1282cc27c468"}, {file = "ruff-0.1.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f57de973de4edef3ad3044d6a50c02ad9fc2dff0d88587f25f1a48e3f72edf5e"},
{file = "ruff-0.1.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1c49e826de55d81a6ef93808b760925e492bad7cc470aaa114a3be158b2c7f99"}, {file = "ruff-0.1.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7a36fa90eb12208272a858475ec43ac811ac37e91ef868759770b71bdabe27b6"},
{file = "ruff-0.1.12-py3-none-win32.whl", hash = "sha256:fbb1c002eeacb60161e51d77b2274c968656599477a1c8c65066953276e8ee2b"}, {file = "ruff-0.1.13-py3-none-win32.whl", hash = "sha256:a623349a505ff768dad6bd57087e2461be8db58305ebd5577bd0e98631f9ae69"},
{file = "ruff-0.1.12-py3-none-win_amd64.whl", hash = "sha256:7fe06ba77e5b7b78db1d058478c47176810f69bb5be7c1b0d06876af59198203"}, {file = "ruff-0.1.13-py3-none-win_amd64.whl", hash = "sha256:f988746e3c3982bea7f824c8fa318ce7f538c4dfefec99cd09c8770bd33e6539"},
{file = "ruff-0.1.12-py3-none-win_arm64.whl", hash = "sha256:bb29f8e3e6c95024902eaec5a9ce1fd5ac4e77f4594f4554e67fbb0f6d9a2f37"}, {file = "ruff-0.1.13-py3-none-win_arm64.whl", hash = "sha256:6bbbc3042075871ec17f28864808540a26f0f79a4478c357d3e3d2284e832998"},
{file = "ruff-0.1.12.tar.gz", hash = "sha256:97189f38c655e573f6bea0d12e9f18aad5539fd08ab50651449450999f45383a"}, {file = "ruff-0.1.13.tar.gz", hash = "sha256:e261f1baed6291f434ffb1d5c6bd8051d1c2a26958072d38dfbec39b3dda7352"},
] ]
[[package]] [[package]]
@ -3762,13 +3762,13 @@ tornado = ["tornado (>=5)"]
[[package]] [[package]]
name = "service-identity" name = "service-identity"
version = "23.1.0" version = "24.1.0"
description = "Service identity verification for pyOpenSSL & cryptography." description = "Service identity verification for pyOpenSSL & cryptography."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "service_identity-23.1.0-py3-none-any.whl", hash = "sha256:87415a691d52fcad954a500cb81f424d0273f8e7e3ee7d766128f4575080f383"}, {file = "service_identity-24.1.0-py3-none-any.whl", hash = "sha256:a28caf8130c8a5c1c7a6f5293faaf239bbfb7751e4862436920ee6f2616f568a"},
{file = "service_identity-23.1.0.tar.gz", hash = "sha256:ecb33cd96307755041e978ab14f8b14e13b40f1fbd525a4dc78f46d2b986431d"}, {file = "service_identity-24.1.0.tar.gz", hash = "sha256:6829c9d62fb832c2e1c435629b0a8c476e1929881f28bee4d20bc24161009221"},
] ]
[package.dependencies] [package.dependencies]
@ -3778,7 +3778,7 @@ pyasn1 = "*"
pyasn1-modules = "*" pyasn1-modules = "*"
[package.extras] [package.extras]
dev = ["pyopenssl", "service-identity[docs,idna,mypy,tests]"] dev = ["pyopenssl", "service-identity[idna,mypy,tests]"]
docs = ["furo", "myst-parser", "pyopenssl", "sphinx", "sphinx-notfound-page"] docs = ["furo", "myst-parser", "pyopenssl", "sphinx", "sphinx-notfound-page"]
idna = ["idna"] idna = ["idna"]
mypy = ["idna", "mypy", "types-pyopenssl"] mypy = ["idna", "mypy", "types-pyopenssl"]
@ -3987,13 +3987,13 @@ wsproto = ">=0.14"
[[package]] [[package]]
name = "twilio" name = "twilio"
version = "8.11.0" version = "8.11.1"
description = "Twilio API client and TwiML generator" description = "Twilio API client and TwiML generator"
optional = false optional = false
python-versions = ">=3.7.0" python-versions = ">=3.7.0"
files = [ files = [
{file = "twilio-8.11.0-py2.py3-none-any.whl", hash = "sha256:90fd47f220e597163020d3755a81aed76fd217e116ab36fd241d9bf48d1a0a18"}, {file = "twilio-8.11.1-py2.py3-none-any.whl", hash = "sha256:0c079601b972cca25dbe0e259d5c4a01c94795842f6b9f1d02c82269019d7cbb"},
{file = "twilio-8.11.0.tar.gz", hash = "sha256:792509da936c4f47d9fa7071d5f1f3bdc9314aaf96225bac4f0ef28f8688a95b"}, {file = "twilio-8.11.1.tar.gz", hash = "sha256:6dfafb60e7a89ad19d2fc4055ce2b86215d30fc68d88452fa588897de8608c71"},
] ]
[package.dependencies] [package.dependencies]

View File

@ -14046,7 +14046,11 @@ paths:
- in: query - in: query
name: managed name: managed
schema: schema:
type: array
items:
type: string type: string
explode: true
style: form
- in: query - in: query
name: name name: name
schema: schema:

View File

@ -17,7 +17,7 @@
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-sonarjs": "^0.23.0", "eslint-plugin-sonarjs": "^0.23.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.1.1", "prettier": "^3.2.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"wdio-wait-for": "^3.0.10" "wdio-wait-for": "^3.0.10"
@ -6508,9 +6508,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.1.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz",
"integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"

View File

@ -14,7 +14,7 @@
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-sonarjs": "^0.23.0", "eslint-plugin-sonarjs": "^0.23.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.1.1", "prettier": "^3.2.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"wdio-wait-for": "^3.0.10" "wdio-wait-for": "^3.0.10"

View File

@ -6,27 +6,27 @@
[ [
"@babel/plugin-proposal-decorators", "@babel/plugin-proposal-decorators",
{ {
"decoratorsBeforeExport": true "decoratorsBeforeExport": true,
} },
], ],
[ [
"@babel/plugin-transform-class-properties", "@babel/plugin-transform-class-properties",
{ {
"loose": true "loose": true,
} },
], ],
[ [
"@babel/plugin-transform-runtime", "@babel/plugin-transform-runtime",
{ {
"regenerator": true "regenerator": true,
} },
], ],
"macros", "macros",
[ [
"@babel/plugin-transform-private-property-in-object", "@babel/plugin-transform-private-property-in-object",
{ {
"loose": true "loose": true,
} },
] ],
] ],
} }

744
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@
"@codemirror/theme-one-dark": "^6.1.2", "@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.3", "@formatjs/intl-listformat": "^7.5.3",
"@fortawesome/fontawesome-free": "^6.5.1", "@fortawesome/fontawesome-free": "^6.5.1",
"@goauthentik/api": "^2023.10.6-1705072854", "@goauthentik/api": "^2023.10.6-1705263684",
"@lit-labs/context": "^0.4.0", "@lit-labs/context": "^0.4.0",
"@lit-labs/task": "^3.1.0", "@lit-labs/task": "^3.1.0",
"@lit/localize": "^0.11.4", "@lit/localize": "^0.11.4",
@ -88,13 +88,13 @@
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"@spotlightjs/spotlight": "^1.2.6", "@spotlightjs/spotlight": "^1.2.6",
"@storybook/addon-essentials": "^7.6.7", "@storybook/addon-essentials": "^7.6.8",
"@storybook/addon-links": "^7.6.7", "@storybook/addon-links": "^7.6.8",
"@storybook/api": "^7.6.7", "@storybook/api": "^7.6.8",
"@storybook/blocks": "^7.6.4", "@storybook/blocks": "^7.6.4",
"@storybook/manager-api": "^7.6.7", "@storybook/manager-api": "^7.6.8",
"@storybook/web-components": "^7.6.7", "@storybook/web-components": "^7.6.8",
"@storybook/web-components-vite": "^7.6.7", "@storybook/web-components-vite": "^7.6.8",
"@trivago/prettier-plugin-sort-imports": "^4.3.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/chart.js": "^2.9.41", "@types/chart.js": "^2.9.41",
"@types/codemirror": "5.60.15", "@types/codemirror": "5.60.15",
@ -113,17 +113,17 @@
"eslint-plugin-storybook": "^0.6.15", "eslint-plugin-storybook": "^0.6.15",
"lit-analyzer": "^2.0.3", "lit-analyzer": "^2.0.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.1.1", "prettier": "^3.2.2",
"pseudolocale": "^2.0.0", "pseudolocale": "^2.0.0",
"pyright": "=1.1.338", "pyright": "=1.1.338",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"rollup": "^4.9.4", "rollup": "^4.9.5",
"rollup-plugin-copy": "^3.5.0", "rollup-plugin-copy": "^3.5.0",
"rollup-plugin-cssimport": "^1.0.3", "rollup-plugin-cssimport": "^1.0.3",
"rollup-plugin-modify": "^3.0.0", "rollup-plugin-modify": "^3.0.0",
"rollup-plugin-postcss-lit": "^2.1.0", "rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^7.6.7", "storybook": "^7.6.8",
"storybook-addon-mock": "^4.3.0", "storybook-addon-mock": "^4.3.0",
"ts-lit-plugin": "^2.0.2", "ts-lit-plugin": "^2.0.2",
"tslib": "^2.6.2", "tslib": "^2.6.2",

View File

@ -5,6 +5,7 @@ import "@goauthentik/admin/property-mappings/PropertyMappingSAMLForm";
import "@goauthentik/admin/property-mappings/PropertyMappingScopeForm"; import "@goauthentik/admin/property-mappings/PropertyMappingScopeForm";
import "@goauthentik/admin/property-mappings/PropertyMappingTestForm"; import "@goauthentik/admin/property-mappings/PropertyMappingTestForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/elements/Alert";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/forms/ProxyForm"; import "@goauthentik/elements/forms/ProxyForm";
import "@goauthentik/elements/wizard/FormWizardPage"; import "@goauthentik/elements/wizard/FormWizardPage";
@ -63,7 +64,7 @@ export class InitialPropertyMappingWizardPage extends WizardPage {
]; ];
this.host.isValid = true; this.host.isValid = true;
}} }}
?disabled=${type.requiresEnterprise ? !this.enterprise?.hasLicense : false} ?disabled=${type.requiresEnterprise ? this.enterprise?.hasLicense : false}
/> />
<label class="pf-c-radio__label" for=${`${type.component}-${type.modelName}`} <label class="pf-c-radio__label" for=${`${type.component}-${type.modelName}`}
>${type.name}</label >${type.name}</label
@ -114,6 +115,7 @@ export class PropertyMappingWizard extends AKElement {
<ak-property-mapping-wizard-initial <ak-property-mapping-wizard-initial
slot="initial" slot="initial"
.mappingTypes=${this.mappingTypes} .mappingTypes=${this.mappingTypes}
.enterprise=${this.enterprise}
> >
</ak-property-mapping-wizard-initial> </ak-property-mapping-wizard-initial>
${this.mappingTypes.map((type) => { ${this.mappingTypes.map((type) => {

View File

@ -203,8 +203,9 @@ export class LDAPProviderViewPage extends AKElement {
class="pf-c-form-control" class="pf-c-form-control"
readonly readonly
type="text" type="text"
value=${`cn=${this.me?.user value=${`cn=${
.username},ou=users,${this.provider?.baseDn?.toLowerCase()}`} this.me?.user.username
},ou=users,${this.provider?.baseDn?.toLowerCase()}`}
/> />
</div> </div>
<div class="pf-c-form__group"> <div class="pf-c-form__group">

View File

@ -257,7 +257,8 @@ select[multiple] option:checked {
.pf-c-login__main-header-desc { .pf-c-login__main-header-desc {
color: var(--ak-dark-foreground); color: var(--ak-dark-foreground);
} }
.pf-c-login__main-footer-links-item img { .pf-c-login__main-footer-links-item img,
.pf-c-login__main-footer-links-item .fas {
filter: invert(1); filter: invert(1);
} }
.pf-c-login__main-footer-band { .pf-c-login__main-footer-band {

View File

@ -83,8 +83,12 @@ export class RacInterface extends Interface {
// Keep track of current connection attempt // Keep track of current connection attempt
connectionAttempt = 0; connectionAttempt = 0;
static domSize(): DOMRect { static domSize(): { width: number; height: number } {
return document.body.getBoundingClientRect(); const size = document.body.getBoundingClientRect();
return {
width: size.width * window.devicePixelRatio,
height: size.height * window.devicePixelRatio,
};
} }
constructor() { constructor() {

View File

@ -0,0 +1,99 @@
---
title: "Happy New Year from Authentik Security"
slug: 2024-1-12-happy-new-year-from-authentik-security
authors:
- name: Jens Langhammer
title: CTO at Authentik Security Inc
url: https://github.com/BeryJu
image_url: https://github.com/BeryJu.png
tags:
- authentik
- happy new year
- new features
- year in review
- SSO
- SaaS
- SCIM
- RADIUS
- remote access
- RBAC
- identity provider
- authentication
- Authentik Security
hide_table_of_contents: false
---
> **_authentik is an open source Identity Provider that unifies your identity needs into a single platform, replacing Okta, Active Directory, and auth0. Authentik Security is a [public benefit company](https://github.com/OpenCoreVentures/ocv-public-benefit-company/blob/main/ocv-public-benefit-company-charter.md) building on top of the open source project._**
---
A hearty Happy New Year to you all, from all of of us at Authentik Security, with sincere wishes that your 2024 may be filled with a maximum of joys (new features and elegant code) and a minimum of pains (bugs and the dreadful reality of not-enough-time).
> The start of a new year makes me want to first say **thank you** for the past year.
## Thank you!
**Thank you to our community**, from the newly joined members to our long-time friends and moderators and holders-of-knowledge. Without you all, well… we literally wouldnt be here. No matter how deep your knowledge of authentik is, its really your willingness to explore and test and give feedback on new and old features, all while supporting each other and staying in touch with good humor and vibes, that make us such a vibrant community.
**Thank you to our users**, from those who run authentik in their homelabs to those who run authentik in production, and everyone in between. We appreciate your trust and guidance, and your input into how we can provide the most-needed features and grow our product in the ways that solve your business needs and challenges.
**And of course thanks to our small team** here at Authentik Security, who joined me on this adventure and brought your skills and talents, your experience and passions, and your dedication to our product and users. We built a lot together last year, and this year has a rock-star list of features and functionality coming up!
## Accomplishments in 2023
Looking back to the work we did in 2023, the new features are just a part of the overall achievements and celebrations (and challenges) of building a new [company](https://goauthentik.io/blog/2022-11-02-the-next-step-for-authentik), growing the team, celebrating our [1st year](https://goauthentik.io/blog/2023-11-1-happy-birthday-to-us), and [defining our tools and processes](https://goauthentik.io/blog/2023-12-21-five-lessons-from-choosing-infrastructure-tooling). But we released quite a few new features that Im proud to share.
### RBAC
[RBAC](https://goauthentik.io/docs/user-group-role/access-control/) (role-based access control) is the gold standard of access control. RBAC provides the ability to finely configure permissions within authentik. These permissions can be used to delegate different tasks, such as user management, application creation and more to users without granting them full superuser permissions. authentik has had internal RBAC for a long time (and of course the policy engine for restricting access to applications), however access to different objects within authentik (like Users, Groups, etc) was not possible previously.
### Enterprise Support
Providing dedicated support with a proper ticketing system was a big accomplishment for 2023. Support was the flagship feature of our [Enterprise release](https://goauthentik.io/blog/2023-08-31-announcing-the-authentik-enterprise-release) in the fall of 2023.
### SCIM support
Our [2023.3 release](https://goauthentik.io/docs/releases/2023.3) added support for SCIM (System for Cross-domain Identity Management) protocol, allowing for the provision of users into other IT systems, where the provider synchronizes Users, Groups and the user membership.
### RADIUS Support
The [RADIUS protocol](https://goauthentik.io/docs/providers/radius/) for authentication allows for the integration of a wider variety of systems such as VPN software, network switches/routers, and others. The RADIUS provider also uses a flow to authenticate users, and supports the same stages as the [LDAP Provider](https://goauthentik.io/docs/providers/ldap/).
## Whats coming up in 2024?
Looking forward to new functionality for the new year, let me share some of the ones I am most excited about. As with any small development team, we tackle what we can, with an eye on which features will be most beneficial for you all, which have dependencies upon later features, maintainability as we further develop the feature, and how to best get them all out the door fully tested and documented.
### Wizardry
The task of adding the applications that you want authentik to authenticate is about to get a lot easier; we have a new wizard that combines the process of defining a new provider and a new application into one single task. This new wizard saves many steps and streamlines the process. Look for it in preview mode in our current 2023.10 release (navigate to the Applications page in the Admin UI), and let us know your thoughts. We will continue tweaking it, specifically the multi-select functionality, but feedback is always welcome!
![](./new-app-wizard.png)
### Remote Access Control (RAC)
With [RAC](https://goauthentik.io/docs/providers/rac/), in preview now with a full release in early 2024, authentik Admins are able to access remote Windows/macOS/Linux machines via [RDP](https://en.wikipedia.org/wiki/Remote_Desktop_Protocol)/[SSH](https://en.wikipedia.org/wiki/Secure_Shell)/[VNC](https://en.wikipedia.org/wiki/Virtual_Network_Computing). The preview version already has capabilities for using a bi-directoinal clipboard between the authentik client and the remote machine, audio redirection (meaning you can hear audio from the remote machine on your local instance), and resizing of the window you view of the remote machine.
### Mobile authenticator app for authentik
Soon you will be able to download our new authentik authentication app from Apple Store, and a bit further into 2024, from Google Play Store. This app can be used for 2FA/MFA verification when authentik users log in to authentik or access any application managed by an authentik instance. The first release of this app will use number-matching as the default verification process; users will view their authentik authenticator app on their phone, be prompted with a set of three numbers, and then need to select the same number that is displayed on their authentik instance login panel.
### Building out our SaaS offering
One of our most exciting, and definitely our biggest, projects for 2024 will be developing our SaaS offering, the hosted, fully-managed Enterprise Cloud. The Enterprise Cloud plan will provide the convenience of our enterprise-level product as a SaaS offering, hosted and managed by Authentik Security. For many organizations, the benefits of decreased operational costs and universal data access (no VPN, servers, and network configuration required) make SaaS the best choice. With the cloud offering, the same enterprise-level support plan is included, and migrating to self-hosted is always an option.
### DX and UX and quality-of-life improvements
As we mentioned in our blog about our one-year anniversary, we also plan to spend some time focused on user experience.
- Increase our focus on UX and ease-of-use, templatizing as much as possible of the frontend components, and developing a UI Style Guide
- A redesigned website, with more information about our solutions, use cases, and offerings
- New structure for our technical documentation; leveraging information architecture and user research to make it easier to find what you are looking for in our docs
- Defining even more robust tests and checks for our CI/CD pipeline and build process
- Stronger integration and migration testing, both automated and manual
- Spending more time on outreach and user research to learn what you all want
### Yes, a big year ahead
As most of us in the software and technology space know, the hard work of building new features and growing a company is, well, actually kind of fun. Challenging, yes, but always rewarding.
Wed love to hear from you all about our upcoming plans; reach out to us with an email to [hello@goauthentik.io](mailto:hello@goauthentik.io) or on [Discord](https://discord.com/channels/809154715984199690/809154716507963434).

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -34,7 +34,7 @@
"@docusaurus/tsconfig": "3.0.1", "@docusaurus/tsconfig": "3.0.1",
"@docusaurus/types": "3.0.1", "@docusaurus/types": "3.0.1",
"@types/react": "^18.2.47", "@types/react": "^18.2.47",
"prettier": "3.1.1", "prettier": "3.2.2",
"typescript": "~5.3.3" "typescript": "~5.3.3"
}, },
"engines": { "engines": {
@ -13754,9 +13754,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.1.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.2.tgz",
"integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "integrity": "sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==",
"dev": true, "dev": true,
"bin": { "bin": {
"prettier": "bin/prettier.cjs" "prettier": "bin/prettier.cjs"

View File

@ -53,7 +53,7 @@
"@docusaurus/tsconfig": "3.0.1", "@docusaurus/tsconfig": "3.0.1",
"@docusaurus/types": "3.0.1", "@docusaurus/types": "3.0.1",
"@types/react": "^18.2.47", "@types/react": "^18.2.47",
"prettier": "3.1.1", "prettier": "3.2.2",
"typescript": "~5.3.3" "typescript": "~5.3.3"
}, },
"engines": { "engines": {