root: bump python deps (django 5) (#7862)

* bump python deps

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* vendor pickle serializer for now

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

#7761

* cleanup some things and re-build api scheme

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix web and go

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* actually fix go...?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* better annotate json fields

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use jsondictfield wherever

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* remove all virtualenvs?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* final version bump

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-12-18 22:07:59 +01:00 committed by GitHub
parent ba174d810b
commit 729ef4d786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 960 additions and 919 deletions

View File

@ -61,10 +61,6 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup authentik env
uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: checkout stable
run: |
# Delete all poetry envs
@ -76,7 +72,7 @@ jobs:
git checkout version/$(python -c "from authentik import __version__; print(__version__)")
rm -rf .github/ scripts/
mv ../.github ../scripts .
- name: Setup authentik env (ensure stable deps are installed)
- name: Setup authentik env (stable)
uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
@ -90,14 +86,13 @@ jobs:
git clean -d -fx .
git checkout $GITHUB_SHA
# Delete previous poetry env
rm -rf $(poetry env info --path)
rm -rf /home/runner/.cache/pypoetry/virtualenvs/*
- name: Setup authentik env (ensure latest deps are installed)
uses: ./.github/actions/setup
with:
postgresql_version: ${{ matrix.psql }}
- name: migrate to latest
run: |
poetry install
poetry run python -m lifecycle.migrate
test-unittest:
name: test-unittest - PostgreSQL ${{ matrix.psql }}

View File

@ -115,8 +115,9 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
npx prettier --write diff.md
gen-clean:
rm -rf web/api/src/
rm -rf api/
rm -rf gen-go-api/
rm -rf gen-ts-api/
rm -rf web/node_modules/@goauthentik/api/
gen-client-ts: ## Build and install the authentik API for Typescript into the authentik UI Application
docker run \

View File

@ -3,7 +3,7 @@ from django.utils.translation import gettext_lazy as _
from drf_spectacular.utils import extend_schema, inline_serializer
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, DateTimeField, JSONField
from rest_framework.fields import CharField, DateTimeField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ListSerializer, ModelSerializer
@ -15,7 +15,7 @@ from authentik.blueprints.v1.importer import Importer
from authentik.blueprints.v1.oci import OCI_PREFIX
from authentik.blueprints.v1.tasks import apply_blueprint, blueprints_find_dict
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import JSONDictField, PassiveSerializer
class ManagedSerializer:
@ -28,7 +28,7 @@ class MetadataSerializer(PassiveSerializer):
"""Serializer for blueprint metadata"""
name = CharField()
labels = JSONField()
labels = JSONDictField()
class BlueprintInstanceSerializer(ModelSerializer):

View File

@ -2,11 +2,11 @@
from typing import TYPE_CHECKING
from rest_framework.exceptions import ValidationError
from rest_framework.fields import BooleanField, JSONField
from rest_framework.fields import BooleanField
from structlog.stdlib import get_logger
from authentik.blueprints.v1.meta.registry import BaseMetaModel, MetaResult, registry
from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.api.utils import JSONDictField, PassiveSerializer
if TYPE_CHECKING:
from authentik.blueprints.models import BlueprintInstance
@ -17,7 +17,7 @@ LOGGER = get_logger()
class ApplyBlueprintMetaSerializer(PassiveSerializer):
"""Serializer for meta apply blueprint model"""
identifiers = JSONField(validators=[is_dict])
identifiers = JSONDictField()
required = BooleanField(default=True)
# We cannot override `instance` as that will confuse rest_framework

View File

@ -8,7 +8,7 @@ from django_filters.filterset import FilterSet
from drf_spectacular.utils import OpenApiResponse, extend_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import CharField, IntegerField, JSONField
from rest_framework.fields import CharField, IntegerField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError
@ -16,7 +16,7 @@ from rest_framework.viewsets import ModelViewSet
from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import Group, User
from authentik.rbac.api.roles import RoleSerializer
@ -24,7 +24,7 @@ from authentik.rbac.api.roles import RoleSerializer
class GroupMemberSerializer(ModelSerializer):
"""Stripped down user serializer to show relevant users for groups"""
attributes = JSONField(validators=[is_dict], required=False)
attributes = JSONDictField(required=False)
uid = CharField(read_only=True)
class Meta:
@ -44,7 +44,7 @@ class GroupMemberSerializer(ModelSerializer):
class GroupSerializer(ModelSerializer):
"""Group Serializer"""
attributes = JSONField(validators=[is_dict], required=False)
attributes = JSONDictField(required=False)
users_obj = ListSerializer(
child=GroupMemberSerializer(), read_only=True, source="users", required=False
)

View File

@ -32,13 +32,7 @@ from drf_spectacular.utils import (
)
from guardian.shortcuts import get_anonymous_user, get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import (
CharField,
IntegerField,
JSONField,
ListField,
SerializerMethodField,
)
from rest_framework.fields import CharField, IntegerField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import (
@ -57,7 +51,7 @@ from authentik.admin.api.metrics import CoordinateSerializer
from authentik.api.decorators import permission_required
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict
from authentik.core.api.utils import JSONDictField, LinkSerializer, PassiveSerializer
from authentik.core.middleware import (
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
SESSION_KEY_IMPERSONATE_USER,
@ -89,7 +83,7 @@ LOGGER = get_logger()
class UserGroupSerializer(ModelSerializer):
"""Simplified Group Serializer for user's groups"""
attributes = JSONField(required=False)
attributes = JSONDictField(required=False)
parent_name = CharField(source="parent.name", read_only=True)
class Meta:
@ -110,7 +104,7 @@ class UserSerializer(ModelSerializer):
is_superuser = BooleanField(read_only=True)
avatar = CharField(read_only=True)
attributes = JSONField(validators=[is_dict], required=False)
attributes = JSONDictField(required=False)
groups = PrimaryKeyRelatedField(
allow_empty=True, many=True, source="ak_groups", queryset=Group.objects.all(), default=list
)

View File

@ -2,6 +2,9 @@
from typing import Any
from django.db.models import Model
from drf_spectacular.extensions import OpenApiSerializerFieldExtension
from drf_spectacular.plumbing import build_basic_type
from drf_spectacular.types import OpenApiTypes
from rest_framework.fields import CharField, IntegerField, JSONField
from rest_framework.serializers import Serializer, SerializerMethodField, ValidationError
@ -13,6 +16,21 @@ def is_dict(value: Any):
raise ValidationError("Value must be a dictionary, and not have any duplicate keys.")
class JSONDictField(JSONField):
"""JSON Field which only allows dictionaries"""
default_validators = [is_dict]
class JSONExtension(OpenApiSerializerFieldExtension):
"""Generate API Schema for JSON fields as"""
target_class = "authentik.core.api.utils.JSONDictField"
def map_serializer_field(self, auto_schema, direction):
return build_basic_type(OpenApiTypes.OBJECT)
class PassiveSerializer(Serializer):
"""Base serializer class which doesn't implement create/update methods"""
@ -26,7 +44,7 @@ class PassiveSerializer(Serializer):
class PropertyMappingPreviewSerializer(PassiveSerializer):
"""Preview how the current user is mapped via the property mappings selected in a provider"""
preview = JSONField(read_only=True)
preview = JSONDictField(read_only=True)
class MetaNameSerializer(PassiveSerializer):

View File

@ -9,13 +9,13 @@ from rest_framework.fields import BooleanField, CharField, DateTimeField
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import JSONField, ModelSerializer, ValidationError
from rest_framework.serializers import ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from authentik import get_build_hash
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import Provider
from authentik.outposts.api.service_connections import ServiceConnectionSerializer
from authentik.outposts.apps import MANAGED_OUTPOST
@ -34,7 +34,7 @@ from authentik.providers.radius.models import RadiusProvider
class OutpostSerializer(ModelSerializer):
"""Outpost Serializer"""
config = JSONField(validators=[is_dict], source="_config")
config = JSONDictField(source="_config")
# Need to set allow_empty=True for the embedded outpost with no providers
# is checked for other providers in the API Viewset
providers = PrimaryKeyRelatedField(
@ -95,7 +95,7 @@ class OutpostSerializer(ModelSerializer):
class OutpostDefaultConfigSerializer(PassiveSerializer):
"""Global default outpost config"""
config = JSONField(read_only=True)
config = JSONDictField(read_only=True)
class OutpostHealthSerializer(PassiveSerializer):

View File

@ -1,8 +1,8 @@
"""Serializer for policy execution"""
from rest_framework.fields import BooleanField, CharField, DictField, JSONField, ListField
from rest_framework.fields import BooleanField, CharField, DictField, ListField
from rest_framework.relations import PrimaryKeyRelatedField
from authentik.core.api.utils import PassiveSerializer, is_dict
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import User
@ -10,7 +10,7 @@ class PolicyTestSerializer(PassiveSerializer):
"""Test policy execution for a user with context"""
user = PrimaryKeyRelatedField(queryset=User.objects.all())
context = JSONField(required=False, validators=[is_dict])
context = JSONDictField(required=False)
class PolicyTestResultSerializer(PassiveSerializer):

View File

View File

@ -0,0 +1,22 @@
"""
Module for abstract serializer/unserializer base classes.
"""
import pickle # nosec
class PickleSerializer:
"""
Simple wrapper around pickle to be used in signing.dumps()/loads() and
cache backends.
"""
def __init__(self, protocol=None):
self.protocol = pickle.HIGHEST_PROTOCOL if protocol is None else protocol
def dumps(self, obj):
"""Pickle data to be stored in redis"""
return pickle.dumps(obj, self.protocol)
def loads(self, data):
"""Unpickle data to be loaded from redis"""
return pickle.loads(data) # nosec

View File

@ -138,6 +138,7 @@ SPECTACULAR_SETTINGS = {
"EventActions": "authentik.events.models.EventAction",
"ChallengeChoices": "authentik.flows.challenge.ChallengeTypes",
"FlowDesignationEnum": "authentik.flows.models.FlowDesignation",
"FlowLayoutEnum": "authentik.flows.models.FlowLayout",
"PolicyEngineMode": "authentik.policies.models.PolicyEngineMode",
"ProxyMode": "authentik.providers.proxy.models.ProxyMode",
"PromptTypeEnum": "authentik.stages.prompt.models.FieldTypes",
@ -204,7 +205,7 @@ DJANGO_REDIS_SCAN_ITERSIZE = 1000
DJANGO_REDIS_IGNORE_EXCEPTIONS = True
DJANGO_REDIS_LOG_IGNORED_EXCEPTIONS = True
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_SERIALIZER = "django.contrib.sessions.serializers.PickleSerializer"
SESSION_SERIALIZER = "authentik.root.sessions.pickle.PickleSerializer"
SESSION_CACHE_ALIAS = "default"
# Configured via custom SessionMiddleware
# SESSION_COOKIE_SAMESITE = "None"

View File

@ -22,8 +22,8 @@ from authentik.stages.authenticator.util import hex_validator, random_hex
class TOTPDigits(models.TextChoices):
"""OTP Time Digits"""
SIX = 6, _("6 digits, widely compatible")
EIGHT = 8, _("8 digits, not compatible with apps like Google Authenticator")
SIX = "6", _("6 digits, widely compatible")
EIGHT = "8", _("8 digits, not compatible with apps like Google Authenticator")
class AuthenticatorTOTPStage(ConfigurableStage, FriendlyNamedStage, Stage):

View File

@ -7,7 +7,7 @@ from django.http.response import Http404
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as __
from django.utils.translation import gettext_lazy as _
from rest_framework.fields import CharField, JSONField
from rest_framework.fields import CharField
from rest_framework.serializers import ValidationError
from structlog.stdlib import get_logger
from webauthn.authentication.generate_authentication_options import generate_authentication_options
@ -16,7 +16,7 @@ from webauthn.helpers.base64url_to_bytes import base64url_to_bytes
from webauthn.helpers.exceptions import InvalidAuthenticationResponse
from webauthn.helpers.structs import AuthenticationCredential
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import Application, User
from authentik.core.signals import login_failed
from authentik.events.models import Event, EventAction
@ -40,7 +40,7 @@ class DeviceChallenge(PassiveSerializer):
device_class = CharField()
device_uid = CharField()
challenge = JSONField()
challenge = JSONDictField()
def get_challenge_for_device(

View File

@ -6,10 +6,10 @@ from typing import Optional
from django.conf import settings
from django.http import HttpRequest, HttpResponse
from jwt import PyJWTError, decode, encode
from rest_framework.fields import CharField, IntegerField, JSONField, ListField, UUIDField
from rest_framework.fields import CharField, IntegerField, ListField, UUIDField
from rest_framework.serializers import ValidationError
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge
@ -68,7 +68,7 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
selected_stage = CharField(required=False)
code = CharField(required=False)
webauthn = JSONField(required=False)
webauthn = JSONDictField(required=False)
duo = IntegerField(required=False)
component = CharField(default="ak-stage-authenticator-validate")

View File

@ -1,7 +1,7 @@
"""WebAuthn stage"""
from django.http import HttpRequest, HttpResponse
from django.http.request import QueryDict
from rest_framework.fields import CharField, JSONField
from rest_framework.fields import CharField
from rest_framework.serializers import ValidationError
from webauthn.helpers.bytes_to_base64url import bytes_to_base64url
from webauthn.helpers.exceptions import InvalidRegistrationResponse
@ -16,6 +16,7 @@ from webauthn.registration.verify_registration_response import (
verify_registration_response,
)
from authentik.core.api.utils import JSONDictField
from authentik.core.models import User
from authentik.flows.challenge import (
Challenge,
@ -33,14 +34,14 @@ SESSION_KEY_WEBAUTHN_CHALLENGE = "authentik/stages/authenticator_webauthn/challe
class AuthenticatorWebAuthnChallenge(WithUserInfoChallenge):
"""WebAuthn Challenge"""
registration = JSONField()
registration = JSONDictField()
component = CharField(default="ak-stage-authenticator-webauthn")
class AuthenticatorWebAuthnChallengeResponse(ChallengeResponse):
"""WebAuthn Challenge response"""
response = JSONField()
response = JSONDictField()
component = CharField(default="ak-stage-authenticator-webauthn")
request: HttpRequest

View File

@ -1,13 +1,12 @@
"""Invitation Stage API Views"""
from django_filters.filters import BooleanFilter
from django_filters.filterset import FilterSet
from rest_framework.fields import JSONField
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import is_dict
from authentik.core.api.utils import JSONDictField
from authentik.flows.api.flows import FlowSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.stages.invitation.models import Invitation, InvitationStage
@ -47,7 +46,7 @@ class InvitationSerializer(ModelSerializer):
"""Invitation Serializer"""
created_by = GroupMemberSerializer(read_only=True)
fixed_data = JSONField(validators=[is_dict], required=False)
fixed_data = JSONDictField(required=False)
flow_obj = FlowSerializer(read_only=True, required=False, source="flow")
class Meta:

View File

@ -81,7 +81,6 @@ var rootCmd = &cobra.Command{
for {
<-ex
}
},
}

2
go.mod
View File

@ -82,3 +82,5 @@ require (
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace goauthentik.io/api/v3 => ./gen-go-api

View File

@ -25,13 +25,13 @@ type Config struct {
}
type RedisConfig struct {
Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"`
Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"`
DB int `yaml:"db" env:"AUTHENTIK_REDIS__DB"`
Username string `yaml:"username" env:"AUTHENTIK_REDIS__USERNAME"`
Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"`
TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"`
TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"`
Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"`
Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"`
DB int `yaml:"db" env:"AUTHENTIK_REDIS__DB"`
Username string `yaml:"username" env:"AUTHENTIK_REDIS__USERNAME"`
Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"`
TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"`
TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"`
}
type ListenConfig struct {

View File

@ -76,7 +76,6 @@ func NewAPIController(akURL url.URL, token string) *APIController {
// Because we don't know the outpost UUID, we simply do a list and pick the first
// The service account this token belongs to should only have access to a single outpost
outposts, _, err := apiClient.OutpostsApi.OutpostsInstancesList(context.Background()).Execute()
if err != nil {
log.WithError(err).Error("Failed to fetch outpost configuration, retrying in 3 seconds")
time.Sleep(time.Second * 3)
@ -168,7 +167,6 @@ func (a *APIController) OnRefresh() error {
// Because we don't know the outpost UUID, we simply do a list and pick the first
// The service account this token belongs to should only have access to a single outpost
outposts, _, err := a.Client.OutpostsApi.OutpostsInstancesList(context.Background()).Execute()
if err != nil {
log.WithError(err).Error("Failed to fetch outpost configuration")
return err

View File

@ -14,8 +14,10 @@ import (
webutils "goauthentik.io/internal/utils/web"
)
var initialSetup = false
var tlsTransport *http.RoundTripper = nil
var (
initialSetup = false
tlsTransport *http.RoundTripper = nil
)
func doGlobalSetup(outpost api.Outpost, globalConfig *api.Config) {
l := log.WithField("logger", "authentik.outpost")

View File

@ -1,4 +1,3 @@
package handler
type Handler interface {
}
type Handler interface{}

View File

@ -78,5 +78,4 @@ func (ls *LDAPServer) fallbackRootDSE(req *search.Request) (ldap.ServerSearchRes
},
Referrals: []string{}, Controls: []ldap.Control{}, ResultCode: ldap.LDAPResultSuccess,
}, nil
}

View File

@ -34,26 +34,26 @@ func (ds *DirectSearcher) SearchBase(req *search.Request) (ldap.ServerSearchResu
Values: []string{"3"},
},
{
Name: "supportedCapabilities",
Name: "supportedCapabilities",
Values: []string{
"1.2.840.113556.1.4.800", //LDAP_CAP_ACTIVE_DIRECTORY_OID
"1.2.840.113556.1.4.1791", //LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID
"1.2.840.113556.1.4.1670", //LDAP_CAP_ACTIVE_DIRECTORY_V51_OID
"1.2.840.113556.1.4.1880", //LDAP_CAP_ACTIVE_DIRECTORY_ADAM_DIGEST_OID
"1.2.840.113556.1.4.1851", //LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID
"1.2.840.113556.1.4.1920", //LDAP_CAP_ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID
"1.2.840.113556.1.4.1935", //LDAP_CAP_ACTIVE_DIRECTORY_V60_OID
"1.2.840.113556.1.4.2080", //LDAP_CAP_ACTIVE_DIRECTORY_V61_R2_OID
"1.2.840.113556.1.4.2237", //LDAP_CAP_ACTIVE_DIRECTORY_W8_OID
"1.2.840.113556.1.4.800", // LDAP_CAP_ACTIVE_DIRECTORY_OID
"1.2.840.113556.1.4.1791", // LDAP_CAP_ACTIVE_DIRECTORY_LDAP_INTEG_OID
"1.2.840.113556.1.4.1670", // LDAP_CAP_ACTIVE_DIRECTORY_V51_OID
"1.2.840.113556.1.4.1880", // LDAP_CAP_ACTIVE_DIRECTORY_ADAM_DIGEST_OID
"1.2.840.113556.1.4.1851", // LDAP_CAP_ACTIVE_DIRECTORY_ADAM_OID
"1.2.840.113556.1.4.1920", // LDAP_CAP_ACTIVE_DIRECTORY_PARTIAL_SECRETS_OID
"1.2.840.113556.1.4.1935", // LDAP_CAP_ACTIVE_DIRECTORY_V60_OID
"1.2.840.113556.1.4.2080", // LDAP_CAP_ACTIVE_DIRECTORY_V61_R2_OID
"1.2.840.113556.1.4.2237", // LDAP_CAP_ACTIVE_DIRECTORY_W8_OID
},
},
{
Name: "supportedControl",
Name: "supportedControl",
Values: []string{
"2.16.840.1.113730.3.4.9", //VLV Request LDAPv3 Control
"2.16.840.1.113730.3.4.10", //VLV Response LDAPv3 Control
"1.2.840.113556.1.4.474", //Sort result
"1.2.840.113556.1.4.319", //Paged Result Control
"2.16.840.1.113730.3.4.9", // VLV Request LDAPv3 Control
"2.16.840.1.113730.3.4.10", // VLV Response LDAPv3 Control
"1.2.840.113556.1.4.474", // Sort result
"1.2.840.113556.1.4.319", // Paged Result Control
},
},
{

View File

@ -143,7 +143,7 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
// as a member.
for _, u := range g.UsersObj {
if flag.UserPk == u.Pk {
//TODO: Is there a better way to clone this object?
// TODO: Is there a better way to clone this object?
fg := api.NewGroup(g.Pk, g.NumPk, g.Name, g.ParentName, []api.GroupMember{u}, []api.Role{})
fg.SetUsers([]int32{flag.UserPk})
if g.Parent.IsSet() {

View File

@ -220,7 +220,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
for _, regex := range strings.Split(*p.SkipPathRegex, "\n") {
re, err := regexp.Compile(regex)
if err != nil {
//TODO: maybe create event for this?
// TODO: maybe create event for this?
a.log.WithError(err).Warning("failed to compile SkipPathRegex")
continue
} else {

View File

@ -59,12 +59,12 @@ func (a *Application) addHeaders(headers http.Header, c *Claims) {
userAttributes := c.Proxy.UserAttributes
a.setAuthorizationHeader(headers, c)
// Check if user has additional headers set that we should sent
if additionalHeaders, ok := userAttributes["additionalHeaders"].(map[string]interface{}); ok {
if additionalHeaders, ok := userAttributes["additionalHeaders"]; ok {
a.log.WithField("headers", additionalHeaders).Trace("setting additional headers")
if additionalHeaders == nil {
return
}
for key, value := range additionalHeaders {
for key, value := range additionalHeaders.(map[string]interface{}) {
headers.Set(key, toString(value))
}
}

View File

@ -1,7 +1,9 @@
package constants
const SessionOAuthState = "oauth_state"
const SessionClaims = "claims"
const (
SessionOAuthState = "oauth_state"
SessionClaims = "claims"
)
const SessionRedirect = "redirect"

View File

@ -15,7 +15,7 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
fe := flow.NewFlowExecutor(r.Context(), r.pi.flowSlug, r.pi.s.ac.Client.GetConfig(), log.Fields{
"username": username,
"client": r.RemoteAddr(),
"requestId": r.ID,
"requestId": r.ID(),
})
fe.DelegateClientIP(r.RemoteAddr())
fe.Params.Add("goauthentik.io/outpost/radius", "true")
@ -27,7 +27,6 @@ func (rs *RadiusServer) Handle_AccessRequest(w radius.ResponseWriter, r *RadiusR
}
passed, err := fe.Execute()
if err != nil {
r.Log().WithField("username", username).WithError(err).Warning("failed to execute flow")
metrics.RequestsRejected.With(prometheus.Labels{

View File

@ -14,12 +14,10 @@ import (
"goauthentik.io/internal/utils/sentry"
)
var (
Requests = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_main_request_duration_seconds",
Help: "API request latencies in seconds",
}, []string{"dest"})
)
var Requests = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_main_request_duration_seconds",
Help: "API request latencies in seconds",
}, []string{"dest"})
func (ws *WebServer) runMetricsServer() {
m := mux.NewRouter()

1461
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -18334,6 +18334,7 @@ paths:
- tr
- tt
- udm
- ug
- uk
- ur
- uz
@ -29205,9 +29206,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
last_applied:
type: string
format: date-time
@ -29227,8 +29226,6 @@ components:
type: string
readOnly: true
metadata:
type: object
additionalProperties: {}
readOnly: true
content:
type: string
@ -29250,9 +29247,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
enabled:
type: boolean
content:
@ -29772,10 +29767,24 @@ components:
cancel_url:
type: string
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/ContextualFlowInfoLayoutEnum'
required:
- cancel_url
- layout
ContextualFlowInfoLayoutEnum:
enum:
- stacked
- content_left
- content_right
- sidebar_left
- sidebar_right
type: string
description: |-
* `stacked` - STACKED
* `content_left` - CONTENT_LEFT
* `content_right` - CONTENT_RIGHT
* `sidebar_left` - SIDEBAR_LEFT
* `sidebar_right` - SIDEBAR_RIGHT
Coordinate:
type: object
description: Coordinates for diagrams
@ -30493,16 +30502,12 @@ components:
format: uuid
readOnly: true
title: Event uuid
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -30513,9 +30518,7 @@ components:
expires:
type: string
format: date-time
tenant:
type: object
additionalProperties: {}
tenant: {}
required:
- action
- app
@ -30992,17 +30995,13 @@ components:
type: object
description: Event Serializer
properties:
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
minLength: 1
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -31010,9 +31009,7 @@ components:
expires:
type: string
format: date-time
tenant:
type: object
additionalProperties: {}
tenant: {}
required:
- action
- app
@ -31311,7 +31308,7 @@ components:
description: Get export URL for flow
readOnly: true
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/FlowLayoutEnum'
denied_action:
allOf:
- $ref: '#/components/schemas/DeniedActionEnum'
@ -31498,6 +31495,20 @@ components:
- next_planned_stage
- plan_context
- session_id
FlowLayoutEnum:
enum:
- stacked
- content_left
- content_right
- sidebar_left
- sidebar_right
type: string
description: |-
* `stacked` - Stacked
* `content_left` - Content Left
* `content_right` - Content Right
* `sidebar_left` - Sidebar Left
* `sidebar_right` - Sidebar Right
FlowRequest:
type: object
description: Flow Serializer
@ -31535,7 +31546,7 @@ components:
description: Enable compatibility mode, increases compatibility with password
managers on mobile devices.
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/FlowLayoutEnum'
denied_action:
allOf:
- $ref: '#/components/schemas/DeniedActionEnum'
@ -31613,7 +31624,7 @@ components:
description: Get export URL for flow
readOnly: true
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/FlowLayoutEnum'
denied_action:
allOf:
- $ref: '#/components/schemas/DeniedActionEnum'
@ -31669,7 +31680,7 @@ components:
description: Enable compatibility mode, increases compatibility with password
managers on mobile devices.
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/FlowLayoutEnum'
denied_action:
allOf:
- $ref: '#/components/schemas/DeniedActionEnum'
@ -32361,8 +32372,6 @@ components:
description: Return internal model name
readOnly: true
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -32387,8 +32396,6 @@ components:
description: If enabled, use the local connection. Required Docker socket/Kubernetes
Integration
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -33053,20 +33060,6 @@ components:
required:
- is_running
- tasks
LayoutEnum:
enum:
- stacked
- content_left
- content_right
- sidebar_left
- sidebar_right
type: string
description: |-
* `stacked` - STACKED
* `content_left` - CONTENT_LEFT
* `content_right` - CONTENT_RIGHT
* `sidebar_left` - SIDEBAR_LEFT
* `sidebar_right` - SIDEBAR_RIGHT
License:
type: object
description: License Serializer
@ -34052,9 +34045,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
required:
- callback_url
- component
@ -34151,9 +34142,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
required:
- consumer_key
- consumer_secret
@ -36042,9 +36031,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
enabled:
type: boolean
content:
@ -36441,17 +36428,13 @@ components:
type: object
description: Event Serializer
properties:
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
minLength: 1
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -36459,9 +36442,7 @@ components:
expires:
type: string
format: date-time
tenant:
type: object
additionalProperties: {}
tenant: {}
PatchedExpressionPolicyRequest:
type: object
description: Group Membership Policy Serializer
@ -36513,7 +36494,7 @@ components:
description: Enable compatibility mode, increases compatibility with password
managers on mobile devices.
layout:
$ref: '#/components/schemas/LayoutEnum'
$ref: '#/components/schemas/FlowLayoutEnum'
denied_action:
allOf:
- $ref: '#/components/schemas/DeniedActionEnum'
@ -36703,8 +36684,6 @@ components:
description: If enabled, use the local connection. Required Docker socket/Kubernetes
Integration
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -37165,9 +37144,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
PatchedOutpostRequest:
type: object
description: Outpost Serializer
@ -38011,9 +37988,7 @@ components:
format: uuid
nullable: true
description: Web Certificate used by the authentik Core webserver.
attributes:
type: object
additionalProperties: {}
attributes: {}
PatchedTokenRequest:
type: object
description: Token Serializer
@ -39686,9 +39661,7 @@ components:
type: string
ip:
type: string
ip_geo_data:
type: object
additionalProperties: {}
ip_geo_data: {}
score:
type: integer
maximum: 9223372036854775807
@ -41415,9 +41388,7 @@ components:
format: uuid
nullable: true
description: Web Certificate used by the authentik Core webserver.
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- domain
- tenant_uuid
@ -41474,9 +41445,7 @@ components:
format: uuid
nullable: true
description: Web Certificate used by the authentik Core webserver.
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- domain
Token:

View File

@ -18,8 +18,8 @@ import {
DeniedActionEnum,
Flow,
FlowDesignationEnum,
FlowLayoutEnum,
FlowsApi,
LayoutEnum,
PolicyEngineMode,
} from "@goauthentik/api";
@ -302,34 +302,34 @@ export class FlowForm extends ModelForm<Flow, string> {
>
<select class="pf-c-form-control">
<option
value=${LayoutEnum.Stacked}
?selected=${this.instance?.layout === LayoutEnum.Stacked}
value=${FlowLayoutEnum.Stacked}
?selected=${this.instance?.layout === FlowLayoutEnum.Stacked}
>
${LayoutToLabel(LayoutEnum.Stacked)}
${LayoutToLabel(FlowLayoutEnum.Stacked)}
</option>
<option
value=${LayoutEnum.ContentLeft}
?selected=${this.instance?.layout === LayoutEnum.ContentLeft}
value=${FlowLayoutEnum.ContentLeft}
?selected=${this.instance?.layout === FlowLayoutEnum.ContentLeft}
>
${LayoutToLabel(LayoutEnum.ContentLeft)}
${LayoutToLabel(FlowLayoutEnum.ContentLeft)}
</option>
<option
value=${LayoutEnum.ContentRight}
?selected=${this.instance?.layout === LayoutEnum.ContentRight}
value=${FlowLayoutEnum.ContentRight}
?selected=${this.instance?.layout === FlowLayoutEnum.ContentRight}
>
${LayoutToLabel(LayoutEnum.ContentRight)}
${LayoutToLabel(FlowLayoutEnum.ContentRight)}
</option>
<option
value=${LayoutEnum.SidebarLeft}
?selected=${this.instance?.layout === LayoutEnum.SidebarLeft}
value=${FlowLayoutEnum.SidebarLeft}
?selected=${this.instance?.layout === FlowLayoutEnum.SidebarLeft}
>
${LayoutToLabel(LayoutEnum.SidebarLeft)}
${LayoutToLabel(FlowLayoutEnum.SidebarLeft)}
</option>
<option
value=${LayoutEnum.SidebarRight}
?selected=${this.instance?.layout === LayoutEnum.SidebarRight}
value=${FlowLayoutEnum.SidebarRight}
?selected=${this.instance?.layout === FlowLayoutEnum.SidebarRight}
>
${LayoutToLabel(LayoutEnum.SidebarRight)}
${LayoutToLabel(FlowLayoutEnum.SidebarRight)}
</option>
</select>
</ak-form-element-horizontal>

View File

@ -1,6 +1,6 @@
import { msg } from "@lit/localize";
import { Flow, FlowDesignationEnum, LayoutEnum } from "@goauthentik/api";
import { Flow, FlowDesignationEnum, FlowLayoutEnum } from "@goauthentik/api";
export function RenderFlowOption(flow: Flow): string {
return `${flow.slug} (${flow.name})`;
@ -27,19 +27,19 @@ export function DesignationToLabel(designation: FlowDesignationEnum): string {
}
}
export function LayoutToLabel(layout: LayoutEnum): string {
export function LayoutToLabel(layout: FlowLayoutEnum): string {
switch (layout) {
case LayoutEnum.Stacked:
case FlowLayoutEnum.Stacked:
return msg("Stacked");
case LayoutEnum.ContentLeft:
case FlowLayoutEnum.ContentLeft:
return msg("Content left");
case LayoutEnum.ContentRight:
case FlowLayoutEnum.ContentRight:
return msg("Content right");
case LayoutEnum.SidebarLeft:
case FlowLayoutEnum.SidebarLeft:
return msg("Sidebar left");
case LayoutEnum.SidebarRight:
case FlowLayoutEnum.SidebarRight:
return msg("Sidebar right");
case LayoutEnum.UnknownDefaultOpenApi:
case FlowLayoutEnum.UnknownDefaultOpenApi:
return msg("Unknown layout");
}
}

View File

@ -37,8 +37,8 @@ import {
ContextualFlowInfo,
FlowChallengeResponseRequest,
FlowErrorChallenge,
FlowLayoutEnum,
FlowsApi,
LayoutEnum,
ResponseError,
ShellChallenge,
UiThemeEnum,
@ -451,7 +451,7 @@ export class FlowExecutor extends Interface implements StageHost {
}
getLayout(): string {
const prefilledFlow = globalAK()?.flow?.layout || LayoutEnum.Stacked;
const prefilledFlow = globalAK()?.flow?.layout || FlowLayoutEnum.Stacked;
if (this.challenge) {
return this.challenge?.flowInfo?.layout || prefilledFlow;
}
@ -461,11 +461,11 @@ export class FlowExecutor extends Interface implements StageHost {
getLayoutClass(): string {
const layout = this.getLayout();
switch (layout) {
case LayoutEnum.ContentLeft:
case FlowLayoutEnum.ContentLeft:
return "pf-c-login__container";
case LayoutEnum.ContentRight:
case FlowLayoutEnum.ContentRight:
return "pf-c-login__container content-right";
case LayoutEnum.Stacked:
case FlowLayoutEnum.Stacked:
default:
return "ak-login-container";
}