Compare commits

..

763 Commits

Author SHA1 Message Date
e9910732bc release: 2021.12.2 2021-12-18 21:03:50 +01:00
246dd4b062 ci: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 21:03:47 +01:00
4425f8d183 ci: only build arm, amd64 on linux and darwin
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 21:02:20 +01:00
c410bb8c36 ci: fix dependency
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 20:50:59 +01:00
44f62a4773 website/docs: add 2021.12.2 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 20:39:16 +01:00
b6ff04694f providers/oauth2: don't rely on expiry task for access codes and refresh tokens
closes #1911

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 17:42:41 +01:00
d4ce0e8e41 web/elements: fix border between search buttons
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 17:34:28 +01:00
362d72da8c ci: fix shouldBuild being based off of harbor
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 17:01:51 +01:00
88d0f8d8a8 web: Update Web API Client version (#1958)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-18 16:19:18 +01:00
61097b9400 policies/password: add minimum digits
closes #1952

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 16:15:56 +01:00
7a73ddfb60 outposts/proxy: match skipPathRegex against full URL on domain auth
closes #1955

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 15:50:42 +01:00
d66f13c249 web: Update Web API Client version (#1957)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-18 15:38:52 +01:00
8cc3cb6a42 website/docs: fix reference to non-existent version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 15:34:39 +01:00
4c5537ddfe sources/oauth: allow writing to user in SourceConnection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1888
2021-12-18 15:33:46 +01:00
a95779157d tests/integration: add rename and full update tests for k8s controller
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 15:32:16 +01:00
70256727fd web: ignore instantSearchSDKJSBridgeClearHighlight error on edge on iOS
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 15:05:40 +01:00
ac6afb2b82 stages/email: add test for non-existent directory
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-18 15:05:40 +01:00
2ea7bd86e8 website/integrations: add Service Provider Binding: Post for rancher (#1956)
Adds a line to the docs that's important for Rancher and Authentik to work
2021-12-18 15:05:27 +01:00
95bce9c9e7 outposts: release binary outposts (#1954)
* outposts/proxy: always embed static assets, still check local

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

* ci: add initial ci to build outpost as binary

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

* ci: fix typo, build web

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

* ci: upload to release on publish, only run linux on ci

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

* ci: ensure latest go is used

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

* ci: split e2e tests into two halves

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-17 19:49:32 +00:00
71a22c2a34 outposts: add unittests for docker controller
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-17 13:42:33 +01:00
f3eb85877d web: Update Web API Client version (#1951)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-17 12:02:22 +01:00
273f5211a0 providers/saml: Fix typo (#1950) 2021-12-17 11:00:20 +00:00
db06428ab9 build(deps): bump goauthentik.io/api from 0.2021104.17 to 0.2021121.1 (#1948)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021104.17 to 0.2021121.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021104.17...v0.2021121.1)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-12-17 10:21:58 +01:00
109d8e48d4 website: update integrations categories to match new version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 21:38:37 +01:00
2ca115285c crypto: fix private keys not being imported correctly
closes #1945

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 21:14:15 +01:00
f5459645a5 web/admin: fix background colour for application sidebar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 21:06:08 +01:00
14c159500d core: don't rotate non-api tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 19:32:39 +01:00
03da87991f outposts: don't use custom environment
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 19:12:05 +01:00
e38ee9c580 web: Update Web API Client version (#1944)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-16 16:56:43 +01:00
3bf53b2db1 root: update security
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 16:54:48 +01:00
f33190caa5 release: 2021.12.1 2021-12-16 15:48:59 +01:00
741822424a Merge branch 'master' into version-2021.12 2021-12-16 15:48:53 +01:00
0ca6fbb224 website/docs: final 2021.12.1 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 15:48:47 +01:00
Sem
f72b652b24 website/integrations: Updated bookstack integration docs page (#1942)
In some cases one might need to define the full SAML property to enable proper group sync. (see: https://github.com/BookStackApp/BookStack/issues/3109 )
2021-12-16 14:23:00 +01:00
0a2c1eb419 web/elements: fix linting error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:27:08 +01:00
eb9593a847 web/elements: close notification drawer when clearing all notifications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:23:44 +01:00
7c71c52791 web/admin: add sidebar to applications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:23:30 +01:00
59493c02c4 web/elements: pass full Markdown object to ak-markdown, get title from metadata
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:18:43 +01:00
83089b47d3 web/elements: add Markdown component to improve rendering
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:10:46 +01:00
103e723d8c web/elements: add support for sidebar on table page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 12:10:28 +01:00
7d6e88061f outposts: check if hub from context is set and fallback
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 11:19:57 +01:00
f8aab40e3e internal: cleanup duplicate and redundant code, properly set sentry SDK scope settings
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 11:00:19 +01:00
5123bc1316 root: add sponsors to readme
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 10:30:13 +01:00
30e8408e85 web/admin: fix notification unread colours not matching on user and admin interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 10:17:17 +01:00
bb34474101 web/admin: fix stage related flows not being shown in a list
closes #1941

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-16 10:13:10 +01:00
a105760123 events: improve app lookup for event creation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 16:46:02 +01:00
f410a77010 lifecycle: add -Ofair to celery
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 16:44:09 +01:00
6ff8fdcc49 root: enable threading integration in sentry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 15:49:08 +01:00
50ca3dc772 core: fix error when attempting to provider from cached application
closes #1940

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 15:11:13 +01:00
2a09fc0ae2 release: 2021.12.1-rc5 2021-12-15 10:21:29 +01:00
fbb6756488 Merge branch 'master' into version-2021.12 2021-12-15 10:16:05 +01:00
f45fb2eac0 website/docs: prepare 2021.12.1-rc5
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 10:15:58 +01:00
7b8cde17e6 web/admin: show warning when deleting currently logged in user
closes #1937

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 10:11:35 +01:00
186634fc67 build(deps): bump @patternfly/patternfly from 4.159.1 to 4.164.2 in /web (#1938) 2021-12-15 08:58:46 +01:00
c84b1b7997 build(deps): bump goauthentik.io/api from 0.2021104.13 to 0.2021104.17 (#1939) 2021-12-15 08:58:30 +01:00
6e83467481 web/flows: fix error when attempting to enroll new webauthn device
closes #1936

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-15 00:24:46 +01:00
72db17f23b stages/identification: fix miscalculated sleep
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 23:31:08 +01:00
ee4e176039 web/admin: fix invalid display for LDAP Source sync status
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 23:00:45 +01:00
e18e681c2b events: dont store full backtrace in systemtask
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 22:55:38 +01:00
10fe67e08d sources/ldap: fix incorrect task names being referenced, use source native slug
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 22:53:14 +01:00
fc1db83be7 web: Update Web API Client version (#1935)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-14 22:19:46 +01:00
3740e65906 web/admin: add dashboard with user creation/login statistics
closes #1867

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 22:08:41 +01:00
30386cd899 events: add custom manager with helpers for metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 21:49:33 +01:00
64a10e9a46 events: fix schema for top_per_user
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 21:08:15 +01:00
77d6242cce web/admin: fix extra closing element
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 20:53:25 +01:00
9a86dcaec3 web: Update Web API Client version (#1934)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-14 16:26:21 +01:00
0b00768b84 events: add flow_execution event type
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 16:13:51 +01:00
d162c79373 flows: fix wrong exception being caught in flow inspector
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 16:06:00 +01:00
05db352a0f web: add link to open API Browser for API Drawer
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 16:03:42 +01:00
5bf3d7fe02 web: Update Web API Client version (#1933)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-14 15:59:26 +01:00
1ae1cbebf4 web/admin: re-organise sidebar items
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:57:03 +01:00
8c16dfc478 stages/invitation: use GroupMemberSerializer serializer to prevent all of the user's groups and their users from being returned
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:56:13 +01:00
c6a3286e4c web/admin: update overview page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:23:32 +01:00
44cfd7e5b0 web: accept header as slot in PageHeader
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:23:20 +01:00
210d4c5058 web: add helper to navigate with params
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:23:02 +01:00
6b39d616b1 web/elements: allow aggregate cards' elements to not be centered
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 15:22:52 +01:00
32ace1bece crypto: add additional validation before importing a certificate
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 14:49:25 +01:00
54f893b84f flows: add additional sentry spans
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 11:59:36 +01:00
b5685ec072 outposts: set sentry-trace on API requests to match them to the outer transaction
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 11:50:31 +01:00
5854833240 stages/authenticator_webauthn: fix migrations for different choices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 11:06:46 +01:00
4b2437a6f1 stages/authenticator_webauthn: use correct choices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 10:51:34 +01:00
2981ac7b10 tests/e2e: use ghcr for e2e tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 10:36:47 +01:00
59a51c859a stages/authenticator_webauthn: add migration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 10:09:35 +01:00
47bab6c182 web: Update Web API Client version (#1932)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-14 10:02:50 +01:00
4e6714fffe stages/authenticator_webauthn: make user_verification configurable
closes #1921

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 09:58:20 +01:00
aa6b595545 root: bump python dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 09:45:36 +01:00
0131b1f6cc sources/oauth: fix wrong redirect URL being generated
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 09:34:47 +01:00
9f53c359dd build(deps): bump typescript from 4.5.3 to 4.5.4 in /web (#1926) 2021-12-14 08:31:56 +01:00
28e4dba3e8 build(deps): bump @babel/core from 7.16.0 to 7.16.5 in /web (#1929) 2021-12-14 08:31:36 +01:00
2afd46e1df build(deps): bump @babel/plugin-transform-runtime in /web (#1922) 2021-12-14 08:31:28 +01:00
f5991b19be build(deps): bump @babel/preset-typescript from 7.16.0 to 7.16.5 in /web (#1925) 2021-12-14 08:31:19 +01:00
5cc75cb25c build(deps): bump @typescript-eslint/parser from 5.6.0 to 5.7.0 in /web (#1923) 2021-12-14 08:31:04 +01:00
68c1df2d39 build(deps): bump @rollup/plugin-node-resolve in /web (#1924) 2021-12-14 08:30:35 +01:00
c83724f45c build(deps): bump @babel/preset-env from 7.16.4 to 7.16.5 in /web (#1930) 2021-12-14 08:29:56 +01:00
5f91c150df build(deps): bump @babel/plugin-proposal-decorators in /web (#1927) 2021-12-14 08:29:36 +01:00
0bfe999442 build(deps): bump @typescript-eslint/eslint-plugin in /web (#1928) 2021-12-14 08:29:13 +01:00
58440b16c4 build(deps): bump goauthentik.io/api from 0.2021104.11 to 0.2021104.13 (#1931) 2021-12-14 08:28:42 +01:00
57757a2ff5 web: Update Web API Client version (#1920) 2021-12-14 01:11:32 +01:00
2993f506a7 sources/oauth: implement apple native sign-in using the apple JS SDK
closes #1881

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-14 00:40:29 +01:00
e4841d54a1 *: migrate ui_* properties to functions to allow context being passed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 23:56:35 +01:00
4f05dcec89 sources/oauth: allow oauth types to override their login button challenge
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 23:45:11 +01:00
ede6bcd31e *: remove debug statements from tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 23:41:08 +01:00
728c8e994d sources/oauth: strip parts of custom apple client_id
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 23:26:00 +01:00
5290b64415 web: Update Web API Client version
commit 96533a743c
Author: BeryJu <BeryJu@users.noreply.github.com>
Date:   Mon Dec 13 20:50:45 2021 +0000

    web: Update Web API Client version

    Signed-off-by: GitHub <noreply@github.com>

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 22:53:28 +01:00
fec6de1ba2 providers/oauth2: add additional logging to show with token path is taken
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 22:49:42 +01:00
69678dcfa6 providers/oauth2: use generate_key instead of uuid4
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 22:13:20 +01:00
4911a243ff sources/oauth: add initial okta type
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1910
2021-12-13 21:48:59 +01:00
70316b37da web/admin: only show source name not description
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 21:48:45 +01:00
307cb94e3b website: add initial redirect (#1918)
* website: add initial redirect

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

* website: add integrations too

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

* website: add docs to netlify config

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

* website: use splats correctly

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

* add status

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 20:42:31 +00:00
ace53a8fa5 root: remove lxml version workaround
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 21:08:50 +01:00
0544dc3f83 web: use correct transaction names for web
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 21:03:30 +01:00
708ff300a3 website: remove remaining /index URLs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 19:01:16 +01:00
4e63f0f215 core: add fallback for missing sentry trace
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 18:06:01 +01:00
141481df3a web: send sentry-trace header in API requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 17:41:11 +01:00
29241cc287 core: always inject sentry trace into template
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 17:41:00 +01:00
e81e97d404 root: add .python-version so dependabot doesn't use broken python 3.10.0
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 17:23:42 +01:00
a5182e5c24 root: custom sentry-sdk, attempt #3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 17:00:18 +01:00
cf5ff6e160 outposts: reset backoff after successful connect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:38:48 +01:00
f2b3a2ec91 providers/saml: optimise excessive queries to user when evaluating attributes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:38:38 +01:00
69780c67a9 lib: set evaluation span's description based on filename
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:32:01 +01:00
ac9cf590bc *: use prefixed span names
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:18:42 +01:00
cb6edcb198 core: set tag with request ID
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:15:27 +01:00
8eecc28c3c events: add sentry for geoip
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:15:20 +01:00
10b16bc36a outposts: add description to span
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 16:12:14 +01:00
2fe88cfea9 root: don't stale enhancement/confirmed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 15:51:30 +01:00
caab396b56 web/admin: improve wording for froward_auth, don't show setup when using proxy mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 15:36:05 +01:00
5f0f4284a2 web/admin: fix rendering for applications on view page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 15:27:28 +01:00
c11be2284d outposts/proxy: also set max length for redis backend
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 15:05:55 +01:00
aa321196d7 outposts/proxy: fix securecookie: the value is too long again, since it can happen even with filesystem storage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 13:33:20 +01:00
ff03db61a8 web/admin: fix rendering of applications with custom icon
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 13:21:14 +01:00
f3b3ce6572 website/docs: add 2021.12.1-rc4 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 12:56:34 +01:00
09b02e1aec release: 2021.12.1-rc4 2021-12-13 12:53:58 +01:00
451a9aaf01 Merge branch 'master' into version-2021.12 2021-12-13 12:53:50 +01:00
eaee7cb562 root: use lxml 4.6.5
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 12:21:27 +01:00
a010c91a52 website/docs: update references for new docusaurus version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 11:56:26 +01:00
709194330f root: install lxml before regular install to prevent xmlsec issues
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 11:26:05 +01:00
5914bbf173 Merge branch 'master' into version-2021.12
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	Dockerfile
2021-12-13 10:54:21 +01:00
5e9166f859 root: lock lxml to 4.6.4 to prevent xmlsec issues with lxml-version.h missing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 10:47:59 +01:00
35b8ef6592 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1912)
Bumps [@docusaurus/plugin-client-redirects](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-plugin-client-redirects) from 2.0.0-beta.9 to 2.0.0-beta.13.
- [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/v2.0.0-beta.13/packages/docusaurus-plugin-client-redirects)

---
updated-dependencies:
- dependency-name: "@docusaurus/plugin-client-redirects"
  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>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 10:21:33 +01:00
772a939f17 tests/e2e: remove version assertion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 09:26:07 +01:00
24971801cf build(deps): bump @docusaurus/preset-classic in /website (#1916)
Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-beta.9 to 2.0.0-beta.13.
- [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/v2.0.0-beta.13/packages/docusaurus-preset-classic)

---
updated-dependencies:
- dependency-name: "@docusaurus/preset-classic"
  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>
2021-12-13 09:24:38 +01:00
43aebe8cb2 build(deps): bump @sentry/tracing from 6.16.0 to 6.16.1 in /web (#1914) 2021-12-13 09:09:32 +01:00
19cfc87c84 build(deps): bump postcss from 8.4.4 to 8.4.5 in /website (#1913) 2021-12-13 08:48:24 +01:00
f920f183c8 build(deps): bump @sentry/browser from 6.16.0 to 6.16.1 in /web (#1915) 2021-12-13 08:47:54 +01:00
97f979c81e build(deps): bump rollup from 2.61.0 to 2.61.1 in /web (#1917) 2021-12-13 08:38:12 +01:00
e61411d396 Revert "Revert "root: use custom sentry-sdk""
This reverts commit c4f985f542.

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-13 00:01:59 +01:00
c4f985f542 Revert "root: use custom sentry-sdk"
This reverts commit 302dee7ab2.
2021-12-12 23:52:11 +01:00
302dee7ab2 root: use custom sentry-sdk
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 22:11:20 +01:00
83c12ad483 flows: fix description for spans
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 21:51:51 +01:00
4224fd5c6f lib: correctly report "faked" IPs to sentry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 20:54:29 +01:00
597ce1eb42 Revert "*: use cache.delete_pattern instead of getting keys and deleting them"
This reverts commit ff481ba6e7.

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

# Conflicts:
#	authentik/flows/views/executor.py
#	authentik/policies/signals.py
2021-12-12 20:41:34 +01:00
5ef385f0bb policies: don't always clear application cache on post_save
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 20:39:04 +01:00
cda4be3d47 flows: add additional tags
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 20:37:20 +01:00
8cdf22fc94 root: set default redis iter to 1000
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 20:24:43 +01:00
6efc7578ef flows: add additional sentry spans to flow executor
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 20:04:21 +01:00
4e2457560d outposts/proxy: use filesystem storage for non-embedded outposts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 17:59:31 +01:00
2ddf122d27 Revert "outposts/proxy: don't save raw jwt in cookie to prevent securecookie: the value is too long"
This reverts commit b3e40c6aed.
2021-12-12 17:58:19 +01:00
a24651437a website/docs: simplify traefik compose example
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 17:18:55 +01:00
30bb7acb17 website/docs: fix escaping for docker-compose annotations
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 17:13:46 +01:00
7859145138 outposts: don't try to create docker client for embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 17:13:26 +01:00
8a8aafec81 root: enable boto3 sentry integration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 14:38:24 +01:00
deebdf2bcc outposts: fix unlabeled transaction
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 13:46:31 +01:00
4982c4abcb outpost: add additional checks for websocket connection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-12 00:11:17 +01:00
1486f90077 tests/e2e: cleanup output from e2e containers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 23:27:57 +01:00
f4988bc45e outpost: rewrite re-connect logic without recws
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 22:53:59 +01:00
8abc9cc031 outposts: cleanup logs for failed binds
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 22:09:18 +01:00
534689895c lib: remove old load_local_files setting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 22:03:06 +01:00
8a0dd6be24 outposts: handle RuntimeError during websocket connect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 22:01:55 +01:00
65d2eed82d stagse/authenticator_webauthn: remove pydantic import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 20:32:25 +01:00
e450e7b107 root: add wsproto to default packages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 20:20:28 +01:00
552ddda909 lifecycle: use custom worker class
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 19:55:09 +01:00
bafeff7306 outposts: improve logging for outpost controllers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 15:35:20 +01:00
6791436302 root: fix certs file missing in container
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 15:01:04 +01:00
7eda794070 outposts: fix docker controller not stopping containers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1859
2021-12-11 14:00:15 +01:00
e3129c1067 root: bump celery messages to info
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-11 13:59:56 +01:00
ff481ba6e7 *: use cache.delete_pattern instead of getting keys and deleting them
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-10 21:35:28 +01:00
a106bad2db tests/e2e: use correct container image
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-10 21:11:37 +01:00
3a1c311d02 website/docs: Added FortiManager Link (#1908) 2021-12-10 20:57:36 +01:00
6465333f4f website/docs: Add FortiManager intergration instructions (#1907) 2021-12-10 20:57:22 +01:00
b761659227 root: use ghcr for containers during testing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-10 20:57:09 +01:00
9321c355f8 build(deps): bump construct-style-sheets-polyfill in /web (#1905)
Bumps [construct-style-sheets-polyfill](https://github.com/calebdwilliams/construct-style-sheets) from 2.4.17 to 3.0.5.
- [Release notes](https://github.com/calebdwilliams/construct-style-sheets/releases)
- [Changelog](https://github.com/calebdwilliams/construct-style-sheets/blob/main/CHANGELOG.md)
- [Commits](https://github.com/calebdwilliams/construct-style-sheets/commits)

---
updated-dependencies:
- dependency-name: construct-style-sheets-polyfill
  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>
2021-12-10 09:41:24 +01:00
86c8e79ea1 website: rollback to beta.9 to fix build issues
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-10 09:26:05 +01:00
8916b1f8ab build(deps): bump @docusaurus/preset-classic in /website (#1902) 2021-12-10 08:40:01 +01:00
41fcf2aba6 build(deps): bump golang from 1.17.4-bullseye to 1.17.5-bullseye (#1900) 2021-12-10 08:39:36 +01:00
87e72b08a9 build(deps): bump rollup from 2.60.2 to 2.61.0 in /web (#1901) 2021-12-10 08:39:25 +01:00
b2fcd42e3c build(deps): bump typescript from 4.5.2 to 4.5.3 in /web (#1903) 2021-12-10 08:38:30 +01:00
fc1b47a80f build(deps): bump @docusaurus/plugin-client-redirects in /website (#1904) 2021-12-10 08:37:56 +01:00
af14e3502e build(deps): bump goauthentik.io/api from 0.2021104.10 to 0.2021104.11 (#1906) 2021-12-10 08:37:36 +01:00
a2faa5ceb5 tests/e2e: use mixed casing in ldap test to ensure search works
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 20:59:55 +01:00
63a19a1381 outposts/ldap: fix searches with mixed casing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 20:55:51 +01:00
b472dcb7e7 tests/e2e: update new outpost service account names
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 20:44:52 +01:00
6303909031 web: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 20:16:53 +01:00
4bdc06865b web: fix borders of sidebars in dark mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 20:10:14 +01:00
2ee48cd039 outposts: set display name for outpost service account
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 19:59:38 +01:00
893d5f452b web: Update Web API Client version (#1899)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-09 19:56:29 +01:00
340a9bc8ee core: fix error when using invalid key-values in attributes query
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 19:53:47 +01:00
cb3d9f83f1 ci: don't rebuild frontend for sentry, extract files from container image
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 14:10:13 +01:00
4ba55aa8e9 flows: fix error when trying to print FlowToken objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 13:55:43 +01:00
bab6f501ec flows: fix error in inspector view
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 13:52:46 +01:00
7327939684 website/docs: add 2021.12.1-rc3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 13:25:23 +01:00
ffb0135f06 release: 2021.12.1-rc3 2021-12-09 13:23:41 +01:00
ee0ddc3d17 Merge branch 'master' into version-2021.12 2021-12-09 13:23:28 +01:00
5dd979d66c root: add flower entrypoint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 11:38:57 +01:00
a9bd34f3c5 events: revert to @prefill_task decorator since base class doesn't get executed until task runs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 10:18:00 +01:00
db316b59c5 stages/prompt: use policyenginemode all
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 09:39:40 +01:00
6209714f87 policies/expression: add ak_call_policy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 09:39:28 +01:00
1ed2bddba7 root: fix celery task ID not being included in log
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-09 09:36:52 +01:00
26b35c9b7b root: fix name conflict in threadlocal
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-08 21:42:48 +01:00
86a9271f75 root: add request_id to celery tasks, prefixed with "task-"
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-08 21:34:20 +01:00
402ed9bd20 root: allow usage of --randomly-seed for testing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-08 21:33:41 +01:00
68a0684569 ci: fix test-migrations-from-stable (#1898)
* ci: copy files instead of checking out

* ci: add marks for prs
2021-12-08 21:00:58 +01:00
bd2e453218 outposts/ldap: Fix search case sensitivity. (#1897) 2021-12-08 20:11:56 +01:00
1f31c63e57 build(deps): bump python from 3.9-slim-bullseye to 3.10.1-slim-bullseye (#1894) 2021-12-08 07:49:01 +01:00
480410efa2 build(deps): bump @sentry/tracing from 6.15.0 to 6.16.0 in /web (#1895) 2021-12-08 07:48:33 +01:00
e9bfee52ed build(deps): bump @sentry/browser from 6.15.0 to 6.16.0 in /web (#1896) 2021-12-08 07:47:03 +01:00
326b574d54 root: update dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-07 16:25:10 +01:00
0a7abcf2ad build(deps): bump @typescript-eslint/eslint-plugin in /web (#1890) 2021-12-07 08:41:43 +01:00
9e5019881e build(deps): bump @typescript-eslint/parser from 5.5.0 to 5.6.0 in /web (#1892) 2021-12-07 08:40:49 +01:00
8071750681 build(deps): bump eslint from 8.4.0 to 8.4.1 in /web (#1891) 2021-12-07 08:39:49 +01:00
f2f0931904 build(deps): bump goauthentik.io/api from 0.2021104.9 to 0.2021104.10 (#1893) 2021-12-07 08:39:10 +01:00
a91204e5b9 web/user: allow custom font-awesome icons for applications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1189
2021-12-06 21:20:15 +01:00
b14c22cbff web: fix duplicate classes, make generic icon clickable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 21:13:04 +01:00
b3e40c6aed outposts/proxy: don't save raw jwt in cookie to prevent securecookie: the value is too long
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 13:54:59 +01:00
873aa4bb22 providers/saml: remove SESSION_KEY_POST from session after using it
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1873
2021-12-06 12:47:25 +01:00
c1ea78c422 core: fix missing permission check for group creating when creating service account
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 12:33:29 +01:00
3c8bbc2621 sources/*: only allow superusers to directly create source connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 12:22:40 +01:00
42a9979d91 web/elements: close dropdown when refresh event is dispatched
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 11:18:22 +01:00
b7f94df4d9 web: fix text colour for bad request on light mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 10:54:21 +01:00
4143d3fe28 events: don't set metrics on import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 10:13:48 +01:00
f95c06b76f web: Update Web API Client version (#1889)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-06 10:13:42 +01:00
e3e9178ccc web/admin: show outpost warning on application page too
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 10:10:44 +01:00
b694816e7b sources/*: Allow creation of source connections via API
closes #1888

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-06 10:05:42 +01:00
e046000f36 build(deps): bump chart.js from 3.6.1 to 3.6.2 in /web (#1886) 2021-12-06 08:42:21 +01:00
edb5caae9b build(deps-dev): bump prettier from 2.5.0 to 2.5.1 in /website (#1883) 2021-12-06 08:41:30 +01:00
02d27651f3 build(deps): bump eslint from 8.3.0 to 8.4.0 in /web (#1884) 2021-12-06 08:41:05 +01:00
44cd4d847d build(deps): bump golang from 1.17.3-bullseye to 1.17.4-bullseye (#1882) 2021-12-06 08:40:18 +01:00
472256794d build(deps): bump prettier from 2.5.0 to 2.5.1 in /web (#1885) 2021-12-06 08:39:52 +01:00
cbb6887983 build(deps): bump goauthentik.io/api from 0.2021104.7 to 0.2021104.9 (#1887) 2021-12-06 08:39:26 +01:00
317e9ec605 core: add FlowToken which saves the pickled flow plan, replace standard token in email stage to allow finishing flows in different sessions
closes #1801

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-05 15:20:11 +01:00
ada2a16412 tests/e2e: add post binding test
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-05 11:18:01 +01:00
61f6b0f122 web: Update Web API Client version (#1880)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-05 11:17:31 +01:00
6a3f7e45cf providers/saml: add ?force_binding to limit bindings for metadata endpoint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-05 11:14:42 +01:00
2b78c4ba86 *: use request.query_params instead of accessing the django request
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-05 11:14:20 +01:00
680ef641fb providers/saml: fix error when propertymapping returns invalid data in list
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-05 10:31:16 +01:00
2b5504ff63 release: 2021.12.1-rc2 2021-12-04 20:06:41 +01:00
f8a6aa3250 root: fix missing certs directly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-04 20:06:02 +01:00
6c23fc4b2b webiste/docs: add 2021.12.1-rc2 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-04 20:03:26 +01:00
639c2f5c2e Merge branch 'master' into version-2021.12 2021-12-04 19:55:37 +01:00
e44632f9a0 web/admin: fix wrong description for reputation policy
closes #1877

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-04 19:54:58 +01:00
3f2ce34468 web: update icons
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 18:54:04 +01:00
426cef998f sources/ldap: make task names more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 18:39:42 +01:00
8ddb62ed0f sources/plex: fix plex token being included in event log
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 18:37:40 +01:00
572f6d4ea0 crypto: add certificate discovery to automatically import certificates from lets encrypt
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1835
2021-12-03 18:27:36 +01:00
8db68410c6 website/docs: re-organise core concepts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 18:27:36 +01:00
caa3c3de32 web: Add Christmas icon (#1879) 2021-12-03 16:50:24 +01:00
23b5ca761a web: Update Web API Client version (#1876)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-03 10:11:44 +01:00
f1b9021e3e sources/ldap: add optional tls verification certificate
closes #1875

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 10:09:13 +01:00
99c62af89e ci: add check to ensure no migrations are missing
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 10:05:21 +01:00
8ae50814fe *: add missing migrations
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 10:04:54 +01:00
2e2b491ec7 source/ldap: fix hanging unittests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-03 09:41:13 +01:00
ac432e78e2 sources/ldap: don't cache LDAP Connection, use random server
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 21:18:20 +01:00
83ac42ac43 stages/prompt: fix error when both default and required are set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 21:11:22 +01:00
4bd1cd127b providers/saml: fix IndexError in signature check
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 20:30:03 +01:00
2eb5a5cc76 sources/ldap: handle typeerror during creation of objects when using wrong kwargs params
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 20:24:24 +01:00
75051687e6 sources/ldap: allow multiple server URIs for loadbalancing and failover
closes #1874

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 20:15:11 +01:00
7e316b5fc2 root: add missing sample_rate default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 19:54:37 +01:00
5594ad0b36 web/admin: add spinner to table refresh to show progress
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 19:34:21 +01:00
ea097afeae outposts/proxy: fix path prefix in static handler
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 19:21:40 +01:00
b77b4b5c80 root: fix paths in proxy dockerfile
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 19:19:45 +01:00
f8dc7f48f2 outposts/proxy: fix path for media
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 18:47:36 +01:00
692e75b057 website/docs: add passwordless docs
closes #1863

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 15:48:34 +01:00
02771683a6 web/flows: fix linting errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 15:32:00 +01:00
40404ff41d outposts/ldap: Rework/improve LDAP search logic. (#1687)
* outposts/ldap: Refactor searching so we key primarily off base dn

* docs: Updating guides on sssd and the ldap outpost.
2021-12-02 15:28:58 +01:00
fdd5211253 web/flows: Revise duo authenticator login prompt text (#1872) 2021-12-02 15:27:47 +01:00
85a417d22e outposts/proxy: re-add rs256 support
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 15:17:32 +01:00
66c530ea06 outposts: always trigger outpost reconcile on startup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 15:06:14 +01:00
347c3793fc outposts/proxy: add additional headers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 14:19:57 +01:00
cf78c89830 events: replace @prefill_task with custom base class to prefill
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 13:47:35 +01:00
20c738c384 crypto: fix default API not having an ordering
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 13:00:41 +01:00
4f54ce6afb providers/saml: fix error when using post bindings and user freshly logged in
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1873
2021-12-02 13:00:21 +01:00
f0d7edb963 *: fix @prefill_task
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 10:05:51 +01:00
e42ad8db93 outposts/proxy: copy user-agent header from upstream request
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 10:01:54 +01:00
e917e756cc outposts/proxy: make logging fields more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-02 09:58:50 +01:00
b4963bec76 providers/proxy: fix defaults for traefik integration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 21:47:13 +01:00
0d23796989 root: fix paths for dockerfile
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 21:25:01 +01:00
d0ceafe79e outposts/proxy: add X-authentik-meta-version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:59:45 +01:00
f2023a7af2 *: don't use go embed to make using custom files easier
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:35:28 +01:00
31d597005f build(deps): bump goauthentik.io/api from 0.2021104.6 to 0.2021104.7 (#1871)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021104.6 to 0.2021104.7.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021104.6...v0.2021104.7)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-12-01 20:30:25 +01:00
62dc86be7b web: Update Web API Client version (#1870)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-12-01 20:21:51 +01:00
7aa8e35f87 providers/proxy: use wildcard for traefik headers copy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:19:35 +01:00
60b95271eb outposts/proxy: add additional headers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:19:09 +01:00
382b0e8941 root: fix overlay outpost api generation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:13:05 +01:00
3b068610b9 outposts/proxy: clean up header setting (don't copy all headers)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 20:05:56 +01:00
9a8f62f42e web/admin: don't show disabled http basic as red
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 17:07:03 +01:00
632e3cf7dc Merge branch 'master' into version-2021.12 2021-12-01 15:27:48 +01:00
e7144649d5 ci: dont use matrix for multiplatform build
This reverts commit 9092d1189b.

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

# Conflicts:
#	.github/workflows/ci-main.yml
#	.github/workflows/ci-outpost.yml
#	.github/workflows/release-publish.yml
2021-12-01 15:27:37 +01:00
dd8909c9b2 website/docs: add v2021.12 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 13:23:55 +01:00
e6818c1f6a release: 2021.12.1-rc1 2021-12-01 13:08:13 +01:00
10c4e3c717 ci: use buildx
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-12-01 13:08:06 +01:00
b8425867c8 build(deps): bump chart.js from 3.6.0 to 3.6.1 in /web (#1864) 2021-12-01 08:54:36 +01:00
a05da8cdbf build(deps): bump rollup from 2.60.1 to 2.60.2 in /web (#1865) 2021-12-01 08:54:08 +01:00
c3aeefa653 website/docs: fix wrong placeholder
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-30 11:21:14 +01:00
62c840df21 website/docs: fix missing placeholder
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-30 11:20:05 +01:00
45d1db8880 website/docs: add proxy custom header docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-30 11:12:34 +01:00
b34f30f1dd build(deps): bump @typescript-eslint/eslint-plugin in /web (#1860) 2021-11-30 08:54:12 +01:00
7a54e84eb4 build(deps): bump @typescript-eslint/parser from 5.4.0 to 5.5.0 in /web (#1861) 2021-11-30 08:52:44 +01:00
917eef96fb lib: add improved log to sentry events being sent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 21:37:29 +01:00
9a393848b2 outpost: configure error reporting based off of main instance config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 14:42:19 +01:00
a6abeb50c6 build(deps): bump goauthentik.io/api from 0.2021104.5 to 0.2021104.6 (#1858)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021104.5 to 0.2021104.6.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021104.5...v0.2021104.6)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-11-29 14:39:17 +01:00
39acb044fb lifecycle: allow custom worker count in k8s
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 14:27:55 +01:00
7d2f622f4b web: Update Web API Client version (#1857)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 14:17:12 +01:00
a2b38caf64 web: update for new config api
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 13:58:00 +01:00
1193b9fd22 root: revert to upstream api generator
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 13:56:18 +01:00
e3a5ef1907 root: make sentry sample rate configurable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-29 13:52:34 +01:00
e597bb4542 policies/expression: fix ak_user_has_authenticator evaluation when not specifying optional device_type (#1849)
* Fix ak_user_has_authenticator evaluation when not specifying optional device_type

* Simpler patch
2021-11-29 10:35:17 +01:00
c31df2b3f9 build(deps): bump @lingui/cli from 3.12.1 to 3.13.0 in /web (#1854) 2021-11-29 09:00:35 +01:00
3f2637cffa build(deps): bump @lingui/detect-locale from 3.12.1 to 3.13.0 in /web (#1852) 2021-11-29 09:00:25 +01:00
3b6d9bec0a build(deps): bump @lingui/macro from 3.12.1 to 3.13.0 in /web (#1853) 2021-11-29 08:49:01 +01:00
b184210610 build(deps): bump postcss from 8.4.1 to 8.4.4 in /website (#1851) 2021-11-29 08:48:29 +01:00
d2010808ee build(deps): bump @lingui/core from 3.12.1 to 3.13.0 in /web (#1855) 2021-11-29 08:48:03 +01:00
f5b185dd06 build(deps): bump goauthentik.io/api from 0.2021104.3 to 0.2021104.5 (#1856) 2021-11-29 08:47:21 +01:00
ae161c1ba9 web/admin: fix actions column on ip reputation page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 21:14:52 +01:00
109283b189 web: use ak-label for boolean values
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 21:12:53 +01:00
235d283def web/elements: use <slot> in ak-label instead of attribute
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 21:05:07 +01:00
96a86b3298 web: include @lit in prettier sort
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 15:45:00 +01:00
db9ea8603c web: cleanup sentry error catching
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 15:17:27 +01:00
8b7f698c7b outposts/proxy: continue compiling additional regexes even when one fails
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-28 15:06:26 +01:00
813c13ce45 web/admin: fix display of banners on provider pages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 20:48:06 +01:00
629a0e1a4d web/admin: make object view pages more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 19:40:40 +01:00
d1e2c018a3 root: fix dockerfile paths
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 14:36:44 +01:00
1e86844823 root: copy website into web builder for docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 14:19:57 +01:00
b58875d4c7 web: add rollup config for proxy outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 14:18:51 +01:00
03e0eecb1d web/admin: redesign provider pages to provide more info
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 14:08:45 +01:00
7aa61d86e4 web: allow markdown import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 13:52:11 +01:00
0e6a799e6d web/elements: allow multiple tabs with different state
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 13:30:02 +01:00
bc6afdf94f website/docs: use common placeholders for forward_auth
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 13:29:38 +01:00
80364b04a9 web/elements: allow app.model names for ak-object-changelog
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 13:03:13 +01:00
0948e0ee1c web: Update Web API Client version (#1848)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-26 10:35:03 +01:00
5c54de66fc *: add meta_model_name field to all models with inheritance
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 10:32:39 +01:00
937edc73bc web: Update Web API Client version (#1847)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-26 10:30:18 +01:00
2c0d8d8943 core: add meta_model_name to MetaNameSerializer to easily show relevant events
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-26 10:27:08 +01:00
059ccdd592 build(deps-dev): bump prettier from 2.4.1 to 2.5.0 in /website (#1845) 2021-11-26 08:49:08 +01:00
0ec0d3f1aa build(deps): bump prettier from 2.4.1 to 2.5.0 in /web (#1846) 2021-11-26 08:48:26 +01:00
0a0eee138a stages/authenticator_validate: catch error when attempting to configure user without flow
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-25 23:44:48 +01:00
3ed4c38101 web: re-fix router height
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-25 23:31:35 +01:00
de8cf65503 stages/email: prevent error with duplicate token
closes #1827

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-25 23:17:37 +01:00
121b36f35f lib: log error for file:// in config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-25 19:21:40 +01:00
363aed2a47 root: url quote redis passwords for connection string
closes https://github.com/goauthentik/helm/issues/39

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-25 18:05:36 +01:00
ef994e0084 lifecycle: improve redis connection debug py printing full URL 2021-11-25 13:44:42 +01:00
e1ef196283 core: remove dump_config, handle directly in config loader without booting django, don't check database 2021-11-25 13:38:31 +01:00
f81ffd54f3 website/docs: fix invalid markdown 2021-11-25 13:37:57 +01:00
f9bfae9190 Merge branch 'master' into next 2021-11-25 13:07:55 +01:00
0d686465a4 ci: bump cache revision 2021-11-25 11:54:30 +00:00
e13b4a561f web/user: fix filtering for applications based on launchURL 2021-11-25 11:32:24 +01:00
f6417f95e5 build(deps): bump postcss from 8.3.11 to 8.4.1 in /website (#1841) 2021-11-25 08:17:28 +01:00
9c6bf5f4ae build(deps): bump goauthentik.io/api from 0.2021104.2 to 0.2021104.3 (#1842) 2021-11-25 08:16:39 +01:00
d2d7acb50e website/integrations: update minio callback URL
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 22:54:45 +01:00
c7681dde32 outposts: reload on signal USR1, fix display of reload offset
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 22:45:27 +01:00
8cf9661e08 root: fix translation, run translation compile on PR
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 18:16:02 +01:00
2dbd76cf90 tests/e2e: use StaticLiveServerTestCase
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 11:32:45 +01:00
28d39f4d80 website: add netlify badge
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 11:30:02 +01:00
760428aa18 website/docs: add outpost integrations docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 10:58:23 +01:00
49bbac7441 web: Update Web API Client version (#1840)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-24 10:04:38 +01:00
0b8cfd437b *: fix typo'd signing pair name
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 09:55:10 +01:00
b69aaf9417 tests/e2e: fix header name
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 09:18:22 +01:00
758d1bdfd4 tests/e2e: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-24 08:50:13 +01:00
ab501ca971 build(deps): bump actions/cache from 2.1.6 to 2.1.7 (#1838) 2021-11-24 07:38:33 +01:00
9657741a3d build(deps): bump github.com/go-openapi/strfmt from 0.21.0 to 0.21.1 (#1839) 2021-11-24 07:38:02 +01:00
29b7368f42 tests/e2e: fix static user checks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:56:23 +01:00
75724b6f8d root: make testing output more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:46:27 +01:00
7c9f821bfd web: attempt to drop fetch errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:29:25 +01:00
5b9e6bed6c lib: fix custom URL schemes being overwritten
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:23:09 +01:00
6113d7d768 website/docs: add application docs
closes #1837

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:15:30 +01:00
0e3602d7eb lib: improve probability of symbols in generated key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 23:01:30 +01:00
2b94e9a687 tests/e2e: bump retries
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 22:54:08 +01:00
6ed7d842e4 *: allow URLs without domain and custom schemas
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 22:51:04 +01:00
8794c840cf web: only show applications with http link
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 22:40:31 +01:00
9c9c00755a core: fix test user not having password set properly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 22:30:09 +01:00
6703c0a5d1 tests/e2e: don't load core migration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 22:05:19 +01:00
060f19ce06 tests/e2e: ensure akadmin is not used
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 21:34:53 +01:00
b2d2e7cbc8 tests/e2e: remove logger
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 21:19:33 +01:00
91fd792f88 tests/e2e: use generated uid
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 19:19:13 +01:00
2d9cd28221 tests/e2e: bump retries
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 19:15:37 +01:00
aa64cf898f ci: enable automerge for generated PRs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 19:15:31 +01:00
27d109c1fe core: compile backend translations (#1836)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-23 19:12:48 +01:00
1b4a14f3ee root: allow .mo files for backend
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 19:09:29 +01:00
9835785864 core: make test user's password optional
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 19:06:44 +01:00
d785998c5a Revert "root: disable random tests for now"
This reverts commit 8ba9553220.
2021-11-23 18:46:51 +01:00
8ba9553220 root: disable random tests for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 17:57:56 +01:00
6eb132c48b tests/e2e: fix ldap provider tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 17:28:35 +01:00
b523cd064b Translate /locale/en/LC_MESSAGES/django.po in de (#1834) 2021-11-23 15:17:57 +01:00
355b832cc3 tests/e2e: fix email backend
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 13:22:28 +01:00
8f5af464a2 web/admin: fix Forms with file uploads not handling errors correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 12:18:39 +01:00
fb70769358 root: add missing importlib-metadata
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 10:11:47 +01:00
ad06778c34 ci: remove v2 suffix in cache
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 10:00:23 +01:00
bcb4451fb7 build(deps): bump rollup from 2.60.0 to 2.60.1 in /web (#1832) 2021-11-23 08:52:34 +01:00
110d558572 build(deps): bump boto3 from 1.20.10 to 1.20.11 (#1833) 2021-11-23 08:47:20 +01:00
e32d4f0095 tests/e2e: don't run e2e tests randomly for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 00:32:24 +01:00
0e413acd61 ci: only try once for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 00:30:10 +01:00
d3397c349f stages/email: minify email css template
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-23 00:10:43 +01:00
fb18a10e61 website/integrations: Add Provider/Uptime Kuma (#1831)
* docs: add integration docs for uptime-kuma

* docs: add integration docs for uptime-kuma
2021-11-23 00:10:31 +01:00
9bb0d04aeb root: Random tests (#1825)
* root: add pytest-randomly to randomise tests

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

* *: generate flows for testing instead of relying on existing ones

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

* *: generate users for testing instead of relying on existing ones

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

* *: use generated certificate

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

* tests/e2e: keep containers

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

* tests/e2e: use websockets test case

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 22:56:02 +01:00
666cf77b04 website/integrations: add integration docs for budibase (#1830) 2021-11-22 22:55:49 +01:00
90ca1b8e5a website/integrations: Add Provider/HedgeDoc (#1829)
* docs: add integration docs for hedgedoc

* docs: add integration docs for hedgedoc
2021-11-22 22:55:14 +01:00
f1e95b8816 website/integrations: Add Provider/PowerDNS-Admin (#1826)
* docs: add integration docs for powerdns-admin

* docs: add integration docs for powerdns-admin
2021-11-22 21:02:30 +01:00
dad8547212 root: remove arm/v7
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 14:29:21 +01:00
a957e1fc45 root: install cargo for cryptography build
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 12:22:19 +01:00
39e3f02503 website: fix build for docs-only target
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 12:11:24 +01:00
2b999e922c ci: disable arm for ci due to duration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 11:48:41 +01:00
4224134a19 tests/e2e: remove deprecated desired_capabilities
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 11:28:26 +01:00
eda260dddd website: fix redirect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 11:13:31 +01:00
8a1dd521e1 website: move integrations to separate folder, separate sidebar and new URL, add URL redirect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 11:10:26 +01:00
1c5e91de1d website: fix selection in navbar not being visible
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 10:55:33 +01:00
4b1744fad0 website/docs: add onlyoffice docs
closes #1820

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 10:28:21 +01:00
f17b83010d root: remove separate postgresql repo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-22 10:07:26 +01:00
12ddf9e73c build(deps): bump boto3 from 1.20.8 to 1.20.10 (#1823) 2021-11-22 09:00:27 +01:00
0b3b300333 build(deps): bump eslint from 8.2.0 to 8.3.0 in /web (#1821) 2021-11-22 08:59:32 +01:00
23f1a19765 build(deps): bump codemirror from 5.63.3 to 5.64.0 in /web (#1822) 2021-11-22 08:58:54 +01:00
b27e998615 build(deps): bump structlog from 21.2.0 to 21.3.0 (#1824) 2021-11-22 08:58:04 +01:00
2b928146a8 root: use amd64 for multistage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 23:59:05 +01:00
a94b0504b7 ci: always disable fail-fast
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 23:44:09 +01:00
4fcbfa7709 ci: add missing qemu action
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 23:35:23 +01:00
986e01db20 root: add missing libraries to compile cryptography for armv7
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 23:34:01 +01:00
9092d1189b ci: disable arm/v7 for now, use matrix for release
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 23:08:55 +01:00
605ed94ba2 ci: use matrix for tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 22:51:07 +01:00
4cbeeb9a0c ci: add cross platform build for dev main image
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1819
2021-11-21 22:44:49 +01:00
993dee6aad ci: build outpost for multi arch in matrix
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 22:33:43 +01:00
c663deb659 website/docs: note to not use quotation marks for email
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-21 21:52:29 +01:00
61621e7d60 lifecycle: improve backup restore by dropping database before
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-20 00:32:24 +01:00
0ee9b07172 web/admin: show changelog on user info page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:59:04 +01:00
431ba6b4ef lib: add cli option for lib.config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:52:10 +01:00
146818793e website/docs: fix kubectl restart command
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:45:03 +01:00
0ce663bce4 web/user: fix height issues on user interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:32:25 +01:00
923ba4fb42 web: improve dark theme for vertical tabs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:29:47 +01:00
bb6eed0db1 root: properly catch 404 errors for websocket connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 23:19:07 +01:00
d1bd8f333b outposts/proxy: use disableIndex for static files
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 10:50:56 +01:00
2ac9f5426d outposts: don't panic when listening for metrics fails
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 10:37:13 +01:00
8d1fd48003 web/admin: allow flow edit on flow view page
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 10:20:31 +01:00
241cb01ec6 web/flows: fix spinner during webauthn not centred
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-19 09:51:52 +01:00
65b4139997 build(deps): bump @patternfly/patternfly from 4.151.4 to 4.159.1 in /web (#1816) 2021-11-19 08:46:35 +01:00
1431be8c44 build(deps): bump geoip2 from 4.4.0 to 4.5.0 (#1817) 2021-11-19 08:45:20 +01:00
049fceeeee web: add more state
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 21:40:34 +01:00
e6638afa3c web: remove manually URL encoded paths
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 21:33:49 +01:00
465898c7d0 web/elements: add new API to store attributes in URL, use for table and tabs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 21:16:00 +01:00
c363b1cfde web/admin: unify rendering and sorting of user lists
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 20:44:15 +01:00
b30ffd1318 web/admin: make user clickable for bound policies list
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 20:43:45 +01:00
fe0d3a64c8 web/admin: fix typo in events action
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 20:32:59 +01:00
ae9f1c1063 outpost/ldap: fix panic when attempting to update without locked users mutex
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 19:36:27 +01:00
ea63d384fd web/flows: fix lint errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-18 09:36:42 +01:00
c28d75754d build(deps): bump boto3 from 1.20.7 to 1.20.8 (#1813) 2021-11-18 08:50:55 +01:00
518b691e00 build(deps): bump packaging from 21.2 to 21.3 (#1812) 2021-11-18 08:50:15 +01:00
cd845be45d build(deps): bump typescript from 4.4.4 to 4.5.2 in /web (#1811) 2021-11-18 08:49:45 +01:00
a813d8e05e build(deps): bump sentry-sdk from 1.4.3 to 1.5.0 (#1814) 2021-11-18 08:49:18 +01:00
75f850f4d2 build(deps): bump @babel/plugin-transform-runtime in /web (#1804)
Bumps [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-runtime) from 7.16.0 to 7.16.4.
- [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.16.4/packages/babel-plugin-transform-runtime)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-runtime"
  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>
2021-11-17 09:40:32 +01:00
c84265c6f0 build(deps): bump @sentry/browser from 6.14.3 to 6.15.0 in /web (#1805)
Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.14.3 to 6.15.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.14.3...6.15.0)

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  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>
2021-11-17 09:39:21 +01:00
a477ea29cd build(deps): bump @babel/preset-env from 7.16.0 to 7.16.4 in /web (#1803)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.16.0 to 7.16.4.
- [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.16.4/packages/babel-preset-env)

---
updated-dependencies:
- dependency-name: "@babel/preset-env"
  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>
2021-11-17 09:39:06 +01:00
f6aa85e340 build(deps): bump @sentry/tracing from 6.14.3 to 6.15.0 in /web (#1806)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.14.3 to 6.15.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/6.14.3...6.15.0)

---
updated-dependencies:
- dependency-name: "@sentry/tracing"
  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>
2021-11-17 09:38:02 +01:00
0aeedb3ad8 build(deps): bump @babel/plugin-proposal-decorators in /web (#1807)
Bumps [@babel/plugin-proposal-decorators](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-proposal-decorators) from 7.16.0 to 7.16.4.
- [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.16.4/packages/babel-plugin-proposal-decorators)

---
updated-dependencies:
- dependency-name: "@babel/plugin-proposal-decorators"
  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>
2021-11-17 09:37:53 +01:00
4b29f238b5 build(deps): bump boto3 from 1.20.6 to 1.20.7 (#1808)
Bumps [boto3](https://github.com/boto/boto3) from 1.20.6 to 1.20.7.
- [Release notes](https://github.com/boto/boto3/releases)
- [Changelog](https://github.com/boto/boto3/blob/develop/CHANGELOG.rst)
- [Commits](https://github.com/boto/boto3/compare/1.20.6...1.20.7)

---
updated-dependencies:
- dependency-name: boto3
  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>
2021-11-17 09:37:16 +01:00
34157db06a build(deps): bump celery from 5.2.0 to 5.2.1 (#1809)
Bumps [celery](https://github.com/celery/celery) from 5.2.0 to 5.2.1.
- [Release notes](https://github.com/celery/celery/releases)
- [Changelog](https://github.com/celery/celery/blob/master/Changelog.rst)
- [Commits](https://github.com/celery/celery/compare/v5.2.0...v5.2.1)

---
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>
2021-11-17 09:37:03 +01:00
84b9e66a97 build(deps): bump goauthentik.io/api from 0.2021104.1 to 0.2021104.2 (#1810)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021104.1 to 0.2021104.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021104.1...v0.2021104.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-11-17 09:36:47 +01:00
e831e4fb94 root: add lifespan shim to prevent errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-16 13:25:03 +01:00
956922820b web: Update Web API Client version (#1802)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-16 12:39:37 +01:00
b0fac9c9f1 providers/saml: fix SessionNotOnOrAfter not being included
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-16 12:36:40 +01:00
f4db09cd59 events: add gdpr_compliance option
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1551
2021-11-16 11:29:13 +01:00
047030f901 web: optionally allow unique messages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-16 11:21:30 +01:00
638e8d741f *: fix multiple tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-16 10:38:21 +01:00
425b87a6d0 outposts: add ack and disconnect tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-16 09:34:37 +01:00
e7dc763612 build(deps): bump @typescript-eslint/eslint-plugin in /web (#1797) 2021-11-16 08:22:27 +01:00
a80cc94da9 build(deps): bump @typescript-eslint/parser from 5.3.1 to 5.4.0 in /web (#1798) 2021-11-16 08:21:19 +01:00
547dd3cb7a build(deps): bump goauthentik.io/api from 0.2021103.2 to 0.2021104.1 (#1799) 2021-11-16 08:20:30 +01:00
95739a934c build(deps): bump boto3 from 1.20.5 to 1.20.6 (#1800) 2021-11-16 08:20:07 +01:00
d12e24017e outposts: add websocket tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 23:58:19 +01:00
e4a0345231 tests/integration: use channels test server
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 22:37:36 +01:00
078633c2af lib: drop all sentry exceptions when debug enabled
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 22:18:56 +01:00
4b8b800648 stages/*: add more tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 20:58:34 +01:00
6f9ed001a1 crypto: add more tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 20:38:03 +01:00
e4095dfffe admin: add more tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 20:10:09 +01:00
d5341c2284 managed: add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 19:53:08 +01:00
357bd65028 web/flows: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 19:52:17 +01:00
867fb0dac0 root: fix settings for managed not loaded
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 19:49:03 +01:00
2666aa2c73 root: add errorhandling in log middleware
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 17:11:44 +01:00
f0e9bafa35 outposts: add tests for management commands
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 16:44:42 +01:00
0d739f5c1a recovery: add additional tests for commands
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 16:41:37 +01:00
e08077c73a root: replace asgi-based logger with middleware
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 16:32:56 +01:00
7cf8a31057 internal: fix integrated docs not working
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 16:13:02 +01:00
c43049a981 website/docs: remove deprecated docker_image_base
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 15:58:17 +01:00
1a9ace6f9d internal: use runserver when debug for code reload
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 14:04:10 +01:00
b8d86bc482 web/flows: update default background
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 13:07:00 +01:00
f7044e41c6 build(deps-dev): bump bandit from 1.7.0 to 1.7.1 (#1793)
* build(deps-dev): bump bandit from 1.7.0 to 1.7.1

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.0 to 1.7.1.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.0...1.7.1)

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

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

* *: fix bandit false positives

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-15 09:16:16 +01:00
fa59fec17a build(deps): bump rollup from 2.59.0 to 2.60.0 in /web (#1792) 2021-11-15 08:39:31 +01:00
e29afa289e build(deps): bump boto3 from 1.20.4 to 1.20.5 (#1794) 2021-11-15 08:39:14 +01:00
4d4193a586 ci: re-add cache
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-14 19:14:18 +01:00
59343ff441 stages/email: fix missing component in response when retrying email send
closes #1791

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-14 17:52:31 +01:00
cab564152d lib: load json strings in config env variables
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-14 12:44:22 +01:00
97b814ab33 outpost/proxy: show better error when hostname isn't configured
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-13 22:45:37 +01:00
88516ba2ca core: make defaults for _change_email and _change_username configurable
closes #1789

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-13 22:33:03 +01:00
f069cfb643 outposts/ldap: copy boundUsers map when running refresh instead of using blank map
closes #1651

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-13 00:26:01 +01:00
4ce3c2341c website/docs: add nginx-proxy-manager
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-12 23:00:10 +01:00
77e42d60cb website/docs: use new headers in docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-12 22:48:01 +01:00
cacb919c6f web: Update Web API Client version (#1787)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-12 14:15:26 +01:00
2a3b049b01 release: 2021.10.4 2021-11-12 12:31:24 +01:00
e4a5e86c93 sources/oauth: Fixed the incorrect padding issue in apple.py (#1773)
* Fixed the incorrect padding issue in apple.py

Fixed the incorrect padding issue in apple.py by adding proper padding to the raw_payload.

* Fixed the incorrect encoding of client_secret in apple.py

In the get_client_secret() method, the "sub" in the payload must be only the client ID. So I have changed self.source.consumer_key to parts[0]

* Added the decode method for the id_token

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-12 12:10:29 +01:00
3a51bcd890 tests/e2e: add retry for webdriver init
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-12 09:37:05 +01:00
c28f68400d build(deps): bump @sentry/tracing from 6.14.1 to 6.14.3 in /web (#1783) 2021-11-12 08:30:16 +01:00
5d50fc281a build(deps): bump boto3 from 1.20.3 to 1.20.4 (#1785) 2021-11-12 08:30:02 +01:00
9f7d1466e9 build(deps): bump @sentry/browser from 6.14.1 to 6.14.3 in /web (#1784) 2021-11-12 08:29:22 +01:00
c815d24806 build(deps): bump psycopg2-binary from 2.9.1 to 2.9.2 (#1786) 2021-11-12 08:29:05 +01:00
d1200a7e40 website/docs: Mention correct logo in Gitea docs (#1782) 2021-11-12 01:02:17 +01:00
edd4f9ceae root: update security
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 23:50:46 +01:00
1cfe81887b stages/authenticator_validate: improve logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 23:33:41 +01:00
bb5e0ebab1 website/docs: Add Integrations/Provider/Gitea (#1781) 2021-11-11 23:23:32 +01:00
dfda76d896 tests/e2e: use cached LDAP lookup for tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 23:20:32 +01:00
8fc5114ce4 website/docs: prepare 2021.10.4 docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 23:20:17 +01:00
e7b4363d21 outposts/ldap: fix logic error in cached ldap searcher
closes #1779

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 23:18:32 +01:00
53905d1a89 stages/authenticator_validate: enable all device classes by default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 22:49:30 +01:00
0ad1392632 web/admin: use more natural default ordering for objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 22:47:10 +01:00
6db1c914ee stages/authenticator_duo: fix devices created with name
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 22:16:47 +01:00
00324f922d outposts: send SelectedChallenge when using MFA with Go FlowExecutor
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 21:27:06 +01:00
8a24ddad28 website/docs: Added missing SSO server URL field for Zabbix (#1780) 2021-11-11 21:06:33 +01:00
0f85fe3c29 website/docs: authentik starts lowercase (#1778)
* website/docs: Add Integrations/Provider/OPNsense

* website/docs: Add missing steps + fix recs

* website/docs: authentik starts lowercase

* website/docs: authentik starts lowercase
2021-11-11 16:53:46 +01:00
1f05eaa420 website/docs: Add Integrations/Provider/OPNsense (#1777)
* website/docs: Add Integrations/Provider/OPNsense

* website/docs: Add missing steps + fix recs

* website/docs: authentik starts lowercase
2021-11-11 16:44:02 +01:00
84e126a32c website/docs: add group hierarchy docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 16:15:40 +01:00
9ae69866bd web/admin: fix display issues with flow execute buttons
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-11 13:51:33 +01:00
56576a7f44 build(deps): bump boto3 from 1.20.2 to 1.20.3 (#1769) 2021-11-11 08:43:22 +01:00
7f0295ba53 build(deps): bump @trivago/prettier-plugin-sort-imports in /web (#1768) 2021-11-11 08:43:13 +01:00
5553b3ff36 build(deps): bump drf-spectacular from 0.20.2 to 0.21.0 (#1771) 2021-11-11 08:43:03 +01:00
6f969525fe build(deps): bump webauthn from 1.0.1 to 1.1.0 (#1770) 2021-11-11 08:42:33 +01:00
bac12246fb build(deps-dev): bump coverage from 6.1.1 to 6.1.2 (#1772) 2021-11-11 08:42:19 +01:00
b53ef6e529 build(deps): bump goauthentik.io/api from 0.2021103.1 to 0.2021103.2 (#1767)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021103.1 to 0.2021103.2.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021103.1...v0.2021103.2)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-11-10 23:26:13 +01:00
39c62afb93 web: Update Web API Client version (#1766)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-10 23:11:26 +01:00
c98bdbacc5 providers/proxy: return list of configured scope names so outpost requests custom scopes
closes #1762

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 23:06:21 +01:00
1e8d45dc15 web: write interfaces to different folders and remove custom chunk names
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 17:54:50 +01:00
202b057ce9 outposts/proxy: fix static files not being served in proxy mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 17:16:13 +01:00
d5d8641b37 stages/*: disable trim_whitespace on important fields
closes #1765

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 16:48:19 +01:00
9dd37689e3 ci: remove cache from translation compile
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 13:19:57 +01:00
cc0832f487 core: force lowercase emails for gravatar usage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 12:40:20 +01:00
b515bf7d2e ci: disable cache again...
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 11:57:22 +01:00
34fbf3941b website/docs: add air-gapped docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 11:28:59 +01:00
e73606b54d root: catch error in analytics on startup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 11:28:08 +01:00
0a413fe21a web/admin: show warnings above tab bar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 10:05:35 +01:00
d1b9f1e6b8 ci: limit pipeline to 2 hours
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-10 09:31:59 +01:00
e5a6e128e4 build(deps): bump boto3 from 1.20.0 to 1.20.2 (#1763) 2021-11-10 08:16:19 +01:00
9295d1ed0b website/docs: fix missing SAML cert in sentry docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 23:42:16 +01:00
5d479a6c8f root: set utm_source
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 23:23:47 +01:00
4a773b2b4f sources/ldap: set connect/receive timeout (default to 15s)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 22:27:58 +01:00
8003d67844 sources/ldap: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 22:24:33 +01:00
58baf97e2d website/docs: Add additionalHeaders to attributes list (#1754)
* Add additionalHeaders to attributes list

Added additional headers with example of usage

* Update user.md
2021-11-09 21:17:36 +01:00
51783c1cbb sorces/ldap: fix user/group sync overwriting attributes instead of merging them
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 21:16:59 +01:00
94290c7e36 root: remove pipenv constraint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 14:19:33 +01:00
123ff7ad1f website/docs: Fix typo (#1761) 2021-11-09 13:27:52 +01:00
8f3e863cce root: use python slim-bullseye as base
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-09 11:34:42 +01:00
3d6c459349 build(deps): bump @typescript-eslint/parser from 5.3.0 to 5.3.1 in /web (#1756) 2021-11-09 08:24:51 +01:00
6a583bae49 build(deps): bump goauthentik.io/api from 0.2021102.6 to 0.2021103.1 (#1758) 2021-11-09 08:24:18 +01:00
78e5879d9a build(deps): bump boto3 from 1.19.12 to 1.20.0 (#1757) 2021-11-09 08:24:09 +01:00
fdcac2a9ed build(deps): bump @typescript-eslint/eslint-plugin in /web (#1755) 2021-11-09 08:23:47 +01:00
e81715caef web: Update Web API Client version (#1753)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-08 21:19:00 +01:00
ab2b13938e release: 2021.10.3 2021-11-08 20:52:11 +01:00
5c97a3aef3 website/docs: final 2021.10.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 20:51:59 +01:00
e6963c543d outpost: remove analytics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 19:35:53 +01:00
9ca15983a2 root: keep last 30 backups
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 17:46:25 +01:00
99ef94b7aa stages/prompt: only set placeholder when in context
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 15:10:32 +01:00
133bedafba web: Update Web API Client version (#1752)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-08 14:53:50 +01:00
c3faa61ed9 stages/prompt: set field placeholder based on plan context
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 14:47:50 +01:00
da74304221 stages/prompt: add text_read_only field
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 14:45:56 +01:00
ed6659a46d outpost/ldap: don't cleanup user info as it is overwritten on bind
closes #1651

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-08 14:41:38 +01:00
0abb1f94a4 build(deps): bump @sentry/tracing from 6.14.0 to 6.14.1 in /web (#1746) 2021-11-08 08:30:37 +01:00
c7e299e0bf build(deps): bump eslint from 8.1.0 to 8.2.0 in /web (#1747) 2021-11-08 08:29:44 +01:00
8a6590bac8 build(deps): bump @sentry/browser from 6.14.0 to 6.14.1 in /web (#1748) 2021-11-08 08:29:35 +01:00
ed717dcfa2 build(deps): bump boto3 from 1.19.11 to 1.19.12 (#1749) 2021-11-08 08:29:23 +01:00
b6df42f580 build(deps): bump goauthentik.io/api from 0.2021102.5 to 0.2021102.6 (#1750) 2021-11-08 08:29:16 +01:00
2ea85bd0c4 build(deps): bump celery from 5.1.2 to 5.2.0 (#1751) 2021-11-08 08:28:33 +01:00
68fa8105e1 Merge branch 'master' into version-2021.10 2021-11-07 23:16:53 +01:00
79db0ce4c1 stages/prompt: use initial instead of default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 22:20:08 +01:00
5e23b11764 stages/prompt: default prompts to the current value of the context
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 21:59:50 +01:00
c4e029ffe2 recovery: add create_admin_group management command
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 21:53:21 +01:00
61b5b36192 core: add command to output full config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 21:45:52 +01:00
c6cc1b1728 root: fix defaults for EMAIL_USE_TLS
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 21:37:14 +01:00
77dd652160 web: Update Web API Client version (#1744)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
# Conflicts:
#	web/package-lock.json
#	web/package.json
2021-11-07 18:04:27 +01:00
1144944adb stages/identification: only allow limited challenges for login sources
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:35 +01:00
7751be284e stages/identification: use random sleep
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:32 +01:00
74382c6287 cmd/server: improve cleanup on shutdown
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:29 +01:00
011babbbd9 web: fix linting errors by adding a wrapper for next param
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:26 +01:00
3c01a1dd7b ci: keep latest github and scripts folder
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:22 +01:00
6e832be2de core: fix auth_method for tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:19 +01:00
46017f2f86 events: ignore creation/deletion of AuthenticatedSession objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:16 +01:00
da50eb0369 web/user: fix redirect after starting configuration flow from user interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:13 +01:00
b996e3cee7 ci: lock pipenv to 2021.11.5 for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:09 +01:00
12735cc14c admin: improve check to remove version notifications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-07 18:03:06 +01:00
4d36699b78 outpost/ldap: cleanup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 19:32:11 +01:00
8110d2861b web: Update Web API Client version (#1744)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-06 19:23:25 +01:00
1cc60f572d root: use forked openapi-generator
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 19:10:17 +01:00
90151a13ae stages/identification: only allow limited challenges for login sources
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 14:53:38 +01:00
f958aa6930 stages/identification: use random sleep
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 14:50:35 +01:00
13fbac30a2 cmd/server: improve cleanup on shutdown
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 13:54:59 +01:00
4f4cdf16f1 web: fix linting errors by adding a wrapper for next param
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 13:19:39 +01:00
7d75599627 ci: keep latest github and scripts folder
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 13:06:51 +01:00
924a13e832 core: fix auth_method for tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 13:04:41 +01:00
ae83c35dfd events: ignore creation/deletion of AuthenticatedSession objects
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 13:04:34 +01:00
e9102f4e28 web/user: fix redirect after starting configuration flow from user interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 12:57:06 +01:00
9b8c1cbea5 ci: lock pipenv to 2021.11.5 for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 12:22:59 +01:00
6424bf98da admin: improve check to remove version notifications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-06 12:15:05 +01:00
74fb0f9e2a website/docs: Document using Proxmox VE as Provider Integration (#1743) 2021-11-06 00:00:57 +01:00
4380f37a77 web/admin: fix missing values for LDAP Provider form
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 11:42:09 +01:00
17fccd44e6 build(deps): bump goauthentik.io/api from 0.2021102.4 to 0.2021102.5 (#1742)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021102.4 to 0.2021102.5.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.2021102.4...v0.2021102.5)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2021-11-05 10:50:59 +01:00
217a8b5610 web: Update Web API Client version (#1741)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-05 10:42:02 +01:00
2cef220a3e providers/ldap: add/squash migrations
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 10:41:50 +01:00
5a8c66d325 providers/ldap: memory Query (#1681)
* outposts/ldap: modularise ldap outpost, to allow different searchers and binders

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

* outposts/ldap: add basic in-memory searcher

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

* providers/ldap: add search mode field

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

* outpost: add search mode field

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 10:37:30 +01:00
8de13d3f67 build(deps): bump goauthentik.io/api from 0.2021102.2 to 0.2021102.4 (#1738)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 09:33:26 +01:00
5c22bedbaf build(deps): bump golang from 1.17.2-bullseye to 1.17.3-bullseye (#1737) 2021-11-05 08:29:51 +01:00
8a0f993f0b build(deps): bump boto3 from 1.19.10 to 1.19.11 (#1739) 2021-11-05 08:29:37 +01:00
abcf515a69 web/admin: also show note for SAML provider
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 01:21:10 +01:00
894f704c27 web: Update Web API Client version (#1736)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-05 01:18:13 +01:00
7798292aa8 sources/plex: use exception_to_string in tasks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 01:16:36 +01:00
3005ca17bd web/admin: show warning on provider when not used with outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 01:15:33 +01:00
909461e533 providers/*: include list of outposts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 01:06:04 +01:00
df838a4023 web: Update Web API Client version (#1735)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-05 01:01:51 +01:00
0f86b62dd3 website/docs: prepare 2021.10.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 00:55:31 +01:00
a40c3aeb68 core: make group membership lookup respect parent groups (upwards)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 00:53:56 +01:00
4080738ded web/elements: fix import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 00:27:23 +01:00
4a89be3048 core: include parent group name
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-05 00:11:17 +01:00
e587c53e18 web: remove deprecated rollup-plugin-node-resolve
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 22:34:48 +01:00
023b97aa69 sources/ldap: remove deprecated default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 22:13:47 +01:00
51365dba74 web: Update Web API Client version (#1734)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-04 21:03:09 +01:00
0d3705685e web/admin: show warning on invitation list when no stage exists or is bound
closes #1720

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 21:00:42 +01:00
738e4d5c74 web/admin: only show flows with an invitation stage configured instead of all enrollment flows
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1720
2021-11-04 20:54:55 +01:00
b14b9cb0dd tests/e2e: fix selector for static token tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:55:30 +01:00
2a21ebf7b0 web/flows: fix authenticator_validate not allowing alpha-numeric codes due to empty pattern
closes #1663

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:39:10 +01:00
5bc1301043 stages/authenticator_*: add default name for authenticators
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:34:51 +01:00
e0e4bf6972 web/user: fix device type for static tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:28:55 +01:00
337677ad12 web/flows: improve display of static tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:21:04 +01:00
3712d5aee2 web/user: fix empty page when no sources to connect exist
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:16:08 +01:00
dd82d55725 outposts: also send outpost type
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 15:08:31 +01:00
8d766efecb root: don't set signal on start when running in ci or dev
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 14:32:21 +01:00
9ac3b29418 outpost: add lightweight, anonymous metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 14:10:43 +01:00
5000c5b061 web/user: fix ak-user-settings-password getting wrong configureUrl
closes #1733

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:50:26 +01:00
b362d2af03 lib: fix linting issue
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:43:09 +01:00
bcd42fce13 root: further improve detection of environment we're running in
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:35:22 +01:00
6deddd038f internal: start embedded outpost directly after backend is healthy instead of waiting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:18:04 +01:00
3b47cb64da root: improve compose detection, add anonymous stats
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:16:21 +01:00
cf5e70c759 lifecycle: revert to non-h11 worker
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-04 13:16:10 +01:00
20bc38a54b build(deps): bump boto3 from 1.19.9 to 1.19.10 (#1731) 2021-11-04 08:36:15 +01:00
672a4ab1f4 build(deps): bump @sentry/browser from 6.13.3 to 6.14.0 in /web (#1728) 2021-11-04 08:35:53 +01:00
47dd667261 build(deps): bump @trivago/prettier-plugin-sort-imports in /web (#1729) 2021-11-04 08:35:40 +01:00
d1ac69789b build(deps): bump @sentry/tracing from 6.13.3 to 6.14.0 in /web (#1730) 2021-11-04 08:34:36 +01:00
08abf81c6d build(deps): bump goauthentik.io/api from 0.2021101.11 to 0.2021102.2 (#1732) 2021-11-04 08:33:50 +01:00
76bd987e6f web: Update Web API Client version (#1727)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-03 21:11:10 +01:00
5374352411 sources/plex: allow users to connect their plex account without login flow
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 21:09:02 +01:00
08eff4cc5d sources/plex: fix missing ordering
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 20:21:33 +01:00
c87a9f9489 web: remove debug entry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 20:19:37 +01:00
8f6d700aa8 sources/oauth: set prompt=none for Discord provider
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 15:48:59 +01:00
c6843b026c web: Update Web API Client version (#1726)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-03 11:41:57 +01:00
3769c33ef0 Merge branch 'version-2021.10' 2021-11-03 11:39:27 +01:00
8982afaf44 website/docs: add 2021.10.2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 10:20:29 +01:00
58c221e867 release: 2021.10.2 2021-11-03 10:07:28 +01:00
108d3e56e3 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1721) 2021-11-03 09:01:54 +01:00
145b32c480 build(deps): bump lxml from 4.6.3 to 4.6.4 (#1725) 2021-11-03 08:33:42 +01:00
c788504bb0 build(deps): bump boto3 from 1.19.8 to 1.19.9 (#1724) 2021-11-03 08:33:32 +01:00
34782b31e5 build(deps): bump @docusaurus/preset-classic in /website (#1722) 2021-11-03 08:33:10 +01:00
5a3ca13d76 build(deps): bump swagger-spec-validator from 2.7.3 to 2.7.4 (#1723) 2021-11-03 08:33:02 +01:00
5dc0f3b91b website: remove static service account, use helm chart instead
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 00:14:01 +01:00
f51515f3de stages/invitation: don't throw 404 error in stage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-03 00:07:13 +01:00
f978575293 stages/invitation: remove invitation from plan context after deletion
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 23:50:12 +01:00
cb64eed90d web: re-fix lint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 14:59:35 +01:00
db1f7f0400 Revert "tests/e2e: remove deprecated desired_capabilities"
This reverts commit 2da7a8fede.
2021-11-02 14:53:52 +01:00
0d02dbf55c api: replace django sentry proxy with go proxy to prevent login issues
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 14:44:37 +01:00
6da78b8c32 web/user: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 13:48:37 +01:00
3a80bc8bda web/user: fix configureUrl not being passed to <ak-user-settings-password>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 13:21:01 +01:00
1aa9c0f9ca root: move pyright config to toml
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 13:05:11 +01:00
2da7a8fede tests/e2e: remove deprecated desired_capabilities
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 11:04:47 +01:00
89cb402f42 root: fix postgres install on bullseye
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 10:56:39 +01:00
b617fd213f web: replace deprecated commonjs plugin
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 10:38:20 +01:00
97b0f58f25 root: build outposts without CGO, use debug images for basic shell
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-02 10:11:51 +01:00
49a98bb744 build(deps): bump @typescript-eslint/eslint-plugin in /web (#1715) 2021-11-02 08:45:25 +01:00
f93a00d773 build(deps): bump rollup from 2.58.3 to 2.59.0 in /web (#1716) 2021-11-02 08:44:16 +01:00
8de40a8a21 build(deps): bump @typescript-eslint/parser from 5.2.0 to 5.3.0 in /web (#1717) 2021-11-02 08:44:08 +01:00
b9c54e97fa build(deps): bump goauthentik.io/api from 0.2021101.10 to 0.2021101.11 (#1718) 2021-11-02 08:44:00 +01:00
f1c55465f7 build(deps): bump boto3 from 1.19.7 to 1.19.8 (#1719) 2021-11-02 08:43:51 +01:00
40c2b2860b web: Update Web API Client version (#1712)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-11-01 21:08:38 +01:00
a92bce322d web/flows: fix sub_text not rendering for static fields
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-01 20:54:43 +01:00
af83308fd4 stages/prompt: fix type in Prompt not having enum set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-01 20:44:48 +01:00
73d991e75a root: update to buster
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-01 16:31:26 +01:00
1eba3f1334 root: update base images for outposts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-01 16:29:53 +01:00
b86251255d website/docs: add azure ad docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-11-01 15:58:59 +01:00
ccab41a6ca build(deps): bump packaging from 21.0 to 21.2 (#1708) 2021-11-01 12:32:42 +01:00
0e051031b1 build(deps): bump django-storages from 1.12.2 to 1.12.3 (#1710) 2021-11-01 12:24:06 +01:00
aecbe8c585 build(deps): bump django from 3.2.8 to 3.2.9 (#1711) 2021-11-01 12:19:17 +01:00
da98022704 build(deps): bump boto3 from 1.19.6 to 1.19.7 (#1709) 2021-11-01 12:16:20 +01:00
e13f9c0b38 build(deps-dev): bump coverage from 6.0.2 to 6.1.1 (#1707) 2021-11-01 12:15:57 +01:00
7941fb9d95 build(deps): bump @babel/plugin-proposal-decorators in /web (#1703) 2021-11-01 10:05:47 +01:00
d2392b0881 build(deps): bump @babel/preset-env from 7.15.8 to 7.16.0 in /web (#1704) 2021-11-01 10:05:37 +01:00
b2044d75fb build(deps): bump @babel/core from 7.15.8 to 7.16.0 in /web (#1701) 2021-11-01 10:04:54 +01:00
617b64b7db build(deps): bump @babel/preset-typescript from 7.15.0 to 7.16.0 in /web (#1700) 2021-11-01 10:03:54 +01:00
2bf5f2709a build(deps): bump @patternfly/patternfly from 4.144.5 to 4.151.4 in /web (#1702) 2021-11-01 10:03:42 +01:00
f03325df28 build(deps): bump @babel/plugin-transform-runtime in /web (#1705) 2021-11-01 10:03:22 +01:00
2b71e5bdfd build(deps): bump goauthentik.io/api from 0.2021101.5 to 0.2021101.10 (#1706) 2021-11-01 10:02:52 +01:00
f861737b85 web/admin: fix formatting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 23:04:26 +01:00
6036d88392 providers/proxy: allow configuring of additional scope mappings for proxy
closes #1255

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 22:25:51 +01:00
bfc8a56a0b *: fix tests for new field show_source_labels
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 18:18:21 +01:00
8d995011b8 web: Update Web API Client version (#1699)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-31 18:00:20 +01:00
5646141fe2 stages/identification: add show_source_labels option, to show labels for sources
closes #1679

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 17:57:48 +01:00
96b0bc324e web/flows: fix invalid validation for static tokens
closes #1663

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 17:32:39 +01:00
335d6edd11 providers/saml: fix error on missing AssertionConsumerServiceURL, fall back to default ACS
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 17:21:15 +01:00
5d9bed130a root: fix Detection of S3 settings for backups
closes #1698

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 16:54:10 +01:00
0a1ab74707 web: Update Web API Client version (#1697)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-31 12:16:09 +01:00
ef24b94585 Merge branch 'version-2021.10' 2021-10-31 12:13:43 +01:00
77b0438aa4 website/docs: prepare 2021.10.1
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 10:57:48 +01:00
2788329880 release: 2021.10.1 2021-10-31 10:56:21 +01:00
15ab11be70 web/user: fix wrong device being selected in user's mfa update form
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-31 00:55:56 +02:00
8d5460a132 outposts: separate websocket re-connection logic to decrease requests on reconnect
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 21:33:50 +02:00
5ba2c80813 Merge branch 'update-web-api-client'
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/src/user/user-settings/mfa/MFADeviceForm.ts
2021-10-30 15:20:16 +02:00
06766bdb25 web/user: update form to update mfa devices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 15:19:17 +02:00
fdae13316c web: Update Web API Client version
Signed-off-by: GitHub <noreply@github.com>
2021-10-30 13:18:31 +00:00
ae21886e8e web/user: update form to update mfa devices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 15:16:27 +02:00
f5dc81907a core: add created field to source connection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 15:02:41 +02:00
40f8ce3c4c web/user: rework MFA Device UI to support multiple devices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 14:56:14 +02:00
c934915776 web: Update Web API Client version (#1695)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-30 14:53:02 +02:00
d70c8fbcc3 core: add API for all user-source connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 14:36:54 +02:00
12b26e49ec flows: optimise stage user_settings API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-30 14:16:28 +02:00
0ac548d56e web: Update Web API Client version (#1693)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-29 09:16:08 +02:00
e771e1857f core: add API to list all authenticator devices
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-29 09:08:48 +02:00
479e9750c7 web/user: also search desc and publisher
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-29 09:08:48 +02:00
c5e7801247 build(deps): bump github.com/go-openapi/runtime from 0.20.0 to 0.21.0 (#1691)
Bumps [github.com/go-openapi/runtime](https://github.com/go-openapi/runtime) from 0.20.0 to 0.21.0.
- [Release notes](https://github.com/go-openapi/runtime/releases)
- [Commits](https://github.com/go-openapi/runtime/compare/v0.20.0...v0.21.0)

---
updated-dependencies:
- dependency-name: github.com/go-openapi/runtime
  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>
2021-10-29 09:06:34 +02:00
48ea15a946 build(deps): bump flowchart.js from 1.16.0 to 1.17.0 in /web (#1689) 2021-10-29 08:32:13 +02:00
e4c06f7356 build(deps): bump boto3 from 1.19.5 to 1.19.6 (#1690) 2021-10-29 08:31:58 +02:00
4d7d866e4b build(deps): bump github.com/go-openapi/strfmt from 0.20.3 to 0.21.0 (#1692) 2021-10-29 08:31:34 +02:00
72a93c0959 root: pin node images to v16
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-28 10:29:48 +02:00
73733b20b6 build(deps): bump @trivago/prettier-plugin-sort-imports from 2.0.4 to 3.0.0 in /web (#1684)
* build(deps): bump @trivago/prettier-plugin-sort-imports in /web

Bumps [@trivago/prettier-plugin-sort-imports](https://github.com/trivago/prettier-plugin-sort-imports) from 2.0.4 to 3.0.0.
- [Release notes](https://github.com/trivago/prettier-plugin-sort-imports/releases)
- [Changelog](https://github.com/trivago/prettier-plugin-sort-imports/blob/master/CHANGELOG.md)
- [Commits](https://github.com/trivago/prettier-plugin-sort-imports/commits)

---
updated-dependencies:
- dependency-name: "@trivago/prettier-plugin-sort-imports"
  dependency-type: direct:production
  update-type: version-update:semver-major
...

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

* web: update prettier config

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-28 09:48:51 +02:00
3872314931 root: update golang ldap server package
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-28 09:48:31 +02:00
85c6ede448 build(deps): bump goauthentik.io/api from 0.2021101.4 to 0.2021101.5 (#1685) 2021-10-28 08:47:04 +02:00
49c2bee9d6 build(deps): bump boto3 from 1.19.4 to 1.19.5 (#1686) 2021-10-28 08:46:54 +02:00
6b2c9d7c44 web: Update Web API Client version (#1683)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-27 22:32:01 +02:00
381010600f release: 2021.10.1-rc3 2021-10-27 18:57:07 +02:00
2a265f706a website/docs: prepare 2021.10.1-rc3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 18:56:52 +02:00
1b21b50b77 providers/oauth2: fallback to uid if UPN was selected but isn't available
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 16:11:35 +02:00
fa6324ab1d sources/ldap: prevent key users from being set as this is an M2M relation
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 15:43:56 +02:00
9e0daf2bcf sources/ldap: skip values which are of type bytes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 15:43:38 +02:00
0273ae16df events: fix error when notification transport doesn't exist anymore
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 15:38:41 +02:00
f2f12ef0ba api: fix error when connection to websocket via secret_key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 15:21:52 +02:00
61d3df5f02 outposts: fix docker controller not using object_naming_template
closes #1682

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-27 15:04:59 +02:00
971de4fcb9 core: add USER_ATTRIBUTE_CHANGE_EMAIL
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1590 and #1677
2021-10-27 13:34:11 +02:00
9c0bc78ca0 build(deps): bump boto3 from 1.19.3 to 1.19.4 (#1678) 2021-10-27 08:30:26 +02:00
92085f1a3c core: add toggle to completely disable backup mechanism
closes #1671

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-26 17:04:33 +02:00
6067406e96 website/docs: add freeipa docs (#1666)
* website/docs: add freeipa docs

Signed-off-by: M. David Bennett <mdavidbennett@syntheticworks.com>

* website/docs: fix freeipa settings screenshot

Signed-off-by: M. David Bennett <mdavidbennett@syntheticworks.com>
2021-10-26 14:29:42 +02:00
9ccd4d69fe build(deps): bump @typescript-eslint/eslint-plugin in /web (#1673) 2021-10-26 13:25:45 +02:00
17ec48332d build(deps): bump rollup from 2.58.0 to 2.58.3 in /web (#1672) 2021-10-26 13:25:01 +02:00
d3f5253a6b build(deps): bump @typescript-eslint/parser from 5.1.0 to 5.2.0 in /web (#1674) 2021-10-26 13:24:38 +02:00
7a70726d57 build(deps): bump kubernetes from v19.15.0b1 to 19.15.0 (#1675) 2021-10-26 13:24:12 +02:00
be303937fb build(deps): bump boto3 from 1.19.2 to 1.19.3 (#1676) 2021-10-26 13:23:59 +02:00
2326fc9ae2 build(deps): bump eslint from 8.0.1 to 8.1.0 in /web (#1669) 2021-10-25 09:58:30 +02:00
9374b0bcf2 build(deps): bump chart.js from 3.5.1 to 3.6.0 in /web (#1668) 2021-10-25 09:58:18 +02:00
47e6028099 build(deps): bump boto3 from 1.19.1 to 1.19.2 (#1670) 2021-10-25 09:57:57 +02:00
24114e8304 Update harbor doc (#1667) 2021-10-24 16:44:04 +02:00
921d9c79a1 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1659) 2021-10-22 07:35:06 +02:00
1119989ab7 build(deps): bump postcss from 8.3.10 to 8.3.11 in /website (#1657) 2021-10-22 07:34:34 +02:00
e17594f0f7 build(deps): bump eslint-plugin-custom-elements in /web (#1658) 2021-10-22 07:34:25 +02:00
5ae3b868d4 build(deps): bump @docusaurus/preset-classic in /website (#1660) 2021-10-22 07:34:11 +02:00
37ee4af5ff build(deps): bump goauthentik.io/api from 0.2021101.2 to 0.2021101.4 (#1661) 2021-10-22 07:33:55 +02:00
829aaca317 build(deps): bump boto3 from 1.19.0 to 1.19.1 (#1662) 2021-10-22 07:33:45 +02:00
8eb4d53810 providers/oauth2: fix events being created from /application/o/authorize/
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-21 22:59:01 +02:00
e60dfc5b3c web: Update Web API Client version (#1656) 2021-10-21 17:06:53 +02:00
cc403d8777 Merge branch 'version-2021.10' 2021-10-21 16:52:18 +02:00
b81e2e69d1 website/docs: prepare 2021.10.1-rc2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-21 16:49:11 +02:00
764 changed files with 24017 additions and 19530 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.10.1-rc2
current_version = 2021.12.2
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)

1
.github/stale.yml vendored
View File

@ -7,6 +7,7 @@ exemptLabels:
- pinned
- security
- pr_wanted
- enhancement/confirmed
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had

View File

@ -18,79 +18,17 @@ env:
POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
jobs:
lint-pylint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: scripts/ci_prepare.sh
- name: run pylint
run: pipenv run pylint authentik tests lifecycle
lint-black:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: scripts/ci_prepare.sh
- name: run black
run: pipenv run black --check authentik tests lifecycle
lint-isort:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: scripts/ci_prepare.sh
- name: run isort
run: pipenv run isort --check authentik tests lifecycle
lint-bandit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: scripts/ci_prepare.sh
- name: run bandit
run: pipenv run bandit -r authentik tests lifecycle
lint-pyright:
lint:
strategy:
fail-fast: false
matrix:
job:
- pylint
- black
- isort
- bandit
- pyright
- pending-migrations
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -100,12 +38,17 @@ jobs:
- uses: actions/setup-node@v2
with:
node-version: '16'
- id: cache-pipenv
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
run: |
scripts/ci_prepare.sh
npm install -g pyright@1.1.136
- name: run bandit
run: pipenv run pyright e2e lifecycle
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: scripts/ci_prepare.sh
- name: run pylint
run: pipenv run make ci-${{ matrix.job }}
test-migrations:
runs-on: ubuntu-latest
steps:
@ -114,7 +57,7 @@ jobs:
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -138,7 +81,7 @@ jobs:
run: |
python ./scripts/gh_env.py
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -146,7 +89,11 @@ jobs:
run: |
# Copy current, latest config to local
cp authentik/lib/default.yml local.env.yml
cp -R .github ..
cp -R scripts ..
git checkout $(git describe --abbrev=0 --match 'version/*')
rm -rf .github/ scripts/
mv ../.github ../scripts .
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
@ -160,7 +107,8 @@ jobs:
run: |
set -x
git fetch
git checkout ${{ steps.ev.outputs.branchName }}
git reset --hard HEAD
git checkout $GITHUB_HEAD_REF
pipenv sync --dev
- name: prepare
env:
@ -176,7 +124,7 @@ jobs:
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -205,7 +153,7 @@ jobs:
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -228,7 +176,7 @@ jobs:
testspace [integration]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
test-e2e:
test-e2e-provider:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -244,7 +192,7 @@ jobs:
with:
domain: ${{github.repository_owner}}
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -255,7 +203,7 @@ jobs:
scripts/ci_prepare.sh
docker-compose -f tests/e2e/docker-compose.yml up -d
- id: cache-web
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/**') }}
@ -267,35 +215,92 @@ jobs:
npm run build
- name: run e2e
run: |
pipenv run make test-e2e
pipenv run make test-e2e-provider
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace [e2e]unittest.xml --link=codecov
testspace [e2e-provider]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
build:
test-e2e-rest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- id: cache-pipenv
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-pipenv.outputs.cache-hit }}
run: |
scripts/ci_prepare.sh
docker-compose -f tests/e2e/docker-compose.yml up -d
- id: cache-web
uses: actions/cache@v2.1.7
with:
path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/**') }}
- name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true'
run: |
cd web
npm i
npm run build
- name: run e2e
run: |
pipenv run make test-e2e-rest
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace [e2e-rest]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
ci-core-mark:
needs:
- lint-pylint
- lint-black
- lint-isort
- lint-bandit
- lint-pyright
- lint
- test-migrations
- test-migrations-from-stable
- test-unittest
- test-integration
- test-e2e
- test-e2e-rest
- test-e2e-provider
runs-on: ubuntu-latest
steps:
- run: echo mark
build:
needs: ci-core-mark
runs-on: ubuntu-latest
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
arch:
- 'linux/amd64'
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.HARBOR_USERNAME }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
python ./scripts/gh_env.py
- name: Login to Container Registry
@ -314,3 +319,4 @@ jobs:
ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.sha }}
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
platforms: ${{ matrix.arch }}

View File

@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '^1.16.3'
go-version: "^1.17"
- name: Run linter
run: |
# Create folder structure for go embeds
@ -30,23 +30,35 @@ jobs:
-w /app \
golangci/golangci-lint:v1.39.0 \
golangci-lint run -v --timeout 200s
build:
ci-outpost-mark:
needs:
- lint-golint
runs-on: ubuntu-latest
steps:
- run: echo mark
build:
timeout-minutes: 120
needs:
- ci-outpost-mark
strategy:
fail-fast: false
matrix:
type:
- proxy
- ldap
arch:
- 'linux/amd64'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.HARBOR_USERNAME }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
python ./scripts/gh_env.py
- name: Login to Container Registry
@ -67,3 +79,42 @@ jobs:
file: ${{ matrix.type }}.Dockerfile
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
platforms: ${{ matrix.arch }}
build-outpost-binary:
timeout-minutes: 120
needs:
- ci-outpost-mark
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
type:
- proxy
- ldap
goos: [linux]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.17"
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- name: Build web
run: |
cd web
npm install
npm run build-proxy
- name: Build outpost
run: |
set -x
export GOOS=${{ matrix.goos }}
export GOARCH=${{ matrix.goarch }}
go build -tags=outpost_static_embed -v -o ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }} ./cmd/${{ matrix.type }}
- uses: actions/upload-artifact@v2
with:
name: authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}
path: ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}

View File

@ -65,12 +65,18 @@ jobs:
run: |
cd web
npm run lit-analyse
build:
ci-web-mark:
needs:
- lint-eslint
- lint-prettier
- lint-lit-analyse
runs-on: ubuntu-latest
steps:
- run: echo mark
build:
needs:
- ci-web-mark
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2

View File

@ -30,14 +30,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.10.1-rc2,
beryju/authentik:2021.12.2,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.10.1-rc2,
ghcr.io/goauthentik/server:2021.12.2,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.10.1-rc2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.12.2', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -45,13 +45,19 @@ jobs:
docker pull ghcr.io/goauthentik/server:latest
docker tag ghcr.io/goauthentik/server:latest ghcr.io/goauthentik/server:stable
docker push ghcr.io/goauthentik/server:stable
build-proxy:
build-outpost:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
type:
- proxy
- ldap
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.15"
go-version: "^1.17"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
@ -72,68 +78,65 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.10.1-rc2,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.10.1-rc2,
ghcr.io/goauthentik/proxy:latest
file: proxy.Dockerfile
beryju/authentik-${{ matrix.type }}:2021.12.2,
beryju/authentik-${{ matrix.type }}:latest,
ghcr.io/goauthentik/${{ matrix.type }}:2021.12.2,
ghcr.io/goauthentik/${{ matrix.type }}:latest
file: ${{ matrix.type }}.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.10.1-rc2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.12.2', 'rc') }}
run: |
docker pull beryju/authentik-proxy:latest
docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable
docker push beryju/authentik-proxy:stable
docker pull ghcr.io/goauthentik/proxy:latest
docker tag ghcr.io/goauthentik/proxy:latest ghcr.io/goauthentik/proxy:stable
docker push ghcr.io/goauthentik/proxy:stable
build-ldap:
docker pull beryju/authentik-${{ matrix.type }}:latest
docker tag beryju/authentik-${{ matrix.type }}:latest beryju/authentik-${{ matrix.type }}:stable
docker push beryju/authentik-${{ matrix.type }}:stable
docker pull ghcr.io/goauthentik/${{ matrix.type }}:latest
docker tag ghcr.io/goauthentik/${{ matrix.type }}:latest ghcr.io/goauthentik/${{ matrix.type }}:stable
docker push ghcr.io/goauthentik/${{ matrix.type }}:stable
build-outpost-binary:
timeout-minutes: 120
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
type:
- proxy
- ldap
goos: [linux, darwin]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: "^1.15"
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.2.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Docker Login Registry
uses: docker/login-action@v1
go-version: "^1.17"
- uses: actions/setup-node@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.10.1-rc2,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.10.1-rc2,
ghcr.io/goauthentik/ldap:latest
file: ldap.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.10.1-rc2', 'rc') }}
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- name: Build web
run: |
docker pull beryju/authentik-ldap:latest
docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable
docker push beryju/authentik-ldap:stable
docker pull ghcr.io/goauthentik/ldap:latest
docker tag ghcr.io/goauthentik/ldap:latest ghcr.io/goauthentik/ldap:stable
docker push ghcr.io/goauthentik/ldap:stable
cd web
npm install
npm run build-proxy
- name: Build outpost
run: |
set -x
export GOOS=${{ matrix.goos }}
export GOARCH=${{ matrix.goarch }}
go build -tags=outpost_static_embed -v -o ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }} ./cmd/${{ matrix.type }}
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}
asset_name: authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}
tag: ${{ github.ref }}
test-release:
needs:
- build-server
- build-proxy
- build-ldap
- build-outpost
- build-outpost-binary
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -151,16 +154,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js environment
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Build web api client and web ui
- name: Get static files from docker image
run: |
export NODE_ENV=production
cd web
npm i
npm run build
docker pull ghcr.io/goauthentik/server:latest
container=$(docker container create ghcr.io/goauthentik/server:latest)
docker cp ${container}:web/ .
- name: Create a Sentry.io release
uses: getsentry/action-release@v1
if: ${{ github.event_name == 'release' }}
@ -170,7 +168,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.10.1-rc2
version: authentik@2021.12.2
environment: beryjuorg-prod
sourcemaps: './web/dist'
url_prefix: '~/static/dist'

View File

@ -15,6 +15,7 @@ jobs:
run: |
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker buildx install
docker build \
--no-cache \
-t testing:latest \

View File

@ -4,6 +4,9 @@ on:
branches: [ master ]
paths:
- '/locale/'
pull_request:
paths:
- '/locale/'
schedule:
- cron: "0 */2 * * *"
workflow_dispatch:
@ -22,7 +25,7 @@ jobs:
with:
python-version: '3.9'
- id: cache-pipenv
uses: actions/cache@v2.1.6
uses: actions/cache@v2.1.7
with:
path: ~/.local/share/virtualenvs
key: ${{ runner.os }}-pipenv-v2-${{ hashFiles('**/Pipfile.lock') }}
@ -37,10 +40,19 @@ jobs:
run: pipenv run ./manage.py compilemessages
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
id: cpr
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: compile-backend-translation
commit-message: "core: compile backend translations"
title: "core: compile backend translations"
body: "core: compile backend translations"
delete-branch: true
signoff: true
- name: Enable Pull Request Automerge
if: steps.cpr.outputs.pull-request-operation == 'created'
uses: peter-evans/enable-pull-request-automerge@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
merge-method: squash

View File

@ -30,10 +30,19 @@ jobs:
npm i @goauthentik/api@$VERSION
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
id: cpr
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: update-web-api-client
commit-message: "web: Update Web API Client version"
title: "web: Update Web API Client version"
body: "web: Update Web API Client version"
delete-branch: true
signoff: true
- name: Enable Pull Request Automerge
if: steps.cpr.outputs.pull-request-operation == 'created'
uses: peter-evans/enable-pull-request-automerge@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
pull-request-number: ${{ steps.cpr.outputs.pull-request-number }}
merge-method: squash

4
.gitignore vendored
View File

@ -66,7 +66,9 @@ coverage.xml
unittest.xml
# Translations
*.mo
# Have to include binary mo files as they are annoying to compile at build time
# since a full postgres and redis instance are required
# *.mo
# Django stuff:

1
.python-version Normal file
View File

@ -0,0 +1 @@
3.9.7

View File

@ -10,7 +10,8 @@
"plex",
"saml",
"totp",
"webauthn"
"webauthn",
"traefik"
],
"python.linting.pylintEnabled": true,
"todo-tree.tree.showCountsInTree": true,

View File

@ -1,5 +1,5 @@
# Stage 1: Lock python dependencies
FROM docker.io/python:3.9-slim-buster as locker
FROM docker.io/python:3.10.1-slim-bullseye as locker
COPY ./Pipfile /app/
COPY ./Pipfile.lock /app/
@ -11,35 +11,32 @@ RUN pip install pipenv && \
pipenv lock -r --dev-only > requirements-dev.txt
# Stage 2: Build website
FROM docker.io/node as website-builder
FROM --platform=${BUILDPLATFORM} docker.io/node:16 as website-builder
COPY ./website /static/
COPY ./website /work/website/
ENV NODE_ENV=production
RUN cd /static && npm i && npm run build-docs-only
RUN cd /work/website && npm i && npm run build-docs-only
# Stage 3: Build webui
FROM docker.io/node as web-builder
FROM --platform=${BUILDPLATFORM} docker.io/node:16 as web-builder
COPY ./web /static/
COPY ./web /work/web/
COPY ./website /work/website/
ENV NODE_ENV=production
RUN cd /static && npm i && npm run build
RUN cd /work/web && npm i && npm run build
# Stage 4: Build go proxy
FROM docker.io/golang:1.17.2 AS builder
FROM docker.io/golang:1.17.5-bullseye AS builder
WORKDIR /work
COPY --from=web-builder /static/robots.txt /work/web/robots.txt
COPY --from=web-builder /static/security.txt /work/web/security.txt
COPY --from=web-builder /static/dist/ /work/web/dist/
COPY --from=web-builder /static/authentik/ /work/web/authentik/
COPY --from=website-builder /static/help/ /work/website/help/
COPY --from=web-builder /work/web/robots.txt /work/web/robots.txt
COPY --from=web-builder /work/web/security.txt /work/web/security.txt
COPY ./cmd /work/cmd
COPY ./web/static.go /work/web/static.go
COPY ./website/static.go /work/website/static.go
COPY ./internal /work/internal
COPY ./go.mod /work/go.mod
COPY ./go.sum /work/go.sum
@ -47,7 +44,7 @@ COPY ./go.sum /work/go.sum
RUN go build -o /work/authentik ./cmd/server/main.go
# Stage 5: Run
FROM docker.io/python:3.9-slim-buster
FROM docker.io/python:3.10.1-slim-bullseye
WORKDIR /
COPY --from=locker /app/requirements.txt /
@ -57,19 +54,18 @@ ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates gnupg git runit && \
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
apt-get update && \
apt-get install -y --no-install-recommends libpq-dev postgresql-client build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \
apt-get install -y --no-install-recommends \
curl ca-certificates gnupg git runit libpq-dev \
postgresql-client build-essential libxmlsec1-dev \
pkg-config libmaxminddb0 && \
pip install -r /requirements.txt --no-cache-dir && \
apt-get remove --purge -y build-essential git && \
apt-get autoremove --purge -y && \
apt-get clean && \
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \
adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \
mkdir /backups && \
chown authentik:authentik /backups
mkdir -p /backups /certs /media && \
chown authentik:authentik /backups /certs /media
COPY ./authentik/ /authentik
COPY ./pyproject.toml /
@ -78,6 +74,9 @@ COPY ./tests /tests
COPY ./manage.py /
COPY ./lifecycle/ /lifecycle
COPY --from=builder /work/authentik /authentik-proxy
COPY --from=web-builder /work/web/dist/ /web/dist/
COPY --from=web-builder /work/web/authentik/ /web/authentik/
COPY --from=website-builder /work/website/help/ /website/help/
USER authentik

View File

@ -4,16 +4,19 @@ UID = $(shell id -u)
GID = $(shell id -g)
NPM_VERSION = $(shell python -m scripts.npm_version)
all: lint-fix lint test gen
all: lint-fix lint test gen web
test-integration:
coverage run manage.py test -v 3 tests/integration
coverage run manage.py test tests/integration
test-e2e:
coverage run manage.py test --failfast -v 3 tests/e2e
test-e2e-provider:
coverage run manage.py test tests/e2e/test_provider*
test-e2e-rest:
coverage run manage.py test tests/e2e/test_flows* tests/e2e/test_source*
test:
coverage run manage.py test -v 3 authentik
coverage run manage.py test authentik
coverage html
coverage report
@ -30,13 +33,13 @@ lint-fix:
website/developer-docs
lint:
pyright authentik tests lifecycle
bandit -r authentik tests lifecycle -x node_modules
pylint authentik tests lifecycle
i18n-extract:
i18n-extract: i18n-extract-core web-extract
i18n-extract-core:
./manage.py makemessages --ignore web --ignore internal --ignore web --ignore web-api --ignore website -l en
cd web && npm run extract
gen-build:
./manage.py spectacular --file schema.yml
@ -61,18 +64,20 @@ gen-web:
\cp -rfv web-api/* web/node_modules/@goauthentik/api
gen-outpost:
wget https://raw.githubusercontent.com/goauthentik/client-go/main/config.yaml -O config.yaml
mkdir -p templates
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/README.mustache -O templates/README.mustache
wget https://raw.githubusercontent.com/goauthentik/client-go/main/templates/go.mod.mustache -O templates/go.mod.mustache
docker run \
--rm -v ${PWD}:/local \
--user ${UID}:${GID} \
openapitools/openapi-generator-cli generate \
--git-host goauthentik.io \
--git-repo-id outpost \
--git-user-id api \
openapitools/openapi-generator-cli:v5.2.1 generate \
-i /local/schema.yml \
-g go \
-o /local/api \
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true,disallowAdditionalPropertiesIfNotPresent=false
rm -f api/go.mod api/go.sum
-c /local/config.yaml
go mod edit -replace goauthentik.io/api=./api
rm -rf config.yaml ./templates/
gen: gen-build gen-clean gen-web
@ -81,3 +86,39 @@ migrate:
run:
go run -v cmd/server/main.go
web-watch:
cd web && npm run watch
web: web-lint-fix web-lint web-extract
web-lint-fix:
cd web && npm run prettier
web-lint:
cd web && npm run lint
cd web && npm run lit-analyse
web-extract:
cd web && npm run extract
# These targets are use by GitHub actions to allow usage of matrix
# which makes the YAML File a lot smaller
ci-pylint:
pylint authentik tests lifecycle
ci-black:
black --check authentik tests lifecycle
ci-isort:
isort --check authentik tests lifecycle
ci-bandit:
bandit -r authentik tests lifecycle
ci-pyright:
pyright e2e lifecycle
ci-pending-migrations:
./manage.py makemigrations --check

22
Pipfile
View File

@ -8,7 +8,10 @@ boto3 = "*"
celery = "*"
channels = "*"
channels-redis = "*"
codespell = "*"
colorama = "*"
dacite = "*"
deepmerge = "*"
defusedxml = "*"
django = "*"
django-dbbackup = { git = 'https://github.com/django-dbbackup/django-dbbackup.git', ref = '9d1909c30a3271c8c9c8450add30d6e0b996e145' }
@ -23,10 +26,11 @@ djangorestframework = "*"
djangorestframework-guardian = "*"
docker = "*"
drf-spectacular = "*"
duo-client = "*"
facebook-sdk = "*"
geoip2 = "*"
gunicorn = "*"
kubernetes = "==v19.15.0b1"
kubernetes = "==v19.15.0"
ldap3 = "*"
lxml = "*"
packaging = "*"
@ -35,24 +39,22 @@ pycryptodome = "*"
pyjwt = "*"
pyyaml = "*"
requests-oauthlib = "*"
sentry-sdk = "*"
sentry-sdk = { git = 'https://github.com/beryju/sentry-python.git', ref = '379aee28b15d3b87b381317746c4efd24b3d7bc3' }
service_identity = "*"
structlog = "*"
swagger-spec-validator = "*"
twisted = "==21.7.0"
ua-parser = "*"
urllib3 = {extras = ["secure"],version = "*"}
uvicorn = {extras = ["standard"],version = "*"}
webauthn = "*"
xmlsec = "*"
duo-client = "*"
ua-parser = "*"
deepmerge = "*"
colorama = "*"
codespell = "*"
flower = "*"
wsproto = "*"
[dev-packages]
bandit = "*"
black = "==21.9b0"
black = "==21.11b1"
bump2version = "*"
colorama = "*"
coverage = {extras = ["toml"],version = "*"}
@ -60,5 +62,7 @@ pylint = "*"
pylint-django = "*"
pytest = "*"
pytest-django = "*"
selenium = "*"
pytest-randomly = "*"
requests-mock = "*"
selenium = "*"
importlib-metadata = "*"

1651
Pipfile.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -38,3 +38,23 @@ See [Development Documentation](https://goauthentik.io/developer-docs/?utm_sourc
## Security
See [SECURITY.md](SECURITY.md)
## Sponsors
This project is proudly sponsored by:
<p>
<a href="https://www.digitalocean.com/?utm_medium=opensource&utm_source=goauthentik.io">
<img src="https://opensource.nyc3.cdn.digitaloceanspaces.com/attribution/assets/SVG/DO_Logo_horizontal_blue.svg" width="201px">
</a>
</p>
DigitalOcean provides development and testing resources for authentik.
<p>
<a href="https://www.netlify.com">
<img src="https://www.netlify.com/img/global/badges/netlify-color-accent.svg" alt="Deploys by Netlify" />
</a>
</p>
Netlify hosts the [goauthentik.io](goauthentik.io) site.

View File

@ -6,8 +6,8 @@
| Version | Supported |
| ---------- | ------------------ |
| 2021.8.x | :white_check_mark: |
| 2021.9.x | :white_check_mark: |
| 2021.10.x | :white_check_mark: |
| 2021.12.x | :white_check_mark: |
## Reporting a Vulnerability

View File

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.10.1-rc2"
__version__ = "2021.12.2"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -1,13 +1,6 @@
"""authentik administration metrics"""
import time
from collections import Counter
from datetime import timedelta
from django.db.models import Count, ExpressionWrapper, F
from django.db.models.fields import DurationField
from django.db.models.functions import ExtractHour
from django.utils.timezone import now
from drf_spectacular.utils import extend_schema, extend_schema_field
from guardian.shortcuts import get_objects_for_user
from rest_framework.fields import IntegerField, SerializerMethodField
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
@ -15,31 +8,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from authentik.core.api.utils import PassiveSerializer
from authentik.events.models import Event, EventAction
def get_events_per_1h(**filter_kwargs) -> list[dict[str, int]]:
"""Get event count by hour in the last day, fill with zeros"""
date_from = now() - timedelta(days=1)
result = (
Event.objects.filter(created__gte=date_from, **filter_kwargs)
.annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField()))
.annotate(age_hours=ExtractHour("age"))
.values("age_hours")
.annotate(count=Count("pk"))
.order_by("age_hours")
)
data = Counter({int(d["age_hours"]): d["count"] for d in result})
results = []
_now = now()
for hour in range(0, -24, -1):
results.append(
{
"x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000,
"y_cord": data[hour * -1],
}
)
return results
from authentik.events.models import EventAction
class CoordinateSerializer(PassiveSerializer):
@ -58,12 +27,22 @@ class LoginMetricsSerializer(PassiveSerializer):
@extend_schema_field(CoordinateSerializer(many=True))
def get_logins_per_1h(self, _):
"""Get successful logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN)
user = self.context["user"]
return (
get_objects_for_user(user, "authentik_events.view_event")
.filter(action=EventAction.LOGIN)
.get_events_per_hour()
)
@extend_schema_field(CoordinateSerializer(many=True))
def get_logins_failed_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours"""
return get_events_per_1h(action=EventAction.LOGIN_FAILED)
user = self.context["user"]
return (
get_objects_for_user(user, "authentik_events.view_event")
.filter(action=EventAction.LOGIN_FAILED)
.get_events_per_hour()
)
class AdministrationMetricsViewSet(APIView):
@ -75,4 +54,5 @@ class AdministrationMetricsViewSet(APIView):
def get(self, request: Request) -> Response:
"""Login Metrics per 1h"""
serializer = LoginMetricsSerializer(True)
serializer.context["user"] = request.user
return Response(serializer.data)

View File

@ -86,7 +86,7 @@ class SystemSerializer(PassiveSerializer):
def get_embedded_outpost_host(self, request: Request) -> str:
"""Get the FQDN configured on the embedded outpost"""
outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST)
if not outposts.exists():
if not outposts.exists(): # pragma: no cover
return ""
return outposts.first().config.authentik_host

View File

@ -36,7 +36,7 @@ class TaskSerializer(PassiveSerializer):
are pickled in cache. In that case, just delete the info"""
try:
return super().to_representation(instance)
except AttributeError:
except AttributeError: # pragma: no cover
if isinstance(self.instance, list):
for inst in self.instance:
inst.delete()

View File

@ -23,6 +23,6 @@ class WorkerView(APIView):
"""Get currently connected worker count."""
count = len(CELERY_APP.control.ping(timeout=0.5))
# In debug we run with `CELERY_TASK_ALWAYS_EAGER`, so tasks are ran on the main process
if settings.DEBUG:
if settings.DEBUG: # pragma: no cover
count += 1
return Response({"count": count})

View File

@ -27,6 +27,7 @@ VERSION_CACHE_TIMEOUT = 8 * 60 * 60 # 8 hours
# Chop of the first ^ because we want to search the entire string
URL_FINDER = URLValidator.regex.pattern[1:]
PROM_INFO = Info("authentik_version", "Currently running authentik version")
LOCAL_VERSION = parse(__version__)
def _set_prom_info():
@ -48,12 +49,12 @@ def clear_update_notifications():
if "new_version" not in notification.event.context:
continue
notification_version = notification.event.context["new_version"]
if notification_version == __version__:
if LOCAL_VERSION >= parse(notification_version):
notification.delete()
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task()
@prefill_task
def update_latest_version(self: MonitoredTask):
"""Update latest version info"""
if CONFIG.y_bool("disable_update_check"):
@ -74,8 +75,7 @@ def update_latest_version(self: MonitoredTask):
_set_prom_info()
# Check if upstream version is newer than what we're running,
# and if no event exists yet, create one.
local_version = parse(__version__)
if local_version < parse(upstream_version):
if LOCAL_VERSION < parse(upstream_version):
# Event has already been created, don't create duplicate
if Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE,

View File

@ -8,6 +8,7 @@ from authentik import __version__
from authentik.core.models import Group, User
from authentik.core.tasks import clean_expired_models
from authentik.events.monitored_tasks import TaskResultStatus
from authentik.managed.tasks import managed_reconcile
class TestAdminAPI(TestCase):
@ -94,5 +95,7 @@ class TestAdminAPI(TestCase):
def test_system(self):
"""Test system API"""
# pyright: reportGeneralTypeIssues=false
managed_reconcile() # pylint: disable=no-value-for-parameter
response = self.client.get(reverse("authentik_api:admin_system"))
self.assertEqual(response.status_code, 200)

View File

@ -3,8 +3,13 @@ from django.core.cache import cache
from django.test import TestCase
from requests_mock import Mocker
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
from authentik.admin.tasks import (
VERSION_CACHE_KEY,
clear_update_notifications,
update_latest_version,
)
from authentik.events.models import Event, EventAction
from authentik.lib.config import CONFIG
RESPONSE_VALID = {
"$schema": "https://version.goauthentik.io/schema.json",
@ -56,3 +61,23 @@ class TestAdminTasks(TestCase):
action=EventAction.UPDATE_AVAILABLE, context__new_version="0.0.0"
).exists()
)
def test_version_disabled(self):
"""Test Update checker while its disabled"""
with CONFIG.patch("disable_update_check", True):
update_latest_version.delay().get()
self.assertEqual(cache.get(VERSION_CACHE_KEY), "0.0.0")
def test_clear_update_notifications(self):
"""Test clear of previous notification"""
Event.objects.create(
action=EventAction.UPDATE_AVAILABLE, context={"new_version": "99999999.9999999.9999999"}
)
Event.objects.create(action=EventAction.UPDATE_AVAILABLE, context={"new_version": "1.1.1"})
Event.objects.create(action=EventAction.UPDATE_AVAILABLE, context={})
clear_update_notifications()
self.assertFalse(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE, context__new_version="1.1"
).exists()
)

View File

@ -45,7 +45,8 @@ def bearer_auth(raw_header: bytes) -> Optional[User]:
if not user:
raise AuthenticationFailed("Token invalid/expired")
return user
LOCAL.authentik[KEY_AUTH_VIA] = "api_token"
if hasattr(LOCAL, "authentik"):
LOCAL.authentik[KEY_AUTH_VIA] = "api_token"
return tokens.first().user
@ -59,7 +60,8 @@ def token_secret_key(value: str) -> Optional[User]:
outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST)
if not outposts:
return None
LOCAL.authentik[KEY_AUTH_VIA] = "secret_key"
if hasattr(LOCAL, "authentik"):
LOCAL.authentik[KEY_AUTH_VIA] = "secret_key"
outpost = outposts.first()
return outpost.user

View File

@ -1,19 +0,0 @@
"""API tasks"""
from authentik.lib.utils.http import get_http_session
from authentik.root.celery import CELERY_APP
SENTRY_SESSION = get_http_session()
@CELERY_APP.task()
def sentry_proxy(payload: str):
"""Relay data to sentry"""
SENTRY_SESSION.post(
"https://sentry.beryju.org/api/8/envelope/",
data=payload,
headers={
"Content-Type": "application/octet-stream",
},
timeout=10,
)

View File

@ -1,18 +0,0 @@
"""Throttling classes"""
from typing import Type
from django.views import View
from rest_framework.request import Request
from rest_framework.throttling import ScopedRateThrottle
class SessionThrottle(ScopedRateThrottle):
"""Throttle based on session key"""
def allow_request(self, request: Request, view):
if request._request.user.is_superuser:
return True
return super().allow_request(request, view)
def get_cache_key(self, request: Request, view: Type[View]) -> str:
return f"authentik-throttle-session-{request._request.session.session_key}"

View File

@ -4,7 +4,7 @@ from django.urls import include, path
from authentik.api.v3.urls import urlpatterns as v3_urls
urlpatterns = [
# Remove in 2022.1
# TODO: Remove in 2022.1
path("v2beta/", include(v3_urls)),
path("v3/", include(v3_urls)),
]

View File

@ -5,7 +5,14 @@ from django.conf import settings
from django.db import models
from drf_spectacular.utils import extend_schema
from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME
from rest_framework.fields import BooleanField, CharField, ChoiceField, IntegerField, ListField
from rest_framework.fields import (
BooleanField,
CharField,
ChoiceField,
FloatField,
IntegerField,
ListField,
)
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
@ -24,13 +31,19 @@ class Capabilities(models.TextChoices):
CAN_BACKUP = "can_backup"
class ErrorReportingConfigSerializer(PassiveSerializer):
"""Config for error reporting"""
enabled = BooleanField(read_only=True)
environment = CharField(read_only=True)
send_pii = BooleanField(read_only=True)
traces_sample_rate = FloatField(read_only=True)
class ConfigSerializer(PassiveSerializer):
"""Serialize authentik Config into DRF Object"""
error_reporting_enabled = BooleanField(read_only=True)
error_reporting_environment = CharField(read_only=True)
error_reporting_send_pii = BooleanField(read_only=True)
error_reporting = ErrorReportingConfigSerializer(required=True)
capabilities = ListField(child=ChoiceField(choices=Capabilities.choices))
cache_timeout = IntegerField(required=True)
@ -66,9 +79,12 @@ class ConfigView(APIView):
"""Retrieve public configuration options"""
config = ConfigSerializer(
{
"error_reporting_enabled": CONFIG.y("error_reporting.enabled"),
"error_reporting_environment": CONFIG.y("error_reporting.environment"),
"error_reporting_send_pii": CONFIG.y("error_reporting.send_pii"),
"error_reporting": {
"enabled": CONFIG.y("error_reporting.enabled"),
"environment": CONFIG.y("error_reporting.environment"),
"send_pii": CONFIG.y("error_reporting.send_pii"),
"traces_sample_rate": float(CONFIG.y("error_reporting.sample_rate", 0.4)),
},
"capabilities": self.get_capabilities(),
"cache_timeout": int(CONFIG.y("redis.cache_timeout")),
"cache_timeout_flows": int(CONFIG.y("redis.cache_timeout_flows")),

View File

@ -1,65 +0,0 @@
"""Sentry tunnel"""
from json import loads
from django.conf import settings
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from rest_framework.authentication import SessionAuthentication
from rest_framework.parsers import BaseParser
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView
from structlog.stdlib import get_logger
from authentik.api.tasks import sentry_proxy
from authentik.lib.config import CONFIG
LOGGER = get_logger()
class PlainTextParser(BaseParser):
"""Plain text parser."""
media_type = "text/plain"
def parse(self, stream, media_type=None, parser_context=None) -> str:
"""Simply return a string representing the body of the request."""
return stream.read()
class CsrfExemptSessionAuthentication(SessionAuthentication):
"""CSRF-exempt Session authentication"""
def enforce_csrf(self, request: Request):
return # To not perform the csrf check previously happening
class SentryTunnelView(APIView):
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
serializer_class = None
parser_classes = [PlainTextParser]
throttle_classes = [AnonRateThrottle]
permission_classes = [AllowAny]
authentication_classes = [CsrfExemptSessionAuthentication]
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
# Only allow usage of this endpoint when error reporting is enabled
if not CONFIG.y_bool("error_reporting.enabled", False):
LOGGER.debug("error reporting disabled")
return HttpResponse(status=400)
# Body is 2 json objects separated by \n
full_body = request.body
lines = full_body.splitlines()
if len(lines) < 1:
return HttpResponse(status=400)
header = loads(lines[0])
# Check that the DSN is what we expect
dsn = header.get("dsn", "")
if dsn != settings.SENTRY_DSN:
LOGGER.debug("Invalid dsn", have=dsn, expected=settings.SENTRY_DSN)
return HttpResponse(status=400)
sentry_proxy.delay(full_body.decode())
return HttpResponse(status=204)

View File

@ -11,14 +11,14 @@ from authentik.admin.api.tasks import TaskViewSet
from authentik.admin.api.version import VersionView
from authentik.admin.api.workers import WorkerView
from authentik.api.v3.config import ConfigView
from authentik.api.v3.sentry import SentryTunnelView
from authentik.api.views import APIBrowserView
from authentik.core.api.applications import ApplicationViewSet
from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet
from authentik.core.api.devices import DeviceViewSet
from authentik.core.api.groups import GroupViewSet
from authentik.core.api.propertymappings import PropertyMappingViewSet
from authentik.core.api.providers import ProviderViewSet
from authentik.core.api.sources import SourceViewSet
from authentik.core.api.sources import SourceViewSet, UserSourceConnectionViewSet
from authentik.core.api.tokens import TokenViewSet
from authentik.core.api.users import UserViewSet
from authentik.crypto.api import CertificateKeyPairViewSet
@ -136,6 +136,7 @@ router.register("events/transports", NotificationTransportViewSet)
router.register("events/rules", NotificationRuleViewSet)
router.register("sources/all", SourceViewSet)
router.register("sources/user_connections/all", UserSourceConnectionViewSet)
router.register("sources/user_connections/oauth", UserOAuthSourceConnectionViewSet)
router.register("sources/user_connections/plex", PlexSourceConnectionViewSet)
router.register("sources/ldap", LDAPSourceViewSet)
@ -169,6 +170,7 @@ router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
router.register("propertymappings/scope", ScopeMappingViewSet)
router.register("propertymappings/notification", NotificationWebhookMappingViewSet)
router.register("authenticators/all", DeviceViewSet, basename="device")
router.register("authenticators/duo", DuoDeviceViewSet)
router.register("authenticators/sms", SMSDeviceViewSet)
router.register("authenticators/static", StaticDeviceViewSet)
@ -246,7 +248,6 @@ urlpatterns = (
FlowInspectorView.as_view(),
name="flow-inspector",
),
path("sentry/", SentryTunnelView.as_view(), name="sentry"),
path("schema/", cache_page(86400)(SpectacularAPIView.as_view()), name="schema"),
]
)

View File

@ -5,6 +5,7 @@ from django.http.response import HttpResponseBadRequest
from django.shortcuts import get_object_or_404
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.fields import ReadOnlyField
from rest_framework.parsers import MultiPartParser
@ -15,7 +16,7 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.admin.api.metrics import CoordinateSerializer
from authentik.api.decorators import permission_required
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
@ -239,8 +240,10 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
"""Metrics for application logins"""
app = self.get_object()
return Response(
get_events_per_1h(
get_objects_for_user(request.user, "authentik_events.view_event")
.filter(
action=EventAction.AUTHORIZE_APPLICATION,
context__authorized_application__pk=app.pk.hex,
)
.get_events_per_hour()
)

View File

@ -0,0 +1,36 @@
"""Authenticator Devices API Views"""
from django_otp import devices_for_user
from django_otp.models import Device
from drf_spectacular.utils import extend_schema
from rest_framework.fields import CharField, IntegerField, SerializerMethodField
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ViewSet
from authentik.core.api.utils import MetaNameSerializer
class DeviceSerializer(MetaNameSerializer):
"""Serializer for Duo authenticator devices"""
pk = IntegerField()
name = CharField()
type = SerializerMethodField()
def get_type(self, instance: Device) -> str:
"""Get type of device"""
return instance._meta.label
class DeviceViewSet(ViewSet):
"""Viewset for authenticator devices"""
serializer_class = DeviceSerializer
permission_classes = [IsAuthenticated]
@extend_schema(responses={200: DeviceSerializer(many=True)})
def list(self, request: Request) -> Response:
"""Get all devices for current user"""
devices = devices_for_user(request.user)
return Response(DeviceSerializer(devices, many=True).data)

View File

@ -1,9 +1,11 @@
"""Groups API Viewset"""
from json import loads
from django.db.models.query import QuerySet
from django_filters.filters import ModelMultipleChoiceFilter
from django_filters.filters import CharFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
from rest_framework.fields import CharField, JSONField
from rest_framework.serializers import ListSerializer, ModelSerializer
from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
@ -42,6 +44,7 @@ class GroupSerializer(ModelSerializer):
users_obj = ListSerializer(
child=GroupMemberSerializer(), read_only=True, source="users", required=False
)
parent_name = CharField(source="parent.name", read_only=True)
class Meta:
@ -51,6 +54,7 @@ class GroupSerializer(ModelSerializer):
"name",
"is_superuser",
"parent",
"parent_name",
"users",
"attributes",
"users_obj",
@ -60,6 +64,13 @@ class GroupSerializer(ModelSerializer):
class GroupFilter(FilterSet):
"""Filter for groups"""
attributes = CharFilter(
field_name="attributes",
lookup_expr="",
label="Attributes",
method="filter_attributes",
)
members_by_username = ModelMultipleChoiceFilter(
field_name="users__username",
to_field_name="username",
@ -70,10 +81,28 @@ class GroupFilter(FilterSet):
queryset=User.objects.all(),
)
# pylint: disable=unused-argument
def filter_attributes(self, queryset, name, value):
"""Filter attributes by query args"""
try:
value = loads(value)
except ValueError:
raise ValidationError(detail="filter: failed to parse JSON")
if not isinstance(value, dict):
raise ValidationError(detail="filter: value must be key:value mapping")
qs = {}
for key, _value in value.items():
qs[f"attributes__{key}"] = _value
try:
_ = len(queryset.filter(**qs))
return queryset.filter(**qs)
except ValueError:
return queryset
class Meta:
model = Group
fields = ["name", "is_superuser", "members_by_pk", "members_by_username"]
fields = ["name", "is_superuser", "members_by_pk", "attributes", "members_by_username"]
class GroupViewSet(UsedByMixin, ModelViewSet):

View File

@ -56,6 +56,7 @@ class PropertyMappingSerializer(ManagedSerializer, ModelSerializer, MetaNameSeri
"component",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
]

View File

@ -43,6 +43,7 @@ class ProviderSerializer(ModelSerializer, MetaNameSerializer):
"assigned_application_name",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
]

View File

@ -1,18 +1,21 @@
"""Source API Views"""
from typing import Iterable
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import GenericViewSet
from structlog.stdlib import get_logger
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.models import Source
from authentik.core.models import Source, UserSourceConnection
from authentik.core.types import UserSettingSerializer
from authentik.lib.utils.reflection import all_subclasses
from authentik.policies.engine import PolicyEngine
@ -45,6 +48,7 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer):
"component",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
"policy_engine_mode",
"user_matching_mode",
]
@ -100,16 +104,52 @@ class SourceViewSet(
)
matching_sources: list[UserSettingSerializer] = []
for source in _all_sources:
user_settings = source.ui_user_settings
user_settings = source.ui_user_settings()
if not user_settings:
continue
policy_engine = PolicyEngine(source, request.user, request)
policy_engine.build()
if not policy_engine.passing:
continue
source_settings = source.ui_user_settings
source_settings = source.ui_user_settings()
source_settings.initial_data["object_uid"] = source.slug
if not source_settings.is_valid():
LOGGER.warning(source_settings.errors)
matching_sources.append(source_settings.validated_data)
return Response(matching_sources)
class UserSourceConnectionSerializer(SourceSerializer):
"""OAuth Source Serializer"""
source = SourceSerializer(read_only=True)
class Meta:
model = UserSourceConnection
fields = [
"pk",
"user",
"source",
"created",
]
extra_kwargs = {
"user": {"read_only": True},
"created": {"read_only": True},
}
class UserSourceConnectionViewSet(
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
UsedByMixin,
mixins.ListModelMixin,
GenericViewSet,
):
"""User-source connection Viewset"""
queryset = UserSourceConnection.objects.all()
serializer_class = UserSourceConnectionSerializer
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
ordering = ["pk"]

View File

@ -38,13 +38,14 @@ from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
from structlog.stdlib import get_logger
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.admin.api.metrics import CoordinateSerializer
from authentik.api.decorators import permission_required
from authentik.core.api.groups import GroupSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict
from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER
from authentik.core.models import (
USER_ATTRIBUTE_CHANGE_EMAIL,
USER_ATTRIBUTE_CHANGE_USERNAME,
USER_ATTRIBUTE_SA,
USER_ATTRIBUTE_TOKEN_EXPIRING,
@ -54,6 +55,7 @@ from authentik.core.models import (
User,
)
from authentik.events.models import EventAction
from authentik.lib.config import CONFIG
from authentik.stages.email.models import EmailStage
from authentik.stages.email.tasks import send_mails
from authentik.stages.email.utils import TemplateEmailMessage
@ -122,9 +124,21 @@ class UserSelfSerializer(ModelSerializer):
"pk": group.pk,
}
def validate_email(self, email: str):
"""Check if the user is allowed to change their email"""
if self.instance.group_attributes().get(
USER_ATTRIBUTE_CHANGE_EMAIL, CONFIG.y_bool("default_user_change_email", True)
):
return email
if email != self.instance.email:
raise ValidationError("Not allowed to change email.")
return email
def validate_username(self, username: str):
"""Check if the user is allowed to change their username"""
if self.instance.group_attributes().get(USER_ATTRIBUTE_CHANGE_USERNAME, True):
if self.instance.group_attributes().get(
USER_ATTRIBUTE_CHANGE_USERNAME, CONFIG.y_bool("default_user_change_username", True)
):
return username
if username != self.instance.username:
raise ValidationError("Not allowed to change username.")
@ -170,19 +184,31 @@ class UserMetricsSerializer(PassiveSerializer):
def get_logins_per_1h(self, _):
"""Get successful logins per hour for the last 24 hours"""
user = self.context["user"]
return get_events_per_1h(action=EventAction.LOGIN, user__pk=user.pk)
return (
get_objects_for_user(user, "authentik_events.view_event")
.filter(action=EventAction.LOGIN, user__pk=user.pk)
.get_events_per_hour()
)
@extend_schema_field(CoordinateSerializer(many=True))
def get_logins_failed_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours"""
user = self.context["user"]
return get_events_per_1h(action=EventAction.LOGIN_FAILED, context__username=user.username)
return (
get_objects_for_user(user, "authentik_events.view_event")
.filter(action=EventAction.LOGIN_FAILED, context__username=user.username)
.get_events_per_hour()
)
@extend_schema_field(CoordinateSerializer(many=True))
def get_authorizations_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours"""
user = self.context["user"]
return get_events_per_1h(action=EventAction.AUTHORIZE_APPLICATION, user__pk=user.pk)
return (
get_objects_for_user(user, "authentik_events.view_event")
.filter(action=EventAction.AUTHORIZE_APPLICATION, user__pk=user.pk)
.get_events_per_hour()
)
class UsersFilter(FilterSet):
@ -219,7 +245,11 @@ class UsersFilter(FilterSet):
qs = {}
for key, _value in value.items():
qs[f"attributes__{key}"] = _value
return queryset.filter(**qs)
try:
_ = len(queryset.filter(**qs))
return queryset.filter(**qs)
except ValueError:
return queryset
class Meta:
model = User
@ -300,7 +330,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
name=username,
attributes={USER_ATTRIBUTE_SA: True, USER_ATTRIBUTE_TOKEN_EXPIRING: False},
)
if create_group:
if create_group and self.request.user.has_perm("authentik_core.add_group"):
group = Group.objects.create(
name=username,
)
@ -320,13 +350,14 @@ class UserViewSet(UsedByMixin, ModelViewSet):
# pylint: disable=invalid-name
def me(self, request: Request) -> Response:
"""Get information about current user"""
serializer = SessionUserSerializer(data={"user": UserSelfSerializer(request.user).data})
serializer = SessionUserSerializer(
data={"user": UserSelfSerializer(instance=request.user).data}
)
if SESSION_IMPERSONATE_USER in request._request.session:
serializer.initial_data["original"] = UserSelfSerializer(
request._request.session[SESSION_IMPERSONATE_ORIGINAL_USER]
instance=request._request.session[SESSION_IMPERSONATE_ORIGINAL_USER]
).data
serializer.is_valid()
return Response(serializer.data)
return Response(serializer.initial_data)
@extend_schema(request=UserSelfSerializer, responses={200: SessionUserSerializer(many=False)})
@action(
@ -346,9 +377,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
# since it caches the full object
if SESSION_IMPERSONATE_USER in request.session:
request.session[SESSION_IMPERSONATE_USER] = new_user
serializer = SessionUserSerializer(data={"user": data.data})
serializer.is_valid()
return Response(serializer.data)
return Response({"user": data.data})
@permission_required("authentik_core.view_user", ["authentik_events.view_event"])
@extend_schema(responses={200: UserMetricsSerializer(many=False)})

View File

@ -41,6 +41,7 @@ class MetaNameSerializer(PassiveSerializer):
verbose_name = SerializerMethodField()
verbose_name_plural = SerializerMethodField()
meta_model_name = SerializerMethodField()
def get_verbose_name(self, obj: Model) -> str:
"""Return object's verbose_name"""
@ -50,6 +51,10 @@ class MetaNameSerializer(PassiveSerializer):
"""Return object's plural verbose_name"""
return obj._meta.verbose_name_plural
def get_meta_model_name(self, obj: Model) -> str:
"""Return internal model name"""
return f"{obj._meta.app_label}.{obj._meta.model_name}"
class TypeCreateSerializer(PassiveSerializer):
"""Types of an object that can be created"""

View File

@ -55,5 +55,5 @@ class TokenBackend(InbuiltBackend):
if not tokens.exists():
return None
token = tokens.first()
self.set_method("password", request, token=token)
self.set_method("token", request, token=token)
return token.user

View File

@ -5,6 +5,7 @@ from typing import Callable
from uuid import uuid4
from django.http import HttpRequest, HttpResponse
from sentry_sdk.api import set_tag
SESSION_IMPERSONATE_USER = "authentik_impersonate_user"
SESSION_IMPERSONATE_ORIGINAL_USER = "authentik_impersonate_original_user"
@ -12,7 +13,6 @@ LOCAL = local()
RESPONSE_HEADER_ID = "X-authentik-id"
KEY_AUTH_VIA = "auth_via"
KEY_USER = "user"
INTERNAL_HEADER_PREFIX = "X-authentik-internal-"
class ImpersonateMiddleware:
@ -51,11 +51,12 @@ class RequestIDMiddleware:
"request_id": request_id,
"host": request.get_host(),
}
set_tag("authentik.request_id", request_id)
response = self.get_response(request)
response[RESPONSE_HEADER_ID] = request.request_id
if auth_via := LOCAL.authentik.get(KEY_AUTH_VIA, None):
response[INTERNAL_HEADER_PREFIX + KEY_AUTH_VIA] = auth_via
response[INTERNAL_HEADER_PREFIX + KEY_USER] = request.user.username
setattr(response, "ak_context", {})
response.ak_context.update(LOCAL.authentik)
response.ak_context[KEY_USER] = request.user.username
for key in list(LOCAL.authentik.keys()):
del LOCAL.authentik[key]
return response
@ -66,4 +67,6 @@ def structlog_add_request_id(logger: Logger, method_name: str, event_dict: dict)
"""If threadlocal has authentik defined, add request_id to log"""
if hasattr(LOCAL, "authentik"):
event_dict.update(LOCAL.authentik)
if hasattr(LOCAL, "authentik_task"):
event_dict.update(LOCAL.authentik_task)
return event_dict

View File

@ -3,7 +3,6 @@
import uuid
from os import environ
import django.core.validators
import django.db.models.deletion
from django.apps.registry import Apps
from django.conf import settings
@ -12,6 +11,7 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.models import Count
import authentik.core.models
import authentik.lib.models
def migrate_sessions(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
@ -161,7 +161,7 @@ class Migration(migrations.Migration):
model_name="application",
name="meta_launch_url",
field=models.TextField(
blank=True, default="", validators=[django.core.validators.URLValidator()]
blank=True, default="", validators=[authentik.lib.models.DomainlessURLValidator()]
),
),
migrations.RunPython(

View File

@ -1,8 +1,9 @@
# Generated by Django 3.2.3 on 2021-06-02 21:51
import django.core.validators
from django.db import migrations, models
import authentik.lib.models
class Migration(migrations.Migration):
@ -17,7 +18,7 @@ class Migration(migrations.Migration):
field=models.TextField(
blank=True,
default="",
validators=[django.core.validators.URLValidator()],
validators=[authentik.lib.models.DomainlessURLValidator()],
),
),
]

View File

@ -9,7 +9,6 @@ from deepmerge import always_merger
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager as DjangoUserManager
from django.core import validators
from django.db import models
from django.db.models import Q, QuerySet, options
from django.http import HttpRequest
@ -26,10 +25,9 @@ from structlog.stdlib import get_logger
from authentik.core.exceptions import PropertyMappingExpressionException
from authentik.core.signals import password_changed
from authentik.core.types import UILoginButton, UserSettingSerializer
from authentik.flows.models import Flow
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_id
from authentik.lib.models import CreatedUpdatedModel, SerializerModel
from authentik.lib.models import CreatedUpdatedModel, DomainlessURLValidator, SerializerModel
from authentik.lib.utils.http import get_client_ip
from authentik.managed.models import ManagedModel
from authentik.policies.models import PolicyBindingModel
@ -39,7 +37,8 @@ USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug"
USER_ATTRIBUTE_SA = "goauthentik.io/user/service-account"
USER_ATTRIBUTE_SOURCES = "goauthentik.io/user/sources"
USER_ATTRIBUTE_TOKEN_EXPIRING = "goauthentik.io/user/token-expires" # nosec
USER_ATTRIBUTE_CHANGE_USERNAME = "goauthentik.io/user/can-change-username" # nosec
USER_ATTRIBUTE_CHANGE_USERNAME = "goauthentik.io/user/can-change-username"
USER_ATTRIBUTE_CHANGE_EMAIL = "goauthentik.io/user/can-change-email"
USER_ATTRIBUTE_CAN_OVERRIDE_IP = "goauthentik.io/user/override-ips"
GRAVATAR_URL = "https://secure.gravatar.com"
@ -80,6 +79,27 @@ class Group(models.Model):
)
attributes = models.JSONField(default=dict, blank=True)
def is_member(self, user: "User") -> bool:
"""Recursively check if `user` is member of us, or any parent."""
query = """
WITH RECURSIVE parents AS (
SELECT authentik_core_group.*, 0 AS relative_depth
FROM authentik_core_group
WHERE authentik_core_group.group_uuid = %s
UNION ALL
SELECT authentik_core_group.*, parents.relative_depth - 1
FROM authentik_core_group,parents
WHERE authentik_core_group.parent_id = parents.group_uuid
)
SELECT group_uuid
FROM parents
GROUP BY group_uuid;
"""
groups = Group.objects.raw(query, [self.group_uuid])
return user.ak_groups.filter(pk__in=[group.pk for group in groups]).exists()
def __str__(self):
return f"Group {self.name}"
@ -152,7 +172,7 @@ class User(GuardianUserMixin, AbstractUser):
if mode == "none":
return DEFAULT_AVATAR
# gravatar uses md5 for their URLs, so md5 can't be avoided
mail_hash = md5(self.email.encode("utf-8")).hexdigest() # nosec
mail_hash = md5(self.email.lower().encode("utf-8")).hexdigest() # nosec
if mode == "gravatar":
parameters = [
("s", "158"),
@ -182,7 +202,7 @@ class Provider(SerializerModel):
name = models.TextField()
authorization_flow = models.ForeignKey(
Flow,
"authentik_flows.Flow",
on_delete=models.CASCADE,
help_text=_("Flow used when authorizing this provider."),
related_name="provider_authorization",
@ -224,7 +244,7 @@ class Application(PolicyBindingModel):
)
meta_launch_url = models.TextField(
default="", blank=True, validators=[validators.URLValidator()]
default="", blank=True, validators=[DomainlessURLValidator()]
)
# For template applications, this can be set to /static/authentik/applications/*
meta_icon = models.FileField(
@ -242,7 +262,7 @@ class Application(PolicyBindingModel):
it is returned as-is"""
if not self.meta_icon:
return None
if self.meta_icon.name.startswith("http") or self.meta_icon.name.startswith("/static"):
if "://" in self.meta_icon.name or self.meta_icon.name.startswith("/static"):
return self.meta_icon.name
return self.meta_icon.url
@ -258,7 +278,13 @@ class Application(PolicyBindingModel):
"""Get casted provider instance"""
if not self.provider:
return None
return Provider.objects.get_subclass(pk=self.provider.pk)
# if the Application class has been cache, self.provider is set
# but doing a direct query lookup will fail.
# In that case, just return None
try:
return Provider.objects.get_subclass(pk=self.provider.pk)
except Provider.DoesNotExist:
return None
def __str__(self):
return self.name
@ -303,7 +329,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
property_mappings = models.ManyToManyField("PropertyMapping", default=None, blank=True)
authentication_flow = models.ForeignKey(
Flow,
"authentik_flows.Flow",
blank=True,
null=True,
default=None,
@ -312,7 +338,7 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
related_name="source_authentication",
)
enrollment_flow = models.ForeignKey(
Flow,
"authentik_flows.Flow",
blank=True,
null=True,
default=None,
@ -339,13 +365,11 @@ class Source(ManagedModel, SerializerModel, PolicyBindingModel):
"""Return component used to edit this object"""
raise NotImplementedError
@property
def ui_login_button(self) -> Optional[UILoginButton]:
def ui_login_button(self, request: HttpRequest) -> Optional[UILoginButton]:
"""If source uses a http-based flow, return UI Information about the login
button. If source doesn't use http-based flow, return None."""
return None
@property
def ui_user_settings(self) -> Optional[UserSettingSerializer]:
"""Entrypoint to integrate with User settings. Can either return None if no
user settings are available, or UserSettingSerializer."""
@ -432,6 +456,14 @@ class Token(ManagedModel, ExpiringModel):
"""Handler which is called when this object is expired."""
from authentik.events.models import Event, EventAction
if self.intent in [
TokenIntents.INTENT_RECOVERY,
TokenIntents.INTENT_VERIFICATION,
TokenIntents.INTENT_APP_PASSWORD,
]:
super().expire_action(*args, **kwargs)
return
self.key = default_token_key()
self.expires = default_token_duration()
self.save(*args, **kwargs)

View File

@ -6,6 +6,7 @@ from os import environ
from boto3.exceptions import Boto3Error
from botocore.exceptions import BotoCoreError, ClientError
from dbbackup.db.exceptions import CommandConnectorError
from django.conf import settings
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core import management
@ -28,7 +29,7 @@ LOGGER = get_logger()
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task()
@prefill_task
def clean_expired_models(self: MonitoredTask):
"""Remove expired objects"""
messages = []
@ -55,24 +56,25 @@ def clean_expired_models(self: MonitoredTask):
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, messages))
def should_backup() -> bool:
"""Check if we should be doing backups"""
if SERVICE_HOST_ENV_NAME in environ and not CONFIG.y("postgresql.s3_backup.bucket"):
LOGGER.info("Running in k8s and s3 backups are not configured, skipping")
return False
if not CONFIG.y_bool("postgresql.backup.enabled"):
return False
if settings.DEBUG:
return False
return True
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task()
@prefill_task
def backup_database(self: MonitoredTask): # pragma: no cover
"""Database backup"""
self.result_timeout_hours = 25
if SERVICE_HOST_ENV_NAME in environ and not CONFIG.y("postgresql.s3_backup.bucket"):
LOGGER.info("Running in k8s and s3 backups are not configured, skipping")
self.set_status(
TaskResult(
TaskResultStatus.WARNING,
[
(
"Skipping backup as authentik is running in Kubernetes "
"without S3 backups configured."
),
],
)
)
if not should_backup():
self.set_status(TaskResult(TaskResultStatus.UNKNOWN, ["Backups are not configured."]))
return
try:
start = datetime.now()

View File

@ -19,6 +19,7 @@
<script src="{% static 'dist/poly.js' %}" type="module"></script>
{% block head %}
{% endblock %}
<meta name="sentry-trace" content="{{ sentry_trace }}" />
</head>
<body>
{% block body %}

View File

@ -4,7 +4,7 @@
{% load i18n %}
{% block head %}
<script src="{% static 'dist/AdminInterface.js' %}" type="module"></script>
<script src="{% static 'dist/admin/AdminInterface.js' %}" type="module"></script>
{% endblock %}
{% block body %}

View File

@ -11,7 +11,7 @@
{% endblock %}
{% block head %}
<script src="{% static 'dist/FlowInterface.js' %}" type="module"></script>
<script src="{% static 'dist/flow/FlowInterface.js' %}" type="module"></script>
<style>
.pf-c-background-image::before {
--ak-flow-background: url("{{ flow.background_url }}");

View File

@ -4,7 +4,7 @@
{% load i18n %}
{% block head %}
<script src="{% static 'dist/UserInterface.js' %}" type="module"></script>
<script src="{% static 'dist/user/UserInterface.js' %}" type="module"></script>
{% endblock %}
{% block body %}

View File

@ -3,7 +3,8 @@ from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import Application, User
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user
from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.models import PolicyBinding
@ -12,7 +13,7 @@ class TestApplicationsAPI(APITestCase):
"""Test applications API"""
def setUp(self) -> None:
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.allowed = Application.objects.create(name="allowed", slug="allowed")
self.denied = Application.objects.create(name="denied", slug="denied")
PolicyBinding.objects.create(

View File

@ -6,6 +6,7 @@ from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
class TestAuthenticatedSessionsAPI(APITestCase):
@ -13,7 +14,7 @@ class TestAuthenticatedSessionsAPI(APITestCase):
def setUp(self) -> None:
super().setUp()
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.other_user = User.objects.create(username="normal-user")
def test_list(self):

View File

@ -0,0 +1,40 @@
"""group tests"""
from django.test.testcases import TestCase
from authentik.core.models import Group, User
class TestGroups(TestCase):
"""Test group membership"""
def test_group_membership_simple(self):
"""Test simple membership"""
user = User.objects.create(username="user")
user2 = User.objects.create(username="user2")
group = Group.objects.create(name="group")
group.users.add(user)
self.assertTrue(group.is_member(user))
self.assertFalse(group.is_member(user2))
def test_group_membership_parent(self):
"""Test parent membership"""
user = User.objects.create(username="user")
user2 = User.objects.create(username="user2")
first = Group.objects.create(name="first")
second = Group.objects.create(name="second", parent=first)
second.users.add(user)
self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2))
def test_group_membership_parent_extra(self):
"""Test parent membership"""
user = User.objects.create(username="user")
user2 = User.objects.create(username="user2")
first = Group.objects.create(name="first")
second = Group.objects.create(name="second", parent=first)
third = Group.objects.create(name="third", parent=second)
second.users.add(user)
self.assertTrue(first.is_member(user))
self.assertFalse(first.is_member(user2))
self.assertFalse(third.is_member(user))
self.assertFalse(third.is_member(user2))

View File

@ -5,6 +5,7 @@ from django.test.testcases import TestCase
from django.urls import reverse
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
class TestImpersonation(TestCase):
@ -13,14 +14,14 @@ class TestImpersonation(TestCase):
def setUp(self) -> None:
super().setUp()
self.other_user = User.objects.create(username="to-impersonate")
self.akadmin = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
def test_impersonate_simple(self):
"""test simple impersonation and un-impersonation"""
# test with an inactive user to ensure that still works
self.other_user.is_active = False
self.other_user.save()
self.client.force_login(self.akadmin)
self.client.force_login(self.user)
self.client.get(
reverse(
@ -32,13 +33,13 @@ class TestImpersonation(TestCase):
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.other_user.username)
self.assertEqual(response_body["original"]["username"], self.akadmin.username)
self.assertEqual(response_body["original"]["username"], self.user.username)
self.client.get(reverse("authentik_core:impersonate-end"))
response = self.client.get(reverse("authentik_api:user-me"))
response_body = loads(response.content.decode())
self.assertEqual(response_body["user"]["username"], self.akadmin.username)
self.assertEqual(response_body["user"]["username"], self.user.username)
self.assertNotIn("original", response_body)
def test_impersonate_denied(self):
@ -46,7 +47,7 @@ class TestImpersonation(TestCase):
self.client.force_login(self.other_user)
self.client.get(
reverse("authentik_core:impersonate-init", kwargs={"user_id": self.akadmin.pk})
reverse("authentik_core:impersonate-init", kwargs={"user_id": self.user.pk})
)
response = self.client.get(reverse("authentik_api:user-me"))

View File

@ -2,7 +2,7 @@
from time import sleep
from typing import Callable, Type
from django.test import TestCase
from django.test import RequestFactory, TestCase
from django.utils.timezone import now
from guardian.shortcuts import get_anonymous_user
@ -30,6 +30,9 @@ class TestModels(TestCase):
def source_tester_factory(test_model: Type[Stage]) -> Callable:
"""Test source"""
factory = RequestFactory()
request = factory.get("/")
def tester(self: TestModels):
model_class = None
if test_model._meta.abstract:
@ -38,8 +41,8 @@ def source_tester_factory(test_model: Type[Stage]) -> Callable:
model_class = test_model()
model_class.slug = "test"
self.assertIsNotNone(model_class.component)
_ = model_class.ui_login_button
_ = model_class.ui_user_settings
_ = model_class.ui_login_button(request)
_ = model_class.ui_user_settings()
return tester
@ -49,7 +52,7 @@ def provider_tester_factory(test_model: Type[Stage]) -> Callable:
def tester(self: TestModels):
model_class = None
if test_model._meta.abstract:
if test_model._meta.abstract: # pragma: no cover
model_class = test_model.__bases__[0]()
else:
model_class = test_model()
@ -59,6 +62,6 @@ def provider_tester_factory(test_model: Type[Stage]) -> Callable:
for model in all_subclasses(Source):
setattr(TestModels, f"test_model_{model.__name__}", source_tester_factory(model))
setattr(TestModels, f"test_source_{model.__name__}", source_tester_factory(model))
for model in all_subclasses(Provider):
setattr(TestModels, f"test_model_{model.__name__}", provider_tester_factory(model))
setattr(TestModels, f"test_provider_{model.__name__}", provider_tester_factory(model))

View File

@ -6,7 +6,8 @@ from rest_framework.serializers import ValidationError
from rest_framework.test import APITestCase
from authentik.core.api.propertymappings import PropertyMappingSerializer
from authentik.core.models import PropertyMapping, User
from authentik.core.models import PropertyMapping
from authentik.core.tests.utils import create_test_admin_user
class TestPropertyMappingAPI(APITestCase):
@ -17,7 +18,7 @@ class TestPropertyMappingAPI(APITestCase):
self.mapping = PropertyMapping.objects.create(
name="dummy", expression="""return {'foo': 'bar'}"""
)
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.client.force_login(self.user)
def test_test_call(self):
@ -40,7 +41,7 @@ class TestPropertyMappingAPI(APITestCase):
expr = "return True"
self.assertEqual(PropertyMappingSerializer().validate_expression(expr), expr)
with self.assertRaises(ValidationError):
print(PropertyMappingSerializer().validate_expression("/"))
PropertyMappingSerializer().validate_expression("/")
def test_types(self):
"""Test PropertyMappigns's types endpoint"""

View File

@ -2,7 +2,8 @@
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import PropertyMapping, User
from authentik.core.models import PropertyMapping
from authentik.core.tests.utils import create_test_admin_user
class TestProvidersAPI(APITestCase):
@ -13,7 +14,7 @@ class TestProvidersAPI(APITestCase):
self.mapping = PropertyMapping.objects.create(
name="dummy", expression="""return {'foo': 'bar'}"""
)
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.client.force_login(self.user)
def test_types(self):

View File

@ -8,6 +8,7 @@ from rest_framework.test import APITestCase
from authentik.core.models import USER_ATTRIBUTE_TOKEN_EXPIRING, Token, TokenIntents, User
from authentik.core.tasks import clean_expired_models
from authentik.core.tests.utils import create_test_admin_user
class TestTokenAPI(APITestCase):
@ -16,7 +17,7 @@ class TestTokenAPI(APITestCase):
def setUp(self) -> None:
super().setUp()
self.user = User.objects.create(username="testuser")
self.admin = User.objects.get(username="akadmin")
self.admin = create_test_admin_user()
self.client.force_login(self.user)
def test_token_create(self):
@ -53,7 +54,9 @@ class TestTokenAPI(APITestCase):
def test_token_expire(self):
"""Test Token expire task"""
token: Token = Token.objects.create(expires=now(), user=get_anonymous_user())
token: Token = Token.objects.create(
expires=now(), user=get_anonymous_user(), intent=TokenIntents.INTENT_API
)
key = token.key
clean_expired_models.delay().get()
token.refresh_from_db()

View File

@ -2,8 +2,9 @@
from django.urls.base import reverse
from rest_framework.test import APITestCase
from authentik.core.models import USER_ATTRIBUTE_CHANGE_USERNAME, User
from authentik.flows.models import Flow, FlowDesignation
from authentik.core.models import USER_ATTRIBUTE_CHANGE_EMAIL, USER_ATTRIBUTE_CHANGE_USERNAME, User
from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_tenant
from authentik.flows.models import FlowDesignation
from authentik.stages.email.models import EmailStage
from authentik.tenants.models import Tenant
@ -12,7 +13,7 @@ class TestUsersAPI(APITestCase):
"""Test Users API"""
def setUp(self) -> None:
self.admin = User.objects.get(username="akadmin")
self.admin = create_test_admin_user()
self.user = User.objects.create(username="test-user")
def test_update_self(self):
@ -33,6 +34,16 @@ class TestUsersAPI(APITestCase):
)
self.assertEqual(response.status_code, 400)
def test_update_self_email_denied(self):
"""Test update_self"""
self.admin.attributes[USER_ATTRIBUTE_CHANGE_EMAIL] = False
self.admin.save()
self.client.force_login(self.admin)
response = self.client.put(
reverse("authentik_api:user-update-self"), data={"email": "foo", "name": "foo"}
)
self.assertEqual(response.status_code, 400)
def test_metrics(self):
"""Test user's metrics"""
self.client.force_login(self.admin)
@ -59,10 +70,8 @@ class TestUsersAPI(APITestCase):
def test_recovery(self):
"""Test user recovery link (no recovery flow set)"""
flow = Flow.objects.create(
name="test", title="test", slug="test", designation=FlowDesignation.RECOVERY
)
tenant: Tenant = Tenant.objects.first()
flow = create_test_flow(FlowDesignation.RECOVERY)
tenant: Tenant = create_test_tenant()
tenant.flow_recovery = flow
tenant.save()
self.client.force_login(self.admin)
@ -89,10 +98,8 @@ class TestUsersAPI(APITestCase):
"""Test user recovery link (no email stage)"""
self.user.email = "foo@bar.baz"
self.user.save()
flow = Flow.objects.create(
name="test", title="test", slug="test", designation=FlowDesignation.RECOVERY
)
tenant: Tenant = Tenant.objects.first()
flow = create_test_flow(designation=FlowDesignation.RECOVERY)
tenant: Tenant = create_test_tenant()
tenant.flow_recovery = flow
tenant.save()
self.client.force_login(self.admin)
@ -105,10 +112,8 @@ class TestUsersAPI(APITestCase):
"""Test user recovery link"""
self.user.email = "foo@bar.baz"
self.user.save()
flow = Flow.objects.create(
name="test", title="test", slug="test", designation=FlowDesignation.RECOVERY
)
tenant: Tenant = Tenant.objects.first()
flow = create_test_flow(FlowDesignation.RECOVERY)
tenant: Tenant = create_test_tenant()
tenant.flow_recovery = flow
tenant.save()

View File

@ -0,0 +1,57 @@
"""Test Utils"""
from typing import Optional
from django.utils.text import slugify
from authentik.core.models import Group, User
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow, FlowDesignation
from authentik.lib.generators import generate_id
from authentik.tenants.models import Tenant
def create_test_flow(designation: FlowDesignation = FlowDesignation.STAGE_CONFIGURATION) -> Flow:
"""Generate a flow that can be used for testing"""
uid = generate_id(10)
return Flow.objects.create(
name=uid,
title=uid,
slug=slugify(uid),
designation=designation,
)
def create_test_admin_user(name: Optional[str] = None) -> User:
"""Generate a test-admin user"""
uid = generate_id(20) if not name else name
group = Group.objects.create(name=uid, is_superuser=True)
user: User = User.objects.create(
username=uid,
name=uid,
email=f"{uid}@goauthentik.io",
)
user.set_password(uid)
user.save()
group.users.add(user)
return user
def create_test_tenant() -> Tenant:
"""Generate a test tenant, removing all other tenants to make sure this one
matches."""
uid = generate_id(20)
Tenant.objects.all().delete()
return Tenant.objects.create(domain=uid, default=True)
def create_test_cert() -> CertificateKeyPair:
"""Generate a certificate for testing"""
CertificateKeyPair.objects.filter(name="goauthentik.io").delete()
builder = CertificateBuilder()
builder.common_name = "goauthentik.io"
builder.build(
subject_alt_names=["goauthentik.io"],
validity_days=360,
)
return builder.save()

View File

@ -20,6 +20,7 @@ from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.managed import MANAGED_KEY
from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction
@ -141,9 +142,11 @@ class CertificateKeyPairFilter(FilterSet):
class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
"""CertificateKeyPair Viewset"""
queryset = CertificateKeyPair.objects.all()
queryset = CertificateKeyPair.objects.exclude(managed=MANAGED_KEY)
serializer_class = CertificateKeyPairSerializer
filterset_class = CertificateKeyPairFilter
ordering = ["name"]
search_fields = ["name"]
@permission_required(None, ["authentik_crypto.add_certificatekeypair"])
@extend_schema(
@ -189,7 +192,7 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
secret=certificate,
type="certificate",
).from_http(request)
if "download" in request._request.GET:
if "download" in request.query_params:
# Mime type from https://pki-tutorial.readthedocs.io/en/latest/mime.html
response = HttpResponse(
certificate.certificate_data, content_type="application/x-pem-file"
@ -220,7 +223,7 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
secret=certificate,
type="private_key",
).from_http(request)
if "download" in request._request.GET:
if "download" in request.query_params:
# Mime type from https://pki-tutorial.readthedocs.io/en/latest/mime.html
response = HttpResponse(certificate.key_data, content_type="application/x-pem-file")
response[

View File

@ -13,3 +13,4 @@ class AuthentikCryptoConfig(AppConfig):
def ready(self):
import_module("authentik.crypto.managed")
import_module("authentik.crypto.tasks")

View File

@ -11,10 +11,13 @@ from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.x509 import Certificate, load_pem_x509_certificate
from django.db import models
from django.utils.translation import gettext_lazy as _
from structlog.stdlib import get_logger
from authentik.lib.models import CreatedUpdatedModel
from authentik.managed.models import ManagedModel
LOGGER = get_logger()
class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
"""CertificateKeyPair that can be used for signing or encrypting if `key_data`
@ -55,14 +58,15 @@ class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
@property
def private_key(self) -> Optional[RSAPrivateKey]:
"""Get python cryptography PrivateKey instance"""
if not self._private_key and self._private_key != "":
if not self._private_key and self.key_data != "":
try:
self._private_key = load_pem_private_key(
str.encode("\n".join([x.strip() for x in self.key_data.split("\n")])),
password=None,
backend=default_backend(),
)
except ValueError:
except ValueError as exc:
LOGGER.warning(exc)
return None
return self._private_key

View File

@ -0,0 +1,10 @@
"""Crypto task Settings"""
from celery.schedules import crontab
CELERY_BEAT_SCHEDULE = {
"crypto_certificate_discovery": {
"task": "authentik.crypto.tasks.certificate_discovery",
"schedule": crontab(minute="*/5"),
"options": {"queue": "authentik_scheduled"},
},
}

92
authentik/crypto/tasks.py Normal file
View File

@ -0,0 +1,92 @@
"""Crypto tasks"""
from glob import glob
from pathlib import Path
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.x509.base import load_pem_x509_certificate
from django.utils.translation import gettext_lazy as _
from structlog.stdlib import get_logger
from authentik.crypto.models import CertificateKeyPair
from authentik.events.monitored_tasks import (
MonitoredTask,
TaskResult,
TaskResultStatus,
prefill_task,
)
from authentik.lib.config import CONFIG
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
MANAGED_DISCOVERED = "goauthentik.io/crypto/discovered/%s"
def ensure_private_key_valid(body: str):
"""Attempt loading of an RSA Private key without password"""
load_pem_private_key(
str.encode("\n".join([x.strip() for x in body.split("\n")])),
password=None,
backend=default_backend(),
)
return body
def ensure_certificate_valid(body: str):
"""Attempt loading of a PEM-encoded certificate"""
load_pem_x509_certificate(body.encode("utf-8"), default_backend())
return body
@CELERY_APP.task(bind=True, base=MonitoredTask)
@prefill_task
def certificate_discovery(self: MonitoredTask):
"""Discover and update certificates form the filesystem"""
certs = {}
private_keys = {}
discovered = 0
for file in glob(CONFIG.y("cert_discovery_dir") + "/**", recursive=True):
path = Path(file)
if not path.exists():
continue
if path.is_dir():
continue
# Support certbot's directory structure
if path.name in ["fullchain.pem", "privkey.pem"]:
cert_name = path.parent.name
else:
cert_name = path.name.replace(path.suffix, "")
try:
with open(path, "r+", encoding="utf-8") as _file:
body = _file.read()
if "BEGIN RSA PRIVATE KEY" in body:
private_keys[cert_name] = ensure_private_key_valid(body)
else:
certs[cert_name] = ensure_certificate_valid(body)
except (OSError, ValueError) as exc:
LOGGER.warning("Failed to open file or invalid format", exc=exc, file=path)
discovered += 1
for name, cert_data in certs.items():
cert = CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % name).first()
if not cert:
cert = CertificateKeyPair(
name=name,
managed=MANAGED_DISCOVERED % name,
)
dirty = False
if cert.certificate_data != cert_data:
cert.certificate_data = cert_data
dirty = True
if name in private_keys:
if cert.key_data != private_keys[name]:
cert.key_data = private_keys[name]
dirty = True
if dirty:
cert.save()
self.set_status(
TaskResult(
TaskResultStatus.SUCCESSFUL,
messages=[_("Successfully imported %(count)d files." % {"count": discovered})],
)
)

View File

@ -1,25 +1,37 @@
"""Crypto tests"""
import datetime
from os import makedirs
from tempfile import TemporaryDirectory
from django.test import TestCase
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.api.used_by import DeleteAction
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user, create_test_cert, create_test_flow
from authentik.crypto.api import CertificateKeyPairSerializer
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow
from authentik.crypto.tasks import MANAGED_DISCOVERED, certificate_discovery
from authentik.lib.config import CONFIG
from authentik.lib.generators import generate_key
from authentik.providers.oauth2.models import OAuth2Provider
class TestCrypto(TestCase):
class TestCrypto(APITestCase):
"""Test Crypto validation"""
def test_model_private(self):
"""Test model private key"""
cert = CertificateKeyPair.objects.create(
name="test",
certificate_data="foo",
key_data="foo",
)
self.assertIsNone(cert.private_key)
def test_serializer(self):
"""Test API Validation"""
keypair = CertificateKeyPair.objects.first()
keypair = create_test_cert()
self.assertTrue(
CertificateKeyPairSerializer(
data={
@ -54,10 +66,38 @@ class TestCrypto(TestCase):
self.assertEqual(instance.name, "test-cert")
self.assertEqual((instance.certificate.not_valid_after - now).days, 2)
def test_builder_api(self):
"""Test Builder (via API)"""
self.client.force_login(create_test_admin_user())
self.client.post(
reverse("authentik_api:certificatekeypair-generate"),
data={"common_name": "foo", "subject_alt_name": "bar,baz", "validity_days": 3},
)
self.assertTrue(CertificateKeyPair.objects.filter(name="foo").exists())
def test_builder_api_invalid(self):
"""Test Builder (via API) (invalid)"""
self.client.force_login(create_test_admin_user())
response = self.client.post(
reverse("authentik_api:certificatekeypair-generate"),
data={},
)
self.assertEqual(response.status_code, 400)
def test_list(self):
"""Test API List"""
self.client.force_login(create_test_admin_user())
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-list",
)
)
self.assertEqual(200, response.status_code)
def test_certificate_download(self):
"""Test certificate export (download)"""
self.client.force_login(User.objects.get(username="akadmin"))
keypair = CertificateKeyPair.objects.first()
self.client.force_login(create_test_admin_user())
keypair = create_test_cert()
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-view-certificate",
@ -77,8 +117,8 @@ class TestCrypto(TestCase):
def test_private_key_download(self):
"""Test private_key export (download)"""
self.client.force_login(User.objects.get(username="akadmin"))
keypair = CertificateKeyPair.objects.first()
self.client.force_login(create_test_admin_user())
keypair = create_test_cert()
response = self.client.get(
reverse(
"authentik_api:certificatekeypair-view-private-key",
@ -98,15 +138,15 @@ class TestCrypto(TestCase):
def test_used_by(self):
"""Test used_by endpoint"""
self.client.force_login(User.objects.get(username="akadmin"))
keypair = CertificateKeyPair.objects.first()
self.client.force_login(create_test_admin_user())
keypair = create_test_cert()
provider = OAuth2Provider.objects.create(
name="test",
client_id="test",
client_secret=generate_key(),
authorization_flow=Flow.objects.first(),
authorization_flow=create_test_flow(),
redirect_uris="http://localhost",
rsa_key=CertificateKeyPair.objects.first(),
rsa_key=keypair,
)
response = self.client.get(
reverse(
@ -127,3 +167,36 @@ class TestCrypto(TestCase):
}
],
)
def test_discovery(self):
"""Test certificate discovery"""
builder = CertificateBuilder()
builder.common_name = "test-cert"
with self.assertRaises(ValueError):
builder.save()
builder.build(
subject_alt_names=[],
validity_days=3,
)
with TemporaryDirectory() as temp_dir:
with open(f"{temp_dir}/foo.pem", "w+", encoding="utf-8") as _cert:
_cert.write(builder.certificate)
with open(f"{temp_dir}/foo.key", "w+", encoding="utf-8") as _key:
_key.write(builder.private_key)
makedirs(f"{temp_dir}/foo.bar", exist_ok=True)
with open(f"{temp_dir}/foo.bar/fullchain.pem", "w+", encoding="utf-8") as _cert:
_cert.write(builder.certificate)
with open(f"{temp_dir}/foo.bar/privkey.pem", "w+", encoding="utf-8") as _key:
_key.write(builder.private_key)
with CONFIG.patch("cert_discovery_dir", temp_dir):
# pyright: reportGeneralTypeIssues=false
certificate_discovery() # pylint: disable=no-value-for-parameter
keypair: CertificateKeyPair = CertificateKeyPair.objects.filter(
managed=MANAGED_DISCOVERED % "foo"
).first()
self.assertIsNotNone(keypair)
self.assertIsNotNone(keypair.certificate)
self.assertIsNotNone(keypair.private_key)
self.assertTrue(
CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % "foo.bar").exists()
)

View File

@ -1,4 +1,6 @@
"""Events API Views"""
from json import loads
import django_filters
from django.db.models.aggregates import Count
from django.db.models.fields.json import KeyTextTransform
@ -12,6 +14,7 @@ from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.admin.api.metrics import CoordinateSerializer
from authentik.core.api.utils import PassiveSerializer, TypeCreateSerializer
from authentik.events.models import Event, EventAction
@ -110,13 +113,20 @@ class EventViewSet(ModelViewSet):
@extend_schema(
methods=["GET"],
responses={200: EventTopPerUserSerializer(many=True)},
filters=[],
parameters=[
OpenApiParameter(
"action",
type=OpenApiTypes.STR,
location=OpenApiParameter.QUERY,
required=False,
),
OpenApiParameter(
"top_n",
type=OpenApiTypes.INT,
location=OpenApiParameter.QUERY,
required=False,
)
),
],
)
@action(detail=False, methods=["GET"], pagination_class=None)
@ -137,6 +147,40 @@ class EventViewSet(ModelViewSet):
.order_by("-counted_events")[:top_n]
)
@extend_schema(
methods=["GET"],
responses={200: CoordinateSerializer(many=True)},
filters=[],
parameters=[
OpenApiParameter(
"action",
type=OpenApiTypes.STR,
location=OpenApiParameter.QUERY,
required=False,
),
OpenApiParameter(
"query",
type=OpenApiTypes.STR,
location=OpenApiParameter.QUERY,
required=False,
),
],
)
@action(detail=False, methods=["GET"], pagination_class=None)
def per_month(self, request: Request):
"""Get the count of events per month"""
filtered_action = request.query_params.get("action", EventAction.LOGIN)
try:
query = loads(request.query_params.get("query", "{}"))
except ValueError:
return Response(status=400)
return Response(
get_objects_for_user(request.user, "authentik_events.view_event")
.filter(action=filtered_action)
.filter(**query)
.get_events_per_day()
)
@extend_schema(responses={200: TypeCreateSerializer(many=True)})
@action(detail=False, pagination_class=None, filter_backends=[])
def actions(self, request: Request) -> Response:

View File

@ -7,6 +7,7 @@ from typing import Optional, TypedDict
from geoip2.database import Reader
from geoip2.errors import GeoIP2Error
from geoip2.models import City
from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger
from authentik.lib.config import CONFIG
@ -62,13 +63,17 @@ class GeoIPReader:
def city(self, ip_address: str) -> Optional[City]:
"""Wrapper for Reader.city"""
if not self.enabled:
return None
self.__check_expired()
try:
return self.__reader.city(ip_address)
except (GeoIP2Error, ValueError):
return None
with Hub.current.start_span(
op="authentik.events.geo.city",
description=ip_address,
):
if not self.enabled:
return None
self.__check_expired()
try:
return self.__reader.city(ip_address)
except (GeoIP2Error, ValueError):
return None
def city_dict(self, ip_address: str) -> Optional[GeoIPDict]:
"""Wrapper for self.city that returns a dict"""

View File

@ -7,16 +7,25 @@ from django.core.exceptions import SuspiciousOperation
from django.db.models import Model
from django.db.models.signals import post_save, pre_delete
from django.http import HttpRequest, HttpResponse
from django_otp.plugins.otp_static.models import StaticToken
from guardian.models import UserObjectPermission
from authentik.core.middleware import LOCAL
from authentik.core.models import User
from authentik.core.models import AuthenticatedSession, User
from authentik.events.models import Event, EventAction, Notification
from authentik.events.signals import EventNewThread
from authentik.events.utils import model_to_dict
from authentik.lib.sentry import before_send
from authentik.lib.utils.errors import exception_to_string
IGNORED_MODELS = (
Event,
Notification,
UserObjectPermission,
AuthenticatedSession,
StaticToken,
)
class AuditMiddleware:
"""Register handlers for duration of request-response that log creation/update/deletion
@ -82,7 +91,7 @@ class AuditMiddleware:
user: User, request: HttpRequest, sender, instance: Model, created: bool, **_
):
"""Signal handler for all object's post_save"""
if isinstance(instance, (Event, Notification, UserObjectPermission)):
if isinstance(instance, IGNORED_MODELS):
return
action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED
@ -92,7 +101,7 @@ class AuditMiddleware:
# pylint: disable=unused-argument
def pre_delete_handler(user: User, request: HttpRequest, sender, instance: Model, **_):
"""Signal handler for all object's pre_delete"""
if isinstance(instance, (Event, Notification, UserObjectPermission)): # pragma: no cover
if isinstance(instance, IGNORED_MODELS): # pragma: no cover
return
EventNewThread(

View File

@ -4,7 +4,6 @@ import uuid
from datetime import timedelta
from typing import Iterable
import django.core.validators
import django.db.models.deletion
from django.apps.registry import Apps
from django.conf import settings
@ -12,6 +11,7 @@ from django.db import migrations, models
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
import authentik.events.models
import authentik.lib.models
from authentik.events.models import EventAction, NotificationSeverity, TransportMode
@ -314,169 +314,10 @@ class Migration(migrations.Migration):
old_name="user_json",
new_name="user",
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("sign_up", "Sign Up"),
("authorize_application", "Authorize Application"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("invitation_created", "Invite Created"),
("invitation_used", "Invite Used"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("invitation_created", "Invite Created"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("custom_", "Custom Prefix"),
]
),
),
migrations.RemoveField(
model_name="event",
name="date",
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("token_view", "Token View"),
("invitation_created", "Invite Created"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("token_view", "Token View"),
("invitation_created", "Invite Created"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("token_view", "Token View"),
("invitation_created", "Invite Created"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("token_view", "Token View"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("configuration_error", "Configuration Error"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.CreateModel(
name="NotificationTransport",
fields=[
@ -610,68 +451,6 @@ class Migration(migrations.Migration):
help_text="Only send notification once, for example when sending a webhook into a chat channel.",
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("token_view", "Token View"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("system_task_execution", "System Task Execution"),
("system_task_exception", "System Task Exception"),
("configuration_error", "Configuration Error"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("secret_view", "Secret View"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("system_task_execution", "System Task Execution"),
("system_task_exception", "System Task Exception"),
("configuration_error", "Configuration Error"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.RunPython(
code=token_view_to_secret_view,
),
@ -688,76 +467,11 @@ class Migration(migrations.Migration):
migrations.RunPython(
code=update_expires,
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("secret_view", "Secret View"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("system_task_execution", "System Task Execution"),
("system_task_exception", "System Task Exception"),
("configuration_error", "Configuration Error"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("email_sent", "Email Sent"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AddField(
model_name="event",
name="tenant",
field=models.JSONField(blank=True, default=authentik.events.models.default_tenant),
),
migrations.AlterField(
model_name="event",
name="action",
field=models.TextField(
choices=[
("login", "Login"),
("login_failed", "Login Failed"),
("logout", "Logout"),
("user_write", "User Write"),
("suspicious_request", "Suspicious Request"),
("password_set", "Password Set"),
("secret_view", "Secret View"),
("invitation_used", "Invite Used"),
("authorize_application", "Authorize Application"),
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
("system_task_execution", "System Task Execution"),
("system_task_exception", "System Task Exception"),
("system_exception", "System Exception"),
("configuration_error", "Configuration Error"),
("model_created", "Model Created"),
("model_updated", "Model Updated"),
("model_deleted", "Model Deleted"),
("email_sent", "Email Sent"),
("update_available", "Update Available"),
("custom_", "Custom Prefix"),
]
),
),
migrations.AlterField(
model_name="event",
name="action",
@ -776,6 +490,7 @@ class Migration(migrations.Migration):
("source_linked", "Source Linked"),
("impersonation_started", "Impersonation Started"),
("impersonation_ended", "Impersonation Ended"),
("flow_execution", "Flow Execution"),
("policy_execution", "Policy Execution"),
("policy_exception", "Policy Exception"),
("property_mapping_exception", "Property Mapping Exception"),
@ -826,6 +541,8 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="notificationtransport",
name="webhook_url",
field=models.TextField(blank=True, validators=[django.core.validators.URLValidator()]),
field=models.TextField(
blank=True, validators=[authentik.lib.models.DomainlessURLValidator()]
),
),
]

View File

@ -1,8 +1,9 @@
# Generated by Django 3.2.7 on 2021-10-04 15:31
import django.core.validators
from django.db import migrations, models
import authentik.lib.models
class Migration(migrations.Migration):
@ -14,6 +15,8 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name="notificationtransport",
name="webhook_url",
field=models.TextField(blank=True, validators=[django.core.validators.URLValidator()]),
field=models.TextField(
blank=True, validators=[authentik.lib.models.DomainlessURLValidator()]
),
),
]

View File

@ -1,13 +1,20 @@
"""authentik events models"""
import time
from collections import Counter
from datetime import timedelta
from inspect import getmodule, stack
from inspect import currentframe
from smtplib import SMTPException
from typing import TYPE_CHECKING, Optional, Type, Union
from uuid import uuid4
from django.conf import settings
from django.core.validators import URLValidator
from django.db import models
from django.db.models import Count, ExpressionWrapper, F
from django.db.models.fields import DurationField
from django.db.models.functions import ExtractHour
from django.db.models.functions.datetime import ExtractDay
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
from django.http import HttpRequest
from django.http.request import QueryDict
from django.utils.timezone import now
@ -20,6 +27,7 @@ from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION
from authentik.core.models import ExpiringModel, Group, PropertyMapping, User
from authentik.events.geo import GEOIP_READER
from authentik.events.utils import cleanse_dict, get_user, model_to_dict, sanitize_dict
from authentik.lib.models import DomainlessURLValidator
from authentik.lib.sentry import SentryIgnoredException
from authentik.lib.utils.http import get_client_ip, get_http_session
from authentik.lib.utils.time import timedelta_from_string
@ -70,6 +78,7 @@ class EventAction(models.TextChoices):
IMPERSONATION_STARTED = "impersonation_started"
IMPERSONATION_ENDED = "impersonation_ended"
FLOW_EXECUTION = "flow_execution"
POLICY_EXECUTION = "policy_execution"
POLICY_EXCEPTION = "policy_exception"
PROPERTY_MAPPING_EXCEPTION = "property_mapping_exception"
@ -90,6 +99,72 @@ class EventAction(models.TextChoices):
CUSTOM_PREFIX = "custom_"
class EventQuerySet(QuerySet):
"""Custom events query set with helper functions"""
def get_events_per_hour(self) -> list[dict[str, int]]:
"""Get event count by hour in the last day, fill with zeros"""
date_from = now() - timedelta(days=1)
result = (
self.filter(created__gte=date_from)
.annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField()))
.annotate(age_hours=ExtractHour("age"))
.values("age_hours")
.annotate(count=Count("pk"))
.order_by("age_hours")
)
data = Counter({int(d["age_hours"]): d["count"] for d in result})
results = []
_now = now()
for hour in range(0, -24, -1):
results.append(
{
"x_cord": time.mktime((_now + timedelta(hours=hour)).timetuple()) * 1000,
"y_cord": data[hour * -1],
}
)
return results
def get_events_per_day(self) -> list[dict[str, int]]:
"""Get event count by hour in the last day, fill with zeros"""
date_from = now() - timedelta(weeks=4)
result = (
self.filter(created__gte=date_from)
.annotate(age=ExpressionWrapper(now() - F("created"), output_field=DurationField()))
.annotate(age_days=ExtractDay("age"))
.values("age_days")
.annotate(count=Count("pk"))
.order_by("age_days")
)
data = Counter({int(d["age_days"]): d["count"] for d in result})
results = []
_now = now()
for day in range(0, -30, -1):
results.append(
{
"x_cord": time.mktime((_now + timedelta(days=day)).timetuple()) * 1000,
"y_cord": data[day * -1],
}
)
return results
class EventManager(Manager):
"""Custom helper methods for Events"""
def get_queryset(self) -> QuerySet:
"""use custom queryset"""
return EventQuerySet(self.model, using=self._db)
def get_events_per_hour(self) -> list[dict[str, int]]:
"""Wrap method from queryset"""
return self.get_queryset().get_events_per_hour()
def get_events_per_day(self) -> list[dict[str, int]]:
"""Wrap method from queryset"""
return self.get_queryset().get_events_per_day()
class Event(ExpiringModel):
"""An individual Audit/Metrics/Notification/Error Event"""
@ -105,6 +180,8 @@ class Event(ExpiringModel):
# Shadow the expires attribute from ExpiringModel to override the default duration
expires = models.DateTimeField(default=default_event_duration)
objects = EventManager()
@staticmethod
def _get_app_from_request(request: HttpRequest) -> str:
if not isinstance(request, HttpRequest):
@ -115,14 +192,15 @@ class Event(ExpiringModel):
def new(
action: Union[str, EventAction],
app: Optional[str] = None,
_inspect_offset: int = 1,
**kwargs,
) -> "Event":
"""Create new Event instance from arguments. Instance is NOT saved."""
if not isinstance(action, EventAction):
action = EventAction.CUSTOM_PREFIX + action
if not app:
app = getmodule(stack()[_inspect_offset][0]).__name__
current = currentframe()
parent = current.f_back
app = parent.f_globals["__name__"]
cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs))
event = Event(action=action, app=app, context=cleaned_kwargs)
return event
@ -224,7 +302,7 @@ class NotificationTransport(models.Model):
name = models.TextField(unique=True)
mode = models.TextField(choices=TransportMode.choices)
webhook_url = models.TextField(blank=True, validators=[URLValidator()])
webhook_url = models.TextField(blank=True, validators=[DomainlessURLValidator()])
webhook_mapping = models.ForeignKey(
"NotificationWebhookMapping", on_delete=models.SET_DEFAULT, null=True, default=None
)

View File

@ -46,7 +46,7 @@ class TaskResult:
def with_error(self, exc: Exception) -> "TaskResult":
"""Since errors might not always be pickle-able, set the traceback"""
self.messages.extend(exception_to_string(exc).splitlines())
self.messages.append(str(exc))
return self
@ -112,30 +112,6 @@ class TaskInfo:
cache.set(key, self, timeout=timeout_hours * 60 * 60)
def prefill_task():
"""Ensure a task's details are always in cache, so it can always be triggered via API"""
def inner_wrap(func):
status = TaskInfo.by_name(func.__name__)
if status:
return func
TaskInfo(
task_name=func.__name__,
task_description=func.__doc__,
result=TaskResult(TaskResultStatus.UNKNOWN, messages=[_("Task has not been run yet.")]),
task_call_module=func.__module__,
task_call_func=func.__name__,
# We don't have real values for these attributes but they cannot be null
start_timestamp=default_timer(),
finish_timestamp=default_timer(),
finish_time=datetime.now(),
).save(86400)
LOGGER.debug("prefilled task", task_name=func.__name__)
return func
return inner_wrap
class MonitoredTask(Task):
"""Task which can save its state to the cache"""
@ -210,5 +186,21 @@ class MonitoredTask(Task):
raise NotImplementedError
for task in TaskInfo.all().values():
task.set_prom_metrics()
def prefill_task(func):
"""Ensure a task's details are always in cache, so it can always be triggered via API"""
status = TaskInfo.by_name(func.__name__)
if status:
return func
TaskInfo(
task_name=func.__name__,
task_description=func.__doc__,
result=TaskResult(TaskResultStatus.UNKNOWN, messages=[_("Task has not been run yet.")]),
task_call_module=func.__module__,
task_call_func=func.__name__,
# We don't have real values for these attributes but they cannot be null
start_timestamp=default_timer(),
finish_timestamp=default_timer(),
finish_time=datetime.now(),
).save(86400)
LOGGER.debug("prefilled task", task_name=func.__name__)
return func

View File

@ -3,14 +3,14 @@ from threading import Thread
from typing import Any, Optional
from django.contrib.auth.signals import user_logged_in, user_logged_out, user_login_failed
from django.db.models.signals import post_save
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from django.http import HttpRequest
from authentik.core.models import User
from authentik.core.signals import password_changed
from authentik.events.models import Event, EventAction
from authentik.events.tasks import event_notification_handler
from authentik.events.tasks import event_notification_handler, gdpr_cleanup
from authentik.flows.planner import PLAN_CONTEXT_SOURCE, FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
from authentik.stages.invitation.models import Invitation
@ -108,3 +108,10 @@ def on_password_changed(sender, user: User, password: str, **_):
def event_post_save_notification(sender, instance: Event, **_):
"""Start task to check if any policies trigger an notification on this event"""
event_notification_handler.delay(instance.event_uuid.hex)
@receiver(pre_delete, sender=User)
# pylint: disable=unused-argument
def event_user_pre_delete_cleanup(sender, instance: User, **_):
"""If gdpr_compliance is enabled, remove all the user's events"""
gdpr_cleanup.delay(instance.pk)

View File

@ -98,9 +98,19 @@ def notification_transport(self: MonitoredTask, notification_pk: int, transport_
notification: Notification = Notification.objects.filter(pk=notification_pk).first()
if not notification:
return
transport: NotificationTransport = NotificationTransport.objects.get(pk=transport_pk)
transport = NotificationTransport.objects.filter(pk=transport_pk).first()
if not transport:
return
transport.send(notification)
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL))
except NotificationTransportError as exc:
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
raise exc
@CELERY_APP.task()
def gdpr_cleanup(user_pk: int):
"""cleanup events from gdpr_compliance"""
events = Event.objects.filter(user__pk=user_pk)
LOGGER.debug("GDPR cleanup, removing events from user", events=events.count())
events.delete()

View File

@ -3,7 +3,7 @@
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.events.models import (
Event,
EventAction,
@ -17,7 +17,7 @@ class TestEventsAPI(APITestCase):
"""Test Event API"""
def setUp(self) -> None:
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.client.force_login(self.user)
def test_top_n(self):

View File

@ -3,7 +3,8 @@
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import Application, User
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_admin_user
from authentik.events.models import Event, EventAction
@ -12,7 +13,7 @@ class TestEventsMiddleware(APITestCase):
def setUp(self) -> None:
super().setUp()
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.client.force_login(self.user)
def test_create(self):

View File

@ -1,6 +1,4 @@
"""Flow Stage API Views"""
from typing import Iterable
from django.urls.base import reverse
from drf_spectacular.utils import extend_schema
from rest_framework import mixins
@ -15,7 +13,7 @@ from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
from authentik.core.types import UserSettingSerializer
from authentik.flows.api.flows import FlowSerializer
from authentik.flows.models import Stage
from authentik.flows.models import ConfigurableStage, Stage
from authentik.lib.utils.reflection import all_subclasses
LOGGER = get_logger()
@ -43,6 +41,7 @@ class StageSerializer(ModelSerializer, MetaNameSerializer):
"component",
"verbose_name",
"verbose_name_plural",
"meta_model_name",
"flow_set",
]
@ -86,10 +85,12 @@ class StageViewSet(
@action(detail=False, pagination_class=None, filter_backends=[])
def user_settings(self, request: Request) -> Response:
"""Get all stages the user can configure"""
_all_stages: Iterable[Stage] = Stage.objects.all().select_subclasses().order_by("name")
stages = []
for configurable_stage in all_subclasses(ConfigurableStage):
stages += list(configurable_stage.objects.all().order_by("name"))
matching_stages: list[dict] = []
for stage in _all_stages:
user_settings = stage.ui_user_settings
for stage in stages:
user_settings = stage.ui_user_settings()
if not user_settings:
continue
user_settings.initial_data["object_uid"] = str(stage.pk)

View File

@ -10,7 +10,7 @@ from django.test import RequestFactory
from structlog.stdlib import get_logger
from authentik import __version__
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.flows.models import Flow
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
@ -68,7 +68,7 @@ class Command(BaseCommand): # pragma: no cover
def benchmark_flows(self, proc_count):
"""Get full recovery link"""
flow = Flow.objects.get(slug="default-authentication-flow")
user = User.objects.get(username="akadmin")
user = create_test_admin_user()
manager = Manager()
return_dict = manager.dict()

View File

@ -0,0 +1,46 @@
# Generated by Django 3.2.9 on 2021-12-05 13:50
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0018_auto_20210330_1345_squashed_0028_alter_token_intent"),
(
"authentik_flows",
"0019_alter_flow_background_squashed_0024_alter_flow_compatibility_mode",
),
]
operations = [
migrations.CreateModel(
name="FlowToken",
fields=[
(
"token_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_core.token",
),
),
("_plan", models.TextField()),
(
"flow",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="authentik_flows.flow"
),
),
],
options={
"verbose_name": "Flow Token",
"verbose_name_plural": "Flow Tokens",
},
bases=("authentik_core.token",),
),
]

View File

@ -1,4 +1,6 @@
"""Flow models"""
from base64 import b64decode, b64encode
from pickle import dumps, loads # nosec
from typing import TYPE_CHECKING, Optional, Type
from uuid import uuid4
@ -9,11 +11,13 @@ from model_utils.managers import InheritanceManager
from rest_framework.serializers import BaseSerializer
from structlog.stdlib import get_logger
from authentik.core.models import Token
from authentik.core.types import UserSettingSerializer
from authentik.lib.models import InheritanceForeignKey, SerializerModel
from authentik.policies.models import PolicyBindingModel
if TYPE_CHECKING:
from authentik.flows.planner import FlowPlan
from authentik.flows.stage import StageView
LOGGER = get_logger()
@ -71,7 +75,6 @@ class Stage(SerializerModel):
"""Return component used to edit this object"""
raise NotImplementedError
@property
def ui_user_settings(self) -> Optional[UserSettingSerializer]:
"""Entrypoint to integrate with User settings. Can either return None if no
user settings are available, or a challenge."""
@ -260,3 +263,30 @@ class ConfigurableStage(models.Model):
class Meta:
abstract = True
class FlowToken(Token):
"""Subclass of a standard Token, stores the currently active flow plan upon creation.
Can be used to later resume a flow."""
flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
_plan = models.TextField()
@staticmethod
def pickle(plan) -> str:
"""Pickle into string"""
data = dumps(plan)
return b64encode(data).decode()
@property
def plan(self) -> "FlowPlan":
"""Load Flow plan from pickled version"""
return loads(b64decode(self._plan.encode())) # nosec
def __str__(self) -> str:
return f"Flow Token {super().__str__()}"
class Meta:
verbose_name = _("Flow Token")
verbose_name_plural = _("Flow Tokens")

View File

@ -24,6 +24,9 @@ PLAN_CONTEXT_SSO = "is_sso"
PLAN_CONTEXT_REDIRECT = "redirect"
PLAN_CONTEXT_APPLICATION = "application"
PLAN_CONTEXT_SOURCE = "source"
# Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan
# was restored.
PLAN_CONTEXT_IS_RESTORED = "is_restored"
GAUGE_FLOWS_CACHED = UpdatingGauge(
"authentik_flows_cached",
"Cached flows",
@ -123,7 +126,9 @@ class FlowPlanner:
) -> FlowPlan:
"""Check each of the flows' policies, check policies for each stage with PolicyBinding
and return ordered list"""
with Hub.current.start_span(op="flow.planner.plan") as span:
with Hub.current.start_span(
op="authentik.flow.planner.plan", description=self.flow.slug
) as span:
span: Span
span.set_data("flow", self.flow)
span.set_data("request", request)
@ -178,7 +183,8 @@ class FlowPlanner:
"""Build flow plan by checking each stage in their respective
order and checking the applied policies"""
with Hub.current.start_span(
op="flow.planner.build_plan"
op="authentik.flow.planner.build_plan",
description=self.flow.slug,
) as span, HIST_FLOWS_PLAN_TIME.labels(flow_slug=self.flow.slug).time():
span: Span
span.set_data("flow", self.flow)

View File

@ -6,6 +6,7 @@ from django.http.response import HttpResponse
from django.urls import reverse
from django.views.generic.base import View
from rest_framework.request import Request
from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger
from authentik.core.models import DEFAULT_AVATAR, User
@ -94,8 +95,16 @@ class ChallengeStageView(StageView):
keep_context=keep_context,
)
return self.executor.restart_flow(keep_context)
return self.challenge_invalid(challenge)
return self.challenge_valid(challenge)
with Hub.current.start_span(
op="authentik.flow.stage.challenge_invalid",
description=self.__class__.__name__,
):
return self.challenge_invalid(challenge)
with Hub.current.start_span(
op="authentik.flow.stage.challenge_valid",
description=self.__class__.__name__,
):
return self.challenge_valid(challenge)
def format_title(self) -> str:
"""Allow usage of placeholder in flow title."""
@ -104,7 +113,11 @@ class ChallengeStageView(StageView):
}
def _get_challenge(self, *args, **kwargs) -> Challenge:
challenge = self.get_challenge(*args, **kwargs)
with Hub.current.start_span(
op="authentik.flow.stage.get_challenge",
description=self.__class__.__name__,
):
challenge = self.get_challenge(*args, **kwargs)
if "flow_info" not in challenge.initial_data:
flow_info = ContextualFlowInfo(
data={
@ -149,7 +162,7 @@ class ChallengeStageView(StageView):
)
challenge_response.initial_data["response_errors"] = full_errors
if not challenge_response.is_valid():
LOGGER.warning(
LOGGER.error(
"f(ch): invalid challenge response",
binding=self.executor.current_binding,
errors=challenge_response.errors,

View File

@ -2,7 +2,7 @@
from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.flows.api.stages import StageSerializer, StageViewSet
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage
from authentik.policies.dummy.models import DummyPolicy
@ -32,7 +32,7 @@ class TestFlowsAPI(APITestCase):
def test_models(self):
"""Test that ui_user_settings returns none"""
self.assertIsNone(Stage().ui_user_settings)
self.assertIsNone(Stage().ui_user_settings())
def test_api_serializer(self):
"""Test that stage serializer returns the correct type"""
@ -47,7 +47,7 @@ class TestFlowsAPI(APITestCase):
def test_api_diagram(self):
"""Test flow diagram."""
user = User.objects.get(username="akadmin")
user = create_test_admin_user()
self.client.force_login(user)
flow = Flow.objects.create(
@ -77,7 +77,7 @@ class TestFlowsAPI(APITestCase):
def test_api_diagram_no_stages(self):
"""Test flow diagram with no stages."""
user = User.objects.get(username="akadmin")
user = create_test_admin_user()
self.client.force_login(user)
flow = Flow.objects.create(
@ -93,7 +93,7 @@ class TestFlowsAPI(APITestCase):
def test_types(self):
"""Test Stage's types endpoint"""
user = User.objects.get(username="akadmin")
user = create_test_admin_user()
self.client.force_login(user)
response = self.client.get(

View File

@ -545,6 +545,7 @@ class TestFlowExecutor(APITestCase):
"password_fields": False,
"primary_action": "Log in",
"sources": [],
"show_source_labels": False,
"user_fields": [UserFields.E_MAIL],
},
)

View File

@ -6,7 +6,7 @@ from django.test.client import RequestFactory
from django.urls.base import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.flows.challenge import ChallengeTypes
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, InvalidResponseAction
from authentik.stages.dummy.models import DummyStage
@ -18,7 +18,7 @@ class TestFlowInspector(APITestCase):
def setUp(self):
self.request_factory = RequestFactory()
self.admin = User.objects.get(username="akadmin")
self.admin = create_test_admin_user()
self.client.force_login(self.admin)
def test(self):
@ -60,6 +60,7 @@ class TestFlowInspector(APITestCase):
"password_fields": False,
"primary_action": "Log in",
"sources": [],
"show_source_labels": False,
"user_fields": ["username"],
},
)
@ -76,7 +77,7 @@ class TestFlowInspector(APITestCase):
self.client.post(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
{"uid_field": "akadmin"},
{"uid_field": self.admin.username},
follow=True,
)
@ -88,5 +89,5 @@ class TestFlowInspector(APITestCase):
self.assertEqual(content["plans"][0]["current_stage"]["stage_obj"]["name"], "ident")
self.assertEqual(content["current_plan"]["current_stage"]["stage_obj"]["name"], "dummy2")
self.assertEqual(
content["current_plan"]["plan_context"]["pending_user"]["username"], "akadmin"
content["current_plan"]["plan_context"]["pending_user"]["username"], self.admin.username
)

View File

@ -17,13 +17,13 @@ def model_tester_factory(test_model: Type[Stage]) -> Callable:
def tester(self: TestModels):
model_class = None
if test_model._meta.abstract:
if test_model._meta.abstract: # pragma: no cover
model_class = test_model.__bases__[0]()
else:
model_class = test_model()
self.assertTrue(issubclass(model_class.type, StageView))
self.assertIsNotNone(test_model.component)
_ = test_model.ui_user_settings
_ = model_class.ui_user_settings()
return tester

View File

@ -2,6 +2,7 @@
from django.test import TestCase
from django.urls import reverse
from authentik.core.tests.utils import create_test_flow
from authentik.flows.models import Flow, FlowDesignation
from authentik.flows.planner import FlowPlan
from authentik.flows.views.executor import SESSION_KEY_PLAN
@ -12,9 +13,8 @@ class TestHelperView(TestCase):
def test_default_view(self):
"""Test that ToDefaultFlow returns the expected URL"""
flow = Flow.objects.filter(
designation=FlowDesignation.INVALIDATION,
).first()
Flow.objects.filter(designation=FlowDesignation.INVALIDATION).delete()
flow = create_test_flow(FlowDesignation.INVALIDATION)
response = self.client.get(
reverse("authentik_flows:default-invalidation"),
)
@ -24,9 +24,8 @@ class TestHelperView(TestCase):
def test_default_view_invalid_plan(self):
"""Test that ToDefaultFlow returns the expected URL (with an invalid plan)"""
flow = Flow.objects.filter(
designation=FlowDesignation.INVALIDATION,
).first()
Flow.objects.filter(designation=FlowDesignation.INVALIDATION).delete()
flow = create_test_flow(FlowDesignation.INVALIDATION)
plan = FlowPlan(flow_pk=flow.pk.hex + "aa")
session = self.client.session
session[SESSION_KEY_PLAN] = plan

View File

@ -19,6 +19,8 @@ from drf_spectacular.utils import OpenApiParameter, PolymorphicProxySerializer,
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from sentry_sdk import capture_exception
from sentry_sdk.api import set_tag
from sentry_sdk.hub import Hub
from structlog.stdlib import BoundLogger, get_logger
from authentik.core.models import USER_ATTRIBUTE_DEBUG
@ -34,8 +36,16 @@ from authentik.flows.challenge import (
WithUserInfoChallenge,
)
from authentik.flows.exceptions import EmptyFlowException, FlowNonApplicableException
from authentik.flows.models import ConfigurableStage, Flow, FlowDesignation, FlowStageBinding, Stage
from authentik.flows.models import (
ConfigurableStage,
Flow,
FlowDesignation,
FlowStageBinding,
FlowToken,
Stage,
)
from authentik.flows.planner import (
PLAN_CONTEXT_IS_RESTORED,
PLAN_CONTEXT_PENDING_USER,
PLAN_CONTEXT_REDIRECT,
FlowPlan,
@ -53,7 +63,9 @@ NEXT_ARG_NAME = "next"
SESSION_KEY_PLAN = "authentik_flows_plan"
SESSION_KEY_APPLICATION_PRE = "authentik_flows_application_pre"
SESSION_KEY_GET = "authentik_flows_get"
SESSION_KEY_POST = "authentik_flows_post"
SESSION_KEY_HISTORY = "authentik_flows_history"
QS_KEY_TOKEN = "flow_token" # nosec
def challenge_types():
@ -116,6 +128,7 @@ class FlowExecutorView(APIView):
super().setup(request, flow_slug=flow_slug)
self.flow = get_object_or_404(Flow.objects.select_related(), slug=flow_slug)
self._logger = get_logger().bind(flow_slug=flow_slug)
set_tag("authentik.flow", self.flow.slug)
def handle_invalid_flow(self, exc: BaseException) -> HttpResponse:
"""When a flow is non-applicable check if user is on the correct domain"""
@ -126,71 +139,100 @@ class FlowExecutorView(APIView):
message = exc.__doc__ if exc.__doc__ else str(exc)
return self.stage_invalid(error_message=message)
def _check_flow_token(self, get_params: QueryDict):
"""Check if the user is using a flow token to restore a plan"""
tokens = FlowToken.filter_not_expired(key=get_params[QS_KEY_TOKEN])
if not tokens.exists():
return False
token: FlowToken = tokens.first()
try:
plan = token.plan
except (AttributeError, EOFError, ImportError, IndexError) as exc:
LOGGER.warning("f(exec): Failed to restore token plan", exc=exc)
finally:
token.delete()
if not isinstance(plan, FlowPlan):
return None
plan.context[PLAN_CONTEXT_IS_RESTORED] = True
self._logger.debug("f(exec): restored flow plan from token", plan=plan)
return plan
# pylint: disable=unused-argument, too-many-return-statements
def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse:
# Early check if there's an active Plan for the current session
if SESSION_KEY_PLAN in self.request.session:
self.plan = self.request.session[SESSION_KEY_PLAN]
if self.plan.flow_pk != self.flow.pk.hex:
self._logger.warning(
"f(exec): Found existing plan for other flow, deleting plan",
)
# Existing plan is deleted from session and instance
self.plan = None
self.cancel()
self._logger.debug("f(exec): Continuing existing plan")
with Hub.current.start_span(
op="authentik.flow.executor.dispatch", description=self.flow.slug
) as span:
span.set_data("authentik Flow", self.flow.slug)
get_params = QueryDict(request.GET.get("query", ""))
if QS_KEY_TOKEN in get_params:
plan = self._check_flow_token(get_params)
if plan:
self.request.session[SESSION_KEY_PLAN] = plan
# Early check if there's an active Plan for the current session
if SESSION_KEY_PLAN in self.request.session:
self.plan = self.request.session[SESSION_KEY_PLAN]
if self.plan.flow_pk != self.flow.pk.hex:
self._logger.warning(
"f(exec): Found existing plan for other flow, deleting plan",
)
# Existing plan is deleted from session and instance
self.plan = None
self.cancel()
self._logger.debug("f(exec): Continuing existing plan")
# Don't check session again as we've either already loaded the plan or we need to plan
if not self.plan:
request.session[SESSION_KEY_HISTORY] = []
self._logger.debug("f(exec): No active Plan found, initiating planner")
# Don't check session again as we've either already loaded the plan or we need to plan
if not self.plan:
request.session[SESSION_KEY_HISTORY] = []
self._logger.debug("f(exec): No active Plan found, initiating planner")
try:
self.plan = self._initiate_plan()
except FlowNonApplicableException as exc:
self._logger.warning("f(exec): Flow not applicable to current user", exc=exc)
return to_stage_response(self.request, self.handle_invalid_flow(exc))
except EmptyFlowException as exc:
self._logger.warning("f(exec): Flow is empty", exc=exc)
# To match behaviour with loading an empty flow plan from cache,
# we don't show an error message here, but rather call _flow_done()
return self._flow_done()
# Initial flow request, check if we have an upstream query string passed in
request.session[SESSION_KEY_GET] = get_params
# We don't save the Plan after getting the next stage
# as it hasn't been successfully passed yet
try:
self.plan = self._initiate_plan()
except FlowNonApplicableException as exc:
self._logger.warning("f(exec): Flow not applicable to current user", exc=exc)
return to_stage_response(self.request, self.handle_invalid_flow(exc))
except EmptyFlowException as exc:
self._logger.warning("f(exec): Flow is empty", exc=exc)
# To match behaviour with loading an empty flow plan from cache,
# we don't show an error message here, but rather call _flow_done()
# This is the first time we actually access any attribute on the selected plan
# if the cached plan is from an older version, it might have different attributes
# in which case we just delete the plan and invalidate everything
next_binding = self.plan.next(self.request)
except Exception as exc: # pylint: disable=broad-except
self._logger.warning(
"f(exec): found incompatible flow plan, invalidating run", exc=exc
)
keys = cache.keys("flow_*")
cache.delete_many(keys)
return self.stage_invalid()
if not next_binding:
self._logger.debug("f(exec): no more stages, flow is done.")
return self._flow_done()
# Initial flow request, check if we have an upstream query string passed in
request.session[SESSION_KEY_GET] = QueryDict(request.GET.get("query", ""))
# We don't save the Plan after getting the next stage
# as it hasn't been successfully passed yet
try:
# This is the first time we actually access any attribute on the selected plan
# if the cached plan is from an older version, it might have different attributes
# in which case we just delete the plan and invalidate everything
next_binding = self.plan.next(self.request)
except Exception as exc: # pylint: disable=broad-except
self._logger.warning("f(exec): found incompatible flow plan, invalidating run", exc=exc)
keys = cache.keys("flow_*")
cache.delete_many(keys)
return self.stage_invalid()
if not next_binding:
self._logger.debug("f(exec): no more stages, flow is done.")
return self._flow_done()
self.current_binding = next_binding
self.current_stage = next_binding.stage
self._logger.debug(
"f(exec): Current stage",
current_stage=self.current_stage,
flow_slug=self.flow.slug,
)
try:
stage_cls = self.current_stage.type
except NotImplementedError as exc:
self._logger.debug("Error getting stage type", exc=exc)
return self.stage_invalid()
self.current_stage_view = stage_cls(self)
self.current_stage_view.args = self.args
self.current_stage_view.kwargs = self.kwargs
self.current_stage_view.request = request
try:
return super().dispatch(request)
except InvalidStageError as exc:
return self.stage_invalid(str(exc))
self.current_binding = next_binding
self.current_stage = next_binding.stage
self._logger.debug(
"f(exec): Current stage",
current_stage=self.current_stage,
flow_slug=self.flow.slug,
)
try:
stage_cls = self.current_stage.type
except NotImplementedError as exc:
self._logger.debug("Error getting stage type", exc=exc)
return self.stage_invalid()
self.current_stage_view = stage_cls(self)
self.current_stage_view.args = self.args
self.current_stage_view.kwargs = self.kwargs
self.current_stage_view.request = request
try:
return super().dispatch(request)
except InvalidStageError as exc:
return self.stage_invalid(str(exc))
def handle_exception(self, exc: Exception) -> HttpResponse:
"""Handle exception in stage execution"""
@ -232,8 +274,15 @@ class FlowExecutorView(APIView):
stage=self.current_stage,
)
try:
stage_response = self.current_stage_view.get(request, *args, **kwargs)
return to_stage_response(request, stage_response)
with Hub.current.start_span(
op="authentik.flow.executor.stage",
description=class_to_path(self.current_stage_view.__class__),
) as span:
span.set_data("Method", "GET")
span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.get(request, *args, **kwargs)
return to_stage_response(request, stage_response)
except Exception as exc: # pylint: disable=broad-except
return self.handle_exception(exc)
@ -269,8 +318,15 @@ class FlowExecutorView(APIView):
stage=self.current_stage,
)
try:
stage_response = self.current_stage_view.post(request, *args, **kwargs)
return to_stage_response(request, stage_response)
with Hub.current.start_span(
op="authentik.flow.executor.stage",
description=class_to_path(self.current_stage_view.__class__),
) as span:
span.set_data("Method", "POST")
span.set_data("authentik Stage", self.current_stage_view)
span.set_data("authentik Flow", self.flow.slug)
stage_response = self.current_stage_view.post(request, *args, **kwargs)
return to_stage_response(request, stage_response)
except Exception as exc: # pylint: disable=broad-except
return self.handle_exception(exc)
@ -315,6 +371,12 @@ class FlowExecutorView(APIView):
NEXT_ARG_NAME, "authentik_core:root-redirect"
)
self.cancel()
Event.new(
action=EventAction.FLOW_EXECUTION,
flow=self.flow,
designation=self.flow.designation,
successful=True,
).from_http(self.request)
return to_stage_response(self.request, redirect_with_qs(next_param))
def stage_ok(self) -> HttpResponse:

View File

@ -87,9 +87,7 @@ class FlowInspectorView(APIView):
@extend_schema(
responses={
200: FlowInspectionSerializer(),
400: OpenApiResponse(
description="No flow plan in session."
), # This error can be raised by the email stage
400: OpenApiResponse(description="No flow plan in session."),
},
request=OpenApiTypes.NONE,
operation_id="flows_inspector_get",
@ -106,7 +104,10 @@ class FlowInspectorView(APIView):
if SESSION_KEY_PLAN in request.session:
current_plan: FlowPlan = request.session[SESSION_KEY_PLAN]
else:
current_plan = request.session[SESSION_KEY_HISTORY][-1]
try:
current_plan = request.session[SESSION_KEY_HISTORY][-1]
except IndexError:
return Response(status=400)
is_completed = True
current_serializer = FlowInspectorPlanSerializer(
instance=current_plan, context={"request": request}

View File

@ -3,7 +3,9 @@ import os
from collections.abc import Mapping
from contextlib import contextmanager
from glob import glob
from json import dumps
from json import dumps, loads
from json.decoder import JSONDecodeError
from sys import argv, stderr
from time import time
from typing import Any
from urllib.parse import urlparse
@ -59,7 +61,7 @@ class ConfigLoader:
"timestamp": time(),
}
output.update(kwargs)
print(dumps(output))
print(dumps(output), file=stderr)
def update(self, root: dict[str, Any], updatee: dict[str, Any]) -> dict[str, Any]:
"""Recursively update dictionary"""
@ -81,8 +83,8 @@ class ConfigLoader:
try:
with open(url.path, "r", encoding="utf8") as _file:
value = _file.read()
except OSError:
self._log("error", f"Failed to read config value from {url.path}")
except OSError as exc:
self._log("error", f"Failed to read config value from {url.path}: {exc}")
value = url.query
return value
@ -123,6 +125,11 @@ class ConfigLoader:
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
try:
value = loads(value)
except JSONDecodeError:
pass
current_obj[dot_parts[-1]] = value
idx += 1
if idx > 0:
@ -174,3 +181,9 @@ class ConfigLoader:
CONFIG = ConfigLoader()
if __name__ == "__main__":
if len(argv) < 2:
print(dumps(CONFIG.raw, indent=4))
else:
print(CONFIG.y(argv[1]))

View File

@ -5,12 +5,21 @@ postgresql:
user: authentik
port: 5432
password: 'env://POSTGRES_PASSWORD'
backup:
enabled: true
s3_backup:
access_key: ""
secret_key: ""
bucket: ""
region: eu-central-1
host: ""
location: ""
insecure_skip_verify: false
web:
listen: 0.0.0.0:9000
listen_tls: 0.0.0.0:9443
listen_metrics: 0.0.0.0:9300
load_local_files: false
outpost_port_offset: 0
redis:
@ -37,6 +46,7 @@ error_reporting:
enabled: false
environment: customer
send_pii: false
sample_rate: 0.5
# Global email settings
email:
@ -54,16 +64,22 @@ outposts:
# %(type)s: Outpost type; proxy, ldap, etc
# %(version)s: Current version; 2021.4.1
# %(build_hash)s: Build hash if you're running a beta version
container_image_base: env://AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE?goauthentik.io/%(type)s:%(version)s
container_image_base: goauthentik.io/%(type)s:%(version)s
cookie_domain: null
disable_update_check: false
disable_startup_analytics: false
avatars: env://AUTHENTIK_AUTHENTIK__AVATARS?gravatar
geoip: "./GeoLite2-City.mmdb"
# Can't currently be configured via environment variables, only yaml
footer_links:
- name: Documentation
href: https://goauthentik.io/docs/?utm_source=authentik
- name: authentik Website
href: https://goauthentik.io/?utm_source=authentik
default_user_change_email: true
default_user_change_username: true
gdpr_compliance: true
cert_discovery_dir: /certs

View File

@ -80,8 +80,9 @@ class BaseEvaluator:
"""Parse and evaluate expression. If the syntax is incorrect, a SyntaxError is raised.
If any exception is raised during execution, it is raised.
The result is returned without any type-checking."""
with Hub.current.start_span(op="lib.evaluator.evaluate") as span:
with Hub.current.start_span(op="authentik.lib.evaluator.evaluate") as span:
span: Span
span.description = self._filename
span.set_data("expression", expression_source)
param_keys = self._context.keys()
try:

View File

@ -66,3 +66,11 @@ class DomainlessURLValidator(URLValidator):
r"\Z",
re.IGNORECASE,
)
self.schemes = ["http", "https", "blank"] + list(self.schemes)
def __call__(self, value: str):
# Check if the scheme is valid.
scheme = value.split("://")[0].lower()
if scheme not in self.schemes:
value = "default" + value
super().__call__(value)

View File

@ -8,11 +8,13 @@ from botocore.exceptions import BotoCoreError
from celery.exceptions import CeleryError
from channels.middleware import BaseMiddleware
from channels_redis.core import ChannelFull
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation, ValidationError
from django.db import InternalError, OperationalError, ProgrammingError
from django.http.response import Http404
from django_redis.exceptions import ConnectionInterrupted
from docker.errors import DockerException
from h11 import LocalProtocolError
from ldap3.core.exceptions import LDAPException
from redis.exceptions import ConnectionError as RedisConnectionError
from redis.exceptions import RedisError, ResponseError
@ -72,6 +74,7 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
# websocket errors
ChannelFull,
WebSocketException,
LocalProtocolError,
# rest_framework error
APIException,
# celery errors
@ -90,6 +93,7 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
# End-user errors
Http404,
)
exc_value = None
if "exc_info" in hint:
_, exc_value, _ = hint["exc_info"]
if isinstance(exc_value, ignored_classes):
@ -103,6 +107,10 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
"asyncio",
"multiprocessing",
"django_redis",
"django.security.DisallowedHost",
]:
return None
LOGGER.debug("sending event to sentry", exc=exc_value, source_logger=event.get("logger", None))
if settings.DEBUG:
return None
return event

View File

@ -1,7 +1,7 @@
"""Test Evaluator base functions"""
from django.test import TestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.expression.evaluator import BaseEvaluator
@ -19,12 +19,11 @@ class TestEvaluator(TestCase):
def test_user_by(self):
"""Test expr_user_by"""
self.assertIsNotNone(BaseEvaluator.expr_user_by(username="akadmin"))
user = create_test_admin_user()
self.assertIsNotNone(BaseEvaluator.expr_user_by(username=user.username))
self.assertIsNone(BaseEvaluator.expr_user_by(username="bar"))
self.assertIsNone(BaseEvaluator.expr_user_by(foo="bar"))
def test_is_group_member(self):
"""Test expr_is_group_member"""
self.assertFalse(
BaseEvaluator.expr_is_group_member(User.objects.get(username="akadmin"), name="test")
)
self.assertFalse(BaseEvaluator.expr_is_group_member(create_test_admin_user(), name="test"))

View File

@ -1,17 +1,24 @@
"""Test HTTP Helpers"""
from django.test import RequestFactory, TestCase
from authentik.core.models import USER_ATTRIBUTE_CAN_OVERRIDE_IP, Token, TokenIntents, User
from authentik.core.models import USER_ATTRIBUTE_CAN_OVERRIDE_IP, Token, TokenIntents
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.utils.http import OUTPOST_REMOTE_IP_HEADER, OUTPOST_TOKEN_HEADER, get_client_ip
from authentik.lib.views import bad_request_message
class TestHTTP(TestCase):
"""Test HTTP Helpers"""
def setUp(self) -> None:
self.user = User.objects.get(username="akadmin")
self.user = create_test_admin_user()
self.factory = RequestFactory()
def test_bad_request_message(self):
"""test bad_request_message"""
request = self.factory.get("/")
self.assertEqual(bad_request_message(request, "foo").status_code, 400)
def test_normal(self):
"""Test normal request"""
request = self.factory.get("/")

View File

@ -4,6 +4,7 @@ from typing import Any, Optional
from django.http import HttpRequest
from requests.sessions import Session
from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
@ -52,6 +53,12 @@ def _get_outpost_override_ip(request: HttpRequest) -> Optional[str]:
fake_ip=fake_ip,
)
return None
# Update sentry scope to include correct IP
user = Hub.current.scope._user
if not user:
user = {}
user["ip_address"] = fake_ip
Hub.current.scope.set_user(user)
return fake_ip

View File

@ -1,8 +1,13 @@
"""authentik lib reflection utilities"""
import os
from importlib import import_module
from pathlib import Path
from typing import Union
from django.conf import settings
from kubernetes.config.incluster_config import SERVICE_HOST_ENV_NAME
from authentik.lib.config import CONFIG
def all_subclasses(cls, sort=True):
@ -42,3 +47,16 @@ def get_apps():
for _app in apps.get_app_configs():
if _app.name.startswith("authentik"):
yield _app
def get_env() -> str:
"""Get environment in which authentik is currently running"""
if SERVICE_HOST_ENV_NAME in os.environ:
return "kubernetes"
if "CI" in os.environ:
return "ci"
if Path("/tmp/authentik-mode").exists(): # nosec
return "compose"
if CONFIG.y_bool("debug"):
return "dev"
return "custom"

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