Compare commits

...
This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.

157 commits

Author SHA1 Message Date
Jens Langhammer 10d76fa4f1
update
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-16 11:52:31 +01:00
Jens Langhammer 16bc7408e7
antlr for scim filter parsing, why
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-16 11:52:31 +01:00
Jens Langhammer 7f12b14145
start user tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer 619f356ecc
only allow SCIM basic auth for testing and debug
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer d99a81d32f
add UI base URL
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer f1426be34c
include root URL in API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer 4698194a4a
rebuild migration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer 1a57f14f59
add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens Langhammer 2cab4b7cda
initial
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2023-11-16 11:52:14 +01:00
Jens L 51d3511f8b
providers/scim: fix missing schemas attribute for User and Group (#7477)
* providers/scim: fix missing schemas attribute for User and Group

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

* make things actually work

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-16 11:36:49 +01:00
dependabot[bot] 6a8eae6780
core: bump pydantic from 2.5.0 to 2.5.1 (#7592)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.5.0 to 2.5.1.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.5.0...v2.5.1)

---
updated-dependencies:
- dependency-name: pydantic
  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-11-16 11:35:49 +01:00
Jens L 99cecdb3ca
web/admin: contextually add user to group when creating user from group page (#7586)
* move related user list to group folder

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

* contextually add user to group when created from group view page

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

* add banner

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

* format

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 23:14:30 +01:00
Tana M Berry bac7e034f8
website/blog: title and slug change (#7585)
* title and slug change

* also rename folder

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 21:02:06 +00:00
Jens L 3d66923310
events: sanitize functions (#7587)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 21:56:16 +01:00
Jens L 95c71016ae
stages/email: use uuid for email confirmation token instead of username (#7581)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 21:13:53 +01:00
Tana M Berry 5cfae6e117
website/blog: Blog about zero trust and wireguard (#7567)
* draft for review

* added images

* Optimised images with calibre/image-actions

* typo

* ken edits

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-11-15 14:04:30 -06:00
Marc 'risson' Schmitt a2e5de1656 ci: translation-advice: avoid commenting after make i18n-extract
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-15 16:51:16 +01:00
Jens L 0d59d24989
web/admin: fix incorrectly encoded chars in translation (#7580)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 16:28:56 +01:00
Jens L 01ffece9ff
web/flows: don't auto-redirect to first source when passwordless is configured (#7579)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-15 14:52:48 +01:00
dependabot[bot] 5b5fc42a0c
core: bump aiohttp from 3.8.5 to 3.8.6 (#7568)
Bumps [aiohttp](https://github.com/aio-libs/aiohttp) from 3.8.5 to 3.8.6.
- [Release notes](https://github.com/aio-libs/aiohttp/releases)
- [Changelog](https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst)
- [Commits](https://github.com/aio-libs/aiohttp/compare/v3.8.5...v3.8.6)

---
updated-dependencies:
- dependency-name: aiohttp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 14:52:15 +01:00
transifex-integration[bot] 8cd352a600
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7578)
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-11-15 13:52:05 +01:00
transifex-integration[bot] 2a3fd88081
translate: Updates for file web/xliff/en.xlf in zh_CN (#7577)
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-11-15 13:51:48 +01:00
dependabot[bot] d39d8e6195
web: bump @formatjs/intl-listformat from 7.5.2 to 7.5.3 in /web (#7573)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.5.2 to 7.5.3.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.5.2...@formatjs/intl-listformat@7.5.3)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  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-11-15 13:44:02 +01:00
dependabot[bot] b3d86374aa
web: bump the wdio group in /tests/wdio with 4 updates (#7571)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.22.1 to 8.23.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.23.0/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.22.1 to 8.23.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.23.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.22.0 to 8.23.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.23.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.21.0 to 8.23.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.23.0/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 13:43:51 +01:00
dependabot[bot] 76db5b69de
web: bump the sentry group in /web with 2 updates (#7572)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.80.0 to 7.80.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.80.0...7.80.1)

Updates `@sentry/tracing` from 7.80.0 to 7.80.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.80.0...7.80.1)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 13:43:42 +01:00
dependabot[bot] 1ac3d6ddcb
web: bump rollup from 4.4.0 to 4.4.1 in /web (#7574)
Bumps [rollup](https://github.com/rollup/rollup) from 4.4.0 to 4.4.1.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.4.0...v4.4.1)

---
updated-dependencies:
- dependency-name: rollup
  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-11-15 13:43:32 +01:00
dependabot[bot] f4c6a0af1f
web: bump pyright from 1.1.335 to 1.1.336 in /web (#7575)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.335 to 1.1.336.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.336/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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-11-15 13:43:22 +01:00
transifex-integration[bot] d0c392f311
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW (#7549)
* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

* Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

---------

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-15 13:43:06 +01:00
transifex-integration[bot] af1fed3308
translate: Updates for file web/xliff/en.xlf in fr (#7565)
Translate web/xliff/en.xlf in fr

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-14 17:59:01 +00:00
Jens L deb0cb236e
web/admin: always show oidc well-known URL fields when they're set (#7560)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-14 13:05:18 +01:00
Jens L 31592712a4
web/elements: keep selected elements in table when fetching (#7519)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-14 11:49:11 +01:00
dependabot[bot] 627b3bc095
ci: bump actions/github-script from 6 to 7 (#7551)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 11:24:29 +01:00
dependabot[bot] ce667c6457
web: bump the eslint group in /web with 2 updates (#7552)
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.10.0 to 6.11.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.11.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.10.0 to 6.11.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.11.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 11:24:18 +01:00
dependabot[bot] 9b89ba0659
core: bump sentry-sdk from 1.34.0 to 1.35.0 (#7553)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.34.0 to 1.35.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.34.0...1.35.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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-11-14 11:24:10 +01:00
dependabot[bot] c86d347034
core: bump pydantic from 2.4.2 to 2.5.0 (#7554)
Bumps [pydantic](https://github.com/pydantic/pydantic) from 2.4.2 to 2.5.0.
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](https://github.com/pydantic/pydantic/compare/v2.4.2...v2.5.0)

---
updated-dependencies:
- dependency-name: pydantic
  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-11-14 11:24:01 +01:00
dependabot[bot] 5b3a15173a
core: bump urllib3 from 2.0.7 to 2.1.0 (#7555)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.0.7 to 2.1.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.0.7...2.1.0)

---
updated-dependencies:
- dependency-name: urllib3
  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-11-14 11:23:54 +01:00
dependabot[bot] 0430c16f8a
web: bump the eslint group in /tests/wdio with 2 updates (#7556)
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.10.0 to 6.11.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.11.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.10.0 to 6.11.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.11.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 11:23:46 +01:00
dependabot[bot] 554481f81f
core: bump goauthentik.io/api/v3 from 3.2023103.1 to 3.2023103.2 (#7557)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023103.1 to 3.2023103.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023103.1...v3.2023103.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api/v3
  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-11-14 11:23:37 +01:00
dependabot[bot] 2c84e3d955
website: bump react-tooltip from 5.22.0 to 5.23.0 in /website (#7558)
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.22.0 to 5.23.0.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.22.0...v5.23.0)

---
updated-dependencies:
- dependency-name: react-tooltip
  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-11-14 11:23:28 +01:00
Jens L dc7ffba8fa
internal: remove special route for /outpost.goauthentik.io (#7539)
With this special route for outpost.goauthentik.io, misdirected requests to /outpost.goauthentik.io/auth/start will create a cookie for the domain authentik is accessed under, which will cause issues with the actual full auth flow. Requests to /outpost.goauthentik.io will still be routed to the outpost, but with this change only when the hostname matches

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-13 17:39:40 +01:00
thijs_a 695719540b
providers/proxy: Fix duplicate cookies when using file system store. (#7541)
Fix duplicate cookies when using file system store.
2023-11-13 15:33:49 +01:00
authentik-automation[bot] 0e019e18c9
web: bump API Client version (#7543)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-11-13 15:06:05 +01:00
Jens L f728bbb14b
sources/ldap: add check command to verify ldap connectivity (#7263)
* sources/ldap: add check command to verify ldap connectivity

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

* default to checking all sources

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

* start adding an API for ldap connectivity

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

* add webui for ldap source connection status

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

* better show sync status, clear previous tasks

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

* set timeout on redis lock for ldap sync

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

* fix py lint

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

* fix web lint

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-13 15:01:40 +01:00
Jens L 4080080acd
internal: remove deprecated metrics (#7540)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-13 14:48:37 +01:00
authentik-automation[bot] 0a0f87b9ca
core: compile backend translations (#7538)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <authentik-automation[bot]@users.noreply.github.com>
2023-11-13 12:13:22 +01:00
dependabot[bot] 7699a119a3
web: bump prettier from 3.0.3 to 3.1.0 in /web (#7528)
Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  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-11-13 12:12:54 +01:00
dependabot[bot] 73fbcde924
web: bump @trivago/prettier-plugin-sort-imports from 4.2.1 to 4.3.0 in /web (#7531)
web: bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.1...v4.3.0)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-type: direct:development
  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-11-13 12:12:43 +01:00
dependabot[bot] a1efcc4da9
web: bump rollup from 4.3.0 to 4.4.0 in /web (#7529)
Bumps [rollup](https://github.com/rollup/rollup) from 4.3.0 to 4.4.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.3.0...v4.4.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  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-11-13 11:18:50 +01:00
dependabot[bot] d594574ffa
core: bump celery from 5.3.4 to 5.3.5 (#7536)
Bumps [celery](https://github.com/celery/celery) from 5.3.4 to 5.3.5.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/main/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.3.4...v5.3.5)

---
updated-dependencies:
- dependency-name: celery
  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-11-13 11:18:11 +01:00
dependabot[bot] dbbb5e75cf
web: bump @formatjs/intl-listformat from 7.5.1 to 7.5.2 in /web (#7530)
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.5.1 to 7.5.2.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.5.1...@formatjs/intl-listformat@7.5.2)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  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-11-13 11:17:23 +01:00
dependabot[bot] ddb73db287
web: bump prettier from 3.0.3 to 3.1.0 in /tests/wdio (#7532)
Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  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-11-13 11:17:02 +01:00
dependabot[bot] 143f092153
web: bump @trivago/prettier-plugin-sort-imports from 4.2.1 to 4.3.0 in /tests/wdio (#7533)
web: bump @trivago/prettier-plugin-sort-imports in /tests/wdio

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 4.2.1 to 4.3.0.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/main/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/compare/v4.2.1...v4.3.0)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-type: direct:development
  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-11-13 11:16:46 +01:00
dependabot[bot] d89adef963
website: bump prettier from 3.0.3 to 3.1.0 in /website (#7534)
Bumps [prettier](https://github.com/prettier/prettier) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/3.0.3...3.1.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  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-11-13 11:16:34 +01:00
dependabot[bot] 5f3cbf6f7f
website: bump prism-react-renderer from 2.1.0 to 2.2.0 in /website (#7535)
Bumps [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) from 2.1.0 to 2.2.0.
- [Release notes](https://github.com/FormidableLabs/prism-react-renderer/releases)
- [Commits](https://github.com/FormidableLabs/prism-react-renderer/compare/prism-react-renderer@2.1.0...prism-react-renderer@2.2.0)

---
updated-dependencies:
- dependency-name: prism-react-renderer
  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-11-13 11:16:25 +01:00
transifex-integration[bot] a9fdacc60b
translate: Updates for file locale/en/LC_MESSAGES/django.po in zh_TW (#7537)
Translate locale/en/LC_MESSAGES/django.po in zh_TW

100% translated source file: 'locale/en/LC_MESSAGES/django.po'
on 'zh_TW'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-13 11:16:00 +01:00
Philipp Kolberg 9db9ad3d66
root: Restructure broker / cache / channel / result configuration (#7097)
* Initial commit

* Remove any remaining mentions of Redis URL

This is handled in https://github.com/goauthentik/authentik/pull/5395

* Allow setting broker transport options

This enables usage of other brokers that require additional settings

* Remove remaining reference to Redis URL

This functionality is not part of this PR

* Reset default TLS requirements to none

* Fix linter errors

* Move dict from base64 encoded json to config.py

Additionally add tests

* Replace ast.literal_eval with json.loads

* Use default channel and cache backend configuration

If more customization is desired users shall look at goauthentik.io/docs/installation/configuration#custom-python-settings

* Send config deprecation notification to all superusers

* Remove duplicate method

* Add configuration explanation

For channel layer settings

* Use Event for deprecation warning

* Fix remove duplicated method

* Add missing comma

* Update authentik/lib/config.py

Signed-off-by: Jens L. <jens@beryju.org>

* Fix Event deprecation handling

---------

Signed-off-by: Jens L. <jens@beryju.org>
Co-authored-by: Jens L <jens@beryju.org>
2023-11-10 15:44:37 +01:00
dependabot[bot] 11dcda77fa
core: bump twilio from 8.10.0 to 8.10.1 (#7474)
Bumps [twilio](https://github.com/twilio/twilio-python) from 8.10.0 to 8.10.1.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/8.10.0...8.10.1)

---
updated-dependencies:
- dependency-name: twilio
  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-11-10 12:41:59 +01:00
dependabot[bot] 4ce5f0931b
web: bump axios from 1.5.0 to 1.6.1 in /web (#7518)
Bumps [axios](https://github.com/axios/axios) from 1.5.0 to 1.6.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.5.0...v1.6.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-10 12:41:04 +01:00
dependabot[bot] f8e2cd5639
web: bump wdio-wait-for from 3.0.7 to 3.0.8 in /tests/wdio (#7514)
Bumps [wdio-wait-for](https://github.com/webdriverio/wdio-wait-for) from 3.0.7 to 3.0.8.
- [Release notes](https://github.com/webdriverio/wdio-wait-for/releases)
- [Commits](https://github.com/webdriverio/wdio-wait-for/compare/3.0.7...3.0.8)

---
updated-dependencies:
- dependency-name: wdio-wait-for
  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-11-10 12:40:26 +01:00
dependabot[bot] 8b4f66e457
core: bump goauthentik.io/api/v3 from 3.2023102.1 to 3.2023103.1 (#7515)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023102.1 to 3.2023103.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023102.1...v3.2023103.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-11-10 12:40:16 +01:00
dependabot[bot] 939631c94e
web: bump the sentry group in /web with 2 updates (#7516)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.79.0 to 7.80.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.79.0...7.80.0)

Updates `@sentry/tracing` from 7.79.0 to 7.80.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.79.0...7.80.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-10 12:40:05 +01:00
dependabot[bot] 467a149c06
web: bump the babel group in /web with 7 updates (#7517)
Bumps the babel group in /web with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.23.2` | `7.23.3` |
| [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) | `7.23.2` | `7.23.3` |
| [@babel/plugin-transform-private-methods](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-private-methods) | `7.22.5` | `7.23.3` |
| [@babel/plugin-transform-private-property-in-object](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-private-property-in-object) | `7.22.11` | `7.23.3` |
| [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) | `7.23.2` | `7.23.3` |
| [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.23.2` | `7.23.3` |
| [@babel/preset-typescript](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-typescript) | `7.23.2` | `7.23.3` |


Updates `@babel/core` from 7.23.2 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-core)

Updates `@babel/plugin-proposal-decorators` from 7.23.2 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-proposal-decorators)

Updates `@babel/plugin-transform-private-methods` from 7.22.5 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-private-methods)

Updates `@babel/plugin-transform-private-property-in-object` from 7.22.11 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-private-property-in-object)

Updates `@babel/plugin-transform-runtime` from 7.23.2 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-plugin-transform-runtime)

Updates `@babel/preset-env` from 7.23.2 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-preset-env)

Updates `@babel/preset-typescript` from 7.23.2 to 7.23.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.3/packages/babel-preset-typescript)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-proposal-decorators"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/plugin-transform-private-methods"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/plugin-transform-private-property-in-object"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: babel
- dependency-name: "@babel/plugin-transform-runtime"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
- dependency-name: "@babel/preset-typescript"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: babel
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-10 12:39:55 +01:00
Tana M Berry f62f720c55
website/blog:IPv6 blog (#7496)
* draft blog on IPv6

* tweak tags

* tweak tags more

* error message

* polishing

* marc edits

* spacing off

* spacing fixes

* rerun prettier

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
2023-11-09 16:01:27 -06:00
authentik-automation[bot] ba8fd9fcb2
web: bump API Client version (#7513)
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-11-09 18:37:57 +00:00
dependabot[bot] fdc323af62
web: bump the sentry group in /web with 2 updates (#7500)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.77.0 to 7.79.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.77.0...7.79.0)

Updates `@sentry/tracing` from 7.77.0 to 7.79.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.77.0...7.79.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 19:24:19 +01:00
dependabot[bot] 44bac0d67b
core: bump pytest-django from 4.6.0 to 4.7.0 (#7497)
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.6.0...v4.7.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  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-11-09 19:24:11 +01:00
dependabot[bot] 191514864e
core: bump black from 23.10.1 to 23.11.0 (#7498)
Bumps [black](https://github.com/psf/black) from 23.10.1 to 23.11.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.1...23.11.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  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-11-09 19:23:56 +01:00
dependabot[bot] 258a4d5283
core: bump ruff from 0.1.4 to 0.1.5 (#7499)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.4 to 0.1.5.
- [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.4...v0.1.5)

---
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-11-09 19:23:40 +01:00
dependabot[bot] 62a85fb888
core: bump golang.org/x/oauth2 from 0.13.0 to 0.14.0 (#7501)
Bumps [golang.org/x/oauth2](https://github.com/golang/oauth2) from 0.13.0 to 0.14.0.
- [Commits](https://github.com/golang/oauth2/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/oauth2
  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-11-09 19:23:31 +01:00
dependabot[bot] 7685320466
web: bump the wdio group in /tests/wdio with 3 updates (#7502)
Bumps the wdio group in /tests/wdio with 3 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner) and [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework).


Updates `@wdio/cli` from 8.21.0 to 8.22.1
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.22.1/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.21.0 to 8.22.1
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.22.1/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.21.0 to 8.22.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.22.0/packages/wdio-mocha-framework)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 19:23:23 +01:00
Jens Langhammer c30a2406a9
release: 2023.10.3 2023-11-09 19:20:28 +01:00
Jens L 9232042c55
ci: fix permissions for release pipeline to publish binaries (#7512)
ci: fix permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-09 19:15:13 +01:00
Marc 'risson' Schmitt d8b1a59dad website/docs: update release notes for 2023.10.3
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-09 18:43:00 +01:00
Jens L 1e05d38059
core: fix worker beat toggle inverted (#7508)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-09 18:33:41 +01:00
Marc 'risson' Schmitt d5871fef4e website/docs: update release notes for 2023.10.3
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-09 18:24:02 +01:00
Andrey 7f4fa70a41
website/docs: fix anchor link (#7492) 2023-11-08 18:57:00 +01:00
Jens Langhammer fa0c4d8410 consistent variable name
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-08 17:02:38 +01:00
Jens Langhammer aeb24889fd add more tooltips and add device authn/authz
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-08 17:02:38 +01:00
Jens Langhammer 8ac9042501 fix wrong color
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-08 17:02:38 +01:00
Marc 'risson' Schmitt 2d821a07c6 events: fix gdpr compliance always running
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-11-08 15:19:49 +01:00
Andrey 9680106b45
website/docs: Fix a small grammar issue (#7490) 2023-11-08 15:10:21 +01:00
dependabot[bot] 709358615c core: bump golang from 1.21.3-bookworm to 1.21.4-bookworm
Bumps golang from 1.21.3-bookworm to 1.21.4-bookworm.

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 11:13:24 +01:00
dependabot[bot] 0ad1b42706 web: bump pyright from 1.1.334 to 1.1.335 in /web
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.334 to 1.1.335.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.335/packages/pyright)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 11:13:14 +01:00
dependabot[bot] 2333e1f434 web: bump @types/grecaptcha from 3.0.6 to 3.0.7 in /web
Bumps [@types/grecaptcha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/grecaptcha) from 3.0.6 to 3.0.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/grecaptcha)

---
updated-dependencies:
- dependency-name: "@types/grecaptcha"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 11:12:52 +01:00
dependabot[bot] 4444db9e6d website: bump @types/react from 18.2.36 to 18.2.37 in /website
Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 18.2.36 to 18.2.37.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)

---
updated-dependencies:
- dependency-name: "@types/react"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 11:12:32 +01:00
dependabot[bot] c5d483a238 web: bump @formatjs/intl-listformat from 7.5.0 to 7.5.1 in /web
Bumps [@formatjs/intl-listformat](https://github.com/formatjs/formatjs) from 7.5.0 to 7.5.1.
- [Release notes](https://github.com/formatjs/formatjs/releases)
- [Commits](https://github.com/formatjs/formatjs/compare/@formatjs/intl-listformat@7.5.0...@formatjs/intl-listformat@7.5.1)

---
updated-dependencies:
- dependency-name: "@formatjs/intl-listformat"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 21:24:17 +01:00
Ken Sternberg cc1c66aa13
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.
2023-11-07 18:10:43 +00:00
Ken Sternberg 67d6c0e8af
web: rollback dependabot context (#7479)
* 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.
2023-11-07 16:03:07 +00:00
dependabot[bot] b9afac5008 web: bump @types/chart.js from 2.9.39 to 2.9.40 in /web
Bumps [@types/chart.js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chart.js) from 2.9.39 to 2.9.40.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chart.js)

---
updated-dependencies:
- dependency-name: "@types/chart.js"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 15:12:31 +01:00
François-Xavier Payet aadda1f314
website/integrations: add FreshRSS (#7301) 2023-11-07 14:28:38 +01:00
dependabot[bot] 293fa2e375 web: bump the eslint group in /web with 2 updates
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.9.1 to 6.10.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.10.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.9.1 to 6.10.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.10.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:09:12 +01:00
dependabot[bot] ddb1597501 core: bump uvicorn from 0.24.0 to 0.24.0.post1
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.24.0 to 0.24.0.post1.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.24.0...0.24.0.post1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:08:53 +01:00
dependabot[bot] 96f8e961ea web: bump the storybook group in /web with 5 updates
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.5.2` | `7.5.3` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.5.2` | `7.5.3` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.5.2` | `7.5.3` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.5.2` | `7.5.3` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.5.2` | `7.5.3` |


Updates `@storybook/addon-essentials` from 7.5.2 to 7.5.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.3/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.3/code/addons/essentials)

Updates `@storybook/addon-links` from 7.5.2 to 7.5.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.3/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.3/code/addons/links)

Updates `@storybook/web-components` from 7.5.2 to 7.5.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.3/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.3/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.5.2 to 7.5.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.3/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.3/code/frameworks/web-components-vite)

Updates `storybook` from 7.5.2 to 7.5.3
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.3/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.3/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:08:41 +01:00
dependabot[bot] f699dba2ae web: bump the eslint group in /tests/wdio with 2 updates
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.9.1 to 6.10.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.10.0/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.9.1 to 6.10.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.10.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:08:31 +01:00
dependabot[bot] 250e8ee4a1 web: bump @types/codemirror from 5.60.12 to 5.60.13 in /web
Bumps [@types/codemirror](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/codemirror) from 5.60.12 to 5.60.13.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/codemirror)

---
updated-dependencies:
- dependency-name: "@types/codemirror"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:08:12 +01:00
dependabot[bot] ce47755049 web: bump mermaid from 10.6.0 to 10.6.1 in /web
Bumps [mermaid](https://github.com/mermaid-js/mermaid) from 10.6.0 to 10.6.1.
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.6.0...v10.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-07 12:07:48 +01:00
transifex-integration[bot] 8125a790a9
translate: Updates for file web/xliff/en.xlf in fr (#7461)
Translate web/xliff/en.xlf in fr

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-06 19:12:21 +00:00
transifex-integration[bot] b7e653db6a
translate: Updates for file web/xliff/en.xlf in zh-Hans (#7459)
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-11-06 10:54:47 -08:00
transifex-integration[bot] 74958693a1
translate: Updates for file web/xliff/en.xlf in zh_CN (#7458)
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-11-06 10:52:11 -08:00
dependabot[bot] cadc311703
web: bump @lit/localize-tools from 0.7.0 to 0.7.1 in /web (#7369)
Bumps [@lit/localize-tools](https://github.com/lit/lit/tree/HEAD/packages/localize-tools) from 0.7.0 to 0.7.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/localize-tools/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit/localize-tools@0.7.1/packages/localize-tools)

---
updated-dependencies:
- dependency-name: "@lit/localize-tools"
  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-11-06 10:39:35 -08:00
dependabot[bot] 924f3c9075
web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web (#7368)
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)

---
updated-dependencies:
- dependency-name: "@lit-labs/context"
  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-11-06 10:38:37 -08:00
Jens L a7933c84c1
web/flows: attempt to fix bitwareden android compatibility (#7455)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-06 17:50:31 +01:00
Jens L fe1a06ebf2
sources/oauth: fix patreon (#7454)
* web/admin: add note for potentially confusing consumer key/secret

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

* sources/oauth: fix patreon default scopes

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-06 15:40:43 +01:00
dependabot[bot] 823e7dbe1a
website: bump the docusaurus group in /website with 3 updates (#7400)
* website: bump the docusaurus group in /website with 3 updates

Bumps the docusaurus group in /website with 3 updates: [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects), [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) and [@docusaurus/theme-mermaid](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-theme-mermaid).


Updates `@docusaurus/plugin-client-redirects` from 2.4.3 to 3.0.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.0.0/packages/docusaurus-plugin-client-redirects)

Updates `@docusaurus/preset-classic` from 2.4.3 to 3.0.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.0.0/packages/docusaurus-preset-classic)

Updates `@docusaurus/theme-mermaid` from 2.4.3 to 3.0.0
- [Release notes](https://github.com/facebook/docusaurus/releases)
- [Changelog](https://github.com/facebook/docusaurus/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/docusaurus/commits/v3.0.0/packages/docusaurus-theme-mermaid)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: docusaurus
- dependency-name: "@docusaurus/preset-classic"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: docusaurus
- dependency-name: "@docusaurus/theme-mermaid"
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: docusaurus
...

Signed-off-by: dependabot[bot] <support@github.com>

* update

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

* migrate docusaurus config to ts

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

* fix docs-only build

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

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-11-06 15:12:23 +01:00
macmoritz 90b8217eb2
web/admin: fix chart label on dashboard user page (#7434)
* web: fix chart label on dashboard user page

* update translation files

* fix prettier lint
2023-11-06 13:51:41 +01:00
dependabot[bot] c897271756
core: bump github.com/gorilla/sessions from 1.2.1 to 1.2.2 (#7446)
Bumps [github.com/gorilla/sessions](https://github.com/gorilla/sessions) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/gorilla/sessions/releases)
- [Commits](https://github.com/gorilla/sessions/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/sessions
  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-11-06 12:28:18 +01:00
dependabot[bot] d1c9d41954
core: bump github.com/gorilla/mux from 1.8.0 to 1.8.1 (#7443)
Bumps [github.com/gorilla/mux](https://github.com/gorilla/mux) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/gorilla/mux/releases)
- [Commits](https://github.com/gorilla/mux/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/gorilla/mux
  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-11-06 11:28:33 +01:00
dependabot[bot] 1906a10b1a
core: bump github.com/spf13/cobra from 1.7.0 to 1.8.0 (#7442)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  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-11-06 11:18:37 +01:00
dependabot[bot] a03cc57473
core: bump github.com/gorilla/websocket from 1.5.0 to 1.5.1 (#7445)
Bumps [github.com/gorilla/websocket](https://github.com/gorilla/websocket) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/gorilla/websocket/releases)
- [Commits](https://github.com/gorilla/websocket/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: github.com/gorilla/websocket
  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-11-06 11:18:21 +01:00
dependabot[bot] e00799b314
core: bump golang.org/x/sync from 0.4.0 to 0.5.0 (#7441)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.4.0 to 0.5.0.
- [Commits](https://github.com/golang/sync/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  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-11-06 11:18:11 +01:00
dependabot[bot] faa5ce3e83
core: bump github.com/gorilla/securecookie from 1.1.1 to 1.1.2 (#7440)
Bumps [github.com/gorilla/securecookie](https://github.com/gorilla/securecookie) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/gorilla/securecookie/releases)
- [Commits](https://github.com/gorilla/securecookie/compare/v1.1.1...v1.1.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/securecookie
  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-11-06 11:17:59 +01:00
dependabot[bot] 937d025ef6
core: bump github.com/gorilla/handlers from 1.5.1 to 1.5.2 (#7444)
Bumps [github.com/gorilla/handlers](https://github.com/gorilla/handlers) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/gorilla/handlers/releases)
- [Commits](https://github.com/gorilla/handlers/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/handlers
  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-11-06 11:17:47 +01:00
dependabot[bot] a748a61cd6
web: bump rollup from 4.2.0 to 4.3.0 in /web (#7448)
Bumps [rollup](https://github.com/rollup/rollup) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  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-11-06 11:17:37 +01:00
dependabot[bot] b24420598c
web: bump the eslint group in /web with 2 updates (#7447)
Bumps the eslint group in /web with 2 updates: [eslint](https://github.com/eslint/eslint) and [eslint-plugin-sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs).


Updates `eslint` from 8.52.0 to 8.53.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.52.0...v8.53.0)

Updates `eslint-plugin-sonarjs` from 0.22.0 to 0.23.0
- [Release notes](https://github.com/SonarSource/eslint-plugin-sonarjs/releases)
- [Commits](https://github.com/SonarSource/eslint-plugin-sonarjs/compare/0.22.0...0.23.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint-plugin-sonarjs
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 11:17:27 +01:00
dependabot[bot] b005ec7684
core: bump uvicorn from 0.23.2 to 0.24.0 (#7450)
Bumps [uvicorn](https://github.com/encode/uvicorn) from 0.23.2 to 0.24.0.
- [Release notes](https://github.com/encode/uvicorn/releases)
- [Changelog](https://github.com/encode/uvicorn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/encode/uvicorn/compare/0.23.2...0.24.0)

---
updated-dependencies:
- dependency-name: uvicorn
  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-11-06 11:16:07 +01:00
dependabot[bot] 6f6ee29738
core: bump selenium from 4.15.1 to 4.15.2 (#7449)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.15.1 to 4.15.2.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits)

---
updated-dependencies:
- dependency-name: selenium
  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-11-06 11:15:58 +01:00
dependabot[bot] ff3fef6d09
core: bump ruff from 0.1.3 to 0.1.4 (#7451)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.1.3 to 0.1.4.
- [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.3...v0.1.4)

---
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-11-06 11:15:45 +01:00
dependabot[bot] 515958157c
web: bump the eslint group in /tests/wdio with 2 updates (#7452)
Bumps the eslint group in /tests/wdio with 2 updates: [eslint](https://github.com/eslint/eslint) and [eslint-plugin-sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs).


Updates `eslint` from 8.52.0 to 8.53.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.52.0...v8.53.0)

Updates `eslint-plugin-sonarjs` from 0.22.0 to 0.23.0
- [Release notes](https://github.com/SonarSource/eslint-plugin-sonarjs/releases)
- [Commits](https://github.com/SonarSource/eslint-plugin-sonarjs/compare/0.22.0...0.23.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint-plugin-sonarjs
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 11:15:33 +01:00
Jens L dd4e9030b4
providers/proxy: fix closed redis client (#7385)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-03 15:19:21 +01:00
Jens L f94670cad7
ci: explicitly give write permissions to packages (#7428)
* ci: explicitly give write permissions to packages

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

* run full CI on cherry-picks

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-03 13:16:15 +01:00
dependabot[bot] b4dd74f2ff
core: bump selenium from 4.15.0 to 4.15.1 (#7422)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.15.0 to 4.15.1.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/commits)

---
updated-dependencies:
- dependency-name: selenium
  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-11-03 11:38:10 +01:00
dependabot[bot] 9a2b548bf6
web: bump yaml from 2.3.3 to 2.3.4 in /web (#7420)
Bumps [yaml](https://github.com/eemeli/yaml) from 2.3.3 to 2.3.4.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.3.3...v2.3.4)

---
updated-dependencies:
- dependency-name: yaml
  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-11-03 11:38:01 +01:00
dependabot[bot] d6e3de4f48
core: bump sentry-sdk from 1.33.1 to 1.34.0 (#7421)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.33.1 to 1.34.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.33.1...1.34.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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-11-03 11:37:49 +01:00
dependabot[bot] 30ccaaf97c
web: bump the wdio group in /tests/wdio with 4 updates (#7423)
Bumps the wdio group in /tests/wdio with 4 updates: [@wdio/cli](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-cli), [@wdio/local-runner](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-local-runner), [@wdio/mocha-framework](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-mocha-framework) and [@wdio/spec-reporter](https://github.com/webdriverio/webdriverio/tree/HEAD/packages/wdio-spec-reporter).


Updates `@wdio/cli` from 8.20.5 to 8.21.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.21.0/packages/wdio-cli)

Updates `@wdio/local-runner` from 8.20.5 to 8.21.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.21.0/packages/wdio-local-runner)

Updates `@wdio/mocha-framework` from 8.20.3 to 8.21.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.21.0/packages/wdio-mocha-framework)

Updates `@wdio/spec-reporter` from 8.20.0 to 8.21.0
- [Release notes](https://github.com/webdriverio/webdriverio/releases)
- [Changelog](https://github.com/webdriverio/webdriverio/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webdriverio/webdriverio/commits/v8.21.0/packages/wdio-spec-reporter)

---
updated-dependencies:
- dependency-name: "@wdio/cli"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/local-runner"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/mocha-framework"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
- dependency-name: "@wdio/spec-reporter"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: wdio
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-03 11:37:36 +01:00
Jens L 3d9f7ee27e
providers/oauth2: set auth_via for token and other endpoints (#7417)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-11-03 00:11:30 +01:00
Tana M Berry 211dcf3272
website/blog: draft for happy bday blog (#7408)
* fights with image

* edits on PR

* further edits

* Optimised images with calibre/image-actions

* spelling

* more edits

---------

Co-authored-by: Tana Berry <tana@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-11-02 11:55:56 -05:00
transifex-integration[bot] 1d0b8a065b
translate: Updates for file web/xliff/en.xlf in fr (#7416)
Translate web/xliff/en.xlf in fr

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

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2023-11-02 14:03:14 +00:00
dependabot[bot] 7f82b555c8
website: bump react-tooltip from 5.21.6 to 5.22.0 in /website (#7412)
Bumps [react-tooltip](https://github.com/ReactTooltip/react-tooltip) from 5.21.6 to 5.22.0.
- [Release notes](https://github.com/ReactTooltip/react-tooltip/releases)
- [Changelog](https://github.com/ReactTooltip/react-tooltip/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ReactTooltip/react-tooltip/compare/v5.21.6...v5.22.0)

---
updated-dependencies:
- dependency-name: react-tooltip
  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-11-02 11:18:56 +01:00
dependabot[bot] f7aec3cf28
core: bump selenium from 4.14.0 to 4.15.0 (#7411)
Bumps [selenium](https://github.com/SeleniumHQ/Selenium) from 4.14.0 to 4.15.0.
- [Release notes](https://github.com/SeleniumHQ/Selenium/releases)
- [Commits](https://github.com/SeleniumHQ/Selenium/compare/selenium-4.14.0...selenium-4.15.0)

---
updated-dependencies:
- dependency-name: selenium
  dependency-type: direct:development
  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-11-02 11:18:44 +01:00
dependabot[bot] c6c133f67d
core: bump django from 4.2.6 to 4.2.7 (#7413)
Bumps [django](https://github.com/django/django) from 4.2.6 to 4.2.7.
- [Commits](https://github.com/django/django/compare/4.2.6...4.2.7)

---
updated-dependencies:
- dependency-name: django
  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-11-02 11:18:38 +01:00
dependabot[bot] 73db23f21f
web: bump the eslint group in /web with 1 update (#7414)
Bumps the eslint group in /web with 1 update: [eslint-plugin-sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs).

- [Release notes](https://github.com/SonarSource/eslint-plugin-sonarjs/releases)
- [Commits](https://github.com/SonarSource/eslint-plugin-sonarjs/compare/0.21.0...0.22.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-sonarjs
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 11:18:32 +01:00
dependabot[bot] 4744f5c6c6
web: bump the eslint group in /tests/wdio with 1 update (#7415)
Bumps the eslint group in /tests/wdio with 1 update: [eslint-plugin-sonarjs](https://github.com/SonarSource/eslint-plugin-sonarjs).

- [Release notes](https://github.com/SonarSource/eslint-plugin-sonarjs/releases)
- [Commits](https://github.com/SonarSource/eslint-plugin-sonarjs/compare/0.21.0...0.22.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-sonarjs
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-02 11:18:24 +01:00
Philipp Kolberg e92bda2659
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
2023-11-01 18:41:48 +01:00
gc4g40u6 a10392efcc
website/integrations: argocd: add missing url in ArgoCD configuration (#7404) 2023-11-01 11:52:44 +00:00
dependabot[bot] e52f13afae
core: bump sentry-sdk from 1.32.0 to 1.33.1 (#7397)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 1.32.0 to 1.33.1.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/1.32.0...1.33.1)

---
updated-dependencies:
- dependency-name: sentry-sdk
  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-11-01 11:18:24 +01:00
dependabot[bot] 07c50a43ae
core: bump webauthn from 1.11.0 to 1.11.1 (#7399)
Bumps [webauthn](https://github.com/duo-labs/py_webauthn) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/duo-labs/py_webauthn/releases)
- [Changelog](https://github.com/duo-labs/py_webauthn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/duo-labs/py_webauthn/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: webauthn
  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-11-01 11:18:14 +01:00
dependabot[bot] 0cd2f68bf3
core: bump github.com/redis/go-redis/v9 from 9.2.1 to 9.3.0 (#7396)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.2.1 to 9.3.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.2.1...v9.3.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  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-11-01 11:17:41 +01:00
dependabot[bot] 4ef10f1cec
core: bump twisted from 23.8.0 to 23.10.0 (#7398)
Bumps [twisted](https://github.com/twisted/twisted) from 23.8.0 to 23.10.0.
- [Release notes](https://github.com/twisted/twisted/releases)
- [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst)
- [Commits](https://github.com/twisted/twisted/compare/twisted-23.8.0...twisted-23.10.0)

---
updated-dependencies:
- dependency-name: twisted
  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-11-01 11:17:32 +01:00
dependabot[bot] 43151c09e2
web: bump the sentry group in /web with 2 updates (#7401)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.76.0 to 7.77.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.76.0...7.77.0)

Updates `@sentry/tracing` from 7.76.0 to 7.77.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.76.0...7.77.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-01 11:17:20 +01:00
dependabot[bot] 871b5f3246
web: bump pyright from 1.1.333 to 1.1.334 in /web (#7402)
Bumps [pyright](https://github.com/Microsoft/pyright/tree/HEAD/packages/pyright) from 1.1.333 to 1.1.334.
- [Release notes](https://github.com/Microsoft/pyright/releases)
- [Commits](https://github.com/Microsoft/pyright/commits/1.1.334/packages/pyright)

---
updated-dependencies:
- dependency-name: pyright
  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-11-01 11:17:12 +01:00
dependabot[bot] ed66bdaec4
web: bump rollup from 4.1.5 to 4.2.0 in /web (#7403)
Bumps [rollup](https://github.com/rollup/rollup) from 4.1.5 to 4.2.0.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.1.5...v4.2.0)

---
updated-dependencies:
- dependency-name: rollup
  dependency-type: direct:development
  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-11-01 11:17:03 +01:00
dependabot[bot] 345022f1aa
core: bump pytest-django from 4.5.2 to 4.6.0 (#7387)
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.5.2 to 4.6.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.5.2...v4.6.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  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-31 11:21:21 +01:00
dependabot[bot] f296862d3c
web: bump the eslint group in /tests/wdio with 2 updates (#7388)
Bumps the eslint group in /tests/wdio with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.9.0 to 6.9.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.9.0 to 6.9.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 11:20:51 +01:00
dependabot[bot] 5aca310d10
web: bump the sentry group in /web with 2 updates (#7366)
Bumps the sentry group in /web with 2 updates: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and [@sentry/tracing](https://github.com/getsentry/sentry-javascript).


Updates `@sentry/browser` from 7.75.1 to 7.76.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.75.1...7.76.0)

Updates `@sentry/tracing` from 7.75.1 to 7.76.0
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.75.1...7.76.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
- dependency-name: "@sentry/tracing"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 11:20:33 +01:00
dependabot[bot] 7dab5dc03f
web: bump the eslint group in /web with 2 updates (#7389)
Bumps the eslint group in /web with 2 updates: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) and [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser).


Updates `@typescript-eslint/eslint-plugin` from 6.9.0 to 6.9.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 6.9.0 to 6.9.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.9.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 11:20:25 +01:00
dependabot[bot] 2d6e0984d1
web: bump core-js from 3.33.1 to 3.33.2 in /web (#7390)
Bumps [core-js](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js) from 3.33.1 to 3.33.2.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/commits/v3.33.2/packages/core-js)

---
updated-dependencies:
- dependency-name: core-js
  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-31 11:20:17 +01:00
Jens L 028c7af00f
stages/email: fix duplicate querystring encoding (#7386)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-31 00:27:34 +01:00
Ken Sternberg 6df83e4259
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.
2023-10-30 15:35:37 -07:00
dependabot[bot] afdca418e1
web: bump rollup from 4.1.4 to 4.1.5 in /web (#7370)
Bumps [rollup](https://github.com/rollup/rollup) from 4.1.4 to 4.1.5.
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.1.4...v4.1.5)

---
updated-dependencies:
- dependency-name: rollup
  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-30 13:35:26 +01:00
senare d8728c1749
website/integrations: add SonarQube (#7167)
Co-authored-by: Manfred Nilsson <manfred.nilsson@synkzone.com>
2023-10-30 13:31:29 +01:00
dependabot[bot] e5afabb221
web: bump the storybook group in /web with 5 updates (#7382)
Bumps the storybook group in /web with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `7.5.1` | `7.5.2` |
| [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `7.5.1` | `7.5.2` |
| [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) | `7.5.1` | `7.5.2` |
| [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite) | `7.5.1` | `7.5.2` |
| [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `7.5.1` | `7.5.2` |


Updates `@storybook/addon-essentials` from 7.5.1 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.2/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/addons/essentials)

Updates `@storybook/addon-links` from 7.5.1 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.2/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/addons/links)

Updates `@storybook/web-components` from 7.5.1 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.2/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 7.5.1 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.2/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/frameworks/web-components-vite)

Updates `storybook` from 7.5.1 to 7.5.2
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v7.5.2/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v7.5.2/code/lib/cli)

---
updated-dependencies:
- dependency-name: "@storybook/addon-essentials"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
- dependency-name: storybook
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-30 13:13:59 +01:00
dependabot[bot] a0a6ee0769
core: bump goauthentik.io/api/v3 from 3.2023101.1 to 3.2023102.1 (#7378)
Bumps [goauthentik.io/api/v3](https://github.com/goauthentik/client-go) from 3.2023101.1 to 3.2023102.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v3.2023101.1...v3.2023102.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-30 12:54:35 +01:00
dependabot[bot] a65bb0b29f
web: bump ts-lit-plugin from 2.0.0 to 2.0.1 in /web (#7379)
Bumps [ts-lit-plugin](https://github.com/runem/lit-analyzer) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/runem/lit-analyzer/releases)
- [Changelog](https://github.com/runem/lit-analyzer/blob/master/CHANGELOG.md)
- [Commits](https://github.com/runem/lit-analyzer/commits)

---
updated-dependencies:
- dependency-name: ts-lit-plugin
  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-30 12:54:28 +01:00
dependabot[bot] 3df7b5504e
web: bump @rollup/plugin-replace from 5.0.4 to 5.0.5 in /web (#7380)
Bumps [@rollup/plugin-replace](https://github.com/rollup/plugins/tree/HEAD/packages/replace) from 5.0.4 to 5.0.5.
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/replace/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/inject-v5.0.5/packages/replace)

---
updated-dependencies:
- dependency-name: "@rollup/plugin-replace"
  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-30 12:54:19 +01:00
authentik-automation[bot] 99f44ea805
web: bump API Client version (#7365) 2023-10-28 23:08:24 +02:00
Jens Langhammer 97ccc84796
Merge branch 'version-2023.10' 2023-10-28 22:52:24 +02:00
Jens Langhammer a43b2fb17c
website/docs: add 2023.8.4 release notes
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-28 22:04:46 +02:00
200 changed files with 22810 additions and 19250 deletions

View file

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

View file

@ -11,6 +11,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
env: env:
POSTGRES_DB: authentik POSTGRES_DB: authentik
@ -185,6 +186,9 @@ jobs:
build: build:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -235,6 +239,9 @@ jobs:
build-arm64: build-arm64:
needs: ci-core-mark needs: ci-core-mark
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View file

@ -9,6 +9,7 @@ on:
pull_request: pull_request:
branches: branches:
- main - main
- version-*
jobs: jobs:
lint-golint: lint-golint:
@ -65,6 +66,9 @@ jobs:
- ldap - ldap
- radius - radius
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View file

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

View file

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

View file

@ -6,6 +6,7 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
# Needed to be able to push to the next branch
contents: write contents: write
jobs: jobs:

View file

@ -7,6 +7,9 @@ on:
jobs: jobs:
build-server: build-server:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
@ -52,6 +55,9 @@ jobs:
VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }} VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
build-outpost: build-outpost:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload contianer images to ghcr.io
packages: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -106,6 +112,9 @@ jobs:
build-outpost-binary: build-outpost-binary:
timeout-minutes: 120 timeout-minutes: 120
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
# Needed to upload binaries to the release
contents: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:

View file

@ -30,7 +30,7 @@ jobs:
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }} private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
- name: Extract version number - name: Extract version number
id: get_version id: get_version
uses: actions/github-script@v6 uses: actions/github-script@v7
with: with:
github-token: ${{ steps.generate_token.outputs.token }} github-token: ${{ steps.generate_token.outputs.token }}
script: | script: |

View file

@ -6,8 +6,8 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
# Needed to update issues and PRs
issues: write issues: write
pull-requests: write
jobs: jobs:
stale: stale:

View file

@ -7,7 +7,8 @@ on:
paths: paths:
- "!**" - "!**"
- "locale/**" - "locale/**"
- "web/src/locales/**" - "!locale/en/**"
- "web/xliff/**"
jobs: jobs:
post-comment: post-comment:

View file

@ -35,7 +35,14 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build RUN npm run build
# Stage 3: Build go proxy # Stage 3: Build go proxy
FROM docker.io/golang:1.21.3-bookworm AS go-builder FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS go-builder
ARG TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
ARG GOOS=$TARGETOS
ARG GOARCH=$TARGETARCH
WORKDIR /go/src/goauthentik.io WORKDIR /go/src/goauthentik.io
@ -57,10 +64,10 @@ ENV CGO_ENABLED=0
RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \ --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 # 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_EDITION_IDS="GeoLite2-City"
ENV GEOIPUPDATE_VERBOSE="true" ENV GEOIPUPDATE_VERBOSE="true"

View file

@ -110,6 +110,8 @@ gen-diff: ## (Release) generate the changelog diff between the current schema a
--markdown /local/diff.md \ --markdown /local/diff.md \
/local/old_schema.yml /local/schema.yml /local/old_schema.yml /local/schema.yml
rm old_schema.yml rm old_schema.yml
sed -i 's/{/&#123;/g' diff.md
sed -i 's/}/&#125;/g' diff.md
npx prettier --write diff.md npx prettier --write diff.md
gen-clean: gen-clean:

View file

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

View file

@ -13,6 +13,8 @@ from rest_framework.settings import api_settings
from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA from authentik.api.pagination import PAGINATION_COMPONENT_NAME, PAGINATION_SCHEMA
from authentik.api.apps import AuthentikAPIConfig
def build_standard_type(obj, **kwargs): def build_standard_type(obj, **kwargs):
"""Build a basic type with optional add owns.""" """Build a basic type with optional add owns."""
@ -100,3 +102,12 @@ def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs):
comp = result["components"]["schemas"][component] comp = result["components"]["schemas"][component]
comp["additionalProperties"] = {} comp["additionalProperties"] = {}
return result return result
def preprocess_schema_exclude_non_api(endpoints, **kwargs):
"""Filter out all API Views which are not mounted under /api"""
return [
(path, path_regex, method, callback)
for path, path_regex, method, callback in endpoints
if path.startswith("/" + AuthentikAPIConfig.mountpoint)
]

View file

@ -93,10 +93,10 @@ class ConfigView(APIView):
"traces_sample_rate": float(CONFIG.get("error_reporting.sample_rate", 0.4)), "traces_sample_rate": float(CONFIG.get("error_reporting.sample_rate", 0.4)),
}, },
"capabilities": self.get_capabilities(), "capabilities": self.get_capabilities(),
"cache_timeout": CONFIG.get_int("redis.cache_timeout"), "cache_timeout": CONFIG.get_int("cache.timeout"),
"cache_timeout_flows": CONFIG.get_int("redis.cache_timeout_flows"), "cache_timeout_flows": CONFIG.get_int("cache.timeout_flows"),
"cache_timeout_policies": CONFIG.get_int("redis.cache_timeout_policies"), "cache_timeout_policies": CONFIG.get_int("cache.timeout_policies"),
"cache_timeout_reputation": CONFIG.get_int("redis.cache_timeout_reputation"), "cache_timeout_reputation": CONFIG.get_int("cache.timeout_reputation"),
} }
) )

View file

@ -17,9 +17,15 @@ class Command(BaseCommand):
"""Run worker""" """Run worker"""
def add_arguments(self, parser): 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): def handle(self, **options):
LOGGER.debug("Celery options", **options)
close_old_connections() close_old_connections()
if CONFIG.get_bool("remote_debug"): if CONFIG.get_bool("remote_debug"):
import debugpy import debugpy

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.models import Stage
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN 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.models import Invitation
from authentik.stages.invitation.signals import invitation_used from authentik.stages.invitation.signals import invitation_used
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS 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) @receiver(pre_delete, sender=User)
def event_user_pre_delete_cleanup(sender, instance: User, **_): def event_user_pre_delete_cleanup(sender, instance: User, **_):
"""If gdpr_compliance is enabled, remove all the user's events""" """If gdpr_compliance is enabled, remove all the user's events"""
if CONFIG.get_bool("gdpr_compliance", True):
gdpr_cleanup.delay(instance.pk) gdpr_cleanup.delay(instance.pk)

View file

@ -153,6 +153,12 @@ def sanitize_item(value: Any) -> Any:
return value.isoformat() return value.isoformat()
if isinstance(value, timedelta): if isinstance(value, timedelta):
return str(value.total_seconds()) return str(value.total_seconds())
if callable(value):
return {
"type": "callable",
"name": value.__name__,
"module": value.__module__,
}
return value return value

View file

@ -33,7 +33,7 @@ PLAN_CONTEXT_SOURCE = "source"
# Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan # Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan
# was restored. # was restored.
PLAN_CONTEXT_IS_RESTORED = "is_restored" PLAN_CONTEXT_IS_RESTORED = "is_restored"
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_flows") CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_flows")
CACHE_PREFIX = "goauthentik.io/flows/planner/" CACHE_PREFIX = "goauthentik.io/flows/planner/"

View file

@ -1,4 +1,6 @@
"""authentik core config loader""" """authentik core config loader"""
import base64
import json
import os import os
from collections.abc import Mapping from collections.abc import Mapping
from contextlib import contextmanager from contextlib import contextmanager
@ -22,6 +24,25 @@ SEARCH_PATHS = ["authentik/lib/default.yml", "/etc/authentik/config.yml", ""] +
ENV_PREFIX = "AUTHENTIK" ENV_PREFIX = "AUTHENTIK"
ENVIRONMENT = os.getenv(f"{ENV_PREFIX}_ENV", "local") ENVIRONMENT = os.getenv(f"{ENV_PREFIX}_ENV", "local")
REDIS_ENV_KEYS = [
f"{ENV_PREFIX}_REDIS__HOST",
f"{ENV_PREFIX}_REDIS__PORT",
f"{ENV_PREFIX}_REDIS__DB",
f"{ENV_PREFIX}_REDIS__USERNAME",
f"{ENV_PREFIX}_REDIS__PASSWORD",
f"{ENV_PREFIX}_REDIS__TLS",
f"{ENV_PREFIX}_REDIS__TLS_REQS",
]
DEPRECATIONS = {
"redis.broker_url": "broker.url",
"redis.broker_transport_options": "broker.transport_options",
"redis.cache_timeout": "cache.timeout",
"redis.cache_timeout_flows": "cache.timeout_flows",
"redis.cache_timeout_policies": "cache.timeout_policies",
"redis.cache_timeout_reputation": "cache.timeout_reputation",
}
def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any: def get_path_from_dict(root: dict, path: str, sep=".", default=None) -> Any:
"""Recursively walk through `root`, checking each part of `path` separated by `sep`. """Recursively walk through `root`, checking each part of `path` separated by `sep`.
@ -81,6 +102,10 @@ class AttrEncoder(JSONEncoder):
return super().default(o) return super().default(o)
class UNSET:
"""Used to test whether configuration key has not been set."""
class ConfigLoader: class ConfigLoader:
"""Search through SEARCH_PATHS and load configuration. Environment variables starting with """Search through SEARCH_PATHS and load configuration. Environment variables starting with
`ENV_PREFIX` are also applied. `ENV_PREFIX` are also applied.
@ -113,6 +138,40 @@ class ConfigLoader:
self.update_from_file(env_file) self.update_from_file(env_file)
self.update_from_env() self.update_from_env()
self.update(self.__config, kwargs) self.update(self.__config, kwargs)
self.check_deprecations()
def check_deprecations(self):
"""Warn if any deprecated configuration options are used"""
def _pop_deprecated_key(current_obj, dot_parts, index):
"""Recursive function to remove deprecated keys in configuration"""
dot_part = dot_parts[index]
if index == len(dot_parts) - 1:
return current_obj.pop(dot_part)
value = _pop_deprecated_key(current_obj[dot_part], dot_parts, index + 1)
if not current_obj[dot_part]:
current_obj.pop(dot_part)
return value
for deprecation, replacement in DEPRECATIONS.items():
if self.get(deprecation, default=UNSET) is not UNSET:
message = (
f"'{deprecation}' has been deprecated in favor of '{replacement}'! "
+ "Please update your configuration."
)
self.log(
"warning",
message,
)
try:
from authentik.events.models import Event, EventAction
Event.new(EventAction.CONFIGURATION_ERROR, message=message).save()
except ImportError:
continue
deprecated_attr = _pop_deprecated_key(self.__config, deprecation.split("."), 0)
self.set(replacement, deprecated_attr.value)
def log(self, level: str, message: str, **kwargs): def log(self, level: str, message: str, **kwargs):
"""Custom Log method, we want to ensure ConfigLoader always logs JSON even when """Custom Log method, we want to ensure ConfigLoader always logs JSON even when
@ -180,6 +239,10 @@ class ConfigLoader:
error=str(exc), error=str(exc),
) )
def update_from_dict(self, update: dict):
"""Update config from dict"""
self.__config.update(update)
def update_from_env(self): def update_from_env(self):
"""Check environment variables""" """Check environment variables"""
outer = {} outer = {}
@ -188,19 +251,13 @@ class ConfigLoader:
if not key.startswith(ENV_PREFIX): if not key.startswith(ENV_PREFIX):
continue continue
relative_key = key.replace(f"{ENV_PREFIX}_", "", 1).replace("__", ".").lower() relative_key = key.replace(f"{ENV_PREFIX}_", "", 1).replace("__", ".").lower()
# Recursively convert path from a.b.c into outer[a][b][c]
current_obj = outer
dot_parts = relative_key.split(".")
for dot_part in dot_parts[:-1]:
if dot_part not in current_obj:
current_obj[dot_part] = {}
current_obj = current_obj[dot_part]
# Check if the value is json, and try to load it # Check if the value is json, and try to load it
try: try:
value = loads(value) value = loads(value)
except JSONDecodeError: except JSONDecodeError:
pass pass
current_obj[dot_parts[-1]] = Attr(value, Attr.Source.ENV, key) attr_value = Attr(value, Attr.Source.ENV, relative_key)
set_path_in_dict(outer, relative_key, attr_value)
idx += 1 idx += 1
if idx > 0: if idx > 0:
self.log("debug", "Loaded environment variables", count=idx) self.log("debug", "Loaded environment variables", count=idx)
@ -241,6 +298,23 @@ class ConfigLoader:
"""Wrapper for get that converts value into boolean""" """Wrapper for get that converts value into boolean"""
return str(self.get(path, default)).lower() == "true" return str(self.get(path, default)).lower() == "true"
def get_dict_from_b64_json(self, path: str, default=None) -> dict:
"""Wrapper for get that converts value from Base64 encoded string into dictionary"""
config_value = self.get(path)
if config_value is None:
return {}
try:
b64decoded_str = base64.b64decode(config_value).decode("utf-8")
b64decoded_str = b64decoded_str.strip().lstrip("{").rstrip("}")
b64decoded_str = "{" + b64decoded_str + "}"
return json.loads(b64decoded_str)
except (JSONDecodeError, TypeError, ValueError) as exc:
self.log(
"warning",
f"Ignored invalid configuration for '{path}' due to exception: {str(exc)}",
)
return default if isinstance(default, dict) else {}
def set(self, path: str, value: Any, sep="."): def set(self, path: str, value: Any, sep="."):
"""Set value using same syntax as get()""" """Set value using same syntax as get()"""
set_path_in_dict(self.raw, path, Attr(value), sep=sep) set_path_in_dict(self.raw, path, Attr(value), sep=sep)

View file

@ -28,14 +28,28 @@ listen:
redis: redis:
host: localhost host: localhost
port: 6379 port: 6379
db: 0
username: ""
password: "" password: ""
tls: false tls: false
tls_reqs: "none" tls_reqs: "none"
db: 0
cache_timeout: 300 # broker:
cache_timeout_flows: 300 # url: ""
cache_timeout_policies: 300 # transport_options: ""
cache_timeout_reputation: 300
cache:
# url: ""
timeout: 300
timeout_flows: 300
timeout_policies: 300
timeout_reputation: 300
# channel:
# url: ""
# result_backend:
# url: ""
paths: paths:
media: ./media media: ./media

View file

@ -1,20 +1,32 @@
"""Test config loader""" """Test config loader"""
import base64
from json import dumps
from os import chmod, environ, unlink, write from os import chmod, environ, unlink, write
from tempfile import mkstemp from tempfile import mkstemp
from unittest import mock
from django.conf import ImproperlyConfigured from django.conf import ImproperlyConfigured
from django.test import TestCase from django.test import TestCase
from authentik.lib.config import ENV_PREFIX, ConfigLoader from authentik.lib.config import ENV_PREFIX, UNSET, Attr, AttrEncoder, ConfigLoader
class TestConfig(TestCase): class TestConfig(TestCase):
"""Test config loader""" """Test config loader"""
check_deprecations_env_vars = {
ENV_PREFIX + "_REDIS__BROKER_URL": "redis://myredis:8327/43",
ENV_PREFIX + "_REDIS__BROKER_TRANSPORT_OPTIONS": "bWFzdGVybmFtZT1teW1hc3Rlcg==",
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT": "124s",
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_FLOWS": "32m",
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_POLICIES": "3920ns",
ENV_PREFIX + "_REDIS__CACHE_TIMEOUT_REPUTATION": "298382us",
}
@mock.patch.dict(environ, {ENV_PREFIX + "_test__test": "bar"})
def test_env(self): def test_env(self):
"""Test simple instance""" """Test simple instance"""
config = ConfigLoader() config = ConfigLoader()
environ[ENV_PREFIX + "_test__test"] = "bar"
config.update_from_env() config.update_from_env()
self.assertEqual(config.get("test.test"), "bar") self.assertEqual(config.get("test.test"), "bar")
@ -27,12 +39,20 @@ class TestConfig(TestCase):
self.assertEqual(config.get("foo.bar"), "baz") self.assertEqual(config.get("foo.bar"), "baz")
self.assertEqual(config.get("foo.bar"), "bar") self.assertEqual(config.get("foo.bar"), "bar")
@mock.patch.dict(environ, {"foo": "bar"})
def test_uri_env(self): def test_uri_env(self):
"""Test URI parsing (environment)""" """Test URI parsing (environment)"""
config = ConfigLoader() config = ConfigLoader()
environ["foo"] = "bar" foo_uri = "env://foo"
self.assertEqual(config.parse_uri("env://foo").value, "bar") foo_parsed = config.parse_uri(foo_uri)
self.assertEqual(config.parse_uri("env://foo?bar").value, "bar") self.assertEqual(foo_parsed.value, "bar")
self.assertEqual(foo_parsed.source_type, Attr.Source.URI)
self.assertEqual(foo_parsed.source, foo_uri)
foo_bar_uri = "env://foo?bar"
foo_bar_parsed = config.parse_uri(foo_bar_uri)
self.assertEqual(foo_bar_parsed.value, "bar")
self.assertEqual(foo_bar_parsed.source_type, Attr.Source.URI)
self.assertEqual(foo_bar_parsed.source, foo_bar_uri)
def test_uri_file(self): def test_uri_file(self):
"""Test URI parsing (file load)""" """Test URI parsing (file load)"""
@ -91,3 +111,60 @@ class TestConfig(TestCase):
config = ConfigLoader() config = ConfigLoader()
config.set("foo", "bar") config.set("foo", "bar")
self.assertEqual(config.get_int("foo", 1234), 1234) self.assertEqual(config.get_int("foo", 1234), 1234)
def test_get_dict_from_b64_json(self):
"""Test get_dict_from_b64_json"""
config = ConfigLoader()
test_value = ' { "foo": "bar" } '.encode("utf-8")
b64_value = base64.b64encode(test_value)
config.set("foo", b64_value)
self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"})
def test_get_dict_from_b64_json_missing_brackets(self):
"""Test get_dict_from_b64_json with missing brackets"""
config = ConfigLoader()
test_value = ' "foo": "bar" '.encode("utf-8")
b64_value = base64.b64encode(test_value)
config.set("foo", b64_value)
self.assertEqual(config.get_dict_from_b64_json("foo"), {"foo": "bar"})
def test_get_dict_from_b64_json_invalid(self):
"""Test get_dict_from_b64_json with invalid value"""
config = ConfigLoader()
config.set("foo", "bar")
self.assertEqual(config.get_dict_from_b64_json("foo"), {})
def test_attr_json_encoder(self):
"""Test AttrEncoder"""
test_attr = Attr("foo", Attr.Source.ENV, "AUTHENTIK_REDIS__USERNAME")
json_attr = dumps(test_attr, indent=4, cls=AttrEncoder)
self.assertEqual(json_attr, '"foo"')
def test_attr_json_encoder_no_attr(self):
"""Test AttrEncoder if no Attr is passed"""
class Test:
"""Non Attr class"""
with self.assertRaises(TypeError):
test_obj = Test()
dumps(test_obj, indent=4, cls=AttrEncoder)
@mock.patch.dict(environ, check_deprecations_env_vars)
def test_check_deprecations(self):
"""Test config key re-write for deprecated env vars"""
config = ConfigLoader()
config.update_from_env()
config.check_deprecations()
self.assertEqual(config.get("redis.broker_url", UNSET), UNSET)
self.assertEqual(config.get("redis.broker_transport_options", UNSET), UNSET)
self.assertEqual(config.get("redis.cache_timeout", UNSET), UNSET)
self.assertEqual(config.get("redis.cache_timeout_flows", UNSET), UNSET)
self.assertEqual(config.get("redis.cache_timeout_policies", UNSET), UNSET)
self.assertEqual(config.get("redis.cache_timeout_reputation", UNSET), UNSET)
self.assertEqual(config.get("broker.url"), "redis://myredis:8327/43")
self.assertEqual(config.get("broker.transport_options"), "bWFzdGVybmFtZT1teW1hc3Rlcg==")
self.assertEqual(config.get("cache.timeout"), "124s")
self.assertEqual(config.get("cache.timeout_flows"), "32m")
self.assertEqual(config.get("cache.timeout_policies"), "3920ns")
self.assertEqual(config.get("cache.timeout_reputation"), "298382us")

View file

@ -93,7 +93,7 @@ class OutpostConsumer(AuthJsonConsumer):
expected=self.outpost.config.kubernetes_replicas, expected=self.outpost.config.kubernetes_replicas,
).dec() ).dec()
def receive_json(self, content: Data): def receive_json(self, content: Data, **kwargs):
msg = from_dict(WebsocketMessage, content) msg = from_dict(WebsocketMessage, content)
uid = msg.args.get("uuid", self.channel_name) uid = msg.args.get("uuid", self.channel_name)
self.last_uid = uid self.last_uid = uid

View file

@ -39,6 +39,7 @@ class Migration(migrations.Migration):
("authentik.sources.oauth", "authentik Sources.OAuth"), ("authentik.sources.oauth", "authentik Sources.OAuth"),
("authentik.sources.plex", "authentik Sources.Plex"), ("authentik.sources.plex", "authentik Sources.Plex"),
("authentik.sources.saml", "authentik Sources.SAML"), ("authentik.sources.saml", "authentik Sources.SAML"),
("authentik.sources.scim", "authentik Sources.SCIM"),
("authentik.stages.authenticator_duo", "authentik Stages.Authenticator.Duo"), ("authentik.stages.authenticator_duo", "authentik Stages.Authenticator.Duo"),
("authentik.stages.authenticator_sms", "authentik Stages.Authenticator.SMS"), ("authentik.stages.authenticator_sms", "authentik Stages.Authenticator.SMS"),
( (

View file

@ -20,7 +20,7 @@ from authentik.policies.types import CACHE_PREFIX, PolicyRequest, PolicyResult
LOGGER = get_logger() LOGGER = get_logger()
FORK_CTX = get_context("fork") FORK_CTX = get_context("fork")
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_policies") CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_policies")
PROCESS_CLASS = FORK_CTX.Process PROCESS_CLASS = FORK_CTX.Process

View file

@ -13,7 +13,7 @@ from authentik.policies.reputation.tasks import save_reputation
from authentik.stages.identification.signals import identification_failed from authentik.stages.identification.signals import identification_failed
LOGGER = get_logger() LOGGER = get_logger()
CACHE_TIMEOUT = CONFIG.get_int("redis.cache_timeout_reputation") CACHE_TIMEOUT = CONFIG.get_int("cache.timeout_reputation")
def update_score(request: HttpRequest, identifier: str, amount: int): def update_score(request: HttpRequest, identifier: str, amount: int):

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: if client_id != provider.client_id or client_secret != provider.client_secret:
LOGGER.debug("(basic) Provider for basic auth does not exist") LOGGER.debug("(basic) Provider for basic auth does not exist")
return None return None
CTX_AUTH_VIA.set("oauth_client_secret")
return provider return provider

View file

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

View file

@ -46,7 +46,9 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
def to_scim(self, obj: Group) -> SCIMGroupSchema: def to_scim(self, obj: Group) -> SCIMGroupSchema:
"""Convert authentik user into SCIM""" """Convert authentik user into SCIM"""
raw_scim_group = {} raw_scim_group = {
"schemas": ("urn:ietf:params:scim:schemas:core:2.0:Group",),
}
for mapping in ( for mapping in (
self.provider.property_mappings_group.all().order_by("name").select_subclasses() self.provider.property_mappings_group.all().order_by("name").select_subclasses()
): ):

View file

@ -15,12 +15,14 @@ from pydanticscim.user import User as BaseUser
class User(BaseUser): class User(BaseUser):
"""Modified User schema with added externalId field""" """Modified User schema with added externalId field"""
schemas: tuple[str] = ("urn:ietf:params:scim:schemas:core:2.0:User",)
externalId: Optional[str] = None externalId: Optional[str] = None
class Group(BaseGroup): class Group(BaseGroup):
"""Modified Group schema with added externalId field""" """Modified Group schema with added externalId field"""
schemas: tuple[str] = ("urn:ietf:params:scim:schemas:core:2.0:Group",)
externalId: Optional[str] = None externalId: Optional[str] = None

View file

@ -39,7 +39,9 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
def to_scim(self, obj: User) -> SCIMUserSchema: def to_scim(self, obj: User) -> SCIMUserSchema:
"""Convert authentik user into SCIM""" """Convert authentik user into SCIM"""
raw_scim_user = {} raw_scim_user = {
"schemas": ("urn:ietf:params:scim:schemas:core:2.0:User",),
}
for mapping in self.provider.property_mappings.all().order_by("name").select_subclasses(): for mapping in self.provider.property_mappings.all().order_by("name").select_subclasses():
if not isinstance(mapping, SCIMMapping): if not isinstance(mapping, SCIMMapping):
continue continue

View file

@ -61,7 +61,11 @@ class SCIMGroupTests(TestCase):
self.assertEqual(mock.request_history[1].method, "POST") self.assertEqual(mock.request_history[1].method, "POST")
self.assertJSONEqual( self.assertJSONEqual(
mock.request_history[1].body, mock.request_history[1].body,
{"externalId": str(group.pk), "displayName": group.name}, {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": str(group.pk),
"displayName": group.name,
},
) )
@Mocker() @Mocker()
@ -96,7 +100,11 @@ class SCIMGroupTests(TestCase):
validate(body, loads(schema.read())) validate(body, loads(schema.read()))
self.assertEqual( self.assertEqual(
body, body,
{"externalId": str(group.pk), "displayName": group.name}, {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": str(group.pk),
"displayName": group.name,
},
) )
group.save() group.save()
self.assertEqual(mock.call_count, 4) self.assertEqual(mock.call_count, 4)
@ -129,7 +137,11 @@ class SCIMGroupTests(TestCase):
self.assertEqual(mock.request_history[1].method, "POST") self.assertEqual(mock.request_history[1].method, "POST")
self.assertJSONEqual( self.assertJSONEqual(
mock.request_history[1].body, mock.request_history[1].body,
{"externalId": str(group.pk), "displayName": group.name}, {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": str(group.pk),
"displayName": group.name,
},
) )
group.delete() group.delete()
self.assertEqual(mock.call_count, 4) self.assertEqual(mock.call_count, 4)

View file

@ -89,6 +89,7 @@ class SCIMMembershipTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[3].body, mocker.request_history[3].body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"emails": [], "emails": [],
"active": True, "active": True,
"externalId": user.uid, "externalId": user.uid,
@ -99,7 +100,11 @@ class SCIMMembershipTests(TestCase):
) )
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[5].body, mocker.request_history[5].body,
{"externalId": str(group.pk), "displayName": group.name}, {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": str(group.pk),
"displayName": group.name,
},
) )
with Mocker() as mocker: with Mocker() as mocker:
@ -118,6 +123,7 @@ class SCIMMembershipTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[1].body, mocker.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [ "Operations": [
{ {
"op": "add", "op": "add",
@ -125,7 +131,6 @@ class SCIMMembershipTests(TestCase):
"value": [{"value": user_scim_id}], "value": [{"value": user_scim_id}],
} }
], ],
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
}, },
) )
@ -174,6 +179,7 @@ class SCIMMembershipTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[3].body, mocker.request_history[3].body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"active": True, "active": True,
"displayName": "", "displayName": "",
"emails": [], "emails": [],
@ -184,7 +190,11 @@ class SCIMMembershipTests(TestCase):
) )
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[5].body, mocker.request_history[5].body,
{"externalId": str(group.pk), "displayName": group.name}, {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"externalId": str(group.pk),
"displayName": group.name,
},
) )
with Mocker() as mocker: with Mocker() as mocker:
@ -203,6 +213,7 @@ class SCIMMembershipTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[1].body, mocker.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [ "Operations": [
{ {
"op": "add", "op": "add",
@ -210,7 +221,6 @@ class SCIMMembershipTests(TestCase):
"value": [{"value": user_scim_id}], "value": [{"value": user_scim_id}],
} }
], ],
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
}, },
) )
@ -230,6 +240,7 @@ class SCIMMembershipTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mocker.request_history[1].body, mocker.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [ "Operations": [
{ {
"op": "remove", "op": "remove",
@ -237,6 +248,5 @@ class SCIMMembershipTests(TestCase):
"value": [{"value": user_scim_id}], "value": [{"value": user_scim_id}],
} }
], ],
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
}, },
) )

View file

@ -66,6 +66,7 @@ class SCIMUserTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mock.request_history[1].body, mock.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"active": True, "active": True,
"emails": [ "emails": [
{ {
@ -121,6 +122,7 @@ class SCIMUserTests(TestCase):
self.assertEqual( self.assertEqual(
body, body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"active": True, "active": True,
"emails": [ "emails": [
{ {
@ -173,6 +175,7 @@ class SCIMUserTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mock.request_history[1].body, mock.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"active": True, "active": True,
"emails": [ "emails": [
{ {
@ -240,6 +243,7 @@ class SCIMUserTests(TestCase):
self.assertJSONEqual( self.assertJSONEqual(
mock.request_history[1].body, mock.request_history[1].body,
{ {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"active": True, "active": True,
"emails": [ "emails": [
{ {

View file

@ -1,5 +1,4 @@
"""root settings for authentik""" """root settings for authentik"""
import importlib import importlib
import os import os
from hashlib import sha512 from hashlib import sha512
@ -83,6 +82,7 @@ INSTALLED_APPS = [
"authentik.sources.oauth", "authentik.sources.oauth",
"authentik.sources.plex", "authentik.sources.plex",
"authentik.sources.saml", "authentik.sources.saml",
"authentik.sources.scim",
"authentik.stages.authenticator", "authentik.stages.authenticator",
"authentik.stages.authenticator_duo", "authentik.stages.authenticator_duo",
"authentik.stages.authenticator_sms", "authentik.stages.authenticator_sms",
@ -147,6 +147,9 @@ SPECTACULAR_SETTINGS = {
"UserTypeEnum": "authentik.core.models.UserTypes", "UserTypeEnum": "authentik.core.models.UserTypes",
}, },
"ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False, "ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE": False,
"PREPROCESSING_HOOKS": [
"authentik.api.schema.preprocess_schema_exclude_non_api",
],
"POSTPROCESSING_HOOKS": [ "POSTPROCESSING_HOOKS": [
"authentik.api.schema.postprocess_schema_responses", "authentik.api.schema.postprocess_schema_responses",
"drf_spectacular.hooks.postprocess_schema_enums", "drf_spectacular.hooks.postprocess_schema_enums",
@ -195,8 +198,8 @@ _redis_url = (
CACHES = { CACHES = {
"default": { "default": {
"BACKEND": "django_redis.cache.RedisCache", "BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"{_redis_url}/{CONFIG.get('redis.db')}", "LOCATION": CONFIG.get("cache.url") or f"{_redis_url}/{CONFIG.get('redis.db')}",
"TIMEOUT": CONFIG.get_int("redis.cache_timeout", 300), "TIMEOUT": CONFIG.get_int("cache.timeout", 300),
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
"KEY_PREFIX": "authentik_cache", "KEY_PREFIX": "authentik_cache",
} }
@ -256,7 +259,7 @@ CHANNEL_LAYERS = {
"default": { "default": {
"BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer", "BACKEND": "channels_redis.pubsub.RedisPubSubChannelLayer",
"CONFIG": { "CONFIG": {
"hosts": [f"{_redis_url}/{CONFIG.get('redis.db')}"], "hosts": [CONFIG.get("channel.url", f"{_redis_url}/{CONFIG.get('redis.db')}")],
"prefix": "authentik_channels_", "prefix": "authentik_channels_",
}, },
}, },
@ -349,8 +352,11 @@ CELERY = {
}, },
"task_create_missing_queues": True, "task_create_missing_queues": True,
"task_default_queue": "authentik", "task_default_queue": "authentik",
"broker_url": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", "broker_url": CONFIG.get("broker.url")
"result_backend": f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}", or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
"broker_transport_options": CONFIG.get_dict_from_b64_json("broker.transport_options"),
"result_backend": CONFIG.get("result_backend.url")
or f"{_redis_url}/{CONFIG.get('redis.db')}{_redis_celery_tls_requirements}",
} }
# Sentry integration # Sentry integration

View file

@ -1,13 +1,14 @@
"""Source API Views""" """Source API Views"""
from typing import Any from typing import Any, Optional
from django.core.cache import cache
from django_filters.filters import AllValuesMultipleFilter from django_filters.filters import AllValuesMultipleFilter
from django_filters.filterset import FilterSet from django_filters.filterset import FilterSet
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer from drf_spectacular.utils import extend_schema, extend_schema_field, inline_serializer
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError from rest_framework.exceptions import ValidationError
from rest_framework.fields import DictField, ListField from rest_framework.fields import BooleanField, DictField, ListField, SerializerMethodField
from rest_framework.relations import PrimaryKeyRelatedField from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
@ -17,15 +18,17 @@ from authentik.admin.api.tasks import TaskSerializer
from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.api.sources import SourceSerializer from authentik.core.api.sources import SourceSerializer
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.events.monitored_tasks import TaskInfo from authentik.events.monitored_tasks import TaskInfo
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.tasks import SYNC_CLASSES from authentik.sources.ldap.tasks import CACHE_KEY_STATUS, SYNC_CLASSES
class LDAPSourceSerializer(SourceSerializer): class LDAPSourceSerializer(SourceSerializer):
"""LDAP Source Serializer""" """LDAP Source Serializer"""
connectivity = SerializerMethodField()
client_certificate = PrimaryKeyRelatedField( client_certificate = PrimaryKeyRelatedField(
allow_null=True, allow_null=True,
help_text="Client certificate to authenticate against the LDAP Server's Certificate.", help_text="Client certificate to authenticate against the LDAP Server's Certificate.",
@ -35,6 +38,10 @@ class LDAPSourceSerializer(SourceSerializer):
required=False, required=False,
) )
def get_connectivity(self, source: LDAPSource) -> Optional[dict[str, dict[str, str]]]:
"""Get cached source connectivity"""
return cache.get(CACHE_KEY_STATUS + source.slug, None)
def validate(self, attrs: dict[str, Any]) -> dict[str, Any]: def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:
"""Check that only a single source has password_sync on""" """Check that only a single source has password_sync on"""
sync_users_password = attrs.get("sync_users_password", True) sync_users_password = attrs.get("sync_users_password", True)
@ -75,10 +82,18 @@ class LDAPSourceSerializer(SourceSerializer):
"sync_parent_group", "sync_parent_group",
"property_mappings", "property_mappings",
"property_mappings_group", "property_mappings_group",
"connectivity",
] ]
extra_kwargs = {"bind_password": {"write_only": True}} extra_kwargs = {"bind_password": {"write_only": True}}
class LDAPSyncStatusSerializer(PassiveSerializer):
"""LDAP Source sync status"""
is_running = BooleanField(read_only=True)
tasks = TaskSerializer(many=True, read_only=True)
class LDAPSourceViewSet(UsedByMixin, ModelViewSet): class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
"""LDAP Source Viewset""" """LDAP Source Viewset"""
@ -114,19 +129,19 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
@extend_schema( @extend_schema(
responses={ responses={
200: TaskSerializer(many=True), 200: LDAPSyncStatusSerializer(),
} }
) )
@action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[]) @action(methods=["GET"], detail=True, pagination_class=None, filter_backends=[])
def sync_status(self, request: Request, slug: str) -> Response: def sync_status(self, request: Request, slug: str) -> Response:
"""Get source's sync status""" """Get source's sync status"""
source = self.get_object() source: LDAPSource = self.get_object()
results = [] tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*") or []
tasks = TaskInfo.by_name(f"ldap_sync:{source.slug}:*") status = {
if tasks: "tasks": tasks,
for task in tasks: "is_running": source.sync_lock.locked(),
results.append(task) }
return Response(TaskSerializer(results, many=True).data) return Response(LDAPSyncStatusSerializer(status).data)
@extend_schema( @extend_schema(
responses={ responses={

View file

@ -0,0 +1,24 @@
"""LDAP Connection check"""
from json import dumps
from django.core.management.base import BaseCommand
from structlog.stdlib import get_logger
from authentik.sources.ldap.models import LDAPSource
LOGGER = get_logger()
class Command(BaseCommand):
"""Check connectivity to LDAP servers for a source"""
def add_arguments(self, parser):
parser.add_argument("source_slugs", nargs="?", type=str)
def handle(self, **options):
sources = LDAPSource.objects.filter(enabled=True)
if options["source_slugs"]:
sources = LDAPSource.objects.filter(slug__in=options["source_slugs"])
for source in sources.order_by("slug"):
status = source.check_connection()
self.stdout.write(dumps(status, indent=4))

View file

@ -4,10 +4,12 @@ from ssl import CERT_REQUIRED
from tempfile import NamedTemporaryFile, mkdtemp from tempfile import NamedTemporaryFile, mkdtemp
from typing import Optional from typing import Optional
from django.core.cache import cache
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls
from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult, LDAPSchemaError from ldap3.core.exceptions import LDAPException, LDAPInsufficientAccessRightsResult, LDAPSchemaError
from redis.lock import Lock
from rest_framework.serializers import Serializer from rest_framework.serializers import Serializer
from authentik.core.models import Group, PropertyMapping, Source from authentik.core.models import Group, PropertyMapping, Source
@ -117,7 +119,7 @@ class LDAPSource(Source):
return LDAPSourceSerializer return LDAPSourceSerializer
def server(self, **kwargs) -> Server: def server(self, **kwargs) -> ServerPool:
"""Get LDAP Server/ServerPool""" """Get LDAP Server/ServerPool"""
servers = [] servers = []
tls_kwargs = {} tls_kwargs = {}
@ -154,7 +156,10 @@ class LDAPSource(Source):
return ServerPool(servers, RANDOM, active=5, exhaust=True) return ServerPool(servers, RANDOM, active=5, exhaust=True)
def connection( def connection(
self, server_kwargs: Optional[dict] = None, connection_kwargs: Optional[dict] = None self,
server: Optional[Server] = None,
server_kwargs: Optional[dict] = None,
connection_kwargs: Optional[dict] = None,
) -> Connection: ) -> Connection:
"""Get a fully connected and bound LDAP Connection""" """Get a fully connected and bound LDAP Connection"""
server_kwargs = server_kwargs or {} server_kwargs = server_kwargs or {}
@ -164,7 +169,7 @@ class LDAPSource(Source):
if self.bind_password is not None: if self.bind_password is not None:
connection_kwargs.setdefault("password", self.bind_password) connection_kwargs.setdefault("password", self.bind_password)
connection = Connection( connection = Connection(
self.server(**server_kwargs), server or self.server(**server_kwargs),
raise_exceptions=True, raise_exceptions=True,
receive_timeout=LDAP_TIMEOUT, receive_timeout=LDAP_TIMEOUT,
**connection_kwargs, **connection_kwargs,
@ -183,9 +188,55 @@ class LDAPSource(Source):
if server_kwargs.get("get_info", ALL) == NONE: if server_kwargs.get("get_info", ALL) == NONE:
raise exc raise exc
server_kwargs["get_info"] = NONE server_kwargs["get_info"] = NONE
return self.connection(server_kwargs, connection_kwargs) return self.connection(server, server_kwargs, connection_kwargs)
return RuntimeError("Failed to bind") return RuntimeError("Failed to bind")
@property
def sync_lock(self) -> Lock:
"""Redis lock for syncing LDAP to prevent multiple parallel syncs happening"""
return Lock(
cache.client.get_client(),
name=f"goauthentik.io/sources/ldap/sync-{self.slug}",
# Convert task timeout hours to seconds, and multiply times 3
# (see authentik/sources/ldap/tasks.py:54)
# multiply by 3 to add even more leeway
timeout=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3,
)
def check_connection(self) -> dict[str, dict[str, str]]:
"""Check LDAP Connection"""
from authentik.sources.ldap.sync.base import flatten
servers = self.server()
server_info = {}
# Check each individual server
for server in servers.servers:
server: Server
try:
connection = self.connection(server=server)
server_info[server.host] = {
"vendor": str(flatten(connection.server.info.vendor_name)),
"version": str(flatten(connection.server.info.vendor_version)),
"status": "ok",
}
except LDAPException as exc:
server_info[server.host] = {
"status": str(exc),
}
# Check server pool
try:
connection = self.connection()
server_info["__all__"] = {
"vendor": str(flatten(connection.server.info.vendor_name)),
"version": str(flatten(connection.server.info.vendor_version)),
"status": "ok",
}
except LDAPException as exc:
server_info["__all__"] = {
"status": str(exc),
}
return server_info
class Meta: class Meta:
verbose_name = _("LDAP Source") verbose_name = _("LDAP Source")
verbose_name_plural = _("LDAP Sources") verbose_name_plural = _("LDAP Sources")

View file

@ -8,5 +8,10 @@ CELERY_BEAT_SCHEDULE = {
"task": "authentik.sources.ldap.tasks.ldap_sync_all", "task": "authentik.sources.ldap.tasks.ldap_sync_all",
"schedule": crontab(minute=fqdn_rand("sources_ldap_sync"), hour="*/2"), "schedule": crontab(minute=fqdn_rand("sources_ldap_sync"), hour="*/2"),
"options": {"queue": "authentik_scheduled"}, "options": {"queue": "authentik_scheduled"},
} },
"sources_ldap_connectivity_check": {
"task": "authentik.sources.ldap.tasks.ldap_connectivity_check",
"schedule": crontab(minute=fqdn_rand("sources_ldap_connectivity_check"), hour="*"),
"options": {"queue": "authentik_scheduled"},
},
} }

View file

@ -14,7 +14,7 @@ from authentik.events.models import Event, EventAction
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
from authentik.sources.ldap.models import LDAPSource from authentik.sources.ldap.models import LDAPSource
from authentik.sources.ldap.password import LDAPPasswordChanger from authentik.sources.ldap.password import LDAPPasswordChanger
from authentik.sources.ldap.tasks import ldap_sync_single from authentik.sources.ldap.tasks import ldap_connectivity_check, ldap_sync_single
from authentik.stages.prompt.signals import password_validate from authentik.stages.prompt.signals import password_validate
LOGGER = get_logger() LOGGER = get_logger()
@ -32,6 +32,7 @@ def sync_ldap_source_on_save(sender, instance: LDAPSource, **_):
if not instance.property_mappings.exists() or not instance.property_mappings_group.exists(): if not instance.property_mappings.exists() or not instance.property_mappings_group.exists():
return return
ldap_sync_single.delay(instance.pk) ldap_sync_single.delay(instance.pk)
ldap_connectivity_check.delay(instance.pk)
@receiver(password_validate) @receiver(password_validate)

View file

@ -17,6 +17,15 @@ from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
LDAP_UNIQUENESS = "ldap_uniq" LDAP_UNIQUENESS = "ldap_uniq"
def flatten(value: Any) -> Any:
"""Flatten `value` if its a list"""
if isinstance(value, list):
if len(value) < 1:
return None
return value[0]
return value
class BaseLDAPSynchronizer: class BaseLDAPSynchronizer:
"""Sync LDAP Users and groups into authentik""" """Sync LDAP Users and groups into authentik"""
@ -122,14 +131,6 @@ class BaseLDAPSynchronizer:
cookie = None cookie = None
yield self._connection.response yield self._connection.response
def _flatten(self, value: Any) -> Any:
"""Flatten `value` if its a list"""
if isinstance(value, list):
if len(value) < 1:
return None
return value[0]
return value
def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]: def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]:
"""Build attributes for User object based on property mappings.""" """Build attributes for User object based on property mappings."""
props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs) props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs)
@ -163,10 +164,10 @@ class BaseLDAPSynchronizer:
object_field = mapping.object_field object_field = mapping.object_field
if object_field.startswith("attributes."): if object_field.startswith("attributes."):
# Because returning a list might desired, we can't # Because returning a list might desired, we can't
# rely on self._flatten here. Instead, just save the result as-is # rely on flatten here. Instead, just save the result as-is
set_path_in_dict(properties, object_field, value) set_path_in_dict(properties, object_field, value)
else: else:
properties[object_field] = self._flatten(value) properties[object_field] = flatten(value)
except PropertyMappingExpressionException as exc: except PropertyMappingExpressionException as exc:
Event.new( Event.new(
EventAction.CONFIGURATION_ERROR, EventAction.CONFIGURATION_ERROR,
@ -177,7 +178,7 @@ class BaseLDAPSynchronizer:
self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping) self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping)
continue continue
if self._source.object_uniqueness_field in kwargs: if self._source.object_uniqueness_field in kwargs:
properties["attributes"][LDAP_UNIQUENESS] = self._flatten( properties["attributes"][LDAP_UNIQUENESS] = flatten(
kwargs.get(self._source.object_uniqueness_field) kwargs.get(self._source.object_uniqueness_field)
) )
properties["attributes"][LDAP_DISTINGUISHED_NAME] = object_dn properties["attributes"][LDAP_DISTINGUISHED_NAME] = object_dn

View file

@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
from authentik.core.models import Group from authentik.core.models import Group
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten
class GroupLDAPSynchronizer(BaseLDAPSynchronizer): class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
@ -39,7 +39,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
if "attributes" not in group: if "attributes" not in group:
continue continue
attributes = group.get("attributes", {}) attributes = group.get("attributes", {})
group_dn = self._flatten(self._flatten(group.get("entryDN", group.get("dn")))) group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
if self._source.object_uniqueness_field not in attributes: if self._source.object_uniqueness_field not in attributes:
self.message( self.message(
f"Cannot find uniqueness field in attributes: '{group_dn}'", f"Cannot find uniqueness field in attributes: '{group_dn}'",
@ -47,7 +47,7 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
dn=group_dn, dn=group_dn,
) )
continue continue
uniq = self._flatten(attributes[self._source.object_uniqueness_field]) uniq = flatten(attributes[self._source.object_uniqueness_field])
try: try:
defaults = self.build_group_properties(group_dn, **attributes) defaults = self.build_group_properties(group_dn, **attributes)
defaults["parent"] = self._source.sync_parent_group defaults["parent"] = self._source.sync_parent_group

View file

@ -7,7 +7,7 @@ from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
from authentik.core.models import User from authentik.core.models import User
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer from authentik.sources.ldap.sync.base import LDAP_UNIQUENESS, BaseLDAPSynchronizer, flatten
from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA from authentik.sources.ldap.sync.vendor.freeipa import FreeIPA
from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory from authentik.sources.ldap.sync.vendor.ms_ad import MicrosoftActiveDirectory
@ -41,7 +41,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
if "attributes" not in user: if "attributes" not in user:
continue continue
attributes = user.get("attributes", {}) attributes = user.get("attributes", {})
user_dn = self._flatten(user.get("entryDN", user.get("dn"))) user_dn = flatten(user.get("entryDN", user.get("dn")))
if self._source.object_uniqueness_field not in attributes: if self._source.object_uniqueness_field not in attributes:
self.message( self.message(
f"Cannot find uniqueness field in attributes: '{user_dn}'", f"Cannot find uniqueness field in attributes: '{user_dn}'",
@ -49,7 +49,7 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
dn=user_dn, dn=user_dn,
) )
continue continue
uniq = self._flatten(attributes[self._source.object_uniqueness_field]) uniq = flatten(attributes[self._source.object_uniqueness_field])
try: try:
defaults = self.build_user_properties(user_dn, **attributes) defaults = self.build_user_properties(user_dn, **attributes)
self._logger.debug("Writing user with attributes", **defaults) self._logger.debug("Writing user with attributes", **defaults)

View file

@ -5,7 +5,7 @@ from typing import Any, Generator
from pytz import UTC from pytz import UTC
from authentik.core.models import User from authentik.core.models import User
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer, flatten
class FreeIPA(BaseLDAPSynchronizer): class FreeIPA(BaseLDAPSynchronizer):
@ -47,7 +47,7 @@ class FreeIPA(BaseLDAPSynchronizer):
return return
# For some reason, nsaccountlock is not defined properly in the schema as bool # For some reason, nsaccountlock is not defined properly in the schema as bool
# hence we get it as a list of strings # hence we get it as a list of strings
_is_locked = str(self._flatten(attributes.get("nsaccountlock", ["FALSE"]))) _is_locked = str(flatten(attributes.get("nsaccountlock", ["FALSE"])))
# So we have to attempt to convert it to a bool # So we have to attempt to convert it to a bool
is_locked = _is_locked.lower() == "true" is_locked = _is_locked.lower() == "true"
# And then invert it since freeipa saves locked and we save active # And then invert it since freeipa saves locked and we save active

View file

@ -1,13 +1,14 @@
"""LDAP Sync tasks""" """LDAP Sync tasks"""
from typing import Optional
from uuid import uuid4 from uuid import uuid4
from celery import chain, group from celery import chain, group
from django.core.cache import cache from django.core.cache import cache
from ldap3.core.exceptions import LDAPException from ldap3.core.exceptions import LDAPException
from redis.exceptions import LockError from redis.exceptions import LockError
from redis.lock import Lock
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
from authentik.events.monitored_tasks import CACHE_KEY_PREFIX as CACHE_KEY_PREFIX_TASKS
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
@ -26,6 +27,7 @@ SYNC_CLASSES = [
MembershipLDAPSynchronizer, MembershipLDAPSynchronizer,
] ]
CACHE_KEY_PREFIX = "goauthentik.io/sources/ldap/page/" CACHE_KEY_PREFIX = "goauthentik.io/sources/ldap/page/"
CACHE_KEY_STATUS = "goauthentik.io/sources/ldap/status/"
@CELERY_APP.task() @CELERY_APP.task()
@ -35,6 +37,19 @@ def ldap_sync_all():
ldap_sync_single.apply_async(args=[source.pk]) ldap_sync_single.apply_async(args=[source.pk])
@CELERY_APP.task()
def ldap_connectivity_check(pk: Optional[str] = None):
"""Check connectivity for LDAP Sources"""
# 2 hour timeout, this task should run every hour
timeout = 60 * 60 * 2
sources = LDAPSource.objects.filter(enabled=True)
if pk:
sources = sources.filter(pk=pk)
for source in sources:
status = source.check_connection()
cache.set(CACHE_KEY_STATUS + source.slug, status, timeout=timeout)
@CELERY_APP.task( @CELERY_APP.task(
# We take the configured hours timeout time by 2.5 as we run user and # We take the configured hours timeout time by 2.5 as we run user and
# group in parallel and then membership, so 2x is to cover the serial tasks, # group in parallel and then membership, so 2x is to cover the serial tasks,
@ -47,12 +62,15 @@ def ldap_sync_single(source_pk: str):
source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first() source: LDAPSource = LDAPSource.objects.filter(pk=source_pk).first()
if not source: if not source:
return return
lock = Lock(cache.client.get_client(), name=f"goauthentik.io/sources/ldap/sync-{source.slug}") lock = source.sync_lock
if lock.locked(): if lock.locked():
LOGGER.debug("LDAP sync locked, skipping task", source=source.slug) LOGGER.debug("LDAP sync locked, skipping task", source=source.slug)
return return
try: try:
with lock: with lock:
# Delete all sync tasks from the cache
keys = cache.keys(f"{CACHE_KEY_PREFIX_TASKS}ldap_sync:{source.slug}*")
cache.delete_many(keys)
task = chain( task = chain(
# User and group sync can happen at once, they have no dependencies on each other # User and group sync can happen at once, they have no dependencies on each other
group( group(

View file

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

View file

View file

@ -0,0 +1,62 @@
"""SCIMSource API Views"""
from django.urls import reverse_lazy
from rest_framework.fields import SerializerMethodField
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.sources import SourceSerializer
from authentik.core.api.tokens import TokenSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.models import Token, TokenIntents, User, UserTypes
from authentik.sources.scim.models import SCIMSource
class SCIMSourceSerializer(SourceSerializer):
"""SCIMSource Serializer"""
root_url = SerializerMethodField()
token_obj = TokenSerializer(source="token", required=False, read_only=True)
def get_root_url(self, instance: SCIMSource) -> str:
"""Get Root URL"""
relative_url = reverse_lazy(
"authentik_sources_scim:v2-root",
kwargs={"source_slug": instance.slug},
)
if "request" not in self.context:
return relative_url
return self.context["request"].build_absolute_uri(relative_url)
def create(self, validated_data):
instance: SCIMSource = super().create(validated_data)
identifier = f"ak-source-scim-{instance.pk}"
user = User.objects.create(
username=identifier,
name=f"SCIM Source {instance.name} Service-Account",
type=UserTypes.SERVICE_ACCOUNT,
)
token = Token.objects.create(
user=user,
identifier=identifier,
intent=TokenIntents.INTENT_API,
expiring=False,
managed=f"goauthentik.io/sources/scim/{instance.pk}",
)
instance.token = token
instance.save()
return instance
class Meta:
model = SCIMSource
fields = SourceSerializer.Meta.fields + ["token", "root_url", "token_obj"]
class SCIMSourceViewSet(UsedByMixin, ModelViewSet):
"""SCIMSource Viewset"""
queryset = SCIMSource.objects.all()
serializer_class = SCIMSourceSerializer
lookup_field = "slug"
filterset_fields = ["name", "slug"]
search_fields = ["name", "slug", "token__identifier", "token__user__username"]
ordering = ["name"]

View file

@ -0,0 +1,11 @@
"""Authentik SCIM app config"""
from django.apps import AppConfig
class AuthentikSourceSCIMConfig(AppConfig):
"""authentik SCIM Source app config"""
name = "authentik.sources.scim"
label = "authentik_sources_scim"
verbose_name = "authentik Sources.SCIM"

View file

@ -0,0 +1,8 @@
"""SCIM Errors"""
from authentik.lib.sentry import SentryIgnoredException
class PatchError(SentryIgnoredException):
"""Error raised within an atomic block when an error happened
so nothing is saved"""

View file

@ -0,0 +1,61 @@
grammar ScimFilter;
parse
: filter
;
filter
: attrPath SP PR #presentExp
| attrPath SP COMPAREOPERATOR SP VALUE #operatorExp
| NOT? SP* '(' filter ')' #braceExp
| attrPath '[' valPathFilter ']' #valPathExp
| filter SP AND SP filter #andExp
| filter SP OR SP filter #orExp
;
valPathFilter
: attrPath SP PR #valPathPresentExp
| attrPath SP COMPAREOPERATOR SP VALUE #valPathOperatorExp
| NOT? SP* '(' valPathFilter ')' #valPathBraceExp
| valPathFilter SP AND SP valPathFilter #valPathAndExp
| valPathFilter SP OR SP valPathFilter #valPathOrExp
;
attrPath
: (SCHEMA)? ATTRNAME ('.' ATTRNAME)?
;
COMPAREOPERATOR : EQ | NE | CO | SW | EW | GT | GE | LT | LE;
EQ : [eE][qQ];
NE : [nN][eE];
CO : [cC][oO];
SW : [sS][wW];
EW : [eE][wW];
PR : [pP][rR];
GT : [gG][tT];
GE : [gG][eE];
LT : [lL][tT];
LE : [lL][eE];
NOT : [nN][oO][tT];
AND : [aA][nN][dD];
OR : [oO][rR];
SP : ' ';
SCHEMA : 'urn:' (SEGMENT ':')+;
ATTRNAME : ALPHA (ALPHA | DIGIT | '_' | '-')+;
fragment SEGMENT : (ALPHA | DIGIT | '_' | '-' | '.')+;
fragment DIGIT : [0-9];
fragment ALPHA : [a-z] | [A-Z];
ESCAPED_QUOTE : '\\"';
VALUE : '"'(ESCAPED_QUOTE | ~'"')*'"' | 'true' | 'false' | 'null' | DIGIT+('.'DIGIT+)?;
EXCLUDE : [\b | \t | \r | \n]+ -> skip;

View file

@ -0,0 +1,65 @@
token literal names:
null
'('
')'
'['
']'
'.'
null
null
null
null
null
null
null
null
null
null
null
null
null
null
' '
null
null
'\\"'
null
null
token symbolic names:
null
null
null
null
null
null
COMPAREOPERATOR
EQ
NE
CO
SW
EW
PR
GT
GE
LT
LE
NOT
AND
OR
SP
SCHEMA
ATTRNAME
ESCAPED_QUOTE
VALUE
EXCLUDE
rule names:
parse
filter
valPathFilter
attrPath
atn:
[4, 1, 25, 106, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 23, 8, 1, 1, 1, 5, 1, 26, 8, 1, 10, 1, 12, 1, 29, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 40, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 52, 8, 1, 10, 1, 12, 1, 55, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 69, 8, 2, 1, 2, 5, 2, 72, 8, 2, 10, 2, 12, 2, 75, 9, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 81, 8, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 5, 2, 93, 8, 2, 10, 2, 12, 2, 96, 9, 2, 1, 3, 3, 3, 99, 8, 3, 1, 3, 1, 3, 1, 3, 3, 3, 104, 8, 3, 1, 3, 0, 2, 2, 4, 4, 0, 2, 4, 6, 0, 0, 116, 0, 8, 1, 0, 0, 0, 2, 39, 1, 0, 0, 0, 4, 80, 1, 0, 0, 0, 6, 98, 1, 0, 0, 0, 8, 9, 3, 2, 1, 0, 9, 1, 1, 0, 0, 0, 10, 11, 6, 1, -1, 0, 11, 12, 3, 6, 3, 0, 12, 13, 5, 20, 0, 0, 13, 14, 5, 12, 0, 0, 14, 40, 1, 0, 0, 0, 15, 16, 3, 6, 3, 0, 16, 17, 5, 20, 0, 0, 17, 18, 5, 6, 0, 0, 18, 19, 5, 20, 0, 0, 19, 20, 5, 24, 0, 0, 20, 40, 1, 0, 0, 0, 21, 23, 5, 17, 0, 0, 22, 21, 1, 0, 0, 0, 22, 23, 1, 0, 0, 0, 23, 27, 1, 0, 0, 0, 24, 26, 5, 20, 0, 0, 25, 24, 1, 0, 0, 0, 26, 29, 1, 0, 0, 0, 27, 25, 1, 0, 0, 0, 27, 28, 1, 0, 0, 0, 28, 30, 1, 0, 0, 0, 29, 27, 1, 0, 0, 0, 30, 31, 5, 1, 0, 0, 31, 32, 3, 2, 1, 0, 32, 33, 5, 2, 0, 0, 33, 40, 1, 0, 0, 0, 34, 35, 3, 6, 3, 0, 35, 36, 5, 3, 0, 0, 36, 37, 3, 4, 2, 0, 37, 38, 5, 4, 0, 0, 38, 40, 1, 0, 0, 0, 39, 10, 1, 0, 0, 0, 39, 15, 1, 0, 0, 0, 39, 22, 1, 0, 0, 0, 39, 34, 1, 0, 0, 0, 40, 53, 1, 0, 0, 0, 41, 42, 10, 2, 0, 0, 42, 43, 5, 20, 0, 0, 43, 44, 5, 18, 0, 0, 44, 45, 5, 20, 0, 0, 45, 52, 3, 2, 1, 3, 46, 47, 10, 1, 0, 0, 47, 48, 5, 20, 0, 0, 48, 49, 5, 19, 0, 0, 49, 50, 5, 20, 0, 0, 50, 52, 3, 2, 1, 2, 51, 41, 1, 0, 0, 0, 51, 46, 1, 0, 0, 0, 52, 55, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 53, 54, 1, 0, 0, 0, 54, 3, 1, 0, 0, 0, 55, 53, 1, 0, 0, 0, 56, 57, 6, 2, -1, 0, 57, 58, 3, 6, 3, 0, 58, 59, 5, 20, 0, 0, 59, 60, 5, 12, 0, 0, 60, 81, 1, 0, 0, 0, 61, 62, 3, 6, 3, 0, 62, 63, 5, 20, 0, 0, 63, 64, 5, 6, 0, 0, 64, 65, 5, 20, 0, 0, 65, 66, 5, 24, 0, 0, 66, 81, 1, 0, 0, 0, 67, 69, 5, 17, 0, 0, 68, 67, 1, 0, 0, 0, 68, 69, 1, 0, 0, 0, 69, 73, 1, 0, 0, 0, 70, 72, 5, 20, 0, 0, 71, 70, 1, 0, 0, 0, 72, 75, 1, 0, 0, 0, 73, 71, 1, 0, 0, 0, 73, 74, 1, 0, 0, 0, 74, 76, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 76, 77, 5, 1, 0, 0, 77, 78, 3, 4, 2, 0, 78, 79, 5, 2, 0, 0, 79, 81, 1, 0, 0, 0, 80, 56, 1, 0, 0, 0, 80, 61, 1, 0, 0, 0, 80, 68, 1, 0, 0, 0, 81, 94, 1, 0, 0, 0, 82, 83, 10, 2, 0, 0, 83, 84, 5, 20, 0, 0, 84, 85, 5, 18, 0, 0, 85, 86, 5, 20, 0, 0, 86, 93, 3, 4, 2, 3, 87, 88, 10, 1, 0, 0, 88, 89, 5, 20, 0, 0, 89, 90, 5, 19, 0, 0, 90, 91, 5, 20, 0, 0, 91, 93, 3, 4, 2, 2, 92, 82, 1, 0, 0, 0, 92, 87, 1, 0, 0, 0, 93, 96, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 5, 1, 0, 0, 0, 96, 94, 1, 0, 0, 0, 97, 99, 5, 21, 0, 0, 98, 97, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 103, 5, 22, 0, 0, 101, 102, 5, 5, 0, 0, 102, 104, 5, 22, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 7, 1, 0, 0, 0, 12, 22, 27, 39, 51, 53, 68, 73, 80, 92, 94, 98, 103]

View file

@ -0,0 +1,32 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
COMPAREOPERATOR=6
EQ=7
NE=8
CO=9
SW=10
EW=11
PR=12
GT=13
GE=14
LT=15
LE=16
NOT=17
AND=18
OR=19
SP=20
SCHEMA=21
ATTRNAME=22
ESCAPED_QUOTE=23
VALUE=24
EXCLUDE=25
'('=1
')'=2
'['=3
']'=4
'.'=5
' '=20
'\\"'=23

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
COMPAREOPERATOR=6
EQ=7
NE=8
CO=9
SW=10
EW=11
PR=12
GT=13
GE=14
LT=15
LE=16
NOT=17
AND=18
OR=19
SP=20
SCHEMA=21
ATTRNAME=22
ESCAPED_QUOTE=23
VALUE=24
EXCLUDE=25
'('=1
')'=2
'['=3
']'=4
'.'=5
' '=20
'\\"'=23

View file

@ -0,0 +1,118 @@
# pylint: skip-file
# Generated from ScimFilter.g4 by ANTLR 4.10.1
from antlr4 import *
if __name__ is not None and "." in __name__:
from .ScimFilterParser import ScimFilterParser
else:
from ScimFilterParser import ScimFilterParser
# This class defines a complete listener for a parse tree produced by ScimFilterParser.
class ScimFilterListener(ParseTreeListener):
# Enter a parse tree produced by ScimFilterParser#parse.
def enterParse(self, ctx: ScimFilterParser.ParseContext):
pass
# Exit a parse tree produced by ScimFilterParser#parse.
def exitParse(self, ctx: ScimFilterParser.ParseContext):
pass
# Enter a parse tree produced by ScimFilterParser#andExp.
def enterAndExp(self, ctx: ScimFilterParser.AndExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#andExp.
def exitAndExp(self, ctx: ScimFilterParser.AndExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathExp.
def enterValPathExp(self, ctx: ScimFilterParser.ValPathExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathExp.
def exitValPathExp(self, ctx: ScimFilterParser.ValPathExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#presentExp.
def enterPresentExp(self, ctx: ScimFilterParser.PresentExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#presentExp.
def exitPresentExp(self, ctx: ScimFilterParser.PresentExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#operatorExp.
def enterOperatorExp(self, ctx: ScimFilterParser.OperatorExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#operatorExp.
def exitOperatorExp(self, ctx: ScimFilterParser.OperatorExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#braceExp.
def enterBraceExp(self, ctx: ScimFilterParser.BraceExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#braceExp.
def exitBraceExp(self, ctx: ScimFilterParser.BraceExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#orExp.
def enterOrExp(self, ctx: ScimFilterParser.OrExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#orExp.
def exitOrExp(self, ctx: ScimFilterParser.OrExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathOperatorExp.
def enterValPathOperatorExp(self, ctx: ScimFilterParser.ValPathOperatorExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathOperatorExp.
def exitValPathOperatorExp(self, ctx: ScimFilterParser.ValPathOperatorExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathPresentExp.
def enterValPathPresentExp(self, ctx: ScimFilterParser.ValPathPresentExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathPresentExp.
def exitValPathPresentExp(self, ctx: ScimFilterParser.ValPathPresentExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathAndExp.
def enterValPathAndExp(self, ctx: ScimFilterParser.ValPathAndExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathAndExp.
def exitValPathAndExp(self, ctx: ScimFilterParser.ValPathAndExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathOrExp.
def enterValPathOrExp(self, ctx: ScimFilterParser.ValPathOrExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathOrExp.
def exitValPathOrExp(self, ctx: ScimFilterParser.ValPathOrExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#valPathBraceExp.
def enterValPathBraceExp(self, ctx: ScimFilterParser.ValPathBraceExpContext):
pass
# Exit a parse tree produced by ScimFilterParser#valPathBraceExp.
def exitValPathBraceExp(self, ctx: ScimFilterParser.ValPathBraceExpContext):
pass
# Enter a parse tree produced by ScimFilterParser#attrPath.
def enterAttrPath(self, ctx: ScimFilterParser.AttrPathContext):
pass
# Exit a parse tree produced by ScimFilterParser#attrPath.
def exitAttrPath(self, ctx: ScimFilterParser.AttrPathContext):
pass
del ScimFilterParser

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,101 @@
"""Django listener"""
from django.db.models import Q
from django.utils.tree import Node
from authentik.sources.scim.filters.ScimFilterListener import ScimFilterListener
from authentik.sources.scim.filters.ScimFilterParser import ScimFilterParser
class DjangoQueryListener(ScimFilterListener):
"""SCIM filter listener that converts it to a query"""
_query: Node
_last_node: Node
def __init__(self) -> None:
super().__init__()
self._query = Q()
self._last_node = Q()
@property
def query(self) -> Node:
return self._query
def enterParse(self, ctx: ScimFilterParser.ParseContext):
print("enterParse", ctx)
def exitParse(self, ctx: ScimFilterParser.ParseContext):
print("exitParse", ctx)
def enterAndExp(self, ctx: ScimFilterParser.AndExpContext):
print("enterAndExp", ctx)
def exitAndExp(self, ctx: ScimFilterParser.AndExpContext):
print("exitAndExp", ctx)
def enterValPathExp(self, ctx: ScimFilterParser.ValPathExpContext):
print("enterValPathExp", ctx.getText())
def exitValPathExp(self, ctx: ScimFilterParser.ValPathExpContext):
print("exitValPathExp", ctx)
def enterPresentExp(self, ctx: ScimFilterParser.PresentExpContext):
print("enterPresentExp", ctx)
def exitPresentExp(self, ctx: ScimFilterParser.PresentExpContext):
print("exitPresentExp", ctx)
def enterOperatorExp(self, ctx: ScimFilterParser.OperatorExpContext):
print("enterOperatorExp", ctx)
def exitOperatorExp(self, ctx: ScimFilterParser.OperatorExpContext):
print("exitOperatorExp", ctx)
def enterBraceExp(self, ctx: ScimFilterParser.BraceExpContext):
print("enterBraceExp", ctx)
def exitBraceExp(self, ctx: ScimFilterParser.BraceExpContext):
print("exitBraceExp", ctx)
def enterOrExp(self, ctx: ScimFilterParser.OrExpContext):
print("enterOrExp", ctx)
def exitOrExp(self, ctx: ScimFilterParser.OrExpContext):
print("exitOrExp", ctx)
def enterValPathOperatorExp(self, ctx: ScimFilterParser.ValPathOperatorExpContext):
print("enterValPathOperatorExp", ctx)
def exitValPathOperatorExp(self, ctx: ScimFilterParser.ValPathOperatorExpContext):
print("exitValPathOperatorExp", ctx)
def enterValPathPresentExp(self, ctx: ScimFilterParser.ValPathPresentExpContext):
print("enterValPathPresentExp", ctx)
def exitValPathPresentExp(self, ctx: ScimFilterParser.ValPathPresentExpContext):
print("exitValPathPresentExp", ctx)
def enterValPathAndExp(self, ctx: ScimFilterParser.ValPathAndExpContext):
print("enterValPathAndExp", ctx.getText())
def exitValPathAndExp(self, ctx: ScimFilterParser.ValPathAndExpContext):
print("exitValPathAndExp", ctx)
def enterValPathOrExp(self, ctx: ScimFilterParser.ValPathOrExpContext):
print("enterValPathOrExp", ctx)
def exitValPathOrExp(self, ctx: ScimFilterParser.ValPathOrExpContext):
print("exitValPathOrExp", ctx)
def enterValPathBraceExp(self, ctx: ScimFilterParser.ValPathBraceExpContext):
print("enterValPathBraceExp", ctx)
def exitValPathBraceExp(self, ctx: ScimFilterParser.ValPathBraceExpContext):
print("exitValPathBraceExp", ctx)
def enterAttrPath(self, ctx: ScimFilterParser.AttrPathContext):
self._last_node = Q(ctx.getText())
def exitAttrPath(self, ctx: ScimFilterParser.AttrPathContext):
self._query = self._last_node
self._last_node = Q()

View file

@ -0,0 +1,46 @@
# Generated by Django 4.0.5 on 2022-06-06 21:37
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("authentik_core", "0020_application_open_in_new_tab"),
]
operations = [
migrations.CreateModel(
name="SCIMSource",
fields=[
(
"source_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_core.source",
),
),
(
"token",
models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="authentik_core.token",
),
),
],
options={
"verbose_name": "SCIM Source",
"verbose_name_plural": "SCIM Sources",
},
bases=("authentik_core.source",),
),
]

View file

@ -0,0 +1,36 @@
"""SCIM Source"""
from django.db import models
from django.utils.translation import gettext_lazy as _
from rest_framework.serializers import BaseSerializer
from authentik.core.models import Source, Token
USER_ATTRIBUTE_SCIM_ID = "goauthentik.io/sources/scim/id"
USER_ATTRIBUTE_SCIM_ADDRESS = "goauthentik.io/sources/scim/address"
USER_ATTRIBUTE_SCIM_ENTERPRISE = "goauthentik.io/sources/scim/enterprise"
class SCIMSource(Source):
"""System for Cross-domain Identity Management Source, allows for
cross-system user provisioning"""
token = models.ForeignKey(Token, on_delete=models.CASCADE, null=True, default=None)
@property
def component(self) -> str:
"""Return component used to edit this object"""
return "ak-source-scim-form"
@property
def serializer(self) -> BaseSerializer:
from authentik.sources.scim.api import SCIMSourceSerializer
return SCIMSourceSerializer
def __str__(self) -> str:
return f"SCIM Source {self.name}"
class Meta:
verbose_name = _("SCIM Source")
verbose_name_plural = _("SCIM Sources")

File diff suppressed because it is too large Load diff

View file

View file

@ -0,0 +1,86 @@
"""Test SCIM Auth"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Token, TokenIntents
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.models import SCIMSource
class TestSCIMAuth(APITestCase):
"""Test SCIM Auth view"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.token = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.token2 = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.token3 = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.source = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token
)
self.source2 = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token2
)
def test_auth_ok(self):
"""Test successful auth"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_auth_missing(self):
"""Test without header"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
},
),
)
self.assertEqual(response.status_code, 403)
def test_auth_wrong_token(self):
"""Test with wrong token"""
# Token for wrong source
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token2.key}",
)
self.assertEqual(response.status_code, 403)
# Token for no source
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token3.key}",
)
self.assertEqual(response.status_code, 403)

View file

@ -0,0 +1,64 @@
"""Test SCIM ResourceTypes"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Token, TokenIntents
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.models import SCIMSource
class TestSCIMResourceTypes(APITestCase):
"""Test SCIM ResourceTypes view"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.token = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.source = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token
)
def test_resource_type(self):
"""Test full resource type view"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_resource_type_single(self):
"""Test single resource type"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.source.slug,
"resource_type": "ServiceProviderConfig",
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_resource_type_single_404(self):
"""Test single resource type (404"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.source.slug,
"resource_type": "foo",
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 404)

View file

@ -0,0 +1,64 @@
"""Test SCIM Schema"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Token, TokenIntents
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.models import SCIMSource
class TestSCIMSchemas(APITestCase):
"""Test SCIM Schema view"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.token = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.source = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token
)
def test_schema(self):
"""Test full schema view"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_schema_single(self):
"""Test single schema"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
"schema_uri": "urn:ietf:params:scim:schemas:core:2.0:Meta",
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_schema_single_404(self):
"""Test single schema (404"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.source.slug,
"schema_uri": "foo",
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 404)

View file

@ -0,0 +1,36 @@
"""Test SCIM ServiceProviderConfig"""
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Token, TokenIntents
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.models import SCIMSource
class TestSCIMServiceProviderConfig(APITestCase):
"""Test SCIM ServiceProviderConfig view"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.token = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.source = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token
)
def test_config(self):
"""Test full config view"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-service-provider-config",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)

View file

@ -0,0 +1,83 @@
"""Test SCIM User"""
from json import dumps
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Token, TokenIntents, User
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.sources.scim.models import USER_ATTRIBUTE_SCIM_ID, SCIMSource
from authentik.sources.scim.views.v2.base import SCIM_CONTENT_TYPE
class TestSCIMUsers(APITestCase):
"""Test SCIM User view"""
def setUp(self) -> None:
self.user = create_test_admin_user()
self.token = Token.objects.create(
user=self.user,
identifier=generate_id(),
intent=TokenIntents.INTENT_API,
)
self.source = SCIMSource.objects.create(
name=generate_id(), slug=generate_id(), token=self.token
)
def test_user_list(self):
"""Test full user list"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-users",
kwargs={
"source_slug": self.source.slug,
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_user_list_single(self):
"""Test full user list (single user)"""
response = self.client.get(
reverse(
"authentik_sources_scim:v2-users",
kwargs={
"source_slug": self.source.slug,
"user_id": str(self.user.pk),
},
),
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 200)
def test_user_create(self):
"""Test user create"""
ext_id = generate_id()
response = self.client.post(
reverse(
"authentik_sources_scim:v2-users",
kwargs={
"source_slug": self.source.slug,
},
),
data=dumps(
{
"userName": generate_id(),
"externalId": ext_id,
"emails": [
{
"primary": True,
"value": self.user.email,
}
],
}
),
content_type=SCIM_CONTENT_TYPE,
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
)
self.assertEqual(response.status_code, 201)
self.assertTrue(
User.objects.filter(**{f"attributes__{USER_ATTRIBUTE_SCIM_ID}": ext_id}).exists()
)

View file

@ -0,0 +1,64 @@
"""SCIM URLs"""
from django.urls import path
from authentik.sources.scim.views.v2 import (
base,
groups,
resource_types,
schemas,
service_provider_config,
users,
)
urlpatterns = [
path(
"<slug:source_slug>/v2",
base.SCIMRootView.as_view(),
name="v2-root",
),
path(
"<slug:source_slug>/v2/Users",
users.UsersView.as_view(),
name="v2-users",
),
path(
"<slug:source_slug>/v2/Users/<str:user_id>",
users.UsersView.as_view(),
name="v2-users",
),
path(
"<slug:source_slug>/v2/Groups",
groups.GroupsView.as_view(),
name="v2-groups",
),
path(
"<slug:source_slug>/v2/Groups/<str:group_id>",
groups.GroupsView.as_view(),
name="v2-groups",
),
path(
"<slug:source_slug>/v2/Schemas",
schemas.SchemaView.as_view(),
name="v2-schema",
),
path(
"<slug:source_slug>/v2/Schemas/<str:schema_uri>",
schemas.SchemaView.as_view(),
name="v2-schema",
),
path(
"<slug:source_slug>/v2/ServiceProviderConfig",
service_provider_config.ServiceProviderConfigView.as_view(),
name="v2-service-provider-config",
),
path(
"<slug:source_slug>/v2/ResourceTypes",
resource_types.ResourceTypesView.as_view(),
name="v2-resource-types",
),
path(
"<slug:source_slug>/v2/ResourceTypes/<str:resource_type>",
resource_types.ResourceTypesView.as_view(),
name="v2-resource-types",
),
]

View file

View file

@ -0,0 +1,46 @@
"""SCIM Token auth"""
from base64 import b64decode
from typing import Any, Optional, Union
from django.conf import settings
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework.request import Request
from authentik.core.models import Token, TokenIntents, User
class SCIMTokenAuth(BaseAuthentication):
"""SCIM Token auth"""
def legacy(self, key: str, source_slug: str) -> Optional[Token]: # pragma: no cover
"""Legacy HTTP-Basic auth for testing"""
if not settings.TEST and not settings.DEBUG:
return None
_username, _, password = b64decode(key.encode()).decode().partition(":")
token = self.check_token(password, source_slug)
if token:
return (token.user, token)
return None
def check_token(self, key: str, source_slug: str) -> Optional[Token]:
"""Check that a token exists, is not expired, and is assigned to the correct source"""
token = Token.filter_not_expired(key=key, intent=TokenIntents.INTENT_API).first()
if not token:
return None
if not token.scimsource_set.exists():
return None
if token.scimsource_set.first().slug != source_slug:
return None
return token
def authenticate(self, request: Request) -> Union[tuple[User, Any], None]:
kwargs = request._request.resolver_match.kwargs
source_slug = kwargs.get("source_slug", None)
auth = get_authorization_header(request).decode()
auth_type, _, key = auth.partition(" ")
if auth_type != "Bearer":
return self.legacy(key, source_slug)
token = self.check_token(key, source_slug)
if not token:
return None
return (token.user, token)

View file

@ -0,0 +1,81 @@
"""SCIM Utils"""
from typing import Optional
from urllib.parse import urlparse
from antlr4 import CommonTokenStream, InputStream, ParseTreeWalker
from django.urls import resolve
from rest_framework.parsers import JSONParser
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from authentik.core.models import Group, User
from authentik.sources.scim.filters.django import DjangoQueryListener
from authentik.sources.scim.filters.ScimFilterLexer import ScimFilterLexer
from authentik.sources.scim.filters.ScimFilterParser import ScimFilterParser
from authentik.sources.scim.views.v2.auth import SCIMTokenAuth
SCIM_CONTENT_TYPE = "application/scim+json"
class SCIMParser(JSONParser):
"""SCIM clients use a custom content type"""
media_type = SCIM_CONTENT_TYPE
class SCIMRenderer(JSONRenderer):
"""SCIM clients also expect a custom content type"""
media_type = SCIM_CONTENT_TYPE
class SCIMView(APIView):
"""Base class for SCIM Views"""
authentication_classes = [SCIMTokenAuth]
permission_classes = [IsAuthenticated]
parser_classes = [SCIMParser]
renderer_classes = [SCIMRenderer]
def patch_resolve_value(self, raw_value: dict) -> Optional[User | Group]:
"""Attempt to resolve a raw `value` attribute of a patch operation into
a database model"""
model = User
query = {}
if "$ref" in raw_value:
url = urlparse(raw_value["$ref"])
if match := resolve(url.path):
if match.url_name == "v2-users":
model = User
query = {"pk": int(match.kwargs["user_id"])}
elif "type" in raw_value:
match raw_value["tyoe"]:
case "User":
model = User
query = {"pk": int(raw_value["value"])}
case "Group":
model = Group
else:
return None
return model.objects.filter(**query).first()
def patch_parse_path(self, path: str):
"""Parse the path of a Patch Operation"""
lexer = ScimFilterLexer(InputStream(path))
stream = CommonTokenStream(lexer)
parser = ScimFilterParser(stream)
tree = parser.filter_()
listener = DjangoQueryListener()
walker = ParseTreeWalker()
walker.walk(listener, tree)
return listener.query
class SCIMRootView(SCIMView):
"""Root SCIM View"""
def dispatch(self, request: Request, *args, **kwargs) -> Response:
return Response({"message": "Use this base-URL with an SCIM-compatible system."})

View file

@ -0,0 +1,126 @@
"""SCIM Group Views"""
from typing import Optional
from django.core.paginator import Paginator
from django.db.transaction import atomic
from django.http import Http404, QueryDict
from django.urls import reverse
from rest_framework.request import Request
from rest_framework.response import Response
from structlog.stdlib import get_logger
from authentik.core.models import Group
from authentik.sources.scim.errors import PatchError
from authentik.sources.scim.views.v2.base import SCIM_CONTENT_TYPE, SCIMView
LOGGER = get_logger()
class GroupsView(SCIMView):
"""SCIM Group View"""
def group_to_scim(self, group: Group) -> dict:
"""Convert group to SCIM"""
return {
"id": str(group.pk),
"meta": {
"resourceType": "Group",
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-groups",
kwargs={
"source_slug": self.kwargs["source_slug"],
"group_id": str(group.pk),
},
)
),
},
"displayName": group.name,
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
}
def get(self, request: Request, group_id: Optional[str] = None, **kwargs) -> Response:
"""List Group handler"""
if group_id:
group = Group.objects.filter(pk=group_id).first()
if not group:
raise Http404
return Response(self.group_to_scim(group))
groups = Group.objects.all().order_by("pk")
per_page = 50
paginator = Paginator(groups, per_page=per_page)
start_index = int(request.query_params.get("startIndex", 1))
page = paginator.page(int(max(start_index / per_page, 1)))
return Response(
{
"totalResults": paginator.count,
"itemsPerPage": per_page,
"startIndex": page.start_index(),
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"Resources": [self.group_to_scim(group) for group in page],
}
)
def update_group(self, group: Group, data: QueryDict) -> Group:
"""Partial update a group"""
if "displayName" in data:
group.name = data.get("displayName")
return group
def post(self, request: Request, **kwargs) -> Response:
"""Create group handler"""
group = Group.objects.filter(name=request.data.get("displayName")).first()
if group:
LOGGER.debug("Found existing group")
return Response(status=409)
group = self.update_group(Group(), request.data)
group.save()
return Response(self.group_to_scim(group), status=201)
def patch(self, request: Request, group_id: str, **kwargs) -> Response:
"""Update group handler"""
group: Optional[Group] = Group.objects.filter(pk=group_id).first()
if not group:
raise Http404
if request.data.get("schemas", []) != ["urn:ietf:params:scim:api:messages:2.0:PatchOp"]:
return Response(status=400)
try:
with atomic():
for op in request.data.get("Operations", []):
path = self.patch_parse_path(op["path"])
operation = op["op"]
raw_value = op.get("value", None)
values = []
for value in raw_value:
values.append(self.patch_resolve_value(value))
match operation:
case "add":
group.users.add(*[x.pk for x in values])
case "remove":
pass
return Response(self.group_to_scim(group), status=200)
except (KeyError, PatchError):
return Response(status=400)
def put(self, request: Request, group_id: str, **kwargs) -> Response:
"""Update group handler"""
group: Optional[Group] = Group.objects.filter(pk=group_id).first()
if not group:
raise Http404
self.update_group(group, request.data)
group.save()
return Response(self.group_to_scim(group), status=200)
def delete(self, request: Request, group_id: str, **kwargs) -> Response:
"""Delete group handler"""
group: Optional[Group] = Group.objects.filter(pk=group_id).first()
if not group:
raise Http404
group.delete()
return Response(
{},
status=204,
headers={
"Content-Type": SCIM_CONTENT_TYPE,
},
)

View file

@ -0,0 +1,153 @@
"""SCIM Meta views"""
from typing import Optional
from django.http import Http404
from django.urls import reverse
from rest_framework.request import Request
from rest_framework.response import Response
from authentik.sources.scim.views.v2.base import SCIMView
class ResourceTypesView(SCIMView):
"""https://ldapwiki.com/wiki/SCIM%20ResourceTypes%20endpoint"""
def get_resource_types(self):
"""List all resource types"""
return [
{
"id": "ServiceProviderConfig",
"name": "ServiceProviderConfig",
"description": "the service providers configuration",
"endpoint": "/ServiceProviderConfig",
"schema": "urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:ResourceType",
],
"meta": {
"resourceType": "ResourceType",
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.kwargs["source_slug"],
"resource_type": "ServiceProviderConfig",
},
)
),
},
},
{
"id": "ResourceType",
"name": "ResourceType",
"description": "ResourceType",
"endpoint": "/ResourceTypes",
"schema": "urn:ietf:params:scim:schemas:core:2.0:ResourceType",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:ResourceType",
],
"meta": {
"resourceType": "ResourceType",
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.kwargs["source_slug"],
"resource_type": "ResourceType",
},
)
),
},
},
{
"id": "Schema",
"name": "Schema",
"description": "Schema endpoint description",
"endpoint": "/Schemas",
"schema": "urn:ietf:params:scim:schemas:core:2.0:Schema",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:ResourceType",
],
"meta": {
"resourceType": "ResourceType",
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.kwargs["source_slug"],
"resource_type": "Schema",
},
)
),
},
},
{
"id": "User",
"name": "User",
"endpoint": "/Users",
"description": "https://tools.ietf.org/html/rfc7643#section-8.7.1",
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ResourceType"],
"schema": "urn:ietf:params:scim:schemas:core:2.0:User",
"schemaExtensions": [
{
"schema": "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
"required": True,
}
],
"meta": {
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.kwargs["source_slug"],
"resource_type": "User",
},
)
),
"resourceType": "ResourceType",
},
},
{
"id": "Group",
"name": "Group",
"description": "Group",
"endpoint": "/Groups",
"schema": "urn:ietf:params:scim:schemas:core:2.0:Group",
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:ResourceType",
],
"meta": {
"resourceType": "ResourceType",
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-resource-types",
kwargs={
"source_slug": self.kwargs["source_slug"],
"resource_type": "Group",
},
)
),
},
},
]
# pylint: disable=unused-argument
def get(
self, request: Request, source_slug: str, resource_type: Optional[str] = None
) -> Response:
"""Get resource types as SCIM response"""
resource_types = self.get_resource_types()
if resource_type:
resource = [x for x in resource_types if x.get("id") == resource_type]
if resource:
return Response(resource[0])
raise Http404
return Response(
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": len(resource_types),
"itemsPerPage": len(resource_types),
"startIndex": 1,
"Resources": resource_types,
}
)

View file

@ -0,0 +1,52 @@
"""Schema Views"""
from json import loads
from typing import Optional
from django.http import Http404
from django.urls import reverse
from rest_framework.request import Request
from rest_framework.response import Response
from authentik.sources.scim.views.v2.base import SCIMView
with open("authentik/sources/scim/schemas/schema.json", "r", encoding="utf-8") as SCHEMA_FILE:
_raw_schemas = loads(SCHEMA_FILE.read())
class SchemaView(SCIMView):
"""https://ldapwiki.com/wiki/SCIM%20Schemas%20Attribute"""
def get_schemas(self):
"""List of all schemas"""
schemas = []
for raw_schema in _raw_schemas:
raw_schema["meta"]["location"] = self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-schema",
kwargs={
"source_slug": self.kwargs["source_slug"],
"schema_uri": raw_schema["id"],
},
)
)
schemas.append(raw_schema)
return schemas
# pylint: disable=unused-argument
def get(self, request: Request, source_slug: str, schema_uri: Optional[str] = None) -> Response:
"""Get schemas as SCIM response"""
schemas = self.get_schemas()
if schema_uri:
schema = [x for x in schemas if x.get("id") == schema_uri]
if schema:
return Response(schema[0])
raise Http404
return Response(
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"totalResults": len(schemas),
"itemsPerPage": len(schemas),
"startIndex": 1,
"Resources": schemas,
}
)

View file

@ -0,0 +1,35 @@
"""SCIM Meta views"""
from rest_framework.request import Request
from rest_framework.response import Response
from authentik.sources.scim.views.v2.base import SCIMView
class ServiceProviderConfigView(SCIMView):
"""ServiceProviderConfig, https://ldapwiki.com/wiki/SCIM%20ServiceProviderConfig%20endpoint"""
# pylint: disable=unused-argument
def get(self, request: Request, source_slug: str) -> Response:
"""Get ServiceProviderConfig"""
return Response(
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
"authenticationSchemes": [
{
"type": "oauthbearertoken",
"name": "OAuth Bearer Token",
"description": (
"Authentication scheme using the OAuth Bearer Token Standard"
),
"specUri": "https://www.rfc-editor.org/info/rfc6750",
"primary": True,
},
],
"patch": {"supported": True},
"bulk": {"supported": False, "maxOperations": 0, "maxPayloadSize": 0},
"filter": {"supported": False, "maxResults": 200},
"changePassword": {"supported": False},
"sort": {"supported": False},
"etag": {"supported": False},
}
)

View file

@ -0,0 +1,154 @@
"""SCIM User Views"""
from typing import Optional
from django.core.paginator import Paginator
from django.http import Http404, QueryDict
from django.urls import reverse
from guardian.shortcuts import get_anonymous_user
from rest_framework.exceptions import ValidationError
from rest_framework.request import Request
from rest_framework.response import Response
from structlog.stdlib import get_logger
from authentik.core.models import User
from authentik.sources.scim.models import (
USER_ATTRIBUTE_SCIM_ADDRESS,
USER_ATTRIBUTE_SCIM_ENTERPRISE,
USER_ATTRIBUTE_SCIM_ID,
)
from authentik.sources.scim.views.v2.base import SCIM_CONTENT_TYPE, SCIMView
LOGGER = get_logger()
class UsersView(SCIMView):
"""SCIM User view"""
def get_email(self, data: list[dict]) -> str:
"""Wrapper to get primary email or first email"""
for email in data:
if email.get("primary", False):
return email.get("value")
return data[0].get("value")
def user_to_scim(self, user: User) -> dict:
"""Convert User to SCIM data"""
payload = {
"id": str(user.pk),
"meta": {
"resourceType": "User",
"created": user.date_joined,
# TODO: use events to find last edit?
"lastModified": user.date_joined,
"location": self.request.build_absolute_uri(
reverse(
"authentik_sources_scim:v2-users",
kwargs={
"source_slug": self.kwargs["source_slug"],
"user_id": str(user.pk),
},
)
),
},
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": user.attributes.get(
USER_ATTRIBUTE_SCIM_ENTERPRISE, {}
),
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
],
"userName": user.username,
"name": {},
"displayName": user.name,
"active": user.is_active,
"emails": [{"value": user.email, "type": "work", "primary": True}],
}
if USER_ATTRIBUTE_SCIM_ID in user.attributes:
payload["externalId"] = user.attributes[USER_ATTRIBUTE_SCIM_ID]
return payload
def get(self, request: Request, user_id: Optional[str] = None, **kwargs) -> Response:
"""List User handler"""
if user_id:
user = User.objects.filter(pk=user_id).first()
if not user:
raise Http404
return Response(self.user_to_scim(user))
users = User.objects.all().exclude(pk=get_anonymous_user().pk).order_by("pk")
per_page = 50
paginator = Paginator(users, per_page=per_page)
start_index = int(request.query_params.get("startIndex", 1))
page = paginator.page(int(max(start_index / per_page, 1)))
return Response(
{
"totalResults": paginator.count,
"itemsPerPage": per_page,
"startIndex": page.start_index(),
"schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"Resources": [self.user_to_scim(user) for user in page],
}
)
def update_user(self, user: User, data: QueryDict) -> User:
"""Partial update a user"""
if "userName" in data:
user.username = data.get("userName")
if "name" in data:
user.name = data.get("name", {}).get("formatted", data.get("displayName"))
if "emails" in data:
user.email = self.get_email(data.get("emails"))
if "active" in data:
user.is_active = data.get("active")
if "externalId" in data:
user.attributes[USER_ATTRIBUTE_SCIM_ID] = data.get("externalId")
if "addresses" in data:
user.attributes[USER_ATTRIBUTE_SCIM_ADDRESS] = data.get("addresses")
if "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User" in data:
user.attributes[USER_ATTRIBUTE_SCIM_ENTERPRISE] = data.get(
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
)
if user.username == "":
raise ValidationError("Invalid user")
return user
def post(self, request: Request, **kwargs) -> Response:
"""Create user handler"""
user = User.objects.filter(
**{
f"attributes__{USER_ATTRIBUTE_SCIM_ID}": request.data.get("externalId"),
"username": request.data.get("userName"),
}
).first()
if user:
LOGGER.debug("Found existing user")
return Response(status=409)
user = self.update_user(User(), request.data)
user.save()
return Response(self.user_to_scim(user), status=201)
def patch(self, request: Request, user_id: str, **kwargs) -> Response:
"""Update user handler"""
return self.put(request, user_id, **kwargs)
def put(self, request: Request, user_id: str, **kwargs) -> Response:
"""Update user handler"""
user: Optional[User] = User.objects.filter(pk=user_id).first()
if not user:
raise Http404
self.update_user(user, request.data)
user.save()
return Response(self.user_to_scim(user), status=200)
def delete(self, request: Request, user_id: str, **kwargs) -> Response:
"""Delete user handler"""
user: Optional[User] = User.objects.filter(pk=user_id).first()
if not user:
raise Http404
user.delete()
return Response(
{},
status=204,
headers={
"Content-Type": SCIM_CONTENT_TYPE,
},
)

View file

@ -1,5 +1,6 @@
"""authentik multi-stage authentication engine""" """authentik multi-stage authentication engine"""
from datetime import timedelta from datetime import timedelta
from uuid import uuid4
from django.contrib import messages from django.contrib import messages
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
@ -52,17 +53,13 @@ class EmailStageView(ChallengeStageView):
kwargs={"flow_slug": self.executor.flow.slug}, kwargs={"flow_slug": self.executor.flow.slug},
) )
# Parse query string from current URL (full query string) # 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) 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) query_params.update(kwargs)
print(query_params)
full_url = base_url full_url = base_url
if len(query_params) > 0: if len(query_params) > 0:
full_url = f"{full_url}?{query_params.urlencode()}" full_url = f"{full_url}?{query_params.urlencode()}"
@ -75,7 +72,7 @@ class EmailStageView(ChallengeStageView):
valid_delta = timedelta( valid_delta = timedelta(
minutes=current_stage.token_expiry + 1 minutes=current_stage.token_expiry + 1
) # + 1 because django timesince always rounds down ) # + 1 because django timesince always rounds down
identifier = slugify(f"ak-email-stage-{current_stage.name}-{pending_user}") identifier = slugify(f"ak-email-stage-{current_stage.name}-{str(uuid4())}")
# Don't check for validity here, we only care if the token exists # Don't check for validity here, we only care if the token exists
tokens = FlowToken.objects.filter(identifier=identifier) tokens = FlowToken.objects.filter(identifier=identifier)
if not tokens.exists(): if not tokens.exists():

View file

@ -259,7 +259,7 @@ class TestEmailStage(FlowTestCase):
session.save() session.save()
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) 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) request = self.factory.get(url)
stage_view = EmailStageView( stage_view = EmailStageView(
FlowExecutorView( FlowExecutorView(
@ -273,31 +273,3 @@ class TestEmailStage(FlowTestCase):
stage_view.get_full_url(**{QS_KEY_TOKEN: token}), stage_view.get_full_url(**{QS_KEY_TOKEN: token}),
f"http://testserver/if/flow/{self.flow.slug}/?foo=bar&flow_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

@ -1521,6 +1521,43 @@
} }
} }
}, },
{
"type": "object",
"required": [
"model",
"identifiers"
],
"properties": {
"model": {
"const": "authentik_sources_scim.scimsource"
},
"id": {
"type": "string"
},
"state": {
"type": "string",
"enum": [
"absent",
"present",
"created",
"must_created"
],
"default": "present"
},
"conditions": {
"type": "array",
"items": {
"type": "boolean"
}
},
"attrs": {
"$ref": "#/$defs/model_authentik_sources_scim.scimsource"
},
"identifiers": {
"$ref": "#/$defs/model_authentik_sources_scim.scimsource"
}
}
},
{ {
"type": "object", "type": "object",
"required": [ "required": [
@ -3452,6 +3489,7 @@
"authentik.sources.oauth", "authentik.sources.oauth",
"authentik.sources.plex", "authentik.sources.plex",
"authentik.sources.saml", "authentik.sources.saml",
"authentik.sources.scim",
"authentik.stages.authenticator", "authentik.stages.authenticator",
"authentik.stages.authenticator_duo", "authentik.stages.authenticator_duo",
"authentik.stages.authenticator_sms", "authentik.stages.authenticator_sms",
@ -3527,6 +3565,7 @@
"authentik_sources_plex.plexsourceconnection", "authentik_sources_plex.plexsourceconnection",
"authentik_sources_saml.samlsource", "authentik_sources_saml.samlsource",
"authentik_sources_saml.usersamlsourceconnection", "authentik_sources_saml.usersamlsourceconnection",
"authentik_sources_scim.scimsource",
"authentik_stages_authenticator_duo.authenticatorduostage", "authentik_stages_authenticator_duo.authenticatorduostage",
"authentik_stages_authenticator_duo.duodevice", "authentik_stages_authenticator_duo.duodevice",
"authentik_stages_authenticator_sms.authenticatorsmsstage", "authentik_stages_authenticator_sms.authenticatorsmsstage",
@ -5700,6 +5739,74 @@
}, },
"required": [] "required": []
}, },
"model_authentik_sources_scim.scimsource": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"title": "Name",
"description": "Source's display Name."
},
"slug": {
"type": "string",
"maxLength": 50,
"minLength": 1,
"pattern": "^[-a-zA-Z0-9_]+$",
"title": "Slug",
"description": "Internal source name, used in URLs."
},
"enabled": {
"type": "boolean",
"title": "Enabled"
},
"authentication_flow": {
"type": "integer",
"title": "Authentication flow",
"description": "Flow to use when authenticating existing users."
},
"enrollment_flow": {
"type": "integer",
"title": "Enrollment flow",
"description": "Flow to use when enrolling new users."
},
"policy_engine_mode": {
"type": "string",
"enum": [
"all",
"any"
],
"title": "Policy engine mode"
},
"user_matching_mode": {
"type": "string",
"enum": [
"identifier",
"email_link",
"email_deny",
"username_link",
"username_deny"
],
"title": "User matching mode",
"description": "How the source determines if an existing user should be authenticated or a new user enrolled."
},
"user_path_template": {
"type": "string",
"minLength": 1,
"title": "User path template"
},
"icon": {
"type": "string",
"minLength": 1,
"title": "Icon"
},
"token": {
"type": "integer",
"title": "Token"
}
},
"required": []
},
"model_authentik_stages_authenticator_duo.authenticatorduostage": { "model_authentik_stages_authenticator_duo.authenticatorduostage": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

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

30
go.mod
View file

@ -13,24 +13,24 @@ require (
github.com/go-openapi/strfmt v0.21.7 github.com/go-openapi/strfmt v0.21.7
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.4.0 github.com/google/uuid v1.4.0
github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.1
github.com/gorilla/securecookie v1.1.1 github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.2.1 github.com/gorilla/sessions v1.2.2
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.1
github.com/jellydator/ttlcache/v3 v3.1.0 github.com/jellydator/ttlcache/v3 v3.1.0
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.7.0 github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.17.0 github.com/prometheus/client_golang v1.17.0
github.com/redis/go-redis/v9 v9.2.1 github.com/redis/go-redis/v9 v9.3.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
goauthentik.io/api/v3 v3.2023101.1 goauthentik.io/api/v3 v3.2023103.2
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.13.0 golang.org/x/oauth2 v0.14.0
golang.org/x/sync v0.4.0 golang.org/x/sync v0.5.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
) )
@ -42,7 +42,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/felixge/httpsnoop v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
@ -72,10 +72,10 @@ require (
go.mongodb.org/mongo-driver v1.11.3 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.14.0 // indirect golang.org/x/crypto v0.15.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.13.0 // indirect golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.14.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/square/go-jose.v2 v2.5.1 // indirect

63
go.sum
View file

@ -62,7 +62,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -73,8 +73,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
@ -200,6 +200,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -216,16 +218,16 @@ 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/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.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -295,8 +297,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -309,8 +311,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@ -356,8 +358,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.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 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2023101.1 h1:KIQ4wmxjE+geAVB0wBfmxW9Uzo/tA0dbd2hSUJ7YJ3M= goauthentik.io/api/v3 v3.2023103.2 h1:k3GOGc5vVfxkS8+a8KjQaqAOPfpCqDYLEIjKEewrxwo=
goauthentik.io/api/v3 v3.2023101.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= goauthentik.io/api/v3 v3.2023103.2/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-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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@ -370,8 +372,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -438,16 +440,16 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -460,8 +462,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -502,8 +504,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -519,8 +521,9 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View file

@ -27,14 +27,11 @@ type Config struct {
type RedisConfig struct { type RedisConfig struct {
Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"` Host string `yaml:"host" env:"AUTHENTIK_REDIS__HOST"`
Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"` Port int `yaml:"port" env:"AUTHENTIK_REDIS__PORT"`
DB int `yaml:"db" env:"AUTHENTIK_REDIS__DB"`
Username string `yaml:"username" env:"AUTHENTIK_REDIS__USERNAME"`
Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"` Password string `yaml:"password" env:"AUTHENTIK_REDIS__PASSWORD"`
TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"` TLS bool `yaml:"tls" env:"AUTHENTIK_REDIS__TLS"`
TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"` TLSReqs string `yaml:"tls_reqs" env:"AUTHENTIK_REDIS__TLS_REQS"`
DB int `yaml:"cache_db" env:"AUTHENTIK_REDIS__DB"`
CacheTimeout int `yaml:"cache_timeout" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT"`
CacheTimeoutFlows int `yaml:"cache_timeout_flows" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_FLOWS"`
CacheTimeoutPolicies int `yaml:"cache_timeout_policies" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_POLICIES"`
CacheTimeoutReputation int `yaml:"cache_timeout_reputation" env:"AUTHENTIK_REDIS__CACHE_TIMEOUT_REPUTATION"`
} }
type ListenConfig struct { type ListenConfig struct {

View file

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

View file

@ -29,16 +29,6 @@ var (
Name: "authentik_outpost_flow_timing_post_seconds", Name: "authentik_outpost_flow_timing_post_seconds",
Help: "Duration it took to send a challenge in seconds", Help: "Duration it took to send a challenge in seconds",
}, []string{"stage", "flow"}) }, []string{"stage", "flow"})
// NOTE: the following metrics are kept for compatibility purpose
FlowTimingGetLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_outpost_flow_timing_get",
Help: "Duration it took to get a challenge",
}, []string{"stage", "flow"})
FlowTimingPostLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_outpost_flow_timing_post",
Help: "Duration it took to send a challenge",
}, []string{"stage", "flow"})
) )
type SolverFunction func(*api.ChallengeTypes, api.ApiFlowsExecutorSolveRequest) (api.FlowChallengeResponseRequest, error) type SolverFunction func(*api.ChallengeTypes, api.ApiFlowsExecutorSolveRequest) (api.FlowChallengeResponseRequest, error)
@ -198,10 +188,6 @@ func (fe *FlowExecutor) getInitialChallenge() (*api.ChallengeTypes, error) {
"stage": ch.GetComponent(), "stage": ch.GetComponent(),
"flow": fe.flowSlug, "flow": fe.flowSlug,
}).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)) / float64(time.Second)) }).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)) / float64(time.Second))
FlowTimingGetLegacy.With(prometheus.Labels{
"stage": ch.GetComponent(),
"flow": fe.flowSlug,
}).Observe(float64(gcsp.EndTime.Sub(gcsp.StartTime)))
return challenge, nil return challenge, nil
} }
@ -259,10 +245,6 @@ func (fe *FlowExecutor) solveFlowChallenge(challenge *api.ChallengeTypes, depth
"stage": ch.GetComponent(), "stage": ch.GetComponent(),
"flow": fe.flowSlug, "flow": fe.flowSlug,
}).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)) / float64(time.Second)) }).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)) / float64(time.Second))
FlowTimingPostLegacy.With(prometheus.Labels{
"stage": ch.GetComponent(),
"flow": fe.flowSlug,
}).Observe(float64(scsp.EndTime.Sub(scsp.StartTime)))
if depth >= 10 { if depth >= 10 {
return false, errors.New("exceeded stage recursion depth") return false, errors.New("exceeded stage recursion depth")

View file

@ -22,11 +22,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD
"type": "bind", "type": "bind",
"app": selectedApp, "app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": ls.ac.Outpost.Name,
"type": "bind",
"app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Bind request") req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Bind request")
}() }()
@ -55,12 +50,6 @@ func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LD
"reason": "no_provider", "reason": "no_provider",
"app": "", "app": "",
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ls.ac.Outpost.Name,
"type": "bind",
"reason": "no_provider",
"app": "",
}).Inc()
return ldap.LDAPResultInsufficientAccessRights, nil return ldap.LDAPResultInsufficientAccessRights, nil
} }

View file

@ -47,12 +47,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
"reason": "flow_error", "reason": "flow_error",
"app": db.si.GetAppSlug(), "app": db.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": db.si.GetOutpostName(),
"type": "bind",
"reason": "flow_error",
"app": db.si.GetAppSlug(),
}).Inc()
req.Log().WithError(err).Warning("failed to execute flow") req.Log().WithError(err).Warning("failed to execute flow")
return ldap.LDAPResultInvalidCredentials, nil return ldap.LDAPResultInvalidCredentials, nil
} }
@ -63,12 +57,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
"reason": "invalid_credentials", "reason": "invalid_credentials",
"app": db.si.GetAppSlug(), "app": db.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": db.si.GetOutpostName(),
"type": "bind",
"reason": "invalid_credentials",
"app": db.si.GetAppSlug(),
}).Inc()
req.Log().Info("Invalid credentials") req.Log().Info("Invalid credentials")
return ldap.LDAPResultInvalidCredentials, nil return ldap.LDAPResultInvalidCredentials, nil
} }
@ -82,12 +70,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
"reason": "access_denied", "reason": "access_denied",
"app": db.si.GetAppSlug(), "app": db.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": db.si.GetOutpostName(),
"type": "bind",
"reason": "access_denied",
"app": db.si.GetAppSlug(),
}).Inc()
return ldap.LDAPResultInsufficientAccessRights, nil return ldap.LDAPResultInsufficientAccessRights, nil
} }
if err != nil { if err != nil {
@ -97,12 +79,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
"reason": "access_check_fail", "reason": "access_check_fail",
"app": db.si.GetAppSlug(), "app": db.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": db.si.GetOutpostName(),
"type": "bind",
"reason": "access_check_fail",
"app": db.si.GetAppSlug(),
}).Inc()
req.Log().WithError(err).Warning("failed to check access") req.Log().WithError(err).Warning("failed to check access")
return ldap.LDAPResultOperationsError, nil return ldap.LDAPResultOperationsError, nil
} }
@ -117,12 +93,6 @@ func (db *DirectBinder) Bind(username string, req *bind.Request) (ldap.LDAPResul
"reason": "user_info_fail", "reason": "user_info_fail",
"app": db.si.GetAppSlug(), "app": db.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": db.si.GetOutpostName(),
"type": "bind",
"reason": "user_info_fail",
"app": db.si.GetAppSlug(),
}).Inc()
req.Log().WithError(err).Warning("failed to get user info") req.Log().WithError(err).Warning("failed to get user info")
return ldap.LDAPResultOperationsError, nil return ldap.LDAPResultOperationsError, nil
} }

View file

@ -22,16 +22,6 @@ var (
Name: "authentik_outpost_ldap_requests_rejected_total", Name: "authentik_outpost_ldap_requests_rejected_total",
Help: "Total number of rejected requests", Help: "Total number of rejected requests",
}, []string{"outpost_name", "type", "reason", "app"}) }, []string{"outpost_name", "type", "reason", "app"})
// NOTE: the following metrics are kept for compatibility purpose
RequestsLegacy = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "authentik_outpost_ldap_requests",
Help: "The total number of configured providers",
}, []string{"outpost_name", "type", "app"})
RequestsRejectedLegacy = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "authentik_outpost_ldap_requests_rejected",
Help: "Total number of rejected requests",
}, []string{"outpost_name", "type", "reason", "app"})
) )
func RunServer() { func RunServer() {

View file

@ -23,11 +23,6 @@ func (ls *LDAPServer) Search(bindDN string, searchReq ldap.SearchRequest, conn n
"type": "search", "type": "search",
"app": selectedApp, "app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": ls.ac.Outpost.Name,
"type": "search",
"app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
req.Log().WithField("attributes", searchReq.Attributes).WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Search request") req.Log().WithField("attributes", searchReq.Attributes).WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Search request")
}() }()

View file

@ -45,12 +45,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "empty_bind_dn", "reason": "empty_bind_dn",
"app": ds.si.GetAppSlug(), "app": ds.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ds.si.GetOutpostName(),
"type": "search",
"reason": "empty_bind_dn",
"app": ds.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN)
} }
if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) {
@ -60,12 +54,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "invalid_bind_dn", "reason": "invalid_bind_dn",
"app": ds.si.GetAppSlug(), "app": ds.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ds.si.GetOutpostName(),
"type": "search",
"reason": "invalid_bind_dn",
"app": ds.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ds.si.GetBaseDN()) return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ds.si.GetBaseDN())
} }
@ -78,12 +66,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "user_info_not_cached", "reason": "user_info_not_cached",
"app": ds.si.GetAppSlug(), "app": ds.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ds.si.GetOutpostName(),
"type": "search",
"reason": "user_info_not_cached",
"app": ds.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied") return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
} }
accsp.Finish() accsp.Finish()
@ -96,12 +78,6 @@ func (ds *DirectSearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "filter_parse_fail", "reason": "filter_parse_fail",
"app": ds.si.GetAppSlug(), "app": ds.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ds.si.GetOutpostName(),
"type": "search",
"reason": "filter_parse_fail",
"app": ds.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: error parsing filter: %s", req.Filter) return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("Search Error: error parsing filter: %s", req.Filter)
} }

View file

@ -62,12 +62,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "empty_bind_dn", "reason": "empty_bind_dn",
"app": ms.si.GetAppSlug(), "app": ms.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ms.si.GetOutpostName(),
"type": "search",
"reason": "empty_bind_dn",
"app": ms.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN) return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: Anonymous BindDN not allowed %s", req.BindDN)
} }
if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) { if !utils.HasSuffixNoCase(req.BindDN, ","+baseDN) {
@ -77,12 +71,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "invalid_bind_dn", "reason": "invalid_bind_dn",
"app": ms.si.GetAppSlug(), "app": ms.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ms.si.GetOutpostName(),
"type": "search",
"reason": "invalid_bind_dn",
"app": ms.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ms.si.GetBaseDN()) return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, fmt.Errorf("Search Error: BindDN %s not in our BaseDN %s", req.BindDN, ms.si.GetBaseDN())
} }
@ -95,12 +83,6 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult,
"reason": "user_info_not_cached", "reason": "user_info_not_cached",
"app": ms.si.GetAppSlug(), "app": ms.si.GetAppSlug(),
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ms.si.GetOutpostName(),
"type": "search",
"reason": "user_info_not_cached",
"app": ms.si.GetAppSlug(),
}).Inc()
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied") return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
} }
accsp.Finish() accsp.Finish()

View file

@ -22,11 +22,6 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode
"type": "unbind", "type": "unbind",
"app": selectedApp, "app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second)) }).Observe(float64(span.EndTime.Sub(span.StartTime)) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": ls.ac.Outpost.Name,
"type": "unbind",
"app": selectedApp,
}).Observe(float64(span.EndTime.Sub(span.StartTime)))
req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Unbind request") req.Log().WithField("took-ms", span.EndTime.Sub(span.StartTime).Milliseconds()).Info("Unbind request")
}() }()
@ -55,11 +50,5 @@ func (ls *LDAPServer) Unbind(boundDN string, conn net.Conn) (ldap.LDAPResultCode
"reason": "no_provider", "reason": "no_provider",
"app": "", "app": "",
}).Inc() }).Inc()
metrics.RequestsRejectedLegacy.With(prometheus.Labels{
"outpost_name": ls.ac.Outpost.Name,
"type": "unbind",
"reason": "no_provider",
"app": "",
}).Inc()
return ldap.LDAPResultOperationsError, nil return ldap.LDAPResultOperationsError, nil
} }

View file

@ -173,12 +173,6 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
"method": r.Method, "method": r.Method,
"host": web.GetHost(r), "host": web.GetHost(r),
}).Observe(float64(elapsed) / float64(time.Second)) }).Observe(float64(elapsed) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": a.outpostName,
"type": "app",
"method": r.Method,
"host": web.GetHost(r),
}).Observe(float64(elapsed))
}) })
}) })
if server.API().GlobalConfig.ErrorReporting.Enabled { if server.API().GlobalConfig.ErrorReporting.Enabled {
@ -241,7 +235,10 @@ func (a *Application) Mode() api.ProxyMode {
return *a.proxyConfig.Mode return *a.proxyConfig.Mode
} }
func (a *Application) HasQuerySignature(r *http.Request) bool { func (a *Application) ShouldHandleURL(r *http.Request) bool {
if strings.HasPrefix(r.URL.Path, "/outpost.goauthentik.io") {
return true
}
if strings.EqualFold(r.URL.Query().Get(CallbackSignature), "true") { if strings.EqualFold(r.URL.Query().Get(CallbackSignature), "true") {
return true return true
} }

View file

@ -64,13 +64,6 @@ func (a *Application) configureProxy() error {
"scheme": r.URL.Scheme, "scheme": r.URL.Scheme,
"host": web.GetHost(r), "host": web.GetHost(r),
}).Observe(float64(elapsed) / float64(time.Second)) }).Observe(float64(elapsed) / float64(time.Second))
metrics.UpstreamTimingLegacy.With(prometheus.Labels{
"outpost_name": a.outpostName,
"upstream_host": r.URL.Host,
"method": r.Method,
"scheme": r.URL.Scheme,
"host": web.GetHost(r),
}).Observe(float64(elapsed))
}) })
return nil return nil
} }

View file

@ -71,7 +71,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL)
cs.Options.Domain = *p.CookieDomain cs.Options.Domain = *p.CookieDomain
cs.Options.SameSite = http.SameSiteLaxMode cs.Options.SameSite = http.SameSiteLaxMode
cs.Options.MaxAge = maxAge cs.Options.MaxAge = maxAge
cs.Options.Path = externalHost.Path cs.Options.Path = "/"
a.log.WithField("dir", dir).Trace("using filesystem session backend") a.log.WithField("dir", dir).Trace("using filesystem session backend")
return cs return cs
} }
@ -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 { if rs, ok := a.sessions.(*redisstore.RedisStore); ok {
client := rs.Client() client := rs.Client()
defer client.Close()
keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result() keys, err := client.Keys(ctx, fmt.Sprintf("%s*", RedisKeyPrefix)).Result()
if err != nil { if err != nil {
return err return err

View file

@ -26,12 +26,6 @@ func (ps *ProxyServer) HandlePing(rw http.ResponseWriter, r *http.Request) {
"host": web.GetHost(r), "host": web.GetHost(r),
"type": "ping", "type": "ping",
}).Observe(float64(elapsed) / float64(time.Second)) }).Observe(float64(elapsed) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": ps.akAPI.Outpost.Name,
"method": r.Method,
"host": web.GetHost(r),
"type": "ping",
}).Observe(float64(elapsed))
} }
func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) { func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
@ -44,12 +38,6 @@ func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
"host": web.GetHost(r), "host": web.GetHost(r),
"type": "static", "type": "static",
}).Observe(float64(elapsed) / float64(time.Second)) }).Observe(float64(elapsed) / float64(time.Second))
metrics.RequestsLegacy.With(prometheus.Labels{
"outpost_name": ps.akAPI.Outpost.Name,
"method": r.Method,
"host": web.GetHost(r),
"type": "static",
}).Observe(float64(elapsed))
} }
func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, string) { func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, string) {

Some files were not shown because too many files have changed in this diff Show more