Compare commits

..

40 Commits

Author SHA1 Message Date
82b5274b15 release: 2023.10.3 2023-11-09 18:37:22 +01:00
af56ce3d78 core: fix worker beat toggle inverted (cherry-pick #7508) (#7509)
core: fix worker beat toggle inverted (#7508)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-09 18:36:56 +01:00
f5c6e7aeb0 Web: bugfix: broken backchannel selector (cherry-pick #7480) (#7507)
Web: bugfix: broken backchannel selector (#7480)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* web: rollback dependabot's upgrade of context

The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.

* web: bugfix: broken backchannel selector

There were two bugs here, both of them introduced by me because I didn't understand the
system well enough the first time through, and because I didn't test thoroughly enough.

The first is that I was calling the wrong confirmation code; the resulting syntax survived
because `confirm()` is actually a legitimate function call in the context of the DOM Window,
a legacy survivor similar to `alert()` but with a yes/no return value. Bleah.

The second is that the confirm code doesn't appear to pass back a dictionary with the
`{ items: Array<Provider> }` list, it passes back just the `items` as an Array.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-09 17:58:38 +01:00
3809400e93 events: fix gdpr compliance always running (cherry-pick #7491) (#7505)
events: fix gdpr compliance always running

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-09 17:57:25 +01:00
1def9865cf web/flows: attempt to fix bitwareden android compatibility (cherry-pick #7455) (#7457)
web/flows: attempt to fix bitwareden android compatibility (#7455)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 23:58:44 +01:00
3716298639 sources/oauth: fix patreon (cherry-pick #7454) (#7456)
sources/oauth: fix patreon (#7454)

* web/admin: add note for potentially confusing consumer key/secret



* sources/oauth: fix patreon default scopes



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-06 16:36:22 +01:00
c16317d7cf providers/proxy: fix closed redis client (cherry-pick #7385) (#7429)
providers/proxy: fix closed redis client (#7385)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:17 +01:00
bbb8fa8269 ci: explicitly give write permissions to packages (cherry-pick #7428) (#7430)
ci: explicitly give write permissions to packages (#7428)

* ci: explicitly give write permissions to packages



* run full CI on cherry-picks



---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 15:46:00 +01:00
e4c251a178 web/admin: fix html error on oauth2 provider page (cherry-pick #7384) (#7424)
web/admin: fix html error on oauth2 provider page (#7384)

* web: break circular dependency between AKElement & Interface.

This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.

I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.

* web: fix broken typescript references

This built... and then it didn't?  Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.

* \# Details

Extra `>` symbol screwed up the reading of the rest of the component.  Unfortunately,
too many fields in an input are optional, so it was easy for this bug to bypass any
checks by the validators.  I should have caught it myself, though.

Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
2023-11-03 13:17:26 +01:00
0fefd5f522 stages/email: fix duplicate querystring encoding (cherry-pick #7386) (#7425)
stages/email: fix duplicate querystring encoding (#7386)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:18 +01:00
88057db0b0 providers/oauth2: set auth_via for token and other endpoints (cherry-pick #7417) (#7427)
providers/oauth2: set auth_via for token and other endpoints (#7417)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-11-03 13:17:10 +01:00
91cb6c9beb root: Improve multi arch Docker image build speed (cherry-pick #7355) (#7426)
root: Improve multi arch Docker image build speed (#7355)

* Improve multi arch Docker image build speed

Use only host architecture for GeoIP database update and for Go cross-compilation

* Speedup Go multi-arch compilation for other images

* Speedup multi-arch ldap image build

Co-authored-by: Philipp Kolberg <39984529+PKizzle@users.noreply.github.com>
2023-11-03 13:16:54 +01:00
8e72fcab59 release: 2023.10.2 2023-10-28 21:43:54 +02:00
261879022d security: fix oobe-flow reuse when akadmin is deleted (#7361)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 21:24:06 +02:00
2a47ff2977 website/docs: prepare 2023.10.2 release notes (#7362)
website/docs: prepare 2023.10.2

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 21:07:57 +02:00
c3a81a1cce website/docs: add missing breaking change due to APPEND_SLASH (#7360)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 18:13:56 +02:00
220d739fef lifecycle: rework otp_merge migration (#7359)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 17:56:04 +02:00
4a57c6f230 translate: Updates for file web/xliff/en.xlf in zh-Hans (#7354)
Translate web/xliff/en.xlf in zh-Hans

100% translated source file: 'web/xliff/en.xlf'
on 'zh-Hans'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-27 20:41:31 +02:00
4a93b97bec translate: Updates for file web/xliff/en.xlf in zh_CN (#7353)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-10-27 20:41:17 +02:00
ac2bbd7e2f website/docs: add warning about Helm breaking change in 2024.x (#7351)
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-10-27 17:22:02 +00:00
ad9f500ad1 crypto: fix race conditions when creating self-signed certificates on startup (#7344)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:29:10 +02:00
15d7175750 blueprints: fix entries with state: absent not being deleted if their serializer has errors (#7345)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:28:56 +02:00
41d372a340 web/admin: fix @change handler for ak-radio elements (#7348)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:28:18 +02:00
83b84e8d26 rbac: handle lookup error (#7341)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 13:38:44 +02:00
f22daca091 website/docs: add warning about upgrading to 2023.10 (#7340)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 12:51:49 +02:00
ae4d5a30f2 web/admin: fix role form reacting to enter (#7330)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 11:39:39 +02:00
9708481005 core: bump github.com/google/uuid from 1.3.1 to 1.4.0 (#7333)
Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.3.1 to 1.4.0.
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.3.1...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 11:13:27 +02:00
1c32c9e06d core: bump goauthentik.io/api/v3 from 3.2023083.10 to 3.2023101.1 (#7334)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023083.10 to 3.2023101.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023083.10...v3.2023101.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 11:13:14 +02:00
7a3d92ffdb core: bump ruff from 0.1.2 to 0.1.3 (#7335)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.2 to 0.1.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/v0.1.2...v0.1.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 11:13:01 +02:00
a72b36d94d core: bump pydantic-scim from 0.0.7 to 0.0.8 (#7336)
Bumps [pydantic-scim](https://chalk.ai) from 0.0.7 to 0.0.8.

---
updated-dependencies:
- dependency-name: pydantic-scim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-27 11:12:52 +02:00
6b25f6f592 website/blogs: Blog dockers (#7328)
* Dockers blog draft

* redo

* renamed dir

* renamed directory

* added email address

* formatting

* title tweak

* Kens edits

* link

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-10-26 21:19:14 -05:00
7d91842e8a providers/proxy: attempt to fix duplicate cookie (#7324)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 00:41:13 +02:00
2b4b1d2f76 stages/email: fix sending emails from task (#7325)
closes #7322

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 00:39:06 +02:00
2ce5c74f33 web: bump API Client version (#7321)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-26 21:50:17 +02:00
168fabfc70 Merge branch 'version-2023.10' 2023-10-26 21:20:55 +02:00
eb53c28352 website/docs: update release notes for 2023.10.1 (#7316)
website/docs: update for 2023.10.1

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 20:16:07 +02:00
64c38909ff release: 2023.10.1 2023-10-26 20:06:05 +02:00
940492a5e1 lifecycle: fix otp merge migration (#7315)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 20:05:33 +02:00
134799c734 root: fix pylint errors (#7312) 2023-10-26 19:57:11 +02:00
e086da68cd web: bump API Client version (#7311)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-26 16:23:15 +00:00
68 changed files with 2120 additions and 1771 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2023.10.0
current_version = 2023.10.3
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)

View File

@ -11,6 +11,7 @@ on:
pull_request:
branches:
- main
- version-*
env:
POSTGRES_DB: authentik
@ -185,6 +186,8 @@ jobs:
build:
needs: ci-core-mark
runs-on: ubuntu-latest
permissions:
packages: write
timeout-minutes: 120
steps:
- uses: actions/checkout@v4
@ -235,6 +238,8 @@ jobs:
build-arm64:
needs: ci-core-mark
runs-on: ubuntu-latest
permissions:
packages: write
timeout-minutes: 120
steps:
- uses: actions/checkout@v4

View File

@ -9,6 +9,7 @@ on:
pull_request:
branches:
- main
- version-*
jobs:
lint-golint:
@ -65,6 +66,8 @@ jobs:
- ldap
- radius
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v4
with:

View File

@ -9,6 +9,7 @@ on:
pull_request:
branches:
- main
- version-*
jobs:
lint-eslint:

View File

@ -9,6 +9,7 @@ on:
pull_request:
branches:
- main
- version-*
jobs:
lint-prettier:

View File

@ -7,6 +7,8 @@ on:
jobs:
build-server:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
@ -52,6 +54,8 @@ jobs:
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
build-outpost:
runs-on: ubuntu-latest
permissions:
packages: write
strategy:
fail-fast: false
matrix:

View File

@ -35,7 +35,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build
# Stage 3: Build go proxy
FROM docker.io/golang:1.21.3-bookworm AS go-builder
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io
@ -57,10 +64,10 @@ ENV CGO_ENABLED=0
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /go/authentik ./cmd/server
GOARM="${TARGETVARIANT#v}" go build -o /go/authentik ./cmd/server
# Stage 4: MaxMind GeoIP
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v6.0 as geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City"
ENV GEOIPUPDATE_VERBOSE="true"

View File

@ -2,7 +2,7 @@
from os import environ
from typing import Optional
__version__ = "2023.10.0"
__version__ = "2023.10.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -584,12 +584,17 @@ class EntryInvalidError(SentryIgnoredException):
entry_model: Optional[str]
entry_id: Optional[str]
validation_error: Optional[ValidationError]
serializer: Optional[Serializer] = None
def __init__(self, *args: object, validation_error: Optional[ValidationError] = None) -> None:
def __init__(
self, *args: object, validation_error: Optional[ValidationError] = None, **kwargs
) -> None:
super().__init__(*args)
self.entry_model = None
self.entry_id = None
self.validation_error = validation_error
for key, value in kwargs.items():
setattr(self, key, value)
@staticmethod
def from_entry(

View File

@ -255,7 +255,10 @@ class Importer:
try:
full_data = self.__update_pks_for_attrs(entry.get_attrs(self._import))
except ValueError as exc:
raise EntryInvalidError.from_entry(exc, entry) from exc
raise EntryInvalidError.from_entry(
exc,
entry,
) from exc
always_merger.merge(full_data, updated_identifiers)
serializer_kwargs["data"] = full_data
@ -272,6 +275,7 @@ class Importer:
f"Serializer errors {serializer.errors}",
validation_error=exc,
entry=entry,
serializer=serializer,
) from exc
return serializer
@ -300,12 +304,14 @@ class Importer:
)
return False
# Validate each single entry
serializer = None
try:
serializer = self._validate_single(entry)
except EntryInvalidError as exc:
# For deleting objects we don't need the serializer to be valid
if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT:
continue
serializer = exc.serializer
else:
self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc)
if raise_errors:
raise exc

View File

@ -82,7 +82,7 @@ class BlueprintEventHandler(FileSystemEventHandler):
path = Path(event.src_path)
root = Path(CONFIG.get("blueprints_dir")).absolute()
rel_path = str(path.relative_to(root))
for instance in BlueprintInstance.objects.filter(path=rel_path):
for instance in BlueprintInstance.objects.filter(path=rel_path, enabled=True):
LOGGER.debug("modified blueprint file, starting apply", instance=instance)
apply_blueprint.delay(instance.pk.hex)

View File

@ -98,6 +98,7 @@ class ApplicationSerializer(ModelSerializer):
class ApplicationViewSet(UsedByMixin, ModelViewSet):
"""Application Viewset"""
# pylint: disable=no-member
queryset = Application.objects.all().prefetch_related("provider")
serializer_class = ApplicationSerializer
search_fields = [

View File

@ -139,6 +139,7 @@ class UserAccountSerializer(PassiveSerializer):
class GroupViewSet(UsedByMixin, ModelViewSet):
"""Group Viewset"""
# pylint: disable=no-member
queryset = Group.objects.all().select_related("parent").prefetch_related("users")
serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"]

View File

@ -17,9 +17,15 @@ class Command(BaseCommand):
"""Run worker"""
def add_arguments(self, parser):
parser.add_argument("-b", "--beat", action="store_true")
parser.add_argument(
"-b",
"--beat",
action="store_false",
help="When set, this worker will _not_ run Beat (scheduled) tasks",
)
def handle(self, **options):
LOGGER.debug("Celery options", **options)
close_old_connections()
if CONFIG.get_bool("remote_debug"):
import debugpy

View File

@ -97,6 +97,7 @@ class SourceFlowManager:
if self.request.user.is_authenticated:
new_connection.user = self.request.user
new_connection = self.update_connection(new_connection, **kwargs)
# pylint: disable=no-member
new_connection.save()
return Action.LINK, new_connection

View File

@ -1,13 +1,10 @@
"""authentik crypto app config"""
from datetime import datetime
from typing import TYPE_CHECKING, Optional
from typing import Optional
from authentik.blueprints.apps import ManagedAppConfig
from authentik.lib.generators import generate_id
if TYPE_CHECKING:
from authentik.crypto.models import CertificateKeyPair
MANAGED_KEY = "goauthentik.io/crypto/jwt-managed"
@ -23,33 +20,37 @@ class AuthentikCryptoConfig(ManagedAppConfig):
"""Load crypto tasks"""
self.import_module("authentik.crypto.tasks")
def _create_update_cert(self, cert: Optional["CertificateKeyPair"] = None):
def _create_update_cert(self):
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair
builder = CertificateBuilder("authentik Internal JWT Certificate")
common_name = "authentik Internal JWT Certificate"
builder = CertificateBuilder(common_name)
builder.build(
subject_alt_names=["goauthentik.io"],
validity_days=360,
)
if not cert:
cert = CertificateKeyPair()
builder.cert = cert
builder.cert.managed = MANAGED_KEY
builder.save()
CertificateKeyPair.objects.update_or_create(
managed=MANAGED_KEY,
defaults={
"name": common_name,
"certificate_data": builder.certificate,
"key_data": builder.private_key,
},
)
def reconcile_managed_jwt_cert(self):
"""Ensure managed JWT certificate"""
from authentik.crypto.models import CertificateKeyPair
certs = CertificateKeyPair.objects.filter(managed=MANAGED_KEY)
if not certs.exists():
self._create_update_cert()
return
cert: CertificateKeyPair = certs.first()
cert: Optional[CertificateKeyPair] = CertificateKeyPair.objects.filter(
managed=MANAGED_KEY
).first()
now = datetime.now()
if now < cert.certificate.not_valid_before or now > cert.certificate.not_valid_after:
self._create_update_cert(cert)
if not cert or (
now < cert.certificate.not_valid_before or now > cert.certificate.not_valid_after
):
self._create_update_cert()
def reconcile_self_signed(self):
"""Create self-signed keypair"""
@ -61,4 +62,10 @@ class AuthentikCryptoConfig(ManagedAppConfig):
return
builder = CertificateBuilder(name)
builder.build(subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"])
builder.save()
CertificateKeyPair.objects.get_or_create(
name=name,
defaults={
"certificate_data": builder.certificate,
"key_data": builder.private_key,
},
)

View File

@ -13,6 +13,7 @@ from authentik.events.tasks import event_notification_handler, gdpr_cleanup
from authentik.flows.models import Stage
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.lib.config import CONFIG
from authentik.stages.invitation.models import Invitation
from authentik.stages.invitation.signals import invitation_used
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
@ -92,4 +93,5 @@ def event_post_save_notification(sender, instance: Event, **_):
@receiver(pre_delete, sender=User)
def event_user_pre_delete_cleanup(sender, instance: User, **_):
"""If gdpr_compliance is enabled, remove all the user's events"""
if CONFIG.get_bool("gdpr_compliance", True):
gdpr_cleanup.delay(instance.pk)

View File

@ -0,0 +1,34 @@
# Generated by Django 4.2.6 on 2023-10-28 14:24
from django.apps.registry import Apps
from django.db import migrations
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
def set_oobe_flow_authentication(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
from guardian.shortcuts import get_anonymous_user
Flow = apps.get_model("authentik_flows", "Flow")
User = apps.get_model("authentik_core", "User")
db_alias = schema_editor.connection.alias
users = User.objects.using(db_alias).exclude(username="akadmin")
try:
users = users.exclude(pk=get_anonymous_user().pk)
# pylint: disable=broad-except
except Exception: # nosec
pass
if users.exists():
Flow.objects.filter(slug="initial-setup").update(authentication="require_superuser")
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0026_alter_flow_options"),
]
operations = [
migrations.RunPython(set_oobe_flow_authentication),
]

View File

@ -188,6 +188,7 @@ def authenticate_provider(request: HttpRequest) -> Optional[OAuth2Provider]:
if client_id != provider.client_id or client_secret != provider.client_secret:
LOGGER.debug("(basic) Provider for basic auth does not exist")
return None
CTX_AUTH_VIA.set("oauth_client_secret")
return provider

View File

@ -17,6 +17,7 @@ from jwt import PyJWK, PyJWT, PyJWTError, decode
from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger
from authentik.core.middleware import CTX_AUTH_VIA
from authentik.core.models import (
USER_ATTRIBUTE_EXPIRES,
USER_ATTRIBUTE_GENERATED,
@ -448,6 +449,7 @@ class TokenView(View):
if not self.provider:
LOGGER.warning("OAuth2Provider does not exist", client_id=client_id)
raise TokenError("invalid_client")
CTX_AUTH_VIA.set("oauth_client_secret")
self.params = TokenParams.parse(request, self.provider, client_id, client_secret)
with Hub.current.start_span(

View File

@ -32,13 +32,19 @@ class PermissionSerializer(ModelSerializer):
def get_app_label_verbose(self, instance: Permission) -> str:
"""Human-readable app label"""
try:
return apps.get_app_config(instance.content_type.app_label).verbose_name
except LookupError:
return f"{instance.content_type.app_label}.{instance.content_type.model}"
def get_model_verbose(self, instance: Permission) -> str:
"""Human-readable model name"""
try:
return apps.get_model(
instance.content_type.app_label, instance.content_type.model
)._meta.verbose_name
except LookupError:
return f"{instance.content_type.app_label}.{instance.content_type.model}"
class Meta:
model = Permission

View File

@ -28,9 +28,12 @@ class ExtraRoleObjectPermissionSerializer(RoleObjectPermissionSerializer):
def get_model_verbose(self, instance: GroupObjectPermission) -> str:
"""Get model label from permission's model"""
try:
return apps.get_model(
instance.content_type.app_label, instance.content_type.model
)._meta.verbose_name
except LookupError:
return f"{instance.content_type.app_label}.{instance.content_type.model}"
def get_object_description(self, instance: GroupObjectPermission) -> Optional[str]:
"""Get model description from attached model. This operation takes at least
@ -38,7 +41,10 @@ class ExtraRoleObjectPermissionSerializer(RoleObjectPermissionSerializer):
view_ permission on the object"""
app_label = instance.content_type.app_label
model = instance.content_type.model
try:
model_class = apps.get_model(app_label, model)
except LookupError:
return None
objects = get_objects_for_group(instance.group, f"{app_label}.view_{model}", model_class)
obj = objects.first()
if not obj:

View File

@ -28,9 +28,12 @@ class ExtraUserObjectPermissionSerializer(UserObjectPermissionSerializer):
def get_model_verbose(self, instance: UserObjectPermission) -> str:
"""Get model label from permission's model"""
try:
return apps.get_model(
instance.content_type.app_label, instance.content_type.model
)._meta.verbose_name
except LookupError:
return f"{instance.content_type.app_label}.{instance.content_type.model}"
def get_object_description(self, instance: UserObjectPermission) -> Optional[str]:
"""Get model description from attached model. This operation takes at least
@ -38,7 +41,10 @@ class ExtraUserObjectPermissionSerializer(UserObjectPermissionSerializer):
view_ permission on the object"""
app_label = instance.content_type.app_label
model = instance.content_type.model
try:
model_class = apps.get_model(app_label, model)
except LookupError:
return None
objects = get_objects_for_user(instance.user, f"{app_label}.view_{model}", model_class)
obj = objects.first()
if not obj:

View File

@ -12,8 +12,9 @@ class PatreonOAuthRedirect(OAuthRedirect):
"""Patreon OAuth2 Redirect"""
def get_additional_parameters(self, source: OAuthSource): # pragma: no cover
# https://docs.patreon.com/#scopes
return {
"scope": ["openid", "email", "profile"],
"scope": ["identity", "identity[email]"],
}

View File

@ -52,17 +52,13 @@ class EmailStageView(ChallengeStageView):
kwargs={"flow_slug": self.executor.flow.slug},
)
# Parse query string from current URL (full query string)
query_params = QueryDict(self.request.META.get("QUERY_STRING", ""), mutable=True)
# this view is only run within a flow executor, where we need to get the query string
# from the query= parameter (double encoded); but for the redirect
# we need to expand it since it'll go through the flow interface
query_params = QueryDict(self.request.GET.get(QS_QUERY), mutable=True)
query_params.pop(QS_KEY_TOKEN, None)
# Check for nested query string used by flow executor, and remove any
# kind of flow token from that
if QS_QUERY in query_params:
inner_query_params = QueryDict(query_params.get(QS_QUERY), mutable=True)
inner_query_params.pop(QS_KEY_TOKEN, None)
query_params[QS_QUERY] = inner_query_params.urlencode()
query_params.update(kwargs)
print(query_params)
full_url = base_url
if len(query_params) > 0:
full_url = f"{full_url}?{query_params.urlencode()}"

View File

@ -13,6 +13,7 @@ from authentik.events.models import Event, EventAction
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
from authentik.root.celery import CELERY_APP
from authentik.stages.email.models import EmailStage
from authentik.stages.email.utils import logo_data
LOGGER = get_logger()
@ -81,6 +82,10 @@ def send_mail(self: MonitoredTask, message: dict[Any, Any], email_stage_pk: Opti
# Because we use the Message-ID as UID for the task, manually assign it
message_object.extra_headers["Message-ID"] = message_id
# Add the logo (we can't add it in the previous message since MIMEImage
# can't be converted to json)
message_object.attach(logo_data())
LOGGER.debug("Sending mail", to=message_object.to)
backend.send_messages([message_object])
Event.new(

View File

@ -259,7 +259,7 @@ class TestEmailStage(FlowTestCase):
session.save()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
url += "?foo=bar"
url += "?query=" + urlencode({"foo": "bar"})
request = self.factory.get(url)
stage_view = EmailStageView(
FlowExecutorView(
@ -273,31 +273,3 @@ class TestEmailStage(FlowTestCase):
stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
f"http://testserver/if/flow/{self.flow.slug}/?foo=bar&flow_token={token}",
)
def test_url_existing_params_nested(self):
"""Test to ensure that URL params are preserved in the URL being sent (including nested)"""
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
plan.context[PLAN_CONTEXT_PENDING_USER] = self.user
session = self.client.session
session[SESSION_KEY_PLAN] = plan
session.save()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
url += "?foo=bar&"
url += "query=" + urlencode({"nested": "value"})
request = self.factory.get(url)
stage_view = EmailStageView(
FlowExecutorView(
request=request,
flow=self.flow,
),
request=request,
)
token = generate_id()
self.assertEqual(
stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
(
f"http://testserver/if/flow/{self.flow.slug}"
f"/?foo=bar&query=nested%3Dvalue&flow_token={token}"
),
)

View File

@ -9,7 +9,7 @@ from django.utils import translation
@lru_cache()
def logo_data():
def logo_data() -> MIMEImage:
"""Get logo as MIME Image for emails"""
path = Path("web/icons/icon_left_brand.png")
if not path.exists():
@ -29,5 +29,4 @@ class TemplateEmailMessage(EmailMultiAlternatives):
super().__init__(**kwargs)
self.content_subtype = "html"
self.mixed_subtype = "related"
self.attach(logo_data())
self.attach_alternative(html_content, "text/html")

View File

@ -85,6 +85,19 @@ entries:
identifiers:
name: default-oobe-password-usable
model: authentik_policies_expression.expressionpolicy
- attrs:
expression: |
# This policy ensures that the setup flow can only be
# used one time
from authentik.flows.models import Flow, FlowAuthenticationRequirement
Flow.objects.filter(slug="initial-setup").update(
authentication=FlowAuthenticationRequirement.REQUIRE_SUPERUSER,
)
return True
id: policy-default-oobe-flow-set-authentication
identifiers:
name: default-oobe-flow-set-authentication
model: authentik_policies_expression.expressionpolicy
- attrs:
fields:
- !KeyOf prompt-field-header
@ -129,6 +142,7 @@ entries:
evaluate_on_plan: true
invalid_response_action: retry
re_evaluate_policies: false
id: binding-login
identifiers:
order: 100
stage: !KeyOf stage-default-authentication-login
@ -144,3 +158,8 @@ entries:
policy: !KeyOf policy-default-oobe-prefill-user
target: !KeyOf binding-password-write
model: authentik_policies.policybinding
- identifiers:
order: 0
policy: !KeyOf policy-default-oobe-flow-set-authentication
target: !KeyOf binding-login
model: authentik_policies.policybinding

View File

@ -42,9 +42,3 @@ entries:
user: !KeyOf admin-user
attrs:
key: !Context token
- model: authentik_blueprints.blueprintinstance
identifiers:
metadata:
labels:
blueprints.goauthentik.io/system-bootstrap: "true"
state: absent

View File

@ -32,7 +32,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.0}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
restart: unless-stopped
command: server
environment:
@ -53,7 +53,7 @@ services:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.0}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2023.10.3}
restart: unless-stopped
command: worker
environment:

4
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/go-openapi/runtime v0.26.0
github.com/go-openapi/strfmt v0.21.7
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.3.1
github.com/google/uuid v1.4.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/securecookie v1.1.1
@ -27,7 +27,7 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
goauthentik.io/api/v3 v3.2023083.10
goauthentik.io/api/v3 v3.2023101.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.13.0
golang.org/x/sync v0.4.0

7
go.sum
View File

@ -211,8 +211,9 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
@ -355,8 +356,8 @@ go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyK
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2023083.10 h1:mMCOfsqjouSSxedSkCK4k0Cwtt68CWzQgR7Um6ooOQs=
goauthentik.io/api/v3 v3.2023083.10/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2023101.1 h1:KIQ4wmxjE+geAVB0wBfmxW9Uzo/tA0dbd2hSUJ7YJ3M=
goauthentik.io/api/v3 v3.2023101.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=

View File

@ -29,4 +29,4 @@ func UserAgent() string {
return fmt.Sprintf("authentik@%s", FullVersion())
}
const VERSION = "2023.10.0"
const VERSION = "2023.10.3"

View File

@ -50,7 +50,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL)
Domain: *p.CookieDomain,
SameSite: http.SameSiteLaxMode,
MaxAge: maxAge,
Path: externalHost.Path,
Path: "/",
})
a.log.Trace("using redis session backend")
@ -131,7 +131,6 @@ func (a *Application) Logout(ctx context.Context, filter func(c Claims) bool) er
}
if rs, ok := a.sessions.(*redisstore.RedisStore); ok {
client := rs.Client()
defer client.Close()
keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result()
if err != nil {
return err

View File

@ -1,5 +1,12 @@
# Stage 1: Build
FROM docker.io/golang:1.21.3-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /go/ldap ./cmd/ldap
GOARM="${TARGETVARIANT#v}" go build -o /go/ldap ./cmd/ldap
# Stage 2: Run
FROM gcr.io/distroless/static-debian11:debug

View File

@ -2,16 +2,22 @@
from lifecycle.migrate import BaseMigration
SQL_STATEMENT = """
DELETE FROM django_migrations WHERE app = 'otp_static';
DELETE FROM django_migrations WHERE app = 'otp_totp';
BEGIN TRANSACTION;
-- Update migrations (static)
UPDATE django_migrations SET app = 'authentik_stages_authenticator_static', name = '0008_initial' WHERE app = 'otp_static' AND name = '0001_initial';
UPDATE django_migrations SET app = 'authentik_stages_authenticator_static', name = '0009_throttling' WHERE app = 'otp_static' AND name = '0002_throttling';
-- Rename tables (static)
ALTER TABLE otp_static_staticdevice RENAME TO authentik_stages_authenticator_static_staticdevice;
ALTER TABLE otp_static_statictoken RENAME TO authentik_stages_authenticator_static_statictoken;
ALTER SEQUENCE otp_static_statictoken_id_seq RENAME TO authentik_stages_authenticator_static_statictoken_id_seq;
ALTER SEQUENCE otp_static_staticdevice_id_seq RENAME TO authentik_stages_authenticator_static_staticdevice_id_seq;
-- Update migrations (totp)
UPDATE django_migrations SET app = 'authentik_stages_authenticator_totp', name = '0008_initial' WHERE app = 'otp_totp' AND name = '0001_initial';
UPDATE django_migrations SET app = 'authentik_stages_authenticator_totp', name = '0009_auto_20190420_0723' WHERE app = 'otp_totp' AND name = '0002_auto_20190420_0723';
-- Rename tables (totp)
ALTER TABLE otp_totp_totpdevice RENAME TO authentik_stages_authenticator_totp_totpdevice;
ALTER SEQUENCE otp_totp_totpdevice_id_seq RENAME TO authentik_stages_authenticator_totp_totpdevice_id_seq;
COMMIT;
"""
@ -23,22 +29,9 @@ class Migration(BaseMigration):
return bool(self.cur.rowcount)
def run(self):
self.cur.execute(SQL_STATEMENT)
self.fake_migration(
(
"authentik_stages_authenticator_static",
"0008_initial",
),
(
"authentik_stages_authenticator_static",
"0009_throttling",
),
(
"authentik_stages_authenticator_totp",
"0008_initial",
),
(
"authentik_stages_authenticator_totp",
"0009_auto_20190420_0723",
),
self.cur.execute(
"SELECT * FROM django_migrations WHERE app = 'authentik_stages_authenticator_static' AND name = '0007_authenticatorstaticstage_token_length_and_more';"
)
if not bool(self.cur.rowcount):
raise Exception("Please upgrade to 2023.8 before upgrading to 2023.10")
self.cur.execute(SQL_STATEMENT)

44
poetry.lock generated
View File

@ -2780,13 +2780,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pydantic-scim"
version = "0.0.7"
version = "0.0.8"
description = "Pydantic types for SCIM"
optional = false
python-versions = ">=3.8.0"
files = [
{file = "pydantic-scim-0.0.7.tar.gz", hash = "sha256:bc043da51c346051dfd372f12d1837c0846b815236340156d663a8514cba5761"},
{file = "pydantic_scim-0.0.7-py3-none-any.whl", hash = "sha256:058eb195f75ef32d04eaf6369c125d5fb7052891694686f8e55e04d184ab1360"},
{file = "pydantic-scim-0.0.8.tar.gz", hash = "sha256:b6c62031126e8c54f0fc7df837678e63934a5b068533fc52e5dfb6cfc24d59e9"},
{file = "pydantic_scim-0.0.8-py3-none-any.whl", hash = "sha256:407b3bf55240947155c77a6dd839881d63368c61d64076d6b167ef124ceac79a"},
]
[package.dependencies]
@ -3374,28 +3374,28 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
version = "0.1.2"
version = "0.1.3"
description = "An extremely fast Python linter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.1.2-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:0d3ee66b825b713611f89aa35d16de984f76f26c50982a25d52cd0910dff3923"},
{file = "ruff-0.1.2-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:f85f850a320ff532b8f93e8d1da6a36ef03698c446357c8c43b46ef90bb321eb"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:809c6d4e45683696d19ca79e4c6bd3b2e9204fe9546923f2eb3b126ec314b0dc"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46005e4abb268e93cad065244e17e2ea16b6fcb55a5c473f34fbc1fd01ae34cb"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10cdb302f519664d5e2cf954562ac86c9d20ca05855e5b5c2f9d542228f45da4"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f89ebcbe57a1eab7d7b4ceb57ddf0af9ed13eae24e443a7c1dc078000bd8cc6b"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7344eaca057d4c32373c9c3a7afb7274f56040c225b6193dd495fcf69453b436"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dffa25f6e03c4950b6ac6f216bc0f98a4be9719cb0c5260c8e88d1bac36f1683"},
{file = "ruff-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42ddaea52cb7ba7c785e8593a7532866c193bc774fe570f0e4b1ccedd95b83c5"},
{file = "ruff-0.1.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a8533efda625bbec0bf27da2886bd641dae0c209104f6c39abc4be5b7b22de2a"},
{file = "ruff-0.1.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b0b1b82221ba7c50e03b7a86b983157b5d3f4d8d4f16728132bdf02c6d651f77"},
{file = "ruff-0.1.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c1362eb9288f8cc95535294cb03bd4665c8cef86ec32745476a4e5c6817034c"},
{file = "ruff-0.1.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ffa7ef5ded0563329a35bd5a1cfdae40f05a75c0cc2dd30f00b1320b1fb461fc"},
{file = "ruff-0.1.2-py3-none-win32.whl", hash = "sha256:6e8073f85e47072256e2e1909f1ae515cf61ff5a4d24730a63b8b4ac24b6704a"},
{file = "ruff-0.1.2-py3-none-win_amd64.whl", hash = "sha256:b836ddff662a45385948ee0878b0a04c3a260949905ad861a37b931d6ee1c210"},
{file = "ruff-0.1.2-py3-none-win_arm64.whl", hash = "sha256:b0c42d00db5639dbd5f7f9923c63648682dd197bf5de1151b595160c96172691"},
{file = "ruff-0.1.2.tar.gz", hash = "sha256:afd4785ae060ce6edcd52436d0c197628a918d6d09e3107a892a1bad6a4c6608"},
{file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"},
{file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"},
{file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"},
{file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"},
{file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"},
{file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"},
{file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"},
{file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"},
]
[[package]]
@ -4332,4 +4332,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "e6b1df989cb5c50609540c1229d05d8458ef1cc343fb5868402db8b7679ad73c"
content-hash = "2fc746976187f4674f04575cffd6a367744723bf78c356b6951c2370bc47ceae"

View File

@ -15,7 +15,14 @@ COPY web .
RUN npm run build-proxy
# Stage 2: Build
FROM docker.io/golang:1.21.3-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io
@ -29,7 +36,7 @@ ENV CGO_ENABLED=0
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /go/proxy ./cmd/proxy
GOARM="${TARGETVARIANT#v}" go build -o /go/proxy ./cmd/proxy
# Stage 3: Run
FROM gcr.io/distroless/static-debian11:debug

View File

@ -113,7 +113,7 @@ filterwarnings = [
[tool.poetry]
name = "authentik"
version = "2023.10.0"
version = "2023.10.3"
description = ""
authors = ["authentik Team <hello@goauthentik.io>"]
@ -152,7 +152,7 @@ paramiko = "*"
psycopg = { extras = ["c"], version = "*" }
pycryptodome = "*"
pydantic = "<3.0.0"
pydantic-scim = "^0.0.7"
pydantic-scim = "^0.0.8"
pyjwt = "*"
python = "^3.11"
pyyaml = "*"

View File

@ -1,5 +1,12 @@
# Stage 1: Build
FROM docker.io/golang:1.21.3-bookworm AS builder
FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.3-bookworm AS builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io
@ -13,7 +20,7 @@ ENV CGO_ENABLED=0
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go build -o /go/radius ./cmd/radius
GOARM="${TARGETVARIANT#v}" go build -o /go/radius ./cmd/radius
# Stage 2: Run
FROM gcr.io/distroless/static-debian11:debug

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2023.10.0
version: 2023.10.3
description: Making authentication simple.
contact:
email: hello@goauthentik.io

8
web/package-lock.json generated
View File

@ -17,7 +17,7 @@
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.0",
"@fortawesome/fontawesome-free": "^6.4.2",
"@goauthentik/api": "^2023.8.3-1698323628",
"@goauthentik/api": "^2023.10.1-1698348102",
"@lit-labs/context": "^0.4.1",
"@lit-labs/task": "^3.1.0",
"@lit/localize": "^0.11.4",
@ -2883,9 +2883,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2023.8.3-1698323628",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.8.3-1698323628.tgz",
"integrity": "sha512-qSpmrbLTCQWevjawXO26WYZcQ6Y4Cp/fIQn3KSl8fohK85MwCYLk9pqt6MZl1sC93A3dlak6sYHp9xEG3JN8wQ=="
"version": "2023.10.1-1698348102",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.1-1698348102.tgz",
"integrity": "sha512-Melx4hoHOLbgAOHREGzx83uN5BKvgql4qIUloxh/abvNeGLlfKL49caiU8++ANUaERr1vb8X2tHFwiwxtqXKeQ=="
},
"node_modules/@hcaptcha/types": {
"version": "1.0.3",

View File

@ -38,7 +38,7 @@
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.0",
"@fortawesome/fontawesome-free": "^6.4.2",
"@goauthentik/api": "^2023.8.3-1698323628",
"@goauthentik/api": "^2023.10.1-1698348102",
"@lit-labs/context": "^0.4.1",
"@lit-labs/task": "^3.1.0",
"@lit/localize": "^0.11.4",

View File

@ -116,7 +116,7 @@ export class ApplicationForm extends ModelForm<Application, string> {
return app;
}
handleConfirmBackchannelProviders({ items }: { items: Provider[] }) {
handleConfirmBackchannelProviders(items: Provider[]) {
this.backchannelProviders = items;
this.requestUpdate();
return Promise.resolve();

View File

@ -63,7 +63,7 @@ export class AkBackchannelProvidersInput extends AKElement {
return html`
<ak-form-element-horizontal label=${this.label} name=${name}>
<div class="pf-c-input-group">
<ak-provider-select-table ?backchannelOnly=${true} .confirm=${confirm}>
<ak-provider-select-table ?backchannelOnly=${true} .confirm=${this.confirm}>
<button slot="trigger" class="pf-c-button pf-m-control" type="button">
${this.tooltip ? this.tooltip : nothing}
<i class="fas fa-plus" aria-hidden="true"></i>

View File

@ -114,8 +114,8 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel {
label=${msg("Client type")}
.value=${provider?.clientType}
required
@change=${(ev: CustomEvent<ClientTypeEnum>) => {
this.showClientSecret = ev.detail !== ClientTypeEnum.Public;
@change=${(ev: CustomEvent<{ value: ClientTypeEnum }>) => {
this.showClientSecret = ev.detail.value !== ClientTypeEnum.Public;
}}
.options=${clientTypeOptions}
>

View File

@ -78,8 +78,8 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Mode")} ?required=${true} name="mode">
<ak-radio
@change=${(ev: CustomEvent<NotificationTransportModeEnum>) => {
this.onModeChange(ev.detail);
@change=${(ev: CustomEvent<{ value: NotificationTransportModeEnum }>) => {
this.onModeChange(ev.detail.value);
}}
.options=${[
{

View File

@ -210,8 +210,8 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
label=${msg("Client type")}
.value=${provider?.clientType}
required
@change=${(ev: CustomEvent<ClientTypeEnum>) => {
this.showClientSecret = ev.detail !== ClientTypeEnum.Public;
@change=${(ev: CustomEvent<{ value: ClientTypeEnum }>) => {
this.showClientSecret = ev.detail.value !== ClientTypeEnum.Public;
}}
.options=${clientTypeOptions}
>
@ -334,13 +334,14 @@ export class OAuth2ProviderFormPage extends ModelForm<OAuth2Provider, number> {
)}
>
</ak-radio-input>
<ak-switch-input name="includeClaimsInIdToken">
<ak-switch-input
name="includeClaimsInIdToken"
label=${msg("Include claims in id_token")}
?checked=${first(provider?.includeClaimsInIdToken, true)}
help=${msg(
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
)}></ak-switch-input
>
)}
></ak-switch-input>
<ak-radio-input
name="issuerMode"
label=${msg("Issuer mode")}

View File

@ -42,15 +42,13 @@ export class RoleForm extends ModelForm<Role, string> {
}
renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
return html`<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input
type="text"
value="${ifDefined(this.instance?.name)}"
class="pf-c-form-control"
required
/>
</ak-form-element-horizontal>
</form>`;
</ak-form-element-horizontal>`;
}
}

View File

@ -386,6 +386,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
class="pf-c-form-control"
required
/>
<p class="pf-c-form__helper-text">${msg("Also known as Client ID.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Consumer secret")}
@ -394,6 +395,7 @@ export class OAuthSourceForm extends ModelForm<OAuthSource, string> {
name="consumerSecret"
>
<textarea class="pf-c-form-control"></textarea>
<p class="pf-c-form__helper-text">${msg("Also known as Client Secret.")}</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes">
<input

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2023.10.0";
export const VERSION = "2023.10.3";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@ -80,11 +80,12 @@ export class IdentificationStage extends BaseStage<
}
createHelperForm(): void {
const compatMode = "ShadyDOM" in window;
this.form = document.createElement("form");
document.documentElement.appendChild(this.form);
// Only add the additional username input if we're in a shadow dom
// otherwise it just confuses browsers
if (!("ShadyDOM" in window)) {
if (!compatMode) {
// This is a workaround for the fact that we're in a shadow dom
// adapted from https://github.com/home-assistant/frontend/issues/3133
const username = document.createElement("input");
@ -104,6 +105,8 @@ export class IdentificationStage extends BaseStage<
};
this.form.appendChild(username);
}
// Only add the password field when we don't already show a password field
if (!compatMode && !this.challenge.passwordFields) {
const password = document.createElement("input");
password.setAttribute("type", "password");
password.setAttribute("name", "password");
@ -128,6 +131,7 @@ export class IdentificationStage extends BaseStage<
});
};
this.form.appendChild(password);
}
const totp = document.createElement("input");
totp.setAttribute("type", "text");
totp.setAttribute("name", "code");

View File

@ -5798,12 +5798,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -6031,6 +6025,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -6079,12 +6079,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -6312,6 +6306,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -5713,12 +5713,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -5946,6 +5940,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -613,9 +613,9 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>L'URL &quot;
<x id="0" equiv-text="${this.url}"/>&quot; n'a pas été trouvée.</target>
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>L'URL "
<x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
@ -1057,8 +1057,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="sa8384c9c26731f83">
<source>To allow any redirect URI, set this value to &quot;.*&quot;. Be aware of the possible security implications this can have.</source>
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur &quot;.*&quot;. Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
<target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur ".*". Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
</trans-unit>
<trans-unit id="s55787f4dfcdce52b">
@ -1630,7 +1630,7 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="s33ed903c210a6209">
<source>Token to authenticate with. Currently only bearer authentication is supported.</source>
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification &quot;bearer authentication&quot; est prise en charge.</target>
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification "bearer authentication" est prise en charge.</target>
</trans-unit>
<trans-unit id="sfc8bb104e2c05af8">
@ -1798,8 +1798,8 @@ Il y a <x id="0" equiv-text="${ago}"/> jour(s)</target>
</trans-unit>
<trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome &quot;fa-test&quot;.</target>
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome "fa-test".</target>
</trans-unit>
<trans-unit id="s0410779cb47de312">
@ -2922,7 +2922,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s33683c3b1dbaf264">
<source>To use SSL instead, use 'ldaps://' and disable this option.</source>
<target>Pour utiliser SSL à la base, utilisez &quot;ldaps://&quot; et désactviez cette option.</target>
<target>Pour utiliser SSL à la base, utilisez "ldaps://" et désactviez cette option.</target>
</trans-unit>
<trans-unit id="s2221fef80f4753a2">
@ -3011,8 +3011,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s76768bebabb7d543">
<source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ &quot;memberUid&quot;, la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'</target>
</trans-unit>
<trans-unit id="s026555347e589f0e">
@ -3307,7 +3307,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s3198c384c2f68b08">
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID &quot;transient&quot; et que l'utilisateur ne se déconnecte pas manuellement.</target>
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID "transient" et que l'utilisateur ne se déconnecte pas manuellement.</target>
</trans-unit>
<trans-unit id="sb32e9c1faa0b8673">
@ -3475,7 +3475,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
<target>Indiquer la valeur &quot;FriendlyName&quot; de l'attribut d'assertion (optionnel)</target>
<target>Indiquer la valeur "FriendlyName" de l'attribut d'assertion (optionnel)</target>
</trans-unit>
<trans-unit id="s851c108679653d2a">
@ -3804,8 +3804,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to &quot;minutes=5&quot;.</source>
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à &quot;minutes=5&quot;.</target>
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
<target>En cas d'utilisation d'une solution de journalisation externe pour l'archivage, cette valeur peut être fixée à "minutes=5".</target>
</trans-unit>
<trans-unit id="s44536d20bb5c8257">
@ -3814,8 +3814,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s3bb51cabb02b997e">
<source>Format: &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</source>
<target>Format : &quot;weeks=3;days=2;hours=3,seconds=2&quot;.</target>
<source>Format: "weeks=3;days=2;hours=3,seconds=2".</source>
<target>Format : "weeks=3;days=2;hours=3,seconds=2".</target>
</trans-unit>
<trans-unit id="s04bfd02201db5ab8">
@ -4011,10 +4011,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> &quot;<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</source>
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
<target>Êtes-vous sûr de vouloir mettre à jour
<x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>&quot; ?</target>
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>" ?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
@ -5100,8 +5100,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<target>Un authentificateur &quot;itinérant&quot;, comme une YubiKey</target>
<source>A "roaming" authenticator, like a YubiKey</source>
<target>Un authentificateur "itinérant", comme une YubiKey</target>
</trans-unit>
<trans-unit id="sfffba7b23d8fb40c">
@ -5426,7 +5426,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s5170f9ef331949c0">
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable &quot;prompt_data&quot;.</target>
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable "prompt_data".</target>
</trans-unit>
<trans-unit id="s36cb242ac90353bc">
@ -5435,10 +5435,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${prompt.name}"/> (&quot;<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<target>
<x id="0" equiv-text="${prompt.name}"/>(&quot;
<x id="1" equiv-text="${prompt.fieldKey}"/>&quot;, de type
<x id="0" equiv-text="${prompt.name}"/>("
<x id="1" equiv-text="${prompt.fieldKey}"/>", de type
<x id="2" equiv-text="${prompt.type}"/>)</target>
</trans-unit>
@ -5487,8 +5487,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to &quot;stay signed in&quot;, which will extend their session by the time specified here.</source>
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de &quot;rester connecté&quot;, ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
<target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de "rester connecté", ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
</trans-unit>
<trans-unit id="s542a71bb8f41e057">
@ -6272,7 +6272,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="sa7fcf026bd25f231">
<source>Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.</source>
<target>Peut être au format &quot;unix://&quot; pour une connexion à un service docker local, &quot;ssh://&quot; pour une connexion via SSH, ou &quot;https://:2376&quot; pour une connexion à un système distant.</target>
<target>Peut être au format "unix://" pour une connexion à un service docker local, "ssh://" pour une connexion via SSH, ou "https://:2376" pour une connexion à un système distant.</target>
</trans-unit>
<trans-unit id="saf1d289e3137c2ea">
@ -7579,7 +7579,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="sff0ac1ace2d90709">
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a managed outpost, this is done for you).</source>
<target>Utilisez ce fournisseur avec l'option &quot;auth_request&quot; de Nginx ou &quot;forwardAuth&quot; de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, &quot;/outpost.goauthentik.io&quot; doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
<target>Utilisez ce fournisseur avec l'option "auth_request" de Nginx ou "forwardAuth" de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, "/outpost.goauthentik.io" doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
</trans-unit>
<trans-unit id="scb58b8a60cad8762">
<source>Default relay state</source>
@ -7617,14 +7617,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>For transparent reverse proxies with required authentication</source>
<target>Pour les reverses proxy transparents avec authentification requise</target>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>Pour nginx auth_request ou traefik forwardAuth</target>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Pour nginx auth_request ou traefik forwardAuth par domaine racine</target>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
<target>Configurer le fournisseur SAML manuellement</target>
@ -7931,14 +7923,17 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>&lt;No name set&gt;</source>
<target>&lt;No name set&gt;</target>
</trans-unit>
<trans-unit id="s66313b45b69cfc88">
<source>Check the release notes</source>
</trans-unit>
<trans-unit id="sb4d7bae2440d9781">
<source>User Statistics</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
</body>
</file>

View File

@ -5921,12 +5921,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -6154,6 +6148,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -7557,14 +7557,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For transparent reverse proxies with required authentication</source>
<target>Ƒōŕ ţŕàńśƥàŕēńţ ŕēvēŕśē ƥŕōxĩēś ŵĩţĥ ŕēǫũĩŕēď àũţĥēńţĩćàţĩōń</target>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>Ƒōŕ ńĝĩńx'ś àũţĥ_ŕēǫũēśţ ōŕ ţŕàēƒĩx'ś ƒōŕŵàŕďÀũţĥ</target>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>Ƒōŕ ńĝĩńx'ś àũţĥ_ŕēǫũēśţ ōŕ ţŕàēƒĩx'ś ƒōŕŵàŕďÀũţĥ ƥēŕ ŕōōţ ďōmàĩń</target>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
<target>Ćōńƒĩĝũŕē ŚÀMĹ ƥŕōvĩďēŕ màńũàĺĺŷ</target>
@ -7844,4 +7836,16 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body></file></xliff>

View File

@ -5706,12 +5706,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -5939,6 +5933,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -7620,14 +7620,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For transparent reverse proxies with required authentication</source>
<target>适用于需要验证身份的透明反向代理</target>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>适用于 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
<target>手动配置 SAML 提供程序</target>
@ -7933,6 +7925,22 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
<target>&lt;未设置名称&gt;</target>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>适用于 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>新创建用户使用的用户类型。</target>
</trans-unit>
</body>
</file>

View File

@ -5754,12 +5754,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -5987,6 +5981,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -7620,14 +7620,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>For transparent reverse proxies with required authentication</source>
<target>适用于需要验证身份的透明反向代理</target>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>适用于 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
<target>手动配置 SAML 提供程序</target>
@ -7933,6 +7925,22 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
<target>&lt;未设置名称&gt;</target>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
<target>适用于 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
<target>适用于按根域名配置的 nginx 的 auth_request 或 traefik 的 forwardAuth</target>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
<target>RBAC 目前处于预览状态。</target>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
<target>新创建用户使用的用户类型。</target>
</trans-unit>
</body>
</file>

View File

@ -5753,12 +5753,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="sadf073913458acbd">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="se770e9498b3bacf6">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
@ -5986,6 +5980,18 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s0924f51b028233a3">
<source>&lt;No name set&gt;</source>
</trans-unit>
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
</trans-unit>
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
</trans-unit>
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
</trans-unit>
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
</trans-unit>
</body>
</file>

View File

@ -0,0 +1,130 @@
---
title: 3 ways you (might be) doing containers wrong
description: “Using containers is not a best practice in itself. Here are some mistakes beginners make with containers, and how we set them up correctly at authentik.”
authors:
- name: Jens Langhammer
title: CTO at Authentik Security Inc
url: https://github.com/BeryJu
image_url: https://github.com/BeryJu.png
tags:
- application
- runtime
- SSO
- Docker
- containers
- :latest
- identity provider
- security
- authentication
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._
---
There are two ways to judge an application:
1. Does it do what its supposed to do?
2. Is it easy to run?
This post is about the second.
Using containers is not a best practice in itself. As an infrastructure engineer by background, Im pretty opinionated about how to set up containers properly. Doing things the “right” way makes things easier not just for you, but for your users as well.
Below are some common mistakes that I see beginners make with containers:
1. Using one container per application
2. Installing things at runtime
3. Writing logs to files instead of stdout
## Mistake #1: One container per application
There tend to be two mindsets when approaching setting up containers:
- The inexperienced usually think 1 container = 1 application
- The other option is 1 container = 1 service
Your application usually consists of multiple services, and to my mind these should always be separated into their own containers (in keeping with the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single-responsibility_principle)).
For example, authentik consists of four components (services):
- Server
- Worker
- Database
- Cache
With our deployment, that means you get four different containers because they each run one of those four services.
### Why you should use one container per _service_
At the point where you need to scale, or need High Availability, having different processes in separate containers enables horizontal scaling. Because of how authentik deploys, if we need to handle more traffic we can scale up to 50 servers, rather than having to scale up _everything_. This wouldnt work if all those components were all bundled together.
Additionally, if youre using a container orchestrator (whether thats Kubernetes or something simpler like [Docker Compose](https://goauthentik.io/docs/installation/docker-compose)), if its all bundled together, the orchestrator cant distinguish between components because theyre all in the black box of your container.
Say you want to start up processes in a specific order. This isnt possible if theyre in a single container (unless you rebuild the entire image). If those processes are separate, you can just tell Docker Compose to start them up in the order you want, or you can run specific components on specific servers.
Of course, your application architecture and deployment model need to support this setup, which is why its critical to think about these things when youre starting out. If youre reading this and thinking, I have a small-scale, hobby project, this doesnt apply to me—let me put it this way: you will never regret setting things up the “right” way. Its not going to come back to bite you if your situation changes later. It also gives users who install the application a lot more freedom and flexibility in how _they_ want to run it.
## Mistake #2: Installing things at runtime
Your container image should be complete in itself: it should contain all code and dependencies—everything it needs to run. This is the point of a container—its self contained.
Ive seen people set up their container to download an application from the vendor and install it into the container on startup. While this does work, what happens if you dont have internet access? What if the vendor shut down and that URL now points to a malicious bit of code?
If you have 100 instances downloading files at startup (or end up scaling to that point), this can lead to rate limiting, failed downloads, or your internet connection getting saturated—its just inefficient and causes problems that can be avoided.
### Also, dont use :latest
This leads me to a different but related bad practice: using the `:latest` tag. Its a common pitfall for folks who use containers but dont necessarily build them themselves.
Its easy to get started with the `:latest` tag and its understandable to want the latest version without having to go into files and manually edit everything. But what can happen is that you update and suddenly its pointing to a new version and breaking things.
Ive seen this happen where youre just running something on a local server and your disk is full, so you empty out your Docker images. The next time you pull, its with a new version which now no longer works and youre stuck trying to figure out what version you were on before.
### Instead: Pin your dependencies
You should be pinning your dependencies to a specific version, and updating to newer versions intentionally rather than by default.
The most reliable way to do this is with a process called GitOps:
- In the context of Kubernetes, all the YAML files you deploy with Kubernetes are stored in the central Git repository.
- You have software in your Kubernetes cluster that automatically pulls the files from your Git repo and installs them into the cluster.
- Then you can use a tool like [Dependabot](https://github.com/dependabot) or [Renovate](https://github.com/renovatebot/renovate) to automatically create PRs with a new version (if there is one) so you can test and approve it, and its all captured in your Git history.
GitOps might be a bit excessive if youre only running a small hobby project on a single server, but in any case you should still pin a version.
For a long time, authentik purposefully didnt have a `:latest` tag, because people would use it inadvertently (sometimes not realizing they had an auto-updater running). Suddenly something wouldnt work and there wasnt really a way to downgrade.
We have since added it due to popular request. This is how authentiks version tags work:
- Our version number is 3 digits reflecting the date of the release, so the latest currently is [2023.10.1](https://goauthentik.io/docs/releases/2023.10).
- You can either use 2023.10.1 as the tag, pinning to that specific version
- You can pin to 2023.10, which you means that you always get the latest patch version, or
- You can use 2023, which means you always get the latest version within that year.
The principle is roughly the same with any project using [SemVer](https://semver.org/): you could just lock to v1, which means you get the latest v1 with all minor patches and fixes, without breaking updates. Then you switch to v2 when youre ready.
With this approach you are putting some trust in the developer not to publish any breaking changes with the wrong version number (but youre technically always putting trust in some developer when using someone elses software!).
## Mistake #3: Writing logs to files instead of stdout
This is another issue on the infrastructure side that mainly happens when you put legacy applications into containers. It used to be standard that applications put their log output into a file, and youd probably have a system daemon set up to rotate those files and archive the old ones. This was great when everything ran on the same server without containers.
A lot of software still logs to files by default, but this makes collecting and aggregating your services logs much harder. Docker (and containers in general) expect that you log to standard output so your orchestration platform can route the logs to your monitoring tool of choice.
Docker puts the logs into a JSON file that it can read itself and see the timestamps and which container the log refers to. You can set up log forwarding with both Docker and Kubernetes. If you have a central logging server, the plugin gets the standard output of a container and sends it to that server.
Not logging to `stdout` just makes it harder for everyone, including making it harder to debug: Instead of just running `docker logs` + the name of the container, you need to `exec` into the container, go to find the files, then look at the files to start debugging.
### This bad practice is arguably the easiest one to work around
As an engineer you can easily redirect the logs back from a file into the standard output, but theres no real reason not to do it the “correct” way.
There arent many use cases where theres an advantage to writing your logs directly to a file instead of stdout—in fact the main one is for when youre making the first mistake (having your whole application in one container)! If youre running multiple services in one container, then youll have logs from multiple different processes in one place, which _could_ be easier to work with in a file vs stdout.
Even if you specifically want your logs to exist in a file, by default if you run `docker logs` it just reads a JSON file that it adds the logs to, so youre not losing anything by logging to stdout. You can configure Docker to just put the logs into a plain text file wherever you want to.
Its a little simplistic, but Id encourage you to check out [The Twelve-Factor App](https://12factor.net/) which outlines good practices for making software thats easy to run.
Are you doing containers differently and is it working for you? Let us know in the comments, or send us an email at hello@goauthentik.io!

View File

@ -3,7 +3,15 @@ title: Release 2023.10
slug: "/releases/2023.10"
---
<!-- ## Breaking changes -->
## Breaking changes
- Requests with missing trailing slash are no longer redirected
In previous versions, requests to a path like `/api/v3/core/users` would be redirected to `[...]/users/`. This redirect would cause mutating requests (such as POST, PUT and PATCH) to fail as they would get redirected to `[...]/users/`. The redirect has been disabled, which will not have have an impact on a correctly configured setup.
- It is only possible to upgrade to 2023.10 from 2023.8. This is due to a bug in the migrations which will be fixed in a future release (#7326).
- Warning: The first 2024.x version of this chart will see a rework that will include breaking changes. The breaking changes will be noted in the next Release notes.
## New features
@ -13,7 +21,7 @@ slug: "/releases/2023.10"
- LDAP Provider improvements
The LDAP Provider now has an expanded schema, increasing the compatibility with clients that use the LDAP schema to parse data and .net applications on Windows.
The LDAP Provider now has an expanded schema, increasing the compatibility with clients that use the LDAP schema to parse data and .Net applications on Windows.
- Improved Proxy provider logout
@ -113,6 +121,22 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2023.10
- web: change 'Attributes' to 'Custom attributes' on Invitation Field (#7145)
- web: the return of pseudolocalization (#7190)
## Fixed in 2023.10.1
- lifecycle: fix otp merge migration (#7315)
## Fixed in 2023.10.2
- \*: fix [GHSA-rjvp-29xq-f62w](../security/GHSA-rjvp-29xq-f62w), Reported by [@devSparkle](https://github.com/devSparkle)
- blueprints: fix entries with state: absent not being deleted if their serializer has errors (#7345)
- crypto: fix race conditions when creating self-signed certificates on startup (#7344)
- lifecycle: rework otp_merge migration (#7359)
- providers/proxy: to fix duplicate cookie (#7324)
- rbac: handle lookup error (#7341)
- stages/email: fix sending emails from task (#7325)
- web/admin: fix @change handler for ak-radio elements (#7348)
- web/admin: fix role form reacting to enter (#7330)
## API Changes
#### What's New

View File

@ -0,0 +1,27 @@
# GHSA-rjvp-29xq-f62w
_Reported by [@devSparkle](https://github.com/devSparkle)_
## Potential Installation takeover when default admin user is deleted
### Summary
In the affected versions, when the default admin user has been deleted, it is potentially possible for an attacker to set the password of the default admin user without any authentication.
### Patches
authentik 2023.8.4 and 2023.10.2 fix this issue, for other versions the workaround can be used.
### Impact
authentik uses a blueprint to create the default admin user, which can also optionally set the default admin users' password from an environment variable. When the user is deleted, the `initial-setup` flow used to configure authentik after the first installation becomes available again.
### Workarounds
Ensure the default admin user (Username `akadmin`) exists and has a password set. It is recommended to use a very strong password for this user, and store it in a secure location like a password manager. It is also possible to deactivate the user to prevent any logins as akadmin.
### For more information
If you have any questions or comments about this advisory:
- Email us at [security@goauthentik.io](mailto:security@goauthentik.io)

View File

@ -407,6 +407,7 @@ const docsSidebar = {
},
items: [
"security/policy",
"security/GHSA-rjvp-29xq-f62w",
"security/CVE-2023-39522",
"security/CVE-2023-36456",
"security/2023-06-cure53",