Compare commits

..

468 Commits

Author SHA1 Message Date
619203c177 release: 2021.9.8 2021-10-10 13:12:26 +02:00
4ae476e58d Revert "build(deps): bump construct-style-sheets-polyfill in /web (#1531)"
This reverts commit 55259adf38.
2021-10-07 22:35:41 +02:00
e444d0d640 release: 2021.9.7 2021-10-06 20:57:56 +02:00
3869965b4c web/admin: fix description for flow import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/src/locales/fr_FR.po
2021-10-06 20:51:36 +02:00
d4e1b95991 root: fix syntax error in dockerfile healthcheck
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-06 09:18:24 +02:00
2b730dec54 release: 2021.9.6 2021-10-05 22:22:54 +02:00
2aacb311bc internal: add internal healthchecking to prevent websocket errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 22:22:38 +02:00
40055ef01b cmd: prevent outposts from panicking when failing to get their config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 22:22:38 +02:00
75608dce5c web: add locale detection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/src/interfaces/locale.ts
2021-10-05 21:22:08 +02:00
b0f7083879 lifecycle: fix syntax error in ak wrapper
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 21:04:01 +02:00
62bf79ce32 root: add docker-native healthcheck for web and celery
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 20:45:38 +02:00
7a16c9cb14 root: remove redundant internal network from compose
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 20:45:38 +02:00
d29d161ac6 admin: clear update notification when notification's version matches current version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 20:45:38 +02:00
653631ac77 Translate /web/src/locales/en.po in fr_FR (#1536)
translation completed for the source file '/web/src/locales/en.po'
on the 'fr_FR' language.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
# Conflicts:
#	web/src/locales/fr_FR.po
2021-10-05 16:24:48 +02:00
cde303e780 web: fix strings not being translated at all when matching browser locale not found
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/src/interfaces/locale.ts
2021-10-05 16:24:31 +02:00
aa359a032c build(deps): bump goauthentik.io/api from 0.202195.3 to 0.202195.4 (#1544)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.202195.3 to 0.202195.4.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.202195.3...v0.202195.4)

---
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-10-05 13:49:15 +02:00
6491065aab web: Update Web API Client version (#1543)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-05 13:49:15 +02:00
79eec5a3a0 core: include group uuids in self serializer
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:49:14 +02:00
cd5e091937 build(deps): bump goauthentik.io/api from 0.202195.1 to 0.202195.3 (#1542)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.202195.1 to 0.202195.3.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.202195.1...v0.202195.3)

---
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>
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
# Conflicts:
#	go.mod
#	go.sum
2021-10-05 13:49:11 +02:00
7ed8952803 web: Update Web API Client version (#1540)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-10-05 13:48:53 +02:00
c1f302fb7c core: only return group names for user_self
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:48:53 +02:00
cb31e52d0e web/flows: adjust message for email stage
closes #1538

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

# Conflicts:
#	web/src/locales/fr_FR.po
2021-10-05 13:48:51 +02:00
782764ac73 api: ensure viewsets have default ordering
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:48:42 +02:00
d0c56325ef web/elements: fix model form always loading when viewport check is disabled
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:48:42 +02:00
73d57d6f82 core: make user's name field fully options
closes #1537

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:48:42 +02:00
2716a26887 web: Update Web API Client version (#1539)
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-10-05 13:48:23 +02:00
0452537e8b web/admin: only show outpost deployment info when not embedded
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:47:55 +02:00
d1a1bfbbc5 web/user: don't show managed tokens in user interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:47:49 +02:00
a69fcbca9a web: fix rendering of token copy button in dark mode
closes #1528

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

# Conflicts:
#	web/src/locales/fr_FR.po
2021-10-05 13:47:29 +02:00
1ac4dacc3b outposts: fix error when comparing ports in docker controller when port mapping is disabled
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-05 13:47:15 +02:00
bcf7e162a4 release: 2021.9.5 2021-10-04 20:08:46 +02:00
f44956bd61 web: Update Web API Client version (#1526)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:52:27 +02:00
cb37e5c10e stages/email: add activate_user_on_success flag, add for all example flows
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/src/locales/fr_FR.po
2021-10-04 18:50:19 +02:00
73bb778d62 stages/user_login: add check for user.is_active and tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:50:00 +02:00
b612a82e16 outposts: don't always build permissions on outpost.user access, only in signals and tasks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:49:57 +02:00
83991c743e lifecycle: switch to h11 uvicorn worker for now
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:49:54 +02:00
09f43ca43b events: add missing migration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:49:50 +02:00
1c91835a26 providers/ldap: use RDN when using posixGroup's memberUid attribute (#1514)
Use the RDN instead of the FDN when establishing group memberships based on posixGroup's 'memberUid' attribute.

fixes #1436

Signed-off-by: Steven Armstrong <steven@armstrong.cc>
2021-10-04 18:49:45 +02:00
c032914092 web/admin: fix search group label
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:49:42 +02:00
3634bf4629 tests/integration: fix tests failing due to incorrect comparison
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-04 18:49:10 +02:00
45f99fbaf0 outposts: fix circular import in kubernetes controller
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 19:25:26 +02:00
e31a3307b5 providers/proxy: always check ingress secret in kubernetes controller
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 19:14:42 +02:00
d28fcca344 outposts: check ports of deployment in kubernetes outpost controller
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 19:14:42 +02:00
c296e1214c web: fix package lock
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 19:14:37 +02:00
d676cf6e3f outposts/proxy: show full error message when user is authenticated
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 18:20:44 +02:00
39d87841d0 outposts/proxy: add new headers with unified naming
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 18:20:44 +02:00
fcd879034c outpost/proxy: fix missing negation for internal host ssl verification
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 18:20:44 +02:00
b285814e24 sources/ldap: fix logic error in Active Directory account disabled status
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-10-03 18:19:07 +02:00
1a6ea72c09 release: 2021.9.4 2021-10-01 09:51:51 +02:00
c251b87f8c sources/ldap: add support for Active Directory userAccountControl attribute
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 19:34:43 +02:00
21a9aa229a sources/ldap: don't sync ldap source when no property mappings are set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 19:34:43 +02:00
5f6565ee27 web/admin: fix LDAP Source form not exposing syncParentGroup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 19:34:43 +02:00
afad55a357 build(deps): bump sentry-sdk from 1.4.2 to 1.4.3 (#1502) 2021-09-30 19:34:43 +02:00
f25d76fa43 build(deps): bump sentry-sdk from 1.4.1 to 1.4.2 (#1488) 2021-09-30 19:34:42 +02:00
10b45d954e outposts: allow disabling of docker controller port mapping
closes #1474

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 00:11:50 +02:00
339eaf37f2 web/elements: use dedicated button for search clear instead of webkit exclusive one
closes #1499

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 00:11:50 +02:00
f723fdd551 web/elements: fix initialLoad not being done when viewportCheck was disabled
closes #1497

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-30 00:11:50 +02:00
8359f0bfb3 web: fix linting again
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-29 10:20:40 +02:00
ee610a906a web: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-29 10:07:04 +02:00
828eeb5ebb root: Use fully qualified names for docker bases base images. (#1490)
Signed-off-by: Steven Armstrong <steven@armstrong.cc>
2021-09-29 10:04:27 +02:00
c9c177d8f9 web/admin: don't require username nor name for activate/deactivate toggles
closes #1491

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-29 10:02:06 +02:00
c19afa4f16 outposts/proxy: fix duplicate protocol in domain auth mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-29 10:02:01 +02:00
941bc61b31 release: 2021.9.3 2021-09-27 17:31:50 +02:00
282b364606 stages/prompt: fix inconsistent policy context for validation policies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-27 17:05:26 +02:00
ad4bc4083d website/docs: update dev docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-27 16:04:41 +02:00
ebe282eb1a web/admin: fix user_write form not writing group
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-27 10:12:45 +02:00
830c26ca25 tests/e2e: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-27 09:52:47 +02:00
ed3b4a3d4a build(deps): bump rapidoc from 9.1.2 to 9.1.3 in /website (#1478)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.1.2 to 9.1.3.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/v9.1.2...v9.1.3)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-27 09:24:43 +02:00
975c4ddc04 build(deps): bump postcss from 8.3.7 to 8.3.8 in /website (#1479)
Bumps [postcss](https://github.com/postcss/postcss) from 8.3.7 to 8.3.8.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.3.7...8.3.8)

---
updated-dependencies:
- dependency-name: postcss
  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-09-27 09:22:49 +02:00
7e2896298a build(deps): bump rapidoc from 9.1.2 to 9.1.3 in /web (#1480)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.1.2 to 9.1.3.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/v9.1.2...v9.1.3)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-27 09:22:31 +02:00
cba9cf8361 build(deps): bump actions/github-script from 4.1 to 5 (#1481)
Bumps [actions/github-script](https://github.com/actions/github-script) from 4.1 to 5.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v4.1...v5)

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

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-09-27 09:22:21 +02:00
bf12580f64 build(deps): bump pycryptodome from 3.10.3 to 3.10.4 (#1482)
Bumps [pycryptodome](https://github.com/Legrandin/pycryptodome) from 3.10.3 to 3.10.4.
- [Release notes](https://github.com/Legrandin/pycryptodome/releases)
- [Changelog](https://github.com/Legrandin/pycryptodome/blob/master/Changelog.rst)
- [Commits](https://github.com/Legrandin/pycryptodome/commits/v3.10.4)

---
updated-dependencies:
- dependency-name: pycryptodome
  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-09-27 09:22:03 +02:00
75ef4ce596 tests/e2e: add new ldap object classes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:57:42 +02:00
c2f3ce11b0 outposts/ldap: fix potential panic when converting attributes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:52:25 +02:00
3c256fecc6 outposts/ldap: add groupofuniquenames
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:49:11 +02:00
0285b84133 outposts/ldap: add query support for all supported object classes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:42:26 +02:00
99a371a02c web/elements: fix token copy button not working on chrome...
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:34:28 +02:00
c7e6eb8896 outposts/ldap: add support for base scope and domain info
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 14:01:22 +02:00
674bd9e05c web/admin: Fix typo 'username address' -> 'username' (#1473) 2021-09-26 12:53:37 +02:00
b79901df87 website/docs: prepare 2021.9.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 12:03:10 +02:00
b248f450dd outposts: make AUTHENTIK_HOST_BROWSER configurable from central config
closes #1471

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 12:00:51 +02:00
05db9e5c40 web/admin: handle error correctly when creating user recovery link
closes #1472

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 11:49:40 +02:00
234a5e2b66 outposts: fix outposts not correctly updating central state
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-26 11:40:21 +02:00
aea1736f70 outposts/proxy: Fix failing traefik healtcheck (#1470) 2021-09-26 11:33:18 +02:00
9f4a4449f5 outposts/proxy: ensure cookies only last as long as tokens
closes #1462

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-25 16:12:59 +02:00
b6b55e2336 build(deps): bump goauthentik.io/api from 0.202192.3 to 0.202192.5 (#1468)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.202192.3 to 0.202192.5.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.202192.3...v0.202192.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-09-25 16:06:10 +02:00
8f2805e05b web: Update Web API Client version (#1467)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-25 16:04:07 +02:00
4f3583cd7e providers/proxy: make token_validity float and optional for backwards compat
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-25 15:54:32 +02:00
617e90dca3 web: Update Web API Client version (#1465)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-25 15:48:05 +02:00
f7408626a8 providers/proxy: return token_validity as total seconds instead of expression
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-25 15:44:16 +02:00
4dcb15af46 build(deps): bump goauthentik.io/api from 0.202192.1 to 0.202192.3 (#1464)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.202192.1 to 0.202192.3.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.202192.1...v0.202192.3)

---
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-09-25 15:11:08 +02:00
89beb7a9f7 web: Update Web API Client version (#1463)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-25 15:02:33 +02:00
28eeb4798e providers/proxy: add token_validity field for outpost configuration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1462
2021-09-25 15:00:06 +02:00
79b92e764e *: fix typos in code
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-25 00:01:11 +02:00
919336a519 outposts: ensure service is always re-created with mismatching ports
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 23:45:15 +02:00
27e04589c1 outposts/proxyv2: fix routing not working correctly for domain auth
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 23:32:16 +02:00
ba44fbdac8 website/docs: fix typos and grammar (#1459) 2021-09-24 15:37:54 +02:00
0e093a8917 web: Update Web API Client version (#1458) 2021-09-24 12:23:14 +02:00
d0bfb99859 web/elements: improve error handling on forms
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 12:19:56 +02:00
93bdea3769 core: fix api return code for user self-update
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 11:51:03 +02:00
e681654af7 web/admin: add notice for recovery
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 11:50:52 +02:00
cab7593dca web/user: fix brand not being shown in safari
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 11:50:46 +02:00
cf92f9aefc web/elements: fix token copy error in safari
closes #1219

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 10:44:28 +02:00
8d72b3498d internal: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-24 10:44:28 +02:00
42ab858c50 build(deps): bump goauthentik.io/api from 0.202191.4 to 0.202192.1 (#1455)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.202191.4 to 0.202192.1.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/compare/v0.202191.4...v0.202192.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-09-24 09:34:10 +02:00
a1abae9ab1 build(deps): bump boto3 from 1.18.46 to 1.18.47 (#1456)
Bumps [boto3](https://github.com/boto/boto3) from 1.18.46 to 1.18.47.
- [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.18.46...1.18.47)

---
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-09-24 09:34:01 +02:00
8f36b49061 web/user: search apps when user typed before apps have loaded
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 16:34:11 +02:00
64b4e851ce events: add additional validation for event transport
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 16:29:58 +02:00
40a62ac1e5 web/admin: fix Transport Form not loading mode correctly on edit
closes #1453

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 16:16:38 +02:00
5df60e4d87 web/admin: fix NotificationWebhookMapping not loading correctly
closes #1452

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 16:13:58 +02:00
50ebc8522d web: Update Web API Client version (#1454)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-23 14:21:49 +02:00
eddca478dc release: 2021.9.2 2021-09-23 12:34:02 +02:00
99a7fca08e website/docs: prepare 2021.9.2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 12:33:42 +02:00
a7e3602908 web: fix import order of polyfills causing shadydom to not work on firefox and safari
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 10:16:49 +02:00
74169860cf api: add logging to sentry proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 09:57:42 +02:00
52bb774f73 internal: add asset paths for user interface
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-23 09:57:24 +02:00
f26fcaf825 website/docs: add warning for example flows (#1444) 2021-09-23 08:34:40 +02:00
b8e92e2f11 build(deps): bump postcss from 8.3.6 to 8.3.7 in /website (#1445) 2021-09-23 08:33:27 +02:00
08adfc94d6 build(deps): bump rollup from 2.56.3 to 2.57.0 in /web (#1446) 2021-09-23 08:33:18 +02:00
236fafb735 build(deps): bump boto3 from 1.18.45 to 1.18.46 (#1447) 2021-09-23 08:33:10 +02:00
5ad9ddee3c build(deps): bump goauthentik.io/api from 0.202191.3 to 0.202191.4 (#1449) 2021-09-23 08:33:01 +02:00
24d220ff49 build(deps): bump urllib3 from 1.26.6 to 1.26.7 (#1448) 2021-09-23 08:32:53 +02:00
3364c195b7 build(deps): bump sentry-sdk from 1.4.0 to 1.4.1 (#1450) 2021-09-23 08:32:43 +02:00
50aa87d141 web/user: enable sentry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 22:35:52 +02:00
72b375023d web: Update Web API Client version (#1443)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-22 20:53:25 +02:00
77ba186818 website/docs: add notice for guacamole token length
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 20:02:30 +02:00
2fe6de0505 release: 2021.9.1 2021-09-22 19:11:20 +02:00
bf9e969b53 website/docs: prepare 2021.9.1
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 18:58:52 +02:00
184f119b16 website: set use_global_settings to true for example flows with email stages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 18:52:55 +02:00
ebc06f1abe outposts/ldap: fix logic error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 13:19:50 +02:00
0f8880ab0a outposts: fix typo
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-22 13:14:28 +02:00
ee56da5092 build(deps): bump @sentry/tracing from 6.13.1 to 6.13.2 in /web (#1438) 2021-09-22 07:32:40 +02:00
2152004502 build(deps): bump @types/codemirror from 5.60.2 to 5.60.3 in /web (#1437) 2021-09-22 07:30:35 +02:00
45d0b80d02 build(deps): bump @sentry/browser from 6.13.1 to 6.13.2 in /web (#1439) 2021-09-22 07:30:27 +02:00
96065eb942 build(deps): bump boto3 from 1.18.44 to 1.18.45 (#1441) 2021-09-22 07:30:01 +02:00
ac944fee8b build(deps): bump drf-spectacular from 0.18.2 to 0.19.0 (#1442) 2021-09-22 07:29:52 +02:00
1d0e5fc353 build(deps): bump sentry-sdk from 1.3.1 to 1.4.0 (#1440) 2021-09-22 07:28:48 +02:00
1f97420207 outposts/ldap: allow custom attributes to shadow built-in attributes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 21:59:39 +02:00
ae07f13a87 outposts: don't map port 9300 on docker, only expose port
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 21:40:08 +02:00
0aec504170 website/docs: add ssl port for ldap
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 15:44:05 +02:00
3b4c9bcc57 root: use tagged go client version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 15:42:07 +02:00
5182a6741e root: format pyproject
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 13:32:28 +02:00
da7635ae5c web: sort imports
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 11:33:51 +02:00
a92a0fb60a web: migrate to lit 2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-21 11:19:26 +02:00
cb10c1753b build(deps): bump lit-html from 1.4.1 to 2.0.0 in /web (#1427) 2021-09-21 08:35:36 +02:00
ae654bd4c8 build(deps): bump lit-element from 2.5.1 to 3.0.0 in /web (#1433) 2021-09-21 08:32:15 +02:00
28192655ec build(deps): bump @typescript-eslint/eslint-plugin in /web (#1426) 2021-09-21 08:32:00 +02:00
9582294eb8 build(deps): bump @sentry/tracing from 6.12.0 to 6.13.1 in /web (#1428) 2021-09-21 08:31:48 +02:00
0172430d7d build(deps): bump @patternfly/patternfly from 4.132.2 to 4.135.2 in /web (#1429) 2021-09-21 08:30:44 +02:00
1454b65933 build(deps): bump @typescript-eslint/parser in /web (#1430) 2021-09-21 08:30:36 +02:00
432a7792e2 build(deps): bump @sentry/browser from 6.12.0 to 6.13.1 in /web (#1431) 2021-09-21 08:30:28 +02:00
54069618b4 build(deps): bump codemirror from 5.62.3 to 5.63.0 in /web (#1432) 2021-09-21 08:30:20 +02:00
81feb313df build(deps): bump geoip2 from 4.2.0 to 4.3.0 (#1434) 2021-09-21 08:29:33 +02:00
e6b275add3 stages/invitation: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 20:41:05 +02:00
27016a5527 stages/invitation: fix tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 20:30:51 +02:00
4c29d517f0 stages/email: use different query arguments for email and invitation tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:55:53 +02:00
180d27cc37 outposts: don't restart container when health checks are starting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:46:05 +02:00
5a8b356dc7 web: fix css for dark mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:38:25 +02:00
3195640776 stages/email: slugify token identifier
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:26:25 +02:00
f463296d47 web: Update Web API Client version (#1421)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-20 19:22:46 +02:00
adf4b23c01 website/docs: add /akprox for nginx auth_request (#1420) 2021-09-20 19:21:30 +02:00
d900a2b6a9 *: fix lookup_fields
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:19:36 +02:00
95a2fddfa8 policies/expression: add ak_user_has_authenticator
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:13:41 +02:00
8f7d21b692 stages/email: don't throw 404 when token can't be found
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 19:01:25 +02:00
3f84abec2f core: fix token identifier not being slugified when created with user-controller input
closes #1390

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 13:43:25 +02:00
b5c857aff4 api: add explicit lookup_value_regex, disable include_format_suffixes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 13:42:56 +02:00
f8dee09107 web/user: allow customisable background colour
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 12:49:17 +02:00
84a800583c web/user: make search configurable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-20 12:15:53 +02:00
88de94f014 build(deps): bump rapidoc from 9.1.0 to 9.1.2 in /website (#1418)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.1.0 to 9.1.2.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/v9.1.0...v9.1.2)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-20 11:50:38 +02:00
25549ec339 build(deps): bump rapidoc from 9.1.0 to 9.1.2 in /web (#1419)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.1.0 to 9.1.2.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/v9.1.0...v9.1.2)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-20 11:50:27 +02:00
fe4923bff6 build(deps): bump boto3 from 1.18.43 to 1.18.44 (#1417)
Bumps [boto3](https://github.com/boto/boto3) from 1.18.43 to 1.18.44.
- [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.18.43...1.18.44)

---
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-09-20 09:09:22 +02:00
bb1a0b6bd2 web: Update Web API Client version (#1416)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-19 22:32:38 +02:00
879b5ead71 web: fix notification badge not refreshing after clearing notifications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 21:58:59 +02:00
1670ec9167 website/docs: update 2021.9.1-rc3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 21:55:21 +02:00
ac52667327 release: 2021.9.1-rc3 2021-09-19 21:52:49 +02:00
0d7c5c2108 web/user: fix edit button for applications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 21:10:57 +02:00
73e3d19384 web/user: add auto-focus search for applications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 21:07:18 +02:00
f6e0f0282d core: fix tokens not being viewable but superusers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 16:11:20 +02:00
3f42067a8f web: improve display of action buttons with non-primary classes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 15:57:12 +02:00
ed6f5b98df sources/ldap: improve messages of sync tasks in UI
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 15:54:22 +02:00
dd290e264c web/admin: trigger refresh after syncing ldap
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 15:34:44 +02:00
c85484fc00 core: allow admins to create tokens with all parameters, re-add user to token form
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 15:25:48 +02:00
663dffd8be web/admin: fix error in firefox when creating token
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 00:28:40 +02:00
c15d0c3d17 web: fix text colour in delete form in dark mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-19 00:14:50 +02:00
bf09a54f35 web/user: optimise load, fix unread status for notifications
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-18 18:16:31 +02:00
930dd51663 web: fix datetime-local fields throwing errors on firefox
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-18 15:31:48 +02:00
12a523c7aa website: remove sentry
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-18 14:33:53 +02:00
ea9a6d57dd build(deps): bump rapidoc from 9.0.0 to 9.1.0 in /website (#1414)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-18 11:23:54 +02:00
91958e1232 build(deps): bump rapidoc from 9.0.0 to 9.1.0 in /web (#1415)
Bumps [rapidoc](https://github.com/mrin9/RapiDoc) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/mrin9/RapiDoc/releases)
- [Commits](https://github.com/mrin9/RapiDoc/compare/9.0.0...v9.1.0)

---
updated-dependencies:
- dependency-name: rapidoc
  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-09-18 11:23:44 +02:00
8925afb089 web/admin: fix linting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 16:54:48 +02:00
ccafe7be4f website/docs: update 2021.9 changelog
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 16:49:36 +02:00
8279690a8f sources/ldap: prevent error when retrying old system task with no arguments
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 16:49:26 +02:00
763d3ae76a web/admin: fix ldap sync status for new API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 16:46:18 +02:00
b775e7f4d3 web: Update Web API Client version (#1412)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-17 12:45:16 +02:00
3d8d93ece5 root: log failed celery tasks to event log
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 12:42:42 +02:00
06af306e8a sources/ldap: bump timeout, run each sync component in its own task
closes #1411

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 12:42:20 +02:00
9257f3c919 web/user: add missing stop impersonation button
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 10:04:47 +02:00
2fe7f4cf04 web/user: fix final redirect after stage setup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 09:53:14 +02:00
04399bc8bb web/admin: fix settings link on user avatar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-17 09:53:04 +02:00
fcbcfbc3c0 website/docs: Minor LDAP and NGINX Documentation Updates (#1406)
* update LDAP documentation

* include domain level nginx forward auth example

* wrap in banner

* update placeholder
2021-09-17 09:47:27 +02:00
3e4ce62dfe build(deps-dev): bump pylint from 2.10.2 to 2.11.1 (#1409)
* build(deps-dev): bump pylint from 2.10.2 to 2.11.1

Bumps [pylint](https://github.com/PyCQA/pylint) from 2.10.2 to 2.11.1.
- [Release notes](https://github.com/PyCQA/pylint/releases)
- [Changelog](https://github.com/PyCQA/pylint/blob/main/ChangeLog)
- [Commits](https://github.com/PyCQA/pylint/compare/v2.10.2...v2.11.1)

---
updated-dependencies:
- dependency-name: pylint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

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

* root: update pylint 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-09-17 09:46:39 +02:00
d8292151e6 build(deps-dev): bump prettier from 2.4.0 to 2.4.1 in /website (#1407) 2021-09-17 09:17:20 +02:00
3d01a59b34 build(deps): bump prettier from 2.4.0 to 2.4.1 in /web (#1408) 2021-09-17 09:17:12 +02:00
5df15c4105 build(deps): bump boto3 from 1.18.42 to 1.18.43 (#1410) 2021-09-17 09:16:43 +02:00
75d695105d web: Update Web API Client version (#1405)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-16 23:44:53 +02:00
28189bdddf release: 2021.9.1-rc2 2021-09-16 23:23:36 +02:00
f6885c7cf8 website: update screenshots
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 23:20:05 +02:00
2c43f0824e tests/e2e: fix e2e tests for new URLs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 22:48:34 +02:00
13e2eea72f web/user: new end-user interface (#1404)
* web/user: migrate to top navbar

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

* web/user: prepare config from server

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

* re-sort

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

* remove old interface

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

* update issue template

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

* use notification badge

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

* web/user: re-add go-to-admin button

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

* *: fix remaining redirects directly to admin

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

* make settings better

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

* api: ensure sources and stages are sorted

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

* web/user: add sessions and consent

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

* providers/oauth2: add post wrapper to stage

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

* website/docs: add new interface to release notes

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 22:17:05 +02:00
9441be1ee2 interface split (#943) 2021-09-16 17:30:16 +02:00
d7ab2a362a ci: bump cache
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 13:46:11 +02:00
e920be3a72 ci: add versioning to cache keys
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 12:31:29 +02:00
f771383c4b cmd: fix outpost metrics not being set in embedded mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 12:09:12 +02:00
65c75f085a website/docs: add 2021.9.1-rc2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 11:06:03 +02:00
17503365f7 policies: improve error handling when using bindings without policy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 11:04:31 +02:00
ebf9f0ca63 stages/email: don't crash when testing stage does not exist
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 11:04:08 +02:00
ae26d2756f providers/saml: improved error handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 10:58:51 +02:00
124071f9be root: remove python requirement from pipfile
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 10:37:43 +02:00
471f7d9c62 outposts: add consistent name and type to metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 10:14:51 +02:00
a6a6b3bd06 outposts: add outpost_name label to metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 10:04:17 +02:00
48ad3dccda outposts/proxy: remove deprecated rs256
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 09:57:47 +02:00
341c58a722 core: fix token expiry for service accounts being only 30 minutes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 09:57:34 +02:00
9b04f2da48 website/docs: add notice for rancher cert
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-16 09:40:04 +02:00
f7a296544f web: Update Web API Client version (#1401)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-15 22:45:32 +02:00
78641a57ad web: update background image
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 22:43:03 +02:00
a77ff5ffec website/docs: add 2021.9 to sidebar
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 22:37:39 +02:00
bdd5e16db1 release: 2021.9.1-rc1 2021-09-15 20:20:54 +02:00
d4672bfe79 events: log parsed query string instead of just full path
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 20:15:04 +02:00
abd9fab41a api: fix call of sentry proxy task
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 19:39:58 +02:00
7c8bf42ef9 api: send proxied sentry events in background
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 19:12:20 +02:00
274b555912 api: add timeout for sentry proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 18:59:27 +02:00
916530f0d8 providers/oauth2: use access_code_validity for id_tokens generated when using an implicit flow, improve wording in web ui
closes #1369

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 17:14:53 +02:00
95efd47f65 root: remove asgi error handler
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 12:23:14 +02:00
90ecb1af7f outposts: fix service account's permissions being checked twice
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 09:55:27 +02:00
d7fdca1b44 stages/email: fix error when retrying email delivery after stage has been deleted
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-15 09:50:11 +02:00
37346763dc sources/oauth: Updating token url to new google url (#1397)
the present url goes to a 404
google openid (https://accounts.google.com/.well-known/openid-configuration) says the new url is `https://oauth2.googleapis.com/token`

not using the new url makes authentik fallback on the default auth flow
2021-09-15 09:15:19 +02:00
c35fd2755f build(deps): bump boto3 from 1.18.41 to 1.18.42 (#1398) 2021-09-15 08:40:42 +02:00
281e3a0518 build(deps): bump django-otp from 1.1.0 to 1.1.1 (#1399) 2021-09-15 08:40:34 +02:00
6349cdad2f web: Update Web API Client version (#1396)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-14 21:50:32 +02:00
ef341dd405 stages/user_write: add option to add newly created users to a group
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 21:45:34 +02:00
198e5ce642 outpost: fix crash when common keys are not defined in config
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 17:40:48 +02:00
923fbac5b0 website/docs: Fix docker-compose example (#1395)
`docker-compose exec` by default allocates a tty and does not support `-it`.

See https://docs.docker.com/compose/reference/exec/
2021-09-14 16:35:01 +02:00
5f28c7ace7 web: fix lint error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 14:44:57 +02:00
d96c96006f web/admin: open URLs group when urls are customisable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 14:38:52 +02:00
3ddf2d6f85 sources/oauth: fix type lookup for openid not matching
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 14:38:35 +02:00
ba6849f29c *: remove string.format()
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 12:06:47 +02:00
942170f902 Revert "sources/oauth: fix access_token being sent as query param and not authorization header"
This reverts commit 248f993541.
2021-09-14 11:59:32 +02:00
248f993541 sources/oauth: fix access_token being sent as query param and not authorization header
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 11:07:36 +02:00
56d40bddd0 web/admin: make token list more consistent
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 10:04:15 +02:00
3a700a449a sources/oauth: don't try to load azure AD user ID as UUID
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 09:33:44 +02:00
a20f552bcf web/flows: fix alignment for duo authenticator
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-14 09:23:10 +02:00
32331a56eb build(deps): bump django-otp from 1.0.6 to 1.1.0 (#1394)
Bumps [django-otp](https://github.com/django-otp/django-otp) from 1.0.6 to 1.1.0.
- [Release notes](https://github.com/django-otp/django-otp/releases)
- [Changelog](https://github.com/django-otp/django-otp/blob/master/CHANGES.rst)
- [Commits](https://github.com/django-otp/django-otp/compare/v1.0.6...v1.1.0)

---
updated-dependencies:
- dependency-name: django-otp
  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-09-14 09:23:01 +02:00
d752b7e41c build(deps): bump @typescript-eslint/parser in /web (#1392) 2021-09-14 08:36:32 +02:00
0b4223c6ca build(deps): bump @typescript-eslint/eslint-plugin in /web (#1391) 2021-09-14 08:35:30 +02:00
a3ec5c13f0 build(deps): bump boto3 from 1.18.40 to 1.18.41 (#1393) 2021-09-14 08:35:05 +02:00
128b582dd6 website/docs: fix inconsistent version number
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 22:05:35 +02:00
e59ede5422 website/docs: fix ports for current outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 22:03:02 +02:00
6d08ba2513 root: update go api client
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 18:36:12 +02:00
23444f4df0 core: fix lint error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 18:19:28 +02:00
3338f7a401 website/docs: prepare 2021.9
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 18:18:14 +02:00
b126519275 web: Update Web API Client version (#1389)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-13 18:10:24 +02:00
71e68b498e core: optimise groups api by removing member superuser status
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 18:06:37 +02:00
fb267ee223 tenants: optimise db queries in middleware
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 17:54:37 +02:00
8e59b06611 lifecycle: migrate to gunicorn instead of runserver
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 17:54:23 +02:00
a4b3519428 api: fix possible error in sentry proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-13 16:36:04 +02:00
4895fc3bbb build(deps): bump typescript from 4.4.2 to 4.4.3 in /web (#1387) 2021-09-13 08:39:24 +02:00
3daabd6fa8 build(deps): bump boto3 from 1.18.39 to 1.18.40 (#1388) 2021-09-13 08:38:58 +02:00
9fccb14065 Merge branch 'update-web-api-client'
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	web/package-lock.json
#	web/package.json
2021-09-12 01:09:40 +02:00
12efe94fd1 web: Update Web API Client version
Signed-off-by: GitHub <noreply@github.com>
2021-09-11 23:07:32 +00:00
375ef27b9f web: Update Web API Client version
Signed-off-by: GitHub <noreply@github.com>
2021-09-12 01:06:28 +02:00
9a7fa39de4 events: allow setting a mapping for webhook transport to customise request payloads
closes #1383

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-12 01:05:42 +02:00
c779ad2e3b *: use common user agent for all outgoing requests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-11 21:08:26 +02:00
7e7ef289ba admin: migrate to new update check, add option to disable update check
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-11 20:35:23 +02:00
223d9ad414 outposts/proxy: fix upstream ssl certificate not being ignored if configured to do so
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-11 19:30:21 +02:00
948ea7b087 web: Update Web API Client version (#1382)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-11 19:24:18 +02:00
bf771f8b6c release: 2021.8.5 2021-09-11 19:20:13 +02:00
6dc8aa396c Update index.md (#1381) 2021-09-11 00:11:48 +02:00
92a48f9dc6 build(deps): bump sqlparse from 0.4.1 to 0.4.2 (#1380) 2021-09-10 20:32:47 +02:00
d0ad9fcb1f web: Update Web API Client version (#1379)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-10 18:19:29 +02:00
539e6deca5 root: use go api client from github (#1378)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 16:18:11 +00:00
df4c8003b8 api: fix items of list fields having nullable set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 18:15:59 +02:00
169e748a78 website: prepare go vanity URL
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 17:18:15 +02:00
39b365c6ae sources/oauth: don't cancel flow when redirecting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 16:36:10 +02:00
9a79bab43d outposts/proxy: fix redirect URL error due to callback url not being joined correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 16:19:29 +02:00
e229eda96e outposts/controllers/kubernetes: don't create service monitor for embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 15:59:39 +02:00
4448145aa9 providers/proxy: use auth/traefik subpath
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 13:53:04 +02:00
3d042e708a outposts/proxy: always redirect on forward_auth for traefik
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 12:43:57 +02:00
2428d5f1c2 outpost: update global outpost config on refresh
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 12:18:19 +02:00
f1dc2b4d2a web: Update Web API Client version (#1377)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-10 11:41:12 +02:00
7dfbcdbb81 stages/authenticator_duo: add API to "import" devices from duo
closes #1371

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-10 11:35:09 +02:00
5fd4f56fa2 build(deps-dev): bump prettier from 2.3.2 to 2.4.0 in /website (#1372) 2021-09-10 08:41:38 +02:00
b9d5ba6b0a build(deps): bump @babel/preset-env from 7.15.4 to 7.15.6 in /web (#1373) 2021-09-10 08:41:29 +02:00
2a4cb07ba8 build(deps): bump prettier from 2.3.2 to 2.4.0 in /web (#1374) 2021-09-10 08:41:20 +02:00
7939286176 build(deps): bump golang from 1.17.0 to 1.17.1 (#1375) 2021-09-10 08:41:10 +02:00
46ef49b897 build(deps): bump boto3 from 1.18.38 to 1.18.39 (#1376) 2021-09-10 08:40:58 +02:00
b923d85f6a web: allow duplicate messages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 20:09:31 +02:00
2862b4ecfb core: remove ?v from static files
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 20:09:12 +02:00
094acc62f0 web: ignore network error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 19:58:43 +02:00
13d17dc729 lib: fix default listening port for metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 16:40:39 +02:00
5cf3a13ca8 flows: fix invalid parameter in tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 16:36:51 +02:00
d0898a3869 flows: ensure all StageViews accept post, add tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 16:30:14 +02:00
7158c9d2ea core: metrics v2 (#1370)
* outposts: add ldap metrics, move ping to 9100

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

* outpost: add flow_executor metrics

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

* use port 9300 for metrics, add core metrics port

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

* outposts/controllers/k8s: add service monitor creation support

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 15:52:24 +02:00
c5cf17b60b lifecycle: fix worker startup error when docker socket's group is not called docker
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 15:24:35 +02:00
da58796768 providers/proxy: fix defaults for old proxy providers (load providers directly)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 13:54:24 +02:00
d98499a3fa providers/proxy: fix defaults for old proxy providers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 13:26:36 +02:00
e5944567e8 outposts/proxy: fix url not being substituted for sign_out
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 11:00:58 +02:00
d296c12d01 outposts/proxy: fix redirect when using forward_auth mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 10:56:20 +02:00
4c3a9e69f2 outposts/proxy: fix securecookie: no codecs provided error with redis
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-09 10:23:46 +02:00
eb2540a3c8 build(deps): bump boto3 from 1.18.37 to 1.18.38 (#1367) 2021-09-09 08:20:41 +02:00
bf9a3615d9 build(deps): bump github.com/pires/go-proxyproto from 0.6.0 to 0.6.1 (#1368) 2021-09-09 08:20:22 +02:00
33fb22e3e7 ci: include build sha in docker tag
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 23:03:32 +02:00
f3ff398a44 providers/proxy: add metrics port to controllers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 23:01:22 +02:00
533eb59a04 outposts/controllers: re-create service when mismatched ports to prevent errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 23:00:53 +02:00
8ca29f6d49 Revert "outpost/proxy: set samesite none"
This reverts commit f7afb60c1f.
2021-09-08 22:56:24 +02:00
0a33d38adf outpost/proxy: fix prometheus errors
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 22:41:41 +02:00
f7afb60c1f outpost/proxy: set samesite none
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 22:06:44 +02:00
b9c605bf1a outpost/proxy: fix double slash when trailing slash in authentik_host
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 22:03:41 +02:00
2983adc719 outpost/proxyv2: fix redirect to localhost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 21:07:16 +02:00
502393ee56 outpost/proxyv2: allow port offset via yaml
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 21:07:06 +02:00
121bba1d9f web: Update Web API Client version (#1366) 2021-09-08 20:23:01 +02:00
3c1b70c355 outposts/proxyv2 (#1365)
* outposts/proxyv2: initial commit

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

add rs256

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

more stuff

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

add forward auth an sign_out

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

match cookie name

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

re-add support for rs256 for backwards compat

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

add error handler

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

ensure unique user-agent is used

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

set cookie duration based on id_token expiry

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

build proxy v2

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

add ssl

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

add basic auth and custom header support

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

add application cert loading

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

implement whitelist

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

add redis

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

migrate embedded outpost to v2

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

remove old proxy

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

providers/proxy: make token expiration configurable

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

add metrics

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

fix tests

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

* providers/proxy: only allow one redirect URI

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

* fix docker build for proxy

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

* remove default port offset

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

* add AUTHENTIK_HOST_BROWSER

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

* tests: fix e2e/integration tests not using proper tags

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

* remove references of old port

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

* fix user_attributes not being loaded correctly

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

* cleanup dependencies

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

* cleanup

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 18:04:56 +00:00
27508dd1f0 build(deps): bump @lingui/core from 3.10.4 to 3.11.1 in /web (#1363) 2021-09-08 08:38:00 +02:00
6d962dbdf3 build(deps): bump @lingui/macro from 3.10.2 to 3.11.1 in /web (#1362) 2021-09-08 08:36:56 +02:00
9194e6368a build(deps): bump @lingui/cli from 3.10.2 to 3.11.1 in /web (#1361) 2021-09-08 08:36:46 +02:00
917fb7d626 build(deps): bump boto3 from 1.18.36 to 1.18.37 (#1364) 2021-09-08 08:36:12 +02:00
3cf5794b96 web/admin: increase default expiry for refresh tokens
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-08 00:12:18 +02:00
631b0a1819 outpost/proxy: improve error logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 23:33:48 +02:00
6662dcc4b0 Revert "web: replace deprecated dependencies"
This reverts commit 95db54b819.
2021-09-07 23:25:38 +02:00
95db54b819 web: replace deprecated dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 23:16:30 +02:00
bc7d5042df outpost/proxy: use common template for proxy error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 16:44:15 +02:00
de3e1c3dbc sources/oauth: fix FlowExecutor view call
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 11:39:03 +02:00
3c6aac5435 sources/oauth: prevent potentially confidential data from being logged
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 11:05:18 +02:00
eeb755ab7d root: show location header in logs when redirecting
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 11:04:00 +02:00
70d0dd51a5 sources/oauth: cancel currently active flows before redirecting out
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 11:03:45 +02:00
073dd8b560 web/admin: fix notification clear all not triggering render
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 10:23:55 +02:00
b5d2924d46 website/docs: update 2021.8.5
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 10:10:43 +02:00
597e279f34 ci: fix old node version in release ci
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-07 10:07:36 +02:00
fc28def83d build(deps): bump @typescript-eslint/eslint-plugin in /web (#1358) 2021-09-07 08:42:57 +02:00
f6efdfded4 build(deps): bump @typescript-eslint/parser in /web (#1357) 2021-09-07 08:31:13 +02:00
91312496e0 ci: simplify testspace setup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-06 16:52:21 +02:00
b557b4337d build(deps): bump @babel/core from 7.15.4 to 7.15.5 in /web (#1351) 2021-09-06 08:36:40 +02:00
bfde186aa0 build(deps): bump actions/cache from 1 to 2.1.6 (#1352) 2021-09-06 08:36:32 +02:00
2bd75dd1a9 build(deps): bump xmlsec from 1.3.11 to 1.3.12 (#1353) 2021-09-06 08:36:16 +02:00
27ab31a9b0 build(deps): bump boto3 from 1.18.35 to 1.18.36 (#1354) 2021-09-06 08:35:56 +02:00
44a8b737d9 build(deps): bump drf-spectacular from 0.18.1 to 0.18.2 (#1355) 2021-09-06 08:35:45 +02:00
b939ee7a09 website/docs: use kubectl exec with deployment, add note for backup version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1349
2021-09-05 20:25:42 +02:00
0bae550520 root: include authentik version in backup naming
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-05 20:25:02 +02:00
b5cc2f2bda website/docs: add missing ENV, changed k8s beta instructions (#1350)
* fixed IsActive and IsSuperuser return string

IsActive and IsSuperuser attributes were interchanged.

* updated docs

Co-authored-by: Tobias Mandjik <tobias.mandjik@linogics.io>
2021-09-05 19:58:42 +02:00
9ad4cf1db9 outposts/ldap: improve logging of client IPs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-05 19:47:30 +02:00
9dbafaaea2 web: Update Web API Client version (#1348)
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-09-04 22:49:16 +02:00
2db8b07578 events: add mark_all_seen
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 22:08:12 +02:00
7c1a7bfd9d ci: use native kind action to test integration
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 16:06:44 +02:00
b7ef076798 outposts: add expected outpost replica count to metrics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 15:56:57 +02:00
37c29a073e policies/password: fix symbols not being checked correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 15:21:48 +02:00
0c288ea64b ci: cache webui for e2e tests
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 15:21:24 +02:00
2476475174 ci: attempt to cache pipenv (#1347)
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:55:54 +02:00
71913c8164 website/docs: fix typos in vikunja docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:38:35 +02:00
6ec8432217 policies/password: don't use regex for symbol detection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:36:01 +02:00
7a12c0e4d1 web/admin: fix user selection in token form
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:33:40 +02:00
23a7eba16b website/docs: add 8.5 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:09:11 +02:00
3ba84a8e8b stages/identification: fix empty user_fields query returning first user
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 14:07:14 +02:00
75476217a0 internal: fix web requests not having a logger set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 13:52:47 +02:00
7771c0b905 internal: fix font loading errors on safari
closes #1057

for some reason safari appends the relative font path to the document URL not to the stylesheet URL. Since I don't want to build a fully custom patternfly base css file, this mounts the static files where safari expects them

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 13:50:29 +02:00
3378e82ec7 root: fix is_secure with safari on debug environments
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 13:45:50 +02:00
126e43dea4 internal: disable directory listing on static files
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 13:40:29 +02:00
f725009530 web/flows: fix display error when using IdentificationStage without input fields
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-04 13:06:37 +02:00
70d1e3a0cb outpost: fix spans being sent without parent context
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 18:17:08 +02:00
e751ce1220 root: update badges
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 18:11:13 +02:00
e09a27cf87 events: remove authentik_events gauge
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 18:04:26 +02:00
06fbf44724 root: update security.md
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 17:26:10 +02:00
200e409d91 core: minor query optimization
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 14:02:57 +02:00
5e5854e256 ci: fix invalid workflow
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 10:58:42 +02:00
3df8bcfc9c web: Update Web API Client version (#1345)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-03 10:53:59 +02:00
e76c14f9e0 ci: run on pr and improve checking for push
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 10:53:39 +02:00
6b6748b1c7 web/admin: show applications instead of providers in outpost form
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 10:43:21 +02:00
d92d8e6dbb api: add additional filters for ldap and proxy providers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 10:43:09 +02:00
c2b9dc5c75 api: cache schema, fix server urls
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-03 10:23:14 +02:00
5c1d27de2b build(deps): bump docker from 5.0.1 to 5.0.2 (#1343) 2021-09-03 08:46:33 +02:00
6ab9e7cd68 build(deps): bump @babel/core from 7.15.0 to 7.15.4 in /web (#1339) 2021-09-03 08:46:23 +02:00
3ef56e9ec1 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1338) 2021-09-03 08:46:05 +02:00
6d8d157772 build(deps): bump @babel/plugin-proposal-decorators in /web (#1340) 2021-09-03 08:44:36 +02:00
cadd466eec build(deps): bump @docusaurus/preset-classic in /website (#1341) 2021-09-03 08:44:27 +02:00
3fea0c1e49 build(deps): bump @babel/preset-env from 7.15.0 to 7.15.4 in /web (#1342) 2021-09-03 08:44:16 +02:00
4c58201adc build(deps): bump boto3 from 1.18.34 to 1.18.35 (#1344) 2021-09-03 08:44:02 +02:00
4fb4e72624 web: Update Web API Client version (#1337)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-02 21:34:04 +02:00
276d8fe5cf release: 2021.8.4 2021-09-02 20:21:21 +02:00
92ce5f0931 web: improve error display when only {'detail'} is returned
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 19:55:37 +02:00
7fea20375f *: fix tests not using APITestCase
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 19:14:21 +02:00
d4d4034d2c web: Update Web API Client version (#1336)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-02 17:42:55 +02:00
f0db408699 api: add v3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 17:40:02 +02:00
5e200655d9 web: Update Web API Client version (#1335)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-02 17:13:16 +02:00
d5d1f2a645 web: show version in logs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 17:10:43 +02:00
cc5cc43baa api: fix sentry endpoint not working due to mime-media
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 16:56:53 +02:00
e512f085db root: allow enabling s3 backup ssl verification
closes #1332

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-02 09:41:55 +02:00
f323c01bd8 build(deps): bump django from 3.2.6 to 3.2.7 (#1333) 2021-09-02 09:12:24 +02:00
f56cacb406 build(deps): bump boto3 from 1.18.33 to 1.18.34 (#1334) 2021-09-02 09:12:03 +02:00
eaecd31e9f ci: always run codecov and testspace
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:59:51 +02:00
36989d82e1 ci: merge on testspace
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:35:17 +02:00
50777d9022 ci: re-add testspace (#1331)
* ci: re-add testspace

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

* ci: fix double k3d

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:33:10 +02:00
a15571bd3e outposts/proxy: detect empty authentik_host
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 22:09:07 +02:00
26fd66d831 stages/authenticator_validate: fix variable shadowing, optimization
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:54:54 +02:00
0be873025a ci: fix bumpversion path
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:38:04 +02:00
28ada49910 website/docs: final 2021.8.4 release notes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:37:00 +02:00
4fc8e61f8c stages/authenticator_validate: show single button for multiple webauthn authenticators
tested with browser + yubikey 5

closes #1096

The order of allowCredentials doesn't seem to matter, chrome seems to always choose the internal authenticator first.

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:28:52 +02:00
7d26ea1a9c web/admin: fix list of webauthn devices not updating after rename
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 19:05:18 +02:00
3a58dc62e1 ci: fix missing branch
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 18:34:57 +02:00
71fe7bc827 ci: fix sha being used instead of timestamp
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 17:10:42 +02:00
933336c38b ci: fix images not being pushed with correct tags
* ci: debug

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

* ci: fix branch and sha

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 16:19:29 +02:00
371feb9a31 ci: fix images not being pushed
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 15:07:13 +02:00
95a2fd3c9e web: Update Web API Client version (#1327)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-09-01 14:48:48 +02:00
17cb76c334 stages/invitation: fix invitation not inheriting ExpiringModel
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 14:25:19 +02:00
88f0dfc8cc web/admin: fallback for invitation list on first load
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 13:33:05 +02:00
f82aada23b web/admin: fix flow executor not opening in new tab
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-09-01 13:19:09 +02:00
ecaee92634 build(deps): bump @sentry/tracing from 6.11.0 to 6.12.0 in /web (#1322)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.11.0 to 6.12.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.11.0...6.12.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-09-01 09:26:53 +02:00
89252ec47b build(deps): bump @sentry/tracing from 6.11.0 to 6.12.0 in /website (#1320)
Bumps [@sentry/tracing](https://github.com/getsentry/sentry-javascript) from 6.11.0 to 6.12.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.11.0...6.12.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-09-01 09:26:33 +02:00
f0f25ab291 build(deps): bump @sentry/react from 6.11.0 to 6.12.0 in /website (#1321) 2021-09-01 08:40:07 +02:00
e4d0fec15a build(deps): bump @sentry/browser from 6.11.0 to 6.12.0 in /web (#1323) 2021-09-01 08:39:56 +02:00
6b10baf086 build(deps): bump docker from 5.0.0 to 5.0.1 (#1324) 2021-09-01 08:39:21 +02:00
f148b5d341 build(deps): bump boto3 from 1.18.32 to 1.18.33 (#1326) 2021-09-01 08:39:12 +02:00
1471ff8940 build(deps): bump drf-spectacular from 0.18.0 to 0.18.1 (#1325) 2021-09-01 08:39:01 +02:00
d9a6ec2ac0 webiste/docs: update extensionvs/v1beta ingress
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-31 21:11:01 +02:00
5745ffa0a8 ci: don't login to docker on forks
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-31 09:31:10 +02:00
b26202db35 build(deps): bump @typescript-eslint/parser in /web (#1316) 2021-08-31 08:42:14 +02:00
6318577a51 build(deps): bump @typescript-eslint/eslint-plugin in /web (#1317) 2021-08-31 08:16:59 +02:00
6a2cd45847 build(deps-dev): bump pytest from 6.2.4 to 6.2.5 (#1318) 2021-08-31 08:16:44 +02:00
ef5cea2c01 build(deps): bump boto3 from 1.18.31 to 1.18.32 (#1319) 2021-08-31 08:16:32 +02:00
69f4d54bae ci: migrate ci to gh actions (#1315) 2021-08-30 20:21:15 +02:00
b1eec5a7d2 outposts/proxy: add more logging
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 17:18:52 +02:00
1b8271d767 flows: disable compatibility_mode by default
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 17:18:43 +02:00
3e9f5ec5ef providers/proxy: improve error handling for non-tls ingresses
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 14:43:57 +02:00
63f57b6a77 events: improve logging for task exceptions
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 14:43:44 +02:00
a016f99450 core: fix user_obj being empty on token API
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-30 12:51:17 +02:00
adc18b2991 build(deps): bump boto3 from 1.18.30 to 1.18.31 (#1314)
Bumps [boto3](https://github.com/boto/boto3) from 1.18.30 to 1.18.31.
- [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.18.30...1.18.31)

---
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-08-30 09:12:58 +02:00
e37a326b95 website/docs: prepare 8.4 docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 22:12:49 +02:00
048467e97d outpost/ldap: delay user information removal upon closing of connection
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 21:13:46 +02:00
cc2cd6919f outpost/embedded: only send requests for non-akprox paths when we're doing proxy mode
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 21:13:28 +02:00
0c6e781e5b providers/proxy: fix traefik middleware being generated with wrong ports for embedded outposts
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 20:49:11 +02:00
7294d8fca5 website/docs: add note for cross-namespace reference in traefik
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 20:46:17 +02:00
16ec5680b4 web: Update Web API Client version (#1313)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-08-29 19:51:10 +02:00
87920fb1d7 website/docs: add docs for websocket connections
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:49:18 +02:00
523b96a6d2 api: add basic rate limiting for sentry endpoint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:33:18 +02:00
45731d8069 cmd: add option to disable embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 19:19:13 +02:00
e872371970 website/docs: add embedded outpost docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 14:43:13 +02:00
08e8cf850a web/flows: fix FlowExecutor not updating when challenge changes from outside
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 13:49:57 +02:00
b1ed2154ac policies/password: fix PasswordStage not being usable with prompt stages, rework validation logic
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-29 00:40:36 +02:00
7ef2aa3eb9 web: Update Web API Client version (#1312) 2021-08-28 19:08:38 +02:00
160139813d release: 2021.8.3 2021-08-28 16:58:44 +02:00
582ad92c76 outposts/k8s: improve error handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 14:58:26 +02:00
f61736e3d1 stages/identification: add error handling when password isn't set
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 12:54:10 +02:00
eb02c96281 website/docs: make it clearer to use context[]
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-28 12:53:57 +02:00
8619552920 website/docs: prepare 2021.8.3
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 23:12:53 +02:00
6237352e25 web/flows: fix checkboxes not being rendered correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 23:09:53 +02:00
2d8b4f543b providers/proxy: fix url parsing for traefik labels on docker containers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 22:21:16 +02:00
8542dc10ab providers/proxy: fix docker container labels not being inherited correctly
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 20:20:34 +02:00
c55b63337c web/flows: fix post-challenge updates not always being called by using setter
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:45:23 +02:00
12ddee3bb6 outpost: add additional labels to docker container
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:26:27 +02:00
dc41d0af27 outposts: add configurable docker_network for outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 19:26:11 +02:00
3323b50036 web/flows: also check for redirects as result of posting challenge
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 10:08:15 +02:00
8acb15a7fd outpost: fix flow executor not sending password for identification stage
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 09:43:07 +02:00
f601e04b38 web/flows: assign location from redirect challenge in request handler not render
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-27 09:43:00 +02:00
f50529cb5b build(deps): bump @docusaurus/preset-classic in /website (#1307)
Bumps [@docusaurus/preset-classic](https://github.com/facebook/docusaurus/tree/HEAD/packages/docusaurus-preset-classic) from 2.0.0-beta.4 to 2.0.0-beta.5.
- [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.5/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-08-27 09:20:09 +02:00
3f1b6f9ed4 build(deps): bump typescript from 4.3.5 to 4.4.2 in /web (#1306) 2021-08-27 08:36:43 +02:00
f1ab0f4314 build(deps): bump @patternfly/patternfly from 4.125.3 to 4.132.2 in /web (#1308) 2021-08-27 08:36:34 +02:00
4d1129f385 build(deps): bump boto3 from 1.18.29 to 1.18.30 (#1310) 2021-08-27 08:36:19 +02:00
03ac9c6e16 build(deps): bump @docusaurus/plugin-client-redirects in /website (#1309) 2021-08-27 08:36:11 +02:00
c0839924f1 build(deps): bump github.com/go-openapi/runtime from 0.19.30 to 0.19.31 (#1311) 2021-08-27 08:35:57 +02:00
91e3aa760a web: Update Web API Client version (#1305)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2021-08-26 19:06:13 +02:00
5c0681d57b website/docs: add 2021.8.2 docs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2021-08-26 18:56:42 +02:00
597 changed files with 18863 additions and 10498 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.8.2
current_version = 2021.9.8
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
@ -23,7 +23,7 @@ values =
[bumpversion:file:schema.yml]
[bumpversion:file:.github/workflows/release.yml]
[bumpversion:file:.github/workflows/release-publish.yml]
[bumpversion:file:authentik/__init__.py]

View File

@ -27,7 +27,7 @@ If applicable, add screenshots to help explain your problem.
Output of docker-compose logs or kubectl logs respectively
**Version and Deployment (please complete the following information):**
- authentik version: [e.g. 0.10.0-stable]
- authentik version: [e.g. 2021.8.5]
- Deployment: [e.g. docker-compose, helm]
**Additional context**

View File

@ -20,7 +20,7 @@ If applicable, add screenshots to help explain your problem.
Output of docker-compose logs or kubectl logs respectively
**Version and Deployment (please complete the following information):**
- authentik version: [e.g. 0.10.0-stable]
- authentik version: [e.g. 2021.8.5]
- Deployment: [e.g. docker-compose, helm]
**Additional context**

1
.github/codespell-words.txt vendored Normal file
View File

@ -0,0 +1 @@
keypair

309
.github/workflows/ci-main.yml vendored Normal file
View File

@ -0,0 +1,309 @@
name: authentik-ci-main
on:
push:
branches:
- master
- next
- version-*
paths-ignore:
- website
pull_request:
branches:
- master
env:
POSTGRES_DB: authentik
POSTGRES_USER: authentik
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:
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'
- name: prepare
run: |
scripts/ci_prepare.sh
npm install -g pyright@1.1.136
- name: run bandit
run: pipenv run pyright e2e lifecycle
test-migrations:
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 migrations
run: pipenv run python -m lifecycle.migrate
test-migrations-from-stable:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: checkout stable
run: |
# Copy current, latest config to local
cp authentik/lib/default.yml local.env.yml
git checkout $(git describe --abbrev=0 --match 'version/*')
# - 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 migrations to stable
run: pipenv run python -m lifecycle.migrate
- name: prepare variables
id: ev
run: |
python ./scripts/gh_do_set_branch.py
- name: checkout current code
run: |
set -x
git fetch
git checkout ${{ steps.ev.outputs.branchName }}
pipenv sync --dev
- name: migrate to latest
run: pipenv run python -m lifecycle.migrate
test-unittest:
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
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: run unittest
run: |
pipenv run make test
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace [unittest]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
test-integration:
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
- uses: testspace-com/setup-testspace@v1
with:
domain: ${{github.repository_owner}}
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1.2.0
- name: run integration
run: |
pipenv run make test-integration
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace [integration]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
test-e2e:
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.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
docker-compose -f tests/e2e/ci.docker-compose.yml up -d
- id: cache-web
uses: actions/cache@v2.1.6
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
pipenv run coverage xml
- name: run testspace
if: ${{ always() }}
run: |
testspace [e2e]unittest.xml --link=codecov
- if: ${{ always() }}
uses: codecov/codecov-action@v2
build:
needs:
- lint-pylint
- lint-black
- lint-isort
- lint-bandit
- lint-pyright
- test-migrations
- test-migrations-from-stable
- test-unittest
- test-integration
- test-e2e
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.HARBOR_USERNAME }}
run: |
python ./scripts/gh_do_set_branch.py
- name: Login to Container Registry
uses: docker/login-action@v1
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
registry: beryju.org
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: ${{ steps.ev.outputs.shouldBuild == 'true' }}
tags: |
beryju.org/authentik/server:gh-${{ steps.ev.outputs.branchName }}
beryju.org/authentik/server:gh-${{ steps.ev.outputs.branchName }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.sha }}
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}

69
.github/workflows/ci-outpost.yml vendored Normal file
View File

@ -0,0 +1,69 @@
name: authentik-ci-outpost
on:
push:
branches:
- master
- next
- version-*
pull_request:
branches:
- master
jobs:
lint-golint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
with:
go-version: '^1.16.3'
- name: Run linter
run: |
# Create folder structure for go embeds
mkdir -p web/dist
mkdir -p website/help
touch web/dist/test website/help/test
docker run \
--rm \
-v $(pwd):/app \
-w /app \
golangci/golangci-lint:v1.39.0 \
golangci-lint run -v --timeout 200s
build:
needs:
- lint-golint
strategy:
matrix:
type:
- proxy
- ldap
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: prepare variables
id: ev
env:
DOCKER_USERNAME: ${{ secrets.HARBOR_USERNAME }}
run: |
python ./scripts/gh_do_set_branch.py
- name: Login to Container Registry
uses: docker/login-action@v1
if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
with:
registry: beryju.org
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Building Docker Image
uses: docker/build-push-action@v2
with:
push: ${{ steps.ev.outputs.shouldBuild == 'true' }}
tags: |
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.branchName }}
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.branchName }}-${{ steps.ev.outputs.timestamp }}
beryju.org/authentik/outpost-${{ matrix.type }}:gh-${{ steps.ev.outputs.sha }}
file: ${{ matrix.type }}.Dockerfile
build-args: |
GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}

89
.github/workflows/ci-web.yml vendored Normal file
View File

@ -0,0 +1,89 @@
name: authentik-ci-web
on:
push:
branches:
- master
- next
- version-*
pull_request:
branches:
- master
jobs:
lint-eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: Eslint
run: |
cd web
npm run lint
lint-prettier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: prettier
run: |
cd web
npm run prettier-check
lint-lit-analyse:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: lit-analyse
run: |
cd web
npm run lit-analyse
build:
needs:
- lint-eslint
- lint-prettier
- lint-lit-analyse
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: |
cd web
npm install
- name: Generate API
run: make gen-web
- name: build
run: |
cd web
npm run build

View File

@ -33,14 +33,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.8.2,
beryju/authentik:2021.9.8,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.8.2,
ghcr.io/goauthentik/server:2021.9.8,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.9.8', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -75,14 +75,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.8.2,
beryju/authentik-proxy:2021.9.8,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.8.2,
ghcr.io/goauthentik/proxy:2021.9.8,
ghcr.io/goauthentik/proxy:latest
file: proxy.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.9.8', 'rc') }}
run: |
docker pull beryju/authentik-proxy:latest
docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable
@ -117,14 +117,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.8.2,
beryju/authentik-ldap:2021.9.8,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.8.2,
ghcr.io/goauthentik/ldap:2021.9.8,
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.8.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.9.8', 'rc') }}
run: |
docker pull beryju/authentik-ldap:latest
docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable
@ -157,9 +157,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup Node.js environment
uses: actions/setup-node@v2.4.0
uses: actions/setup-node@v2
with:
node-version: 12.x
node-version: '16'
- name: Build web api client and web ui
run: |
export NODE_ENV=production
@ -175,7 +175,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.8.2
version: authentik@2021.9.8
environment: beryjuorg-prod
sourcemaps: './web/dist'
url_prefix: '~/static/dist'

View File

@ -27,7 +27,7 @@ jobs:
docker-compose run -u root server test
- name: Extract version number
id: get_version
uses: actions/github-script@v4.1
uses: actions/github-script@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@ -12,7 +12,7 @@ jobs:
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v2
with:
node-version: '16.x'
node-version: '16'
registry-url: 'https://registry.npmjs.org'
- name: Generate API Client
run: make gen-web

View File

@ -117,7 +117,7 @@ This section guides you through submitting a bug report for authentik. Following
Whenever authentik encounters an error, it will be logged as an Event with the type `system_exception`. This event type has a button to directly open a pre-filled GitHub issue form.
This form will have the full stack trace of the error that ocurred and shouldn't contain any sensitive data.
This form will have the full stack trace of the error that occurred and shouldn't contain any sensitive data.
### Suggesting Enhancements

View File

@ -1,5 +1,5 @@
# Stage 1: Lock python dependencies
FROM python:3.9-slim-buster as locker
FROM docker.io/python:3.9-slim-buster as locker
COPY ./Pipfile /app/
COPY ./Pipfile.lock /app/
@ -11,38 +11,23 @@ RUN pip install pipenv && \
pipenv lock -r --dev-only > requirements-dev.txt
# Stage 2: Build website
FROM node as website-builder
FROM docker.io/node as website-builder
COPY ./website /static/
ENV NODE_ENV=production
RUN cd /static && npm i && npm run build-docs-only
# Stage 3: Generate API Client
FROM openapitools/openapi-generator-cli as go-api-builder
COPY ./schema.yml /local/schema.yml
RUN docker-entrypoint.sh generate \
--git-host goauthentik.io \
--git-repo-id outpost \
--git-user-id api \
-i /local/schema.yml \
-g go \
-o /local/api \
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true && \
rm -f /local/api/go.mod /local/api/go.sum
# Stage 4: Build webui
FROM node as web-builder
# Stage 3: Build webui
FROM docker.io/node as web-builder
COPY ./web /static/
ENV NODE_ENV=production
RUN cd /static && npm i && npm run build
# Stage 5: Build go proxy
FROM golang:1.17.0 AS builder
# Stage 4: Build go proxy
FROM docker.io/golang:1.17.1 AS builder
WORKDIR /work
@ -52,7 +37,6 @@ 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=go-api-builder /local/api api
COPY ./cmd /work/cmd
COPY ./web/static.go /work/web/static.go
COPY ./website/static.go /work/website/static.go
@ -62,8 +46,8 @@ COPY ./go.sum /work/go.sum
RUN go build -o /work/authentik ./cmd/server/main.go
# Stage 6: Run
FROM python:3.9-slim-buster
# Stage 5: Run
FROM docker.io/python:3.9-slim-buster
WORKDIR /
COPY --from=locker /app/requirements.txt /
@ -96,7 +80,12 @@ COPY ./lifecycle/ /lifecycle
COPY --from=builder /work/authentik /authentik-proxy
USER authentik
ENV TMPDIR /dev/shm/
ENV PYTHONUBUFFERED 1
ENV PYTHONUNBUFFERED 1
ENV prometheus_multiproc_dir /dev/shm/
ENV PATH "/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/lifecycle"
HEALTHCHECK --interval=30s --timeout=30s --start-period=60s --retries=3 CMD [ "/lifecycle/ak", "healthcheck" ]
ENTRYPOINT [ "/lifecycle/ak" ]

View File

@ -7,8 +7,6 @@ NPM_VERSION = $(shell python -m scripts.npm_version)
all: lint-fix lint test gen
test-integration:
k3d cluster create || exit 0
k3d kubeconfig write -o ~/.kube/config --overwrite
coverage run manage.py test -v 3 tests/integration
test-e2e:
@ -22,6 +20,7 @@ test:
lint-fix:
isort authentik tests lifecycle
black authentik tests lifecycle
codespell -I .github/codespell-words.txt -S 'web/src/locales/**' -w authentik internal cmd web/src website/src
lint:
pyright authentik tests lifecycle
@ -61,13 +60,13 @@ gen-outpost:
-i /local/schema.yml \
-g go \
-o /local/api \
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true
--additional-properties=packageName=api,enumClassPrefix=true,useOneOfDiscriminatorLookup=true,disallowAdditionalPropertiesIfNotPresent=false
rm -f api/go.mod api/go.sum
gen: gen-build gen-clean gen-web gen-outpost
gen: gen-build gen-clean gen-web
migrate:
python -m lifecycle.migrate
run:
go run -v cmd/server/main.go
WORKERS=1 go run -v cmd/server/main.go

View File

@ -48,9 +48,7 @@ duo-client = "*"
ua-parser = "*"
deepmerge = "*"
colorama = "*"
[requires]
python_version = "3.9"
codespell = "*"
[dev-packages]
bandit = "*"

457
Pipfile.lock generated
View File

@ -1,12 +1,10 @@
{
"_meta": {
"hash": {
"sha256": "f0befa9b3dacc1c3363b9442fa7a43f6be2c46a8fcb80a994230d288a384e54d"
"sha256": "babb6061c555f8f239f00210b2a0356763bdaaca2f3d704cf3444891b84db84d"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"requires": {},
"sources": [
{
"name": "pypi",
@ -122,27 +120,27 @@
},
"boto3": {
"hashes": [
"sha256:4dc7e346e92c01e8a997daa58a4c990151841d2d2962067325d963f665c7287a",
"sha256:79b7e6e0167def749352968ed6eb96954d9e2dd1dca8f297f122414753ce73a3"
"sha256:7b45b224442c479de4bc6e6e9cb0557b642fc7a77edc8702e393ccaa2e0aa128",
"sha256:c388da7dc1a596755f39de990a72e05cee558d098e81de63de55bd9598cc5134"
],
"index": "pypi",
"version": "==1.18.29"
"version": "==1.18.48"
},
"botocore": {
"hashes": [
"sha256:1f16998b4f5a88e6844196feee7fa5eef6b36034d377f9845c7df12b8803b3be",
"sha256:fec924f63b40bd29b522fa109ecbc45f16eedcbeb22b68c6c79773c22a552b16"
"sha256:17a10dd33334e7e3aaa4e12f66317284f96bb53267e20bc877a187c442681772",
"sha256:2089f9fa36a59d8c02435c49d58ccc7b3ceb9c0c054ea4f71631c3c3a1c5245e"
],
"markers": "python_version >= '3.6'",
"version": "==1.21.29"
"version": "==1.21.51"
},
"cachetools": {
"hashes": [
"sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001",
"sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff"
"sha256:0a3d3556c2c3befdbba2f93b78792c199c66201c999e97947ea0b7437758246b",
"sha256:6a6fa6802188ab7e77bab2db001d676e854499552b0037d999d5b9f211db5250"
],
"markers": "python_version ~= '3.5'",
"version": "==4.2.2"
"version": "==4.2.3"
},
"cbor2": {
"hashes": [
@ -254,11 +252,11 @@
},
"charset-normalizer": {
"hashes": [
"sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
"sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
"sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6",
"sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"
],
"markers": "python_version >= '3'",
"version": "==2.0.4"
"version": "==2.0.6"
},
"click": {
"hashes": [
@ -270,9 +268,11 @@
},
"click-didyoumean": {
"hashes": [
"sha256:112229485c9704ff51362fe34b2d4f0b12fc71cc20f6d2b3afabed4b8bfa6aeb"
"sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667",
"sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035"
],
"version": "==0.0.3"
"markers": "python_version < '4' and python_full_version >= '3.6.2'",
"version": "==0.3.0"
},
"click-plugins": {
"hashes": [
@ -288,6 +288,14 @@
],
"version": "==0.2.0"
},
"codespell": {
"hashes": [
"sha256:19d3fe5644fef3425777e66f225a8c82d39059dcfe9edb3349a8a2cf48383ee5",
"sha256:b864c7d917316316ac24272ee992d7937c3519be4569209c5b60035ac5d569b5"
],
"index": "pypi",
"version": "==2.1.0"
},
"colorama": {
"hashes": [
"sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
@ -305,25 +313,28 @@
},
"cryptography": {
"hashes": [
"sha256:0a7dcbcd3f1913f664aca35d47c1331fce738d44ec34b7be8b9d332151b0b01e",
"sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b",
"sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7",
"sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085",
"sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc",
"sha256:3fa3a7ccf96e826affdf1a0a9432be74dc73423125c8f96a909e3835a5ef194a",
"sha256:5b0fbfae7ff7febdb74b574055c7466da334a5371f253732d7e2e7525d570498",
"sha256:8695456444f277af73a4877db9fc979849cd3ee74c198d04fc0776ebc3db52b9",
"sha256:94cc5ed4ceaefcbe5bf38c8fba6a21fc1d365bb8fb826ea1688e3370b2e24a1c",
"sha256:94fff993ee9bc1b2440d3b7243d488c6a3d9724cc2b09cdb297f6a886d040ef7",
"sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb",
"sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14",
"sha256:a305600e7a6b7b855cd798e00278161b681ad6e9b7eca94c721d5f588ab212af",
"sha256:cd65b60cfe004790c795cc35f272e41a3df4631e2fb6b35aa7ac6ef2859d554e",
"sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5",
"sha256:d9ec0e67a14f9d1d48dd87a2531009a9b251c02ea42851c060b25c782516ff06",
"sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"
"sha256:07bb7fbfb5de0980590ddfc7f13081520def06dc9ed214000ad4372fb4e3c7f6",
"sha256:18d90f4711bf63e2fb21e8c8e51ed8189438e6b35a6d996201ebd98a26abbbe6",
"sha256:1ed82abf16df40a60942a8c211251ae72858b25b7421ce2497c2eb7a1cee817c",
"sha256:22a38e96118a4ce3b97509443feace1d1011d0571fae81fc3ad35f25ba3ea999",
"sha256:2d69645f535f4b2c722cfb07a8eab916265545b3475fdb34e0be2f4ee8b0b15e",
"sha256:4a2d0e0acc20ede0f06ef7aa58546eee96d2592c00f450c9acb89c5879b61992",
"sha256:54b2605e5475944e2213258e0ab8696f4f357a31371e538ef21e8d61c843c28d",
"sha256:7075b304cd567694dc692ffc9747f3e9cb393cc4aa4fb7b9f3abd6f5c4e43588",
"sha256:7b7ceeff114c31f285528ba8b390d3e9cfa2da17b56f11d366769a807f17cbaa",
"sha256:7eba2cebca600a7806b893cb1d541a6e910afa87e97acf2021a22b32da1df52d",
"sha256:928185a6d1ccdb816e883f56ebe92e975a262d31cc536429041921f8cb5a62fd",
"sha256:9933f28f70d0517686bd7de36166dda42094eac49415459d9bdf5e7df3e0086d",
"sha256:a688ebcd08250eab5bb5bca318cc05a8c66de5e4171a65ca51db6bd753ff8953",
"sha256:abb5a361d2585bb95012a19ed9b2c8f412c5d723a9836418fab7aaa0243e67d2",
"sha256:c10c797ac89c746e488d2ee92bd4abd593615694ee17b2500578b63cad6b93a8",
"sha256:ced40344e811d6abba00295ced98c01aecf0c2de39481792d87af4fa58b7b4d6",
"sha256:d57e0cdc1b44b6cdf8af1d01807db06886f10177469312fbde8f44ccbb284bc9",
"sha256:d99915d6ab265c22873f1b4d6ea5ef462ef797b4140be4c9d8b179915e0985c6",
"sha256:eb80e8a1f91e4b7ef8b33041591e6d89b2b8e122d787e87eeb2b08da71bb16ad",
"sha256:ebeddd119f526bcf323a89f853afb12e225902a24d29b55fe18dd6fcb2838a76"
],
"version": "==3.4.8"
"version": "==35.0.0"
},
"dacite": {
"hashes": [
@ -359,11 +370,11 @@
},
"django": {
"hashes": [
"sha256:7f92413529aa0e291f3be78ab19be31aefb1e1c9a52cd59e130f505f27a51f13",
"sha256:f27f8544c9d4c383bbe007c57e3235918e258364577373d4920e9162837be022"
"sha256:95b318319d6997bac3595517101ad9cc83fe5672ac498ba48d1a410f47afecd2",
"sha256:e93c93565005b37ddebf2396b4dc4b6913c1838baa82efdfb79acedd5816c240"
],
"index": "pypi",
"version": "==3.2.6"
"version": "==3.2.7"
},
"django-dbbackup": {
"git": "https://github.com/django-dbbackup/django-dbbackup.git",
@ -371,11 +382,11 @@
},
"django-filter": {
"hashes": [
"sha256:84e9d5bb93f237e451db814ed422a3a625751cbc9968b484ecc74964a8696b06",
"sha256:e00d32cebdb3d54273c48f4f878f898dced8d5dfaad009438fe61ebdf535ace1"
"sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e",
"sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063"
],
"index": "pypi",
"version": "==2.4.0"
"version": "==21.1"
},
"django-guardian": {
"hashes": [
@ -395,11 +406,11 @@
},
"django-otp": {
"hashes": [
"sha256:01b5888f0bde5125e139433aacb947e52d5c406fa56c9db43c3e8d75b5c323c4",
"sha256:0d56dd2a7fbb6ee6e54557e036ca64add0bd3596f471794bad673b7637d5e935"
"sha256:0c03a471db9e876f3671314bc9a65bd56a5c3c108ee0562c473701310bba4a77",
"sha256:4c90cdaed683d736b0efafc034a3c6b410e1be2a53c24da287165b1f371d8776"
],
"index": "pypi",
"version": "==1.0.6"
"version": "==1.1.1"
},
"django-prometheus": {
"hashes": [
@ -443,19 +454,19 @@
},
"docker": {
"hashes": [
"sha256:3e8bc47534e0ca9331d72c32f2881bb13b93ded0bcdeab3c833fb7cf61c0a9a5",
"sha256:fc961d622160e8021c10d1bcabc388c57d55fb1f917175afbe24af442e6879bd"
"sha256:21ec4998e90dff7a7aaaa098ca8d839c7de412b89e6f6c30908372d58fecf663",
"sha256:9b17f0723d83c1f3418d2aa17bf90b24dbe97deda06208dd4262fa30a6ee87eb"
],
"index": "pypi",
"version": "==5.0.0"
"version": "==5.0.2"
},
"drf-spectacular": {
"hashes": [
"sha256:5b1c27de127c86564be5a967a6fa195cfe161b552d98364282ae9e6ed3d75a85",
"sha256:8588706c27f44adfbb3405bae9ef9cd6506f4b59d4cbd66c59780dce035602d9"
"sha256:65df818226477cdfa629947ea52bc0cc13eb40550b192eeccec64a6b782651fd",
"sha256:f71205da3645d770545abeaf48e8a15afd6ee9a76e57c03df4592e51be1059bf"
],
"index": "pypi",
"version": "==0.18.0"
"version": "==0.19.0"
},
"duo-client": {
"hashes": [
@ -482,19 +493,19 @@
},
"geoip2": {
"hashes": [
"sha256:906a1dbf15a179a1af3522970e8420ab15bb3e0afc526942cc179e12146d9c1d",
"sha256:b97b44031fdc463e84eb1316b4f19edd978cb1d78703465fcb1e36dc5a822ba6"
"sha256:f150bed3190d543712a17467208388d31bd8ddb49b2226fba53db8aaedb8ba89",
"sha256:f9172cdfb2a5f9225ace5e30dd7426413ad28798a5f474cd1538780686bd6a87"
],
"index": "pypi",
"version": "==4.2.0"
"version": "==4.4.0"
},
"google-auth": {
"hashes": [
"sha256:c012c8be7c442c8309ca8fa0876fef33f5fd977c467be1e1c1c2f721e8ebd73c",
"sha256:ea1af050b3e06eb73e4470f704d23007307bc0e87c13e015f6b90460f1407bd3"
"sha256:2a92b485afed5292946b324e91fcbe03db277ee4cb64c998c6cfa66d4af01dee",
"sha256:6dc8173abd50f25b6e62fc5b42802c96fc7cd9deb9bfeeb10a79f5606225cdf4"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.1"
"version": "==2.2.1"
},
"gunicorn": {
"hashes": [
@ -618,10 +629,10 @@
},
"jsonschema": {
"hashes": [
"sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163",
"sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"
"sha256:bc51325b929171791c42ebc1c70b9713eb134d3bb8ebd5474c8b659b15be6d86",
"sha256:c773028c649441ab980015b5b622f4cd5134cf563daaf0235ca4b73cc3734f20"
],
"version": "==3.2.0"
"version": "==4.0.0"
},
"kombu": {
"hashes": [
@ -706,10 +717,10 @@
},
"maxminddb": {
"hashes": [
"sha256:47e86a084dd814fac88c99ea34ba3278a74bc9de5a25f4b815b608798747c7dc"
"sha256:e37707ec4fab115804670e0fb7aedb4b57075a8b6f80052bdc648d3c005184e5"
],
"markers": "python_version >= '3.6'",
"version": "==2.0.3"
"version": "==2.2.0"
},
"msgpack": {
"hashes": [
@ -900,39 +911,39 @@
},
"pycryptodome": {
"hashes": [
"sha256:09c1555a3fa450e7eaca41ea11cd00afe7c91fef52353488e65663777d8524e0",
"sha256:12222a5edc9ca4a29de15fbd5339099c4c26c56e13c2ceddf0b920794f26165d",
"sha256:1723ebee5561628ce96748501cdaa7afaa67329d753933296321f0be55358dce",
"sha256:1c5e1ca507de2ad93474be5cfe2bfa76b7cf039a1a32fc196f40935944871a06",
"sha256:2603c98ae04aac675fefcf71a6c87dc4bb74a75e9071ae3923bbc91a59f08d35",
"sha256:2dea65df54349cdfa43d6b2e8edb83f5f8d6861e5cf7b1fbc3e34c5694c85e27",
"sha256:31c1df17b3dc5f39600a4057d7db53ac372f492c955b9b75dd439f5d8b460129",
"sha256:38661348ecb71476037f1e1f553159b80d256c00f6c0b00502acac891f7116d9",
"sha256:3e2e3a06580c5f190df843cdb90ea28d61099cf4924334d5297a995de68e4673",
"sha256:3f840c49d38986f6e17dbc0673d37947c88bc9d2d9dba1c01b979b36f8447db1",
"sha256:501ab36aae360e31d0ec370cf5ce8ace6cb4112060d099b993bc02b36ac83fb6",
"sha256:60386d1d4cfaad299803b45a5bc2089696eaf6cdd56f9fc17479a6f89595cfc8",
"sha256:6260e24d41149268122dd39d4ebd5941e9d107f49463f7e071fd397e29923b0c",
"sha256:6bbf7fee7b7948b29d7e71fcacf48bac0c57fb41332007061a933f2d996f9713",
"sha256:6d2df5223b12437e644ce0a3be7809471ffa71de44ccd28b02180401982594a6",
"sha256:758949ca62690b1540dfb24ad773c6da9cd0e425189e83e39c038bbd52b8e438",
"sha256:77997519d8eb8a4adcd9a47b9cec18f9b323e296986528186c0e9a7a15d6a07e",
"sha256:7fd519b89585abf57bf47d90166903ec7b43af4fe23c92273ea09e6336af5c07",
"sha256:98213ac2b18dc1969a47bc65a79a8fca02a414249d0c8635abb081c7f38c91b6",
"sha256:99b2f3fc51d308286071d0953f92055504a6ffe829a832a9fc7a04318a7683dd",
"sha256:9b6f711b25e01931f1c61ce0115245a23cdc8b80bf8539ac0363bdcf27d649b6",
"sha256:a3105a0eb63eacf98c2ecb0eb4aa03f77f40fbac2bdde22020bb8a536b226bb8",
"sha256:a8eb8b6ea09ec1c2535bf39914377bc8abcab2c7d30fa9225eb4fe412024e427",
"sha256:a92d5c414e8ee1249e850789052608f582416e82422502dc0ac8c577808a9067",
"sha256:d3d6958d53ad307df5e8469cc44474a75393a434addf20ecd451f38a72fe29b8",
"sha256:e0a4d5933a88a2c98bbe19c0c722f5483dc628d7a38338ac2cb64a7dbd34064b",
"sha256:e3bf558c6aeb49afa9f0c06cee7fb5947ee5a1ff3bd794b653d39926b49077fa",
"sha256:e61e363d9a5d7916f3a4ce984a929514c0df3daf3b1b2eb5e6edbb131ee771cf",
"sha256:f977cdf725b20f6b8229b0c87acb98c7717e742ef9f46b113985303ae12a99da",
"sha256:fc7489a50323a0df02378bc2fff86eb69d94cc5639914346c736be981c6a02e7"
"sha256:04e14c732c3693d2830839feed5129286ce47ffa8bfe90e4ae042c773e51c677",
"sha256:11d3164fb49fdee000fde05baecce103c0c698168ef1a18d9c7429dd66f0f5bb",
"sha256:217dcc0c92503f7dd4b3d3b7d974331a4419f97f555c99a845c3b366fed7056b",
"sha256:24c1b7705d19d8ae3e7255431efd2e526006855df62620118dd7b5374c6372f6",
"sha256:309529d2526f3fb47102aeef376b3459110a6af7efb162e860b32e3a17a46f06",
"sha256:3a153658d97258ca20bf18f7fe31c09cc7c558b6f8974a6ec74e19f6c634bd64",
"sha256:3f9fb499e267039262569d08658132c9cd8b136bf1d8c56b72f70ed05551e526",
"sha256:3faa6ebd35c61718f3f8862569c1f38450c24f3ededb213e1a64806f02f584bc",
"sha256:40083b0d7f277452c7f2dd4841801f058cc12a74c219ee4110d65774c6a58bef",
"sha256:49e54f2245befb0193848c8c8031d8d1358ed4af5a1ae8d0a3ba669a5cdd3a72",
"sha256:4e8fc4c48365ce8a542fe48bf1360da05bb2851df12f64fc94d751705e7cdbe7",
"sha256:54d4e4d45f349d8c4e2f31c2734637ff62a844af391b833f789da88e43a8f338",
"sha256:66301e4c42dee43ee2da256625d3fe81ef98cc9924c2bd535008cc3ad8ded77b",
"sha256:6b45fcace5a5d9c57ba87cf804b161adc62aa826295ce7f7acbcbdc0df74ed37",
"sha256:7efec2418e9746ec48e264eea431f8e422d931f71c57b1c96ee202b117f58fa9",
"sha256:851e6d4930b160417235955322db44adbdb19589918670d63f4acd5d92959ac0",
"sha256:8e82524e7c354033508891405574d12e612cc4fdd3b55d2c238fc1a3e300b606",
"sha256:8ec154ec445412df31acf0096e7f715e30e167c8f2318b8f5b1ab7c28f4c82f7",
"sha256:91ba4215a1f37d0f371fe43bc88c5ff49c274849f3868321c889313787de7672",
"sha256:97e7df67a4da2e3f60612bbfd6c3f243a63a15d8f4797dd275e1d7b44a65cb12",
"sha256:9a2312440057bf29b9582f72f14d79692044e63bfbc4b4bbea8559355f44f3dd",
"sha256:a7471646d8cd1a58bb696d667dcb3853e5c9b341b68dcf3c3cc0893d0f98ca5f",
"sha256:ac3012c36633564b2b5539bb7c6d9175f31d2ce74844e9abe654c428f02d0fd8",
"sha256:b1daf251395af7336ddde6a0015ba5e632c18fe646ba930ef87402537358e3b4",
"sha256:b217b4525e60e1af552d62bec01b4685095436d4de5ecde0f05d75b2f95ba6d4",
"sha256:c61ea053bd5d4c12a063d7e704fbe1c45abb5d2510dab55bd95d166ba661604f",
"sha256:c6469d1453f5864e3321a172b0aa671b938d753cbf2376b99fa2ab8841539bb8",
"sha256:cefe6b267b8e5c3c72e11adec35a9c7285b62e8ea141b63e87055e9a9e5f2f8c",
"sha256:d713dc0910e5ded07852a05e9b75f1dd9d3a31895eebee0668f612779b2a748c",
"sha256:db15fa07d2a4c00beeb5e9acdfdbc1c79f9ccfbdc1a8f36c82c4aa44951b33c9"
],
"index": "pypi",
"version": "==3.10.1"
"version": "==3.10.4"
},
"pyjwt": {
"hashes": [
@ -944,10 +955,10 @@
},
"pyopenssl": {
"hashes": [
"sha256:4c231c759543ba02560fcd2480c48dcec4dae34c9da7d3747c508227e0624b51",
"sha256:818ae18e06922c066f777a33f1fca45786d85edfe71cd043de6379337a7f274b"
"sha256:5e2d8c5e46d0d865ae933bef5230090bdaf5506281e9eec60fa250ee80600cb3",
"sha256:8935bd4920ab9abfebb07c41a4f58296407ed77f04bd1a92914044b848ba1ed6"
],
"version": "==20.0.1"
"version": "==21.0.0"
},
"pyparsing": {
"hashes": [
@ -1084,11 +1095,11 @@
},
"sentry-sdk": {
"hashes": [
"sha256:ebe99144fa9618d4b0e7617e7929b75acd905d258c3c779edcd34c0adfffe26c",
"sha256:f33d34c886d0ba24c75ea8885a8b3a172358853c7cbde05979fc99c29ef7bc52"
"sha256:b9844751e40710e84a457c5bc29b21c383ccb2b63d76eeaad72f7f1c808c8828",
"sha256:c091cc7115ff25fe3a0e410dbecd7a996f81a3f6137d2272daef32d6c3cfa6dc"
],
"index": "pypi",
"version": "==1.3.1"
"version": "==1.4.3"
},
"service-identity": {
"hashes": [
@ -1108,11 +1119,11 @@
},
"sqlparse": {
"hashes": [
"sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0",
"sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8"
"sha256:0c00730c74263a94e5a9919ade150dfc3b19c574389985446148402998287dae",
"sha256:48719e356bb8b42991bdbb1e8b83223757b93789c00910a616a071910ca4a64d"
],
"markers": "python_version >= '3.5'",
"version": "==0.4.1"
"version": "==0.4.2"
},
"structlog": {
"hashes": [
@ -1151,11 +1162,11 @@
},
"typing-extensions": {
"hashes": [
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
"sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e",
"sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7",
"sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"
],
"version": "==3.10.0.0"
"version": "==3.10.0.2"
},
"ua-parser": {
"hashes": [
@ -1178,11 +1189,11 @@
"secure"
],
"hashes": [
"sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
"sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
"sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece",
"sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"
],
"index": "pypi",
"version": "==1.26.6"
"version": "==1.26.7"
},
"uvicorn": {
"extras": [
@ -1256,58 +1267,50 @@
},
"websockets": {
"hashes": [
"sha256:0dd4eb8e0bbf365d6f652711ce21b8fd2b596f873d32aabb0fbb53ec604418cc",
"sha256:1d0971cc7251aeff955aa742ec541ee8aaea4bb2ebf0245748fbec62f744a37e",
"sha256:1d6b4fddb12ab9adf87b843cd4316c4bd602db8d5efd2fb83147f0458fe85135",
"sha256:230a3506df6b5f446fed2398e58dcaafdff12d67fe1397dff196411a9e820d02",
"sha256:276d2339ebf0df4f45df453923ebd2270b87900eda5dfd4a6b0cfa15f82111c3",
"sha256:2cf04601633a4ec176b9cc3d3e73789c037641001dbfaf7c411f89cd3e04fcaf",
"sha256:3ddff38894c7857c476feb3538dd847514379d6dc844961dc99f04b0384b1b1b",
"sha256:48c222feb3ced18f3dc61168ca18952a22fb88e5eb8902d2bf1b50faefdc34a2",
"sha256:51d04df04ed9d08077d10ccbe21e6805791b78eac49d16d30a1f1fe2e44ba0af",
"sha256:597c28f3aa7a09e8c070a86b03107094ee5cdafcc0d55f2f2eac92faac8dc67d",
"sha256:5c8f0d82ea2468282e08b0cf5307f3ad022290ed50c45d5cb7767957ca782880",
"sha256:7189e51955f9268b2bdd6cc537e0faa06f8fffda7fb386e5922c6391de51b077",
"sha256:7df3596838b2a0c07c6f6d67752c53859a54993d4f062689fdf547cb56d0f84f",
"sha256:826ccf85d4514609219725ba4a7abd569228c2c9f1968e8be05be366f68291ec",
"sha256:836d14eb53b500fd92bd5db2fc5894f7c72b634f9c2a28f546f75967503d8e25",
"sha256:85db8090ba94e22d964498a47fdd933b8875a1add6ebc514c7ac8703eb97bbf0",
"sha256:85e701a6c316b7067f1e8675c638036a796fe5116783a4c932e7eb8e305a3ffe",
"sha256:900589e19200be76dd7cbaa95e9771605b5ce3f62512d039fb3bc5da9014912a",
"sha256:9147868bb0cc01e6846606cd65cbf9c58598f187b96d14dd1ca17338b08793bb",
"sha256:9e7fdc775fe7403dbd8bc883ba59576a6232eac96dacb56512daacf7af5d618d",
"sha256:ab5ee15d3462198c794c49ccd31773d8a2b8c17d622aa184f669d2b98c2f0857",
"sha256:ad893d889bc700a5835e0a95a3e4f2c39e91577ab232a3dc03c262a0f8fc4b5c",
"sha256:b2e71c4670ebe1067fa8632f0d081e47254ee2d3d409de54168b43b0ba9147e0",
"sha256:b43b13e5622c5a53ab12f3272e6f42f1ce37cd5b6684b2676cb365403295cd40",
"sha256:b4ad84b156cf50529b8ac5cc1638c2cf8680490e3fccb6121316c8c02620a2e4",
"sha256:be5fd35e99970518547edc906efab29afd392319f020c3c58b0e1a158e16ed20",
"sha256:caa68c95bc1776d3521f81eeb4d5b9438be92514ec2a79fececda814099c8314",
"sha256:d144b350045c53c8ff09aa1cfa955012dd32f00c7e0862c199edcabb1a8b32da",
"sha256:d2c2d9b24d3c65b5a02cac12cbb4e4194e590314519ed49db2f67ef561c3cf58",
"sha256:e9e5fd6dbdf95d99bc03732ded1fc8ef22ebbc05999ac7e0c7bf57fe6e4e5ae2",
"sha256:ebf459a1c069f9866d8569439c06193c586e72c9330db1390af7c6a0a32c4afd",
"sha256:f31722f1c033c198aa4a39a01905951c00bd1c74f922e8afc1b1c62adbcdd56a",
"sha256:f68c352a68e5fdf1e97288d5cec9296664c590c25932a8476224124aaf90dbcd"
"sha256:01db0ecd1a0ca6702d02a5ed40413e18b7d22f94afb3bbe0d323bac86c42c1c8",
"sha256:085bb8a6e780d30eaa1ba48ac7f3a6707f925edea787cfb761ce5a39e77ac09b",
"sha256:1ac35426fe3e7d3d0fac3d63c8965c76ed67a8fd713937be072bf0ce22808539",
"sha256:1f6b814cff6aadc4288297cb3a248614829c6e4ff5556593c44a115e9dd49939",
"sha256:2a43072e434c041a99f2e1eb9b692df0232a38c37c61d00e9f24db79474329e4",
"sha256:5b2600e01c7ca6f840c42c747ffbe0254f319594ed108db847eb3d75f4aacb80",
"sha256:62160772314920397f9d219147f958b33fa27a12c662d4455c9ccbba9a07e474",
"sha256:706e200fc7f03bed99ad0574cd1ea8b0951477dd18cc978ccb190683c69dba76",
"sha256:71358c7816e2762f3e4af3adf0040f268e219f5a38cb3487a9d0fc2e554fef6a",
"sha256:7d2e12e4f901f1bc062dfdf91831712c4106ed18a9a4cdb65e2e5f502124ca37",
"sha256:7f79f02c7f9a8320aff7d3321cd1c7e3a7dbc15d922ac996cca827301ee75238",
"sha256:82b17524b1ce6ae7f7dd93e4d18e9b9474071e28b65dbf1dfe9b5767778db379",
"sha256:82bd921885231f4a30d9bc550552495b3fc36b1235add6d374e7c65c3babd805",
"sha256:8bbf8660c3f833ddc8b1afab90213f2e672a9ddac6eecb3cde968e6b2807c1c7",
"sha256:9a4d889162bd48588e80950e07fa5e039eee9deb76a58092e8c3ece96d7ef537",
"sha256:b4ade7569b6fd17912452f9c3757d96f8e4044016b6d22b3b8391e641ca50456",
"sha256:b8176deb6be540a46695960a765a77c28ac8b2e3ef2ec95d50a4f5df901edb1c",
"sha256:c4fc9a1d242317892590abe5b61a9127f1a61740477bfb121743f290b8054002",
"sha256:c5880442f5fc268f1ef6d37b2c152c114deccca73f48e3a8c48004d2f16f4567",
"sha256:cd8c6f2ec24aedace251017bc7a414525171d4e6578f914acab9349362def4da",
"sha256:d67646ddd17a86117ae21c27005d83c1895c0cef5d7be548b7549646372f868a",
"sha256:e42a1f1e03437b017af341e9bbfdc09252cd48ef32a8c3c3ead769eab3b17368",
"sha256:eb282127e9c136f860c6068a4fba5756eb25e755baffb5940b6f1eae071928b2",
"sha256:fe83b3ec9ef34063d86dfe1029160a85f24a5a94271036e5714a57acfdd089a1",
"sha256:ff59c6bdb87b31f7e2d596f09353d5a38c8c8ff571b0e2238e8ee2d55ad68465"
],
"version": "==9.1"
"version": "==10.0"
},
"xmlsec": {
"hashes": [
"sha256:23f209260b37bdc2fd96af837494c47dd1e67964f077442b63acd83c0f62e212",
"sha256:4fb38ab0bf3e47cbae136119674a869e09d61c939b510350f369c8ac46087373",
"sha256:705ab5b848afdf3a5c78b1322276054c885f44dc51601e14cb883a9c86cbe20f",
"sha256:843d10bba4c480609da74ee11fff1ee0fc1c12821c656979f12a7a4ecb043e03",
"sha256:86d54b93f8278e2f0c504d0744e39a483c1c7ce9993f2ca70184cc7770faa982",
"sha256:8922fba55a060ee81de4a7f5efc593c5bf121047763aecf0eead02e061c9d2db",
"sha256:c7b49d4fce83186b89f7ce6cec765245d36a70d0acc2f3ed0ba95c735b3667da",
"sha256:cd2eaaff7f31784a07dd99ce81fa767313df3ba1834faa4143ee2c07000cac7a",
"sha256:dea5bef9b5830c36ccb7a68a0d94d49eaea4d03fbbd04179652bf661b7e6e30f",
"sha256:eadff662d89c80db409c69d82eb3e695e16d4a5e8ab56b5b22670a54e9c6ff20",
"sha256:ee233d0bc27fb8f447ca2622b0de2ac2df45b8795f02ef263825912011fe4fe9"
"sha256:135724cdce60e6bbd072fca6f09a21f72e2cecc59eebb4eed7740c316ecabc7b",
"sha256:1b4377f6d37ad714ba95a227ef40fb54ba1b22ef5170ce04c330fe45ee6ad184",
"sha256:2c86ac6ce570c9e04f04da0cd5e7d3db346e4b5b1d006311606368f17c756ef9",
"sha256:4e5f565de311afa33aaee4724566e685f951afe301212b6cf82f98cf9d8a1749",
"sha256:9a2b8a780093b0fe8cecae53a81a8cd9edd50c08980d374c5317c91f065042d9",
"sha256:ce9c681adbc87b4f06c2b16725d9b2edbdbd508117dae4288b5faf78c1406038",
"sha256:d22da4d3dcc559fb2e54e782f39c9ddad5f8d5b356f86a79bbb80b0a45115c97",
"sha256:db3e18ca883c01bbe28c9f5197c66f676c9772cf2d85f667e6122fc4d0702225",
"sha256:e4783f7814aa2a3e318385cce8ef87c82954b9a59535a48f67da4e2c21c08ce1",
"sha256:f32e54065f0404ceff71388daa7fa7df10e1fb800051dfe302d63abb0acf0020",
"sha256:f5d242b1a19a36078608f5d7f4d561c5ca55cac8061a323a071c06275267dc19"
],
"index": "pypi",
"version": "==1.3.11"
"version": "==1.3.12"
},
"yarl": {
"hashes": [
@ -1420,11 +1423,11 @@
},
"astroid": {
"hashes": [
"sha256:b6c2d75cd7c2982d09e7d41d70213e863b3ba34d3bd4014e08f167cee966e99e",
"sha256:ecc50f9b3803ebf8ea19aa2c6df5622d8a5c31456a53c741d3be044d96ff0948"
"sha256:dcc06f6165f415220013801642bd6c9808a02967070919c4b746c6864c205471",
"sha256:fe81f80c0b35264acb5653302ffbd935d394f1775c5e4487df745bf9c2442708"
],
"markers": "python_version ~= '3.6'",
"version": "==2.7.2"
"version": "==2.8.0"
},
"attrs": {
"hashes": [
@ -1467,11 +1470,11 @@
},
"charset-normalizer": {
"hashes": [
"sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b",
"sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"
"sha256:5d209c0a931f215cee683b6445e2d77677e7e75e159f78def0db09d68fafcaa6",
"sha256:5ec46d183433dcbd0ab716f2d7f29d8dee50505b3fdb40c6b985c7c4f5a3591f"
],
"markers": "python_version >= '3'",
"version": "==2.0.4"
"version": "==2.0.6"
},
"click": {
"hashes": [
@ -1557,11 +1560,11 @@
},
"gitpython": {
"hashes": [
"sha256:b838a895977b45ab6f0cc926a9045c8d1c44e2b653c1fcc39fe91f42c6e8f05b",
"sha256:fce760879cd2aebd2991b3542876dc5c4a909b30c9d69dfc488e504a8db37ee8"
"sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647",
"sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"
],
"markers": "python_version >= '3.6'",
"version": "==3.1.18"
"markers": "python_version >= '3.7'",
"version": "==3.1.24"
},
"idna": {
"hashes": [
@ -1652,19 +1655,19 @@
},
"platformdirs": {
"hashes": [
"sha256:4666d822218db6a262bdfdc9c39d21f23b4cfdb08af331a81e92751daf6c866c",
"sha256:632daad3ab546bd8e6af0537d09805cec458dce201bccfe23012df73332e181e"
"sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2",
"sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"
],
"markers": "python_version >= '3.6'",
"version": "==2.2.0"
"version": "==2.4.0"
},
"pluggy": {
"hashes": [
"sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
"sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
"sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159",
"sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.13.1"
"markers": "python_version >= '3.6'",
"version": "==1.0.0"
},
"py": {
"hashes": [
@ -1676,11 +1679,11 @@
},
"pylint": {
"hashes": [
"sha256:6758cce3ddbab60c52b57dcc07f0c5d779e5daf0cf50f6faacbef1d3ea62d2a1",
"sha256:e178e96b6ba171f8ef51fbce9ca30931e6acbea4a155074d80cc081596c9e852"
"sha256:0f358e221c45cbd4dad2a1e4b883e75d28acdcccd29d40c76eb72b307269b126",
"sha256:2c9843fff1a88ca0ad98a256806c82c5a8f86086e7ccbdb93297d86c3f90c436"
],
"index": "pypi",
"version": "==2.10.2"
"version": "==2.11.1"
},
"pylint-django": {
"hashes": [
@ -1707,11 +1710,11 @@
},
"pytest": {
"hashes": [
"sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b",
"sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89",
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"
],
"index": "pypi",
"version": "==6.2.4"
"version": "==6.2.5"
},
"pytest-django": {
"hashes": [
@ -1758,49 +1761,49 @@
},
"regex": {
"hashes": [
"sha256:03840a07a402576b8e3a6261f17eb88abd653ad4e18ec46ef10c9a63f8c99ebd",
"sha256:06ba444bbf7ede3890a912bd4904bb65bf0da8f0d8808b90545481362c978642",
"sha256:1f9974826aeeda32a76648fc677e3125ade379869a84aa964b683984a2dea9f1",
"sha256:330836ad89ff0be756b58758878409f591d4737b6a8cef26a162e2a4961c3321",
"sha256:38600fd58c2996829480de7d034fb2d3a0307110e44dae80b6b4f9b3d2eea529",
"sha256:3a195e26df1fbb40ebee75865f9b64ba692a5824ecb91c078cc665b01f7a9a36",
"sha256:41acdd6d64cd56f857e271009966c2ffcbd07ec9149ca91f71088574eaa4278a",
"sha256:45f97ade892ace20252e5ccecdd7515c7df5feeb42c3d2a8b8c55920c3551c30",
"sha256:4b0c211c55d4aac4309c3209833c803fada3fc21cdf7b74abedda42a0c9dc3ce",
"sha256:5d5209c3ba25864b1a57461526ebde31483db295fc6195fdfc4f8355e10f7376",
"sha256:615fb5a524cffc91ab4490b69e10ae76c1ccbfa3383ea2fad72e54a85c7d47dd",
"sha256:61e734c2bcb3742c3f454dfa930ea60ea08f56fd1a0eb52d8cb189a2f6be9586",
"sha256:640ccca4d0a6fcc6590f005ecd7b16c3d8f5d52174e4854f96b16f34c39d6cb7",
"sha256:6dbd51c3db300ce9d3171f4106da18fe49e7045232630fe3d4c6e37cb2b39ab9",
"sha256:71a904da8c9c02aee581f4452a5a988c3003207cb8033db426f29e5b2c0b7aea",
"sha256:8021dee64899f993f4b5cca323aae65aabc01a546ed44356a0965e29d7893c94",
"sha256:8b8d551f1bd60b3e1c59ff55b9e8d74607a5308f66e2916948cafd13480b44a3",
"sha256:93f9f720081d97acee38a411e861d4ce84cbc8ea5319bc1f8e38c972c47af49f",
"sha256:96f0c79a70642dfdf7e6a018ebcbea7ea5205e27d8e019cad442d2acfc9af267",
"sha256:9966337353e436e6ba652814b0a957a517feb492a98b8f9d3b6ba76d22301dcc",
"sha256:a34ba9e39f8269fd66ab4f7a802794ffea6d6ac500568ec05b327a862c21ce23",
"sha256:a49f85f0a099a5755d0a2cc6fc337e3cb945ad6390ec892332c691ab0a045882",
"sha256:a795829dc522227265d72b25d6ee6f6d41eb2105c15912c230097c8f5bfdbcdc",
"sha256:a89ca4105f8099de349d139d1090bad387fe2b208b717b288699ca26f179acbe",
"sha256:ac95101736239260189f426b1e361dc1b704513963357dc474beb0f39f5b7759",
"sha256:ae87ab669431f611c56e581679db33b9a467f87d7bf197ac384e71e4956b4456",
"sha256:b091dcfee169ad8de21b61eb2c3a75f9f0f859f851f64fdaf9320759a3244239",
"sha256:b511c6009d50d5c0dd0bab85ed25bc8ad6b6f5611de3a63a59786207e82824bb",
"sha256:b79dc2b2e313565416c1e62807c7c25c67a6ff0a0f8d83a318df464555b65948",
"sha256:bca14dfcfd9aae06d7d8d7e105539bd77d39d06caaae57a1ce945670bae744e0",
"sha256:c835c30f3af5c63a80917b72115e1defb83de99c73bc727bddd979a3b449e183",
"sha256:ccd721f1d4fc42b541b633d6e339018a08dd0290dc67269df79552843a06ca92",
"sha256:d6c2b1d78ceceb6741d703508cd0e9197b34f6bf6864dab30f940f8886e04ade",
"sha256:d6ec4ae13760ceda023b2e5ef1f9bc0b21e4b0830458db143794a117fdbdc044",
"sha256:d8b623fc429a38a881ab2d9a56ef30e8ea20c72a891c193f5ebbddc016e083ee",
"sha256:ea9753d64cba6f226947c318a923dadaf1e21cd8db02f71652405263daa1f033",
"sha256:ebbceefbffae118ab954d3cd6bf718f5790db66152f95202ebc231d58ad4e2c2",
"sha256:ecb6e7c45f9cd199c10ec35262b53b2247fb9a408803ed00ee5bb2b54aa626f5",
"sha256:ef9326c64349e2d718373415814e754183057ebc092261387a2c2f732d9172b2",
"sha256:f93a9d8804f4cec9da6c26c8cfae2c777028b4fdd9f49de0302e26e00bb86504",
"sha256:faf08b0341828f6a29b8f7dd94d5cf8cc7c39bfc3e67b78514c54b494b66915a"
"sha256:0628ed7d6334e8f896f882a5c1240de8c4d9b0dd7c7fb8e9f4692f5684b7d656",
"sha256:09eb62654030f39f3ba46bc6726bea464069c29d00a9709e28c9ee9623a8da4a",
"sha256:0bba1f6df4eafe79db2ecf38835c2626dbd47911e0516f6962c806f83e7a99ae",
"sha256:10a7a9cbe30bd90b7d9a1b4749ef20e13a3528e4215a2852be35784b6bd070f0",
"sha256:17310b181902e0bb42b29c700e2c2346b8d81f26e900b1328f642e225c88bce1",
"sha256:1e8d1898d4fb817120a5f684363b30108d7b0b46c7261264b100d14ec90a70e7",
"sha256:2054dea683f1bda3a804fcfdb0c1c74821acb968093d0be16233873190d459e3",
"sha256:29385c4dbb3f8b3a55ce13de6a97a3d21bd00de66acd7cdfc0b49cb2f08c906c",
"sha256:295bc8a13554a25ad31e44c4bedabd3c3e28bba027e4feeb9bb157647a2344a7",
"sha256:2cdb3789736f91d0b3333ac54d12a7e4f9efbc98f53cb905d3496259a893a8b3",
"sha256:3baf3eaa41044d4ced2463fd5d23bf7bd4b03d68739c6c99a59ce1f95599a673",
"sha256:4e61100200fa6ab7c99b61476f9f9653962ae71b931391d0264acfb4d9527d9c",
"sha256:6266fde576e12357b25096351aac2b4b880b0066263e7bc7a9a1b4307991bb0e",
"sha256:650c4f1fc4273f4e783e1d8e8b51a3e2311c2488ba0fcae6425b1e2c248a189d",
"sha256:658e3477676009083422042c4bac2bdad77b696e932a3de001c42cc046f8eda2",
"sha256:6adc1bd68f81968c9d249aab8c09cdc2cbe384bf2d2cb7f190f56875000cdc72",
"sha256:6c4d83d21d23dd854ffbc8154cf293f4e43ba630aa9bd2539c899343d7f59da3",
"sha256:6f74b6d8f59f3cfb8237e25c532b11f794b96f5c89a6f4a25857d85f84fbef11",
"sha256:7783d89bd5413d183a38761fbc68279b984b9afcfbb39fa89d91f63763fbfb90",
"sha256:7e3536f305f42ad6d31fc86636c54c7dafce8d634e56fef790fbacb59d499dd5",
"sha256:821e10b73e0898544807a0692a276e539e5bafe0a055506a6882814b6a02c3ec",
"sha256:835962f432bce92dc9bf22903d46c50003c8d11b1dc64084c8fae63bca98564a",
"sha256:85c61bee5957e2d7be390392feac7e1d7abd3a49cbaed0c8cee1541b784c8561",
"sha256:86f9931eb92e521809d4b64ec8514f18faa8e11e97d6c2d1afa1bcf6c20a8eab",
"sha256:8a5c2250c0a74428fd5507ae8853706fdde0f23bfb62ee1ec9418eeacf216078",
"sha256:8aec4b4da165c4a64ea80443c16e49e3b15df0f56c124ac5f2f8708a65a0eddc",
"sha256:8c268e78d175798cd71d29114b0a1f1391c7d011995267d3b62319ec1a4ecaa1",
"sha256:8d80087320632457aefc73f686f66139801959bf5b066b4419b92be85be3543c",
"sha256:95e89a8558c8c48626dcffdf9c8abac26b7c251d352688e7ab9baf351e1c7da6",
"sha256:9c371dd326289d85906c27ec2bc1dcdedd9d0be12b543d16e37bad35754bde48",
"sha256:9c7cb25adba814d5f419733fe565f3289d6fa629ab9e0b78f6dff5fa94ab0456",
"sha256:a731552729ee8ae9c546fb1c651c97bf5f759018fdd40d0e9b4d129e1e3a44c8",
"sha256:aea4006b73b555fc5bdb650a8b92cf486d678afa168cf9b38402bb60bf0f9c18",
"sha256:b0e3f59d3c772f2c3baaef2db425e6fc4149d35a052d874bb95ccfca10a1b9f4",
"sha256:b15dc34273aefe522df25096d5d087abc626e388a28a28ac75a4404bb7668736",
"sha256:c000635fd78400a558bd7a3c2981bb2a430005ebaa909d31e6e300719739a949",
"sha256:c31f35a984caffb75f00a86852951a337540b44e4a22171354fb760cefa09346",
"sha256:c50a6379763c733562b1fee877372234d271e5c78cd13ade5f25978aa06744db",
"sha256:c94722bf403b8da744b7d0bb87e1f2529383003ceec92e754f768ef9323f69ad",
"sha256:dcbbc9cfa147d55a577d285fd479b43103188855074552708df7acc31a476dd9",
"sha256:fb9f5844db480e2ef9fce3a72e71122dd010ab7b2920f777966ba25f7eb63819"
],
"version": "==2021.8.21"
"version": "==2021.9.24"
},
"requests": {
"hashes": [
@ -1858,16 +1861,24 @@
"markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==0.10.2"
},
"typing-extensions": {
"hashes": [
"sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e",
"sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7",
"sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"
],
"version": "==3.10.0.2"
},
"urllib3": {
"extras": [
"secure"
],
"hashes": [
"sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4",
"sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"
"sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece",
"sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"
],
"index": "pypi",
"version": "==1.26.6"
"version": "==1.26.7"
},
"wrapt": {
"hashes": [

View File

@ -4,14 +4,15 @@
---
[![](https://img.shields.io/discord/809154715984199690?label=Discord&style=for-the-badge)](https://discord.gg/jg33eMhnj6)
[![CI Build status](https://img.shields.io/azure-devops/build/beryjuorg/authentik/6?style=for-the-badge)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=6)
[![Tests](https://img.shields.io/azure-devops/tests/beryjuorg/authentik/6?compact_message&style=for-the-badge)](https://dev.azure.com/beryjuorg/authentik/_build?definitionId=6)
[![Join Discord](https://img.shields.io/discord/809154715984199690?label=Discord&style=for-the-badge)](https://discord.gg/jg33eMhnj6)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-main?label=core%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-main.yml)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-outpost?label=outpost%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-outpost.yml)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/goauthentik/authentik/authentik-ci-web?label=web%20build&style=for-the-badge)](https://github.com/goauthentik/authentik/actions/workflows/ci-web.yml)
[![Code Coverage](https://img.shields.io/codecov/c/gh/goauthentik/authentik?style=for-the-badge)](https://codecov.io/gh/goauthentik/authentik)
[![Testspace tests](https://img.shields.io/testspace/total/goauthentik/goauthentik:authentik/master?style=for-the-badge)](https://goauthentik.testspace.com/)
![Docker pulls](https://img.shields.io/docker/pulls/beryju/authentik.svg?style=for-the-badge)
![Latest version](https://img.shields.io/docker/v/beryju/authentik?sort=semver&style=for-the-badge)
![LGTM Grade](https://img.shields.io/lgtm/grade/python/github/goauthentik/authentik?style=for-the-badge)
[Transifex](https://www.transifex.com/beryjuorg/authentik/)
[![](https://img.shields.io/badge/Help%20translate-transifex-blue?style=for-the-badge)](https://www.transifex.com/beryjuorg/authentik/)
## What is authentik?

View File

@ -6,9 +6,8 @@
| Version | Supported |
| ---------- | ------------------ |
| 2021.5.x | :white_check_mark: |
| 2021.6.x | :white_check_mark: |
| 2021.7.x | :white_check_mark: |
| 2021.8.x | :white_check_mark: |
## Reporting a Vulnerability

View File

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.8.2"
__version__ = "2021.9.8"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -84,7 +84,7 @@ class SystemSerializer(PassiveSerializer):
return now()
def get_embedded_outpost_host(self, request: Request) -> str:
"""Get the FQDN configured on the embeddded outpost"""
"""Get the FQDN configured on the embedded outpost"""
outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST)
if not outposts.exists():
return ""

View File

@ -8,3 +8,8 @@ class AuthentikAdminConfig(AppConfig):
name = "authentik.admin"
label = "authentik_admin"
verbose_name = "authentik Admin"
def ready(self):
from authentik.admin.tasks import clear_update_notifications
clear_update_notifications.delay()

View File

@ -6,12 +6,14 @@ from django.core.cache import cache
from django.core.validators import URLValidator
from packaging.version import parse
from prometheus_client import Info
from requests import RequestException, get
from requests import RequestException
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik.events.models import Event, EventAction
from authentik.events.models import Event, EventAction, Notification
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
from authentik.lib.config import CONFIG
from authentik.lib.utils.http import get_http_session
from authentik.root.celery import CELERY_APP
LOGGER = get_logger()
@ -33,15 +35,32 @@ def _set_prom_info():
)
@CELERY_APP.task()
def clear_update_notifications():
"""Clear update notifications on startup if the notification was for the version
we're running now."""
for notification in Notification.objects.filter(event__action=EventAction.UPDATE_AVAILABLE):
if "new_version" not in notification.event.context:
continue
notification_version = notification.event.context["new_version"]
if notification_version == __version__:
notification.delete()
@CELERY_APP.task(bind=True, base=MonitoredTask)
def update_latest_version(self: MonitoredTask):
"""Update latest version info"""
if CONFIG.y_bool("disable_update_check"):
cache.set(VERSION_CACHE_KEY, "0.0.0", VERSION_CACHE_TIMEOUT)
self.set_status(TaskResult(TaskResultStatus.WARNING, messages=["Version check disabled."]))
return
try:
response = get("https://api.github.com/repos/goauthentik/authentik/releases/latest")
response = get_http_session().get(
"https://version.goauthentik.io/version.json",
)
response.raise_for_status()
data = response.json()
tag_name = data.get("tag_name")
upstream_version = tag_name.split("/")[1]
upstream_version = data.get("stable", {}).get("version")
cache.set(VERSION_CACHE_KEY, upstream_version, VERSION_CACHE_TIMEOUT)
self.set_status(
TaskResult(TaskResultStatus.SUCCESSFUL, ["Successfully updated latest Version"])
@ -58,7 +77,7 @@ def update_latest_version(self: MonitoredTask):
).exists():
return
event_dict = {"new_version": upstream_version}
if match := re.search(URL_FINDER, data.get("body", "")):
if match := re.search(URL_FINDER, data.get("stable", {}).get("changelog", "")):
event_dict["message"] = f"Changelog: {match.group()}"
Event.new(EventAction.UPDATE_AVAILABLE, **event_dict).save()
except (RequestException, IndexError) as exc:

View File

@ -1,81 +1,58 @@
"""test admin tasks"""
import json
from dataclasses import dataclass
from unittest.mock import Mock, patch
from django.core.cache import cache
from django.test import TestCase
from requests.exceptions import RequestException
from requests_mock import Mocker
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
from authentik.events.models import Event, EventAction
@dataclass
class MockResponse:
"""Mock class to emulate the methods of requests's Response we need"""
status_code: int
response: str
def json(self) -> dict:
"""Get json parsed response"""
return json.loads(self.response)
def raise_for_status(self):
"""raise RequestException if status code is 400 or more"""
if self.status_code >= 400:
raise RequestException
REQUEST_MOCK_VALID = Mock(
return_value=MockResponse(
200,
"""{
"tag_name": "version/99999999.9999999",
"body": "https://goauthentik.io/test"
}""",
)
)
REQUEST_MOCK_INVALID = Mock(return_value=MockResponse(400, "{}"))
RESPONSE_VALID = {
"$schema": "https://version.goauthentik.io/schema.json",
"stable": {
"version": "99999999.9999999",
"changelog": "See https://goauthentik.io/test",
"reason": "bugfix",
},
}
class TestAdminTasks(TestCase):
"""test admin tasks"""
@patch("authentik.admin.tasks.get", REQUEST_MOCK_VALID)
def test_version_valid_response(self):
"""Test Update checker with valid response"""
update_latest_version.delay().get()
self.assertEqual(cache.get(VERSION_CACHE_KEY), "99999999.9999999")
self.assertTrue(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE,
context__new_version="99999999.9999999",
context__message="Changelog: https://goauthentik.io/test",
).exists()
)
# test that a consecutive check doesn't create a duplicate event
update_latest_version.delay().get()
self.assertEqual(
len(
with Mocker() as mocker:
mocker.get("https://version.goauthentik.io/version.json", json=RESPONSE_VALID)
update_latest_version.delay().get()
self.assertEqual(cache.get(VERSION_CACHE_KEY), "99999999.9999999")
self.assertTrue(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE,
context__new_version="99999999.9999999",
context__message="Changelog: https://goauthentik.io/test",
)
),
1,
)
).exists()
)
# test that a consecutive check doesn't create a duplicate event
update_latest_version.delay().get()
self.assertEqual(
len(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE,
context__new_version="99999999.9999999",
context__message="Changelog: https://goauthentik.io/test",
)
),
1,
)
@patch("authentik.admin.tasks.get", REQUEST_MOCK_INVALID)
def test_version_error(self):
"""Test Update checker with invalid response"""
update_latest_version.delay().get()
self.assertEqual(cache.get(VERSION_CACHE_KEY), "0.0.0")
self.assertFalse(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE, context__new_version="0.0.0"
).exists()
)
with Mocker() as mocker:
mocker.get("https://version.goauthentik.io/version.json", status_code=400)
update_latest_version.delay().get()
self.assertEqual(cache.get(VERSION_CACHE_KEY), "0.0.0")
self.assertFalse(
Event.objects.filter(
action=EventAction.UPDATE_AVAILABLE, context__new_version="0.0.0"
).exists()
)

View File

@ -40,7 +40,6 @@ def bearer_auth(raw_header: bytes) -> Optional[User]:
raise AuthenticationFailed("Malformed header")
tokens = Token.filter_not_expired(key=password, intent=TokenIntents.INTENT_API)
if not tokens.exists():
LOGGER.info("Authenticating via secret_key")
user = token_secret_key(password)
if not user:
raise AuthenticationFailed("Token invalid/expired")
@ -58,6 +57,7 @@ def token_secret_key(value: str) -> Optional[User]:
outposts = Outpost.objects.filter(managed=MANAGED_OUTPOST)
if not outposts:
return None
LOGGER.info("Authenticating via secret_key")
outpost = outposts.first()
return outpost.user

View File

@ -33,3 +33,12 @@ class OwnerPermissions(BasePermission):
if owner != request.user:
return False
return True
class OwnerSuperuserPermissions(OwnerPermissions):
"""Similar to OwnerPermissions, except always allow access for superusers"""
def has_object_permission(self, request: Request, view, obj: Model) -> bool:
if request.user.is_superuser:
return True
return super().has_object_permission(request, view, obj)

View File

@ -5,6 +5,9 @@ from typing import Callable, Optional
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
LOGGER = get_logger()
def permission_required(perm: Optional[str] = None, other_perms: Optional[list[str]] = None):
@ -18,10 +21,12 @@ def permission_required(perm: Optional[str] = None, other_perms: Optional[list[s
if perm:
obj = self.get_object()
if not request.user.has_perm(perm, obj):
LOGGER.debug("denying access for object", user=request.user, perm=perm, obj=obj)
return self.permission_denied(request)
if other_perms:
for other_perm in other_perms:
if not request.user.has_perm(other_perm):
LOGGER.debug("denying access for other", user=request.user, perm=perm)
return self.permission_denied(request)
return func(self, request, *args, **kwargs)

View File

@ -11,7 +11,7 @@ from drf_spectacular.types import OpenApiTypes
def build_standard_type(obj, **kwargs):
"""Build a basic type with optional add ons."""
"""Build a basic type with optional add owns."""
schema = build_basic_type(obj)
schema.update(kwargs)
return schema
@ -31,7 +31,7 @@ VALIDATION_ERROR = build_object_type(
"non_field_errors": build_array_type(build_standard_type(OpenApiTypes.STR)),
"code": build_standard_type(OpenApiTypes.STR),
},
required=["detail"],
required=[],
additionalProperties={},
)

19
authentik/api/tasks.py Normal file
View File

@ -0,0 +1,19 @@
"""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,8 +1,10 @@
"""authentik api urls"""
from django.urls import include, path
from authentik.api.v2.urls import urlpatterns as v2_urls
from authentik.api.v3.urls import urlpatterns as v3_urls
urlpatterns = [
path("v2beta/", include(v2_urls)),
# Remove in 2022.1
path("v2beta/", include(v3_urls)),
path("v3/", include(v3_urls)),
]

View File

@ -1,38 +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 django.views.generic.base import View
from requests import post
from requests.exceptions import RequestException
from authentik.lib.config import CONFIG
class SentryTunnelView(View):
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
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):
return HttpResponse(status=400)
# Body is 2 json objects separated by \n
full_body = request.body
header = loads(full_body.splitlines()[0])
# Check that the DSN is what we expect
dsn = header.get("dsn", "")
if dsn != settings.SENTRY_DSN:
return HttpResponse(status=400)
response = post(
"https://sentry.beryju.org/api/8/envelope/",
data=full_body,
headers={"Content-Type": "application/octet-stream"},
)
try:
response.raise_for_status()
except RequestException:
return HttpResponse(status=500)
return HttpResponse(status=response.status_code)

View File

@ -63,7 +63,7 @@ class ConfigView(APIView):
@extend_schema(responses={200: ConfigSerializer(many=False)})
def get(self, request: Request) -> Response:
"""Retrive public configuration options"""
"""Retrieve public configuration options"""
config = ConfigSerializer(
{
"error_reporting_enabled": CONFIG.y("error_reporting.enabled"),

View File

@ -0,0 +1,65 @@
"""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

@ -1,6 +1,6 @@
"""api v2 urls"""
"""api v3 urls"""
from django.urls import path
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.cache import cache_page
from drf_spectacular.views import SpectacularAPIView
from rest_framework import routers
@ -10,8 +10,8 @@ from authentik.admin.api.system import SystemView
from authentik.admin.api.tasks import TaskViewSet
from authentik.admin.api.version import VersionView
from authentik.admin.api.workers import WorkerView
from authentik.api.v2.config import ConfigView
from authentik.api.v2.sentry import SentryTunnelView
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
@ -24,6 +24,7 @@ from authentik.core.api.users import UserViewSet
from authentik.crypto.api import CertificateKeyPairViewSet
from authentik.events.api.event import EventViewSet
from authentik.events.api.notification import NotificationViewSet
from authentik.events.api.notification_mapping import NotificationWebhookMappingViewSet
from authentik.events.api.notification_rule import NotificationRuleViewSet
from authentik.events.api.notification_transport import NotificationTransportViewSet
from authentik.flows.api.bindings import FlowStageBindingViewSet
@ -98,6 +99,7 @@ from authentik.stages.user_write.api import UserWriteStageViewSet
from authentik.tenants.api import TenantViewSet
router = routers.DefaultRouter()
router.include_format_suffixes = False
router.register("admin/system_tasks", TaskViewSet, basename="admin_system_tasks")
router.register("admin/apps", AppsViewSet, basename="apps")
@ -159,6 +161,7 @@ router.register("propertymappings/all", PropertyMappingViewSet)
router.register("propertymappings/ldap", LDAPPropertyMappingViewSet)
router.register("propertymappings/saml", SAMLPropertyMappingViewSet)
router.register("propertymappings/scope", ScopeMappingViewSet)
router.register("propertymappings/notification", NotificationWebhookMappingViewSet)
router.register("authenticators/duo", DuoDeviceViewSet)
router.register("authenticators/static", StaticDeviceViewSet)
@ -225,7 +228,7 @@ urlpatterns = (
FlowExecutorView.as_view(),
name="flow-executor",
),
path("sentry/", csrf_exempt(SentryTunnelView.as_view()), name="sentry"),
path("schema/", SpectacularAPIView.as_view(), name="schema"),
path("sentry/", SentryTunnelView.as_view(), name="sentry"),
path("schema/", cache_page(86400)(SpectacularAPIView.as_view()), name="schema"),
]
)

View File

@ -67,7 +67,7 @@ class ApplicationSerializer(ModelSerializer):
class ApplicationViewSet(UsedByMixin, ModelViewSet):
"""Application Viewset"""
queryset = Application.objects.all()
queryset = Application.objects.all().prefetch_related("provider")
serializer_class = ApplicationSerializer
search_fields = [
"name",

View File

@ -11,6 +11,7 @@ from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from ua_parser import user_agent_parser
from authentik.api.authorization import OwnerSuperuserPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.models import AuthenticatedSession
from authentik.events.geo import GEOIP_READER, GeoIPDict
@ -102,11 +103,8 @@ class AuthenticatedSessionViewSet(
search_fields = ["user__username", "last_ip", "last_user_agent"]
filterset_fields = ["user__username", "last_ip", "last_user_agent"]
ordering = ["user__username"]
filter_backends = [
DjangoFilterBackend,
OrderingFilter,
SearchFilter,
]
permission_classes = [OwnerSuperuserPermissions]
filter_backends = [DjangoFilterBackend, OrderingFilter, SearchFilter]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()

View File

@ -2,7 +2,7 @@
from django.db.models.query import QuerySet
from django_filters.filters import ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
from rest_framework.fields import BooleanField, CharField, JSONField
from rest_framework.fields import CharField, JSONField
from rest_framework.serializers import ListSerializer, ModelSerializer
from rest_framework.viewsets import ModelViewSet
from rest_framework_guardian.filters import ObjectPermissionsFilter
@ -15,7 +15,6 @@ from authentik.core.models import Group, User
class GroupMemberSerializer(ModelSerializer):
"""Stripped down user serializer to show relevant users for groups"""
is_superuser = BooleanField(read_only=True)
avatar = CharField(read_only=True)
attributes = JSONField(validators=[is_dict], required=False)
uid = CharField(read_only=True)
@ -29,7 +28,6 @@ class GroupMemberSerializer(ModelSerializer):
"name",
"is_active",
"last_login",
"is_superuser",
"email",
"avatar",
"attributes",
@ -81,7 +79,7 @@ class GroupFilter(FilterSet):
class GroupViewSet(UsedByMixin, ModelViewSet):
"""Group Viewset"""
queryset = Group.objects.all()
queryset = Group.objects.all().select_related("parent").prefetch_related("users")
serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"]
filterset_class = GroupFilter

View File

@ -95,7 +95,9 @@ class SourceViewSet(
@action(detail=False, pagination_class=None, filter_backends=[])
def user_settings(self, request: Request) -> Response:
"""Get all sources the user can configure"""
_all_sources: Iterable[Source] = Source.objects.filter(enabled=True).select_subclasses()
_all_sources: Iterable[Source] = (
Source.objects.filter(enabled=True).select_subclasses().order_by("name")
)
matching_sources: list[UserSettingSerializer] = []
for source in _all_sources:
user_settings = source.ui_user_settings

View File

@ -2,15 +2,19 @@
from typing import Any
from django.http.response import Http404
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import OpenApiResponse, extend_schema
from guardian.shortcuts import get_anonymous_user
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField
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
from rest_framework.viewsets import ModelViewSet
from authentik.api.authorization import OwnerSuperuserPermissions
from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserSerializer
@ -23,7 +27,7 @@ from authentik.managed.api import ManagedSerializer
class TokenSerializer(ManagedSerializer, ModelSerializer):
"""Token Serializer"""
user_obj = UserSerializer(required=False)
user_obj = UserSerializer(required=False, source="user")
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
"""Ensure only API or App password tokens are created."""
@ -78,14 +82,25 @@ class TokenViewSet(UsedByMixin, ModelViewSet):
"description",
"expires",
"expiring",
"managed",
]
ordering = ["expires"]
ordering = ["identifier", "expires"]
permission_classes = [OwnerSuperuserPermissions]
filter_backends = [DjangoFilterBackend, OrderingFilter, SearchFilter]
def get_queryset(self):
user = self.request.user if self.request else get_anonymous_user()
if user.is_superuser:
return super().get_queryset()
return super().get_queryset().filter(user=user.pk)
def perform_create(self, serializer: TokenSerializer):
serializer.save(
user=self.request.user,
expiring=self.request.user.attributes.get(USER_ATTRIBUTE_TOKEN_EXPIRING, True),
)
if not self.request.user.is_superuser:
return serializer.save(
user=self.request.user,
expiring=self.request.user.attributes.get(USER_ATTRIBUTE_TOKEN_EXPIRING, True),
)
return super().perform_create(serializer)
@permission_required("authentik_core.view_token_key")
@extend_schema(

View File

@ -1,4 +1,5 @@
"""User API Views"""
from datetime import timedelta
from json import loads
from typing import Optional
@ -7,6 +8,8 @@ from django.db.transaction import atomic
from django.db.utils import IntegrityError
from django.urls import reverse_lazy
from django.utils.http import urlencode
from django.utils.text import slugify
from django.utils.timezone import now
from django.utils.translation import gettext as _
from django_filters.filters import BooleanFilter, CharFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
@ -87,6 +90,9 @@ class UserSerializer(ModelSerializer):
"attributes",
"uid",
]
extra_kwargs = {
"name": {"allow_blank": True},
}
class UserSelfSerializer(ModelSerializer):
@ -95,9 +101,25 @@ class UserSelfSerializer(ModelSerializer):
is_superuser = BooleanField(read_only=True)
avatar = CharField(read_only=True)
groups = ListSerializer(child=GroupSerializer(), read_only=True, source="ak_groups")
groups = SerializerMethodField()
uid = CharField(read_only=True)
@extend_schema_field(
ListSerializer(
child=inline_serializer(
"UserSelfGroups",
{"name": CharField(read_only=True), "pk": CharField(read_only=True)},
)
)
)
def get_groups(self, user: User):
"""Return only the group names a user is member of"""
for group in user.ak_groups.all():
yield {
"name": group.name,
"pk": group.pk,
}
class Meta:
model = User
@ -114,6 +136,7 @@ class UserSelfSerializer(ModelSerializer):
]
extra_kwargs = {
"is_active": {"read_only": True},
"name": {"allow_blank": True},
}
@ -205,6 +228,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
"""User Viewset"""
queryset = User.objects.none()
ordering = ["username"]
serializer_class = UserSerializer
search_fields = ["username", "name", "is_active", "email"]
filterset_class = UsersFilter
@ -271,9 +295,10 @@ class UserViewSet(UsedByMixin, ModelViewSet):
)
group.users.add(user)
token = Token.objects.create(
identifier=f"service-account-{username}-password",
identifier=slugify(f"service-account-{username}-password"),
intent=TokenIntents.INTENT_APP_PASSWORD,
user=user,
expires=now() + timedelta(days=360),
)
return Response({"username": user.username, "token": token.key})
except (IntegrityError) as exc:
@ -304,7 +329,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
"""Allow users to change information on their own profile"""
data = UserSelfSerializer(instance=User.objects.get(pk=request.user.pk), data=request.data)
if not data.is_valid():
return Response(data.errors)
return Response(data.errors, status=400)
new_user = data.save()
# If we're impersonating, we need to update that user object
# since it caches the full object

View File

@ -26,7 +26,7 @@ class Migration(migrations.Migration):
),
(
"username_link",
"Link to a user with identical username address. Can have security implications when a username is used with another source.",
"Link to a user with identical username. Can have security implications when a username is used with another source.",
),
(
"username_deny",

View File

@ -283,7 +283,7 @@ class SourceUserMatchingModes(models.TextChoices):
)
USERNAME_LINK = "username_link", _(
(
"Link to a user with identical username address. Can have security implications "
"Link to a user with identical username. Can have security implications "
"when a username is used with another source."
)
)

View File

@ -184,7 +184,7 @@ class SourceFlowManager:
# Ensure redirect is carried through when user was trying to
# authorize application
final_redirect = self.request.session.get(SESSION_KEY_GET, {}).get(
NEXT_ARG_NAME, "authentik_core:if-admin"
NEXT_ARG_NAME, "authentik_core:if-user"
)
kwargs.update(
{
@ -243,9 +243,9 @@ class SourceFlowManager:
return self.handle_auth_user(connection)
return redirect(
reverse(
"authentik_core:if-admin",
"authentik_core:if-user",
)
+ f"#/user;page-{self.source.slug}"
+ f"#/settings;page-{self.source.slug}"
)
def handle_enroll(

View File

@ -28,3 +28,7 @@ class PostUserEnrollmentStage(StageView):
source=connection.source,
).from_http(self.request)
return self.executor.stage_ok()
def post(self, request: HttpRequest) -> HttpResponse:
"""Wrapper for post requests"""
return self.get(request)

View File

@ -8,16 +8,15 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{% block title %}{% trans title|default:tenant.branding_title %}{% endblock %}</title>
<link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/page.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/empty-state.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/spinner.css' %}?v={{ ak_version }}">
<link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly-base.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/page.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/empty-state.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/spinner.css' %}">
{% block head_before %}
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}?v={{ ak_version }}">
<script src="{% static 'dist/poly.js' %}?v={{ ak_version }}" type="module"></script>
<script>window["polymerSkipLoadingFontRoboto"] = true;</script>
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<script src="{% static 'dist/poly.js' %}" type="module"></script>
{% block head %}
{% endblock %}
</head>

View File

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

View File

@ -21,7 +21,7 @@ You've logged out of {{ application }}.
{% endblocktrans %}
</p>
<a id="ak-back-home" href="{% url 'authentik_core:if-admin' %}" class="pf-c-button pf-m-primary">{% trans 'Go back to overview' %}</a>
<a id="ak-back-home" href="{% url 'authentik_core:root-redirect' %}" class="pf-c-button pf-m-primary">{% trans 'Go back to overview' %}</a>
<a id="logout" href="{% url 'authentik_flows:default-invalidation' %}" class="pf-c-button pf-m-secondary">{% trans 'Log out of authentik' %}</a>

View File

@ -4,13 +4,14 @@
{% load i18n %}
{% block head_before %}
{{ block.super }}
{% if flow.compatibility_mode %}
<script>ShadyDOM = { force: !navigator.webdriver };</script>
{% endif %}
{% endblock %}
{% block head %}
<script src="{% static 'dist/FlowInterface.js' %}?v={{ ak_version }}" type="module"></script>
<script src="{% static 'dist/FlowInterface.js' %}" type="module"></script>
<style>
.pf-c-background-image::before {
--ak-flow-background: url("{{ flow.background_url }}");

View File

@ -0,0 +1,28 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load i18n %}
{% block head %}
<script src="{% static 'dist/UserInterface.js' %}" type="module"></script>
{% endblock %}
{% block body %}
<ak-message-container></ak-message-container>
<ak-interface-user>
<section class="ak-static-page pf-c-page__main-section pf-m-no-padding-mobile pf-m-xl">
<div class="pf-c-empty-state" style="height: 100vh;">
<div class="pf-c-empty-state__content">
<span class="pf-c-spinner pf-m-xl pf-c-empty-state__icon" role="progressbar" aria-valuetext="{% trans 'Loading...' %}">
<span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span>
</span>
<h1 class="pf-c-title pf-m-lg">
{% trans "Loading..." %}
</h1>
</div>
</div>
</section>
</ak-interface-user>
{% endblock %}

View File

@ -4,7 +4,7 @@
{% load i18n %}
{% block head_before %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}">
{% endblock %}
{% block head %}

View File

@ -58,4 +58,4 @@ class TestImpersonation(TestCase):
self.client.force_login(self.other_user)
response = self.client.get(reverse("authentik_core:impersonate-end"))
self.assertRedirects(response, reverse("authentik_core:if-admin"))
self.assertRedirects(response, reverse("authentik_core:if-user"))

View File

@ -1,4 +1,6 @@
"""Test token API"""
from json import loads
from django.urls.base import reverse
from django.utils.timezone import now
from guardian.shortcuts import get_anonymous_user
@ -13,7 +15,8 @@ class TestTokenAPI(APITestCase):
def setUp(self) -> None:
super().setUp()
self.user = User.objects.get(username="akadmin")
self.user = User.objects.create(username="testuser")
self.admin = User.objects.get(username="akadmin")
self.client.force_login(self.user)
def test_token_create(self):
@ -55,3 +58,29 @@ class TestTokenAPI(APITestCase):
clean_expired_models.delay().get()
token.refresh_from_db()
self.assertNotEqual(key, token.key)
def test_list(self):
"""Test Token List (Test normal authentication)"""
token_should: Token = Token.objects.create(
identifier="test", expiring=False, user=self.user
)
Token.objects.create(identifier="test-2", expiring=False, user=get_anonymous_user())
response = self.client.get(reverse(("authentik_api:token-list")))
body = loads(response.content)
self.assertEqual(len(body["results"]), 1)
self.assertEqual(body["results"][0]["identifier"], token_should.identifier)
def test_list_admin(self):
"""Test Token List (Test with admin auth)"""
self.client.force_login(self.admin)
token_should: Token = Token.objects.create(
identifier="test", expiring=False, user=self.user
)
token_should_not: Token = Token.objects.create(
identifier="test-2", expiring=False, user=get_anonymous_user()
)
response = self.client.get(reverse(("authentik_api:token-list")))
body = loads(response.content)
self.assertEqual(len(body["results"]), 2)
self.assertEqual(body["results"][0]["identifier"], token_should.identifier)
self.assertEqual(body["results"][1]["identifier"], token_should_not.identifier)

View File

@ -12,7 +12,7 @@ from authentik.core.views.session import EndSessionView
urlpatterns = [
path(
"",
login_required(RedirectView.as_view(pattern_name="authentik_core:if-admin")),
login_required(RedirectView.as_view(pattern_name="authentik_core:if-user")),
name="root-redirect",
),
# Impersonation
@ -32,6 +32,11 @@ urlpatterns = [
ensure_csrf_cookie(TemplateView.as_view(template_name="if/admin.html")),
name="if-admin",
),
path(
"if/user/",
ensure_csrf_cookie(TemplateView.as_view(template_name="if/user.html")),
name="if-user",
),
path(
"if/flow/<slug:flow_slug>/",
ensure_csrf_cookie(FlowInterfaceView.as_view()),

View File

@ -28,7 +28,7 @@ class ImpersonateInitView(View):
Event.new(EventAction.IMPERSONATION_STARTED).from_http(request, user_to_be)
return redirect("authentik_core:if-admin")
return redirect("authentik_core:if-user")
class ImpersonateEndView(View):
@ -41,7 +41,7 @@ class ImpersonateEndView(View):
or SESSION_IMPERSONATE_ORIGINAL_USER not in request.session
):
LOGGER.debug("Can't end impersonation", user=request.user)
return redirect("authentik_core:if-admin")
return redirect("authentik_core:if-user")
original_user = request.session[SESSION_IMPERSONATE_ORIGINAL_USER]

View File

@ -78,9 +78,7 @@ class CertificateKeyPair(CreatedUpdatedModel):
@property
def kid(self):
"""Get Key ID used for JWKS"""
return "{0}".format(
md5(self.key_data.encode("utf-8")).hexdigest() if self.key_data else "" # nosec
)
return md5(self.key_data.encode("utf-8")).hexdigest() if self.key_data else "" # nosec
def __str__(self) -> str:
return f"Certificate-Key Pair {self.name}"

View File

@ -1,8 +1,13 @@
"""Notification API Views"""
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.fields import ReadOnlyField
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
from rest_framework.viewsets import GenericViewSet
@ -53,3 +58,18 @@ class NotificationViewSet(
]
permission_classes = [OwnerPermissions]
filter_backends = [OwnerFilter, DjangoFilterBackend, OrderingFilter, SearchFilter]
@extend_schema(
request=OpenApiTypes.NONE,
responses={
204: OpenApiResponse(description="Marked tasks as read successfully."),
},
)
@action(detail=False, methods=["post"])
def mark_all_seen(self, request: Request) -> Response:
"""Mark all the user's notifications as seen"""
notifications = Notification.objects.filter(user=request.user)
for notification in notifications:
notification.seen = True
Notification.objects.bulk_update(notifications, ["seen"])
return Response({}, status=204)

View File

@ -0,0 +1,28 @@
"""NotificationWebhookMapping API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.events.models import NotificationWebhookMapping
class NotificationWebhookMappingSerializer(ModelSerializer):
"""NotificationWebhookMapping Serializer"""
class Meta:
model = NotificationWebhookMapping
fields = [
"pk",
"name",
"expression",
]
class NotificationWebhookMappingViewSet(UsedByMixin, ModelViewSet):
"""NotificationWebhookMapping Viewset"""
queryset = NotificationWebhookMapping.objects.all()
serializer_class = NotificationWebhookMappingSerializer
filterset_fields = ["name"]
ordering = ["name"]

View File

@ -1,7 +1,10 @@
"""NotificationTransport API Views"""
from typing import Any
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
@ -29,6 +32,14 @@ class NotificationTransportSerializer(ModelSerializer):
"""Return selected mode with a UI Label"""
return TransportMode(instance.mode).label
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
"""Ensure the required fields are set."""
mode = attrs.get("mode")
if mode in [TransportMode.WEBHOOK, TransportMode.WEBHOOK_SLACK]:
if "webhook_url" not in attrs or attrs.get("webhook_url", "") == "":
raise ValidationError("Webhook URL may not be empty.")
return attrs
class Meta:
model = NotificationTransport
@ -38,6 +49,7 @@ class NotificationTransportSerializer(ModelSerializer):
"mode",
"mode_verbose",
"webhook_url",
"webhook_mapping",
"send_once",
]

View File

@ -1,10 +1,7 @@
"""authentik events app"""
from datetime import timedelta
from importlib import import_module
from django.apps import AppConfig
from django.db import ProgrammingError
from django.utils.timezone import now
class AuthentikEventsConfig(AppConfig):
@ -16,12 +13,3 @@ class AuthentikEventsConfig(AppConfig):
def ready(self):
import_module("authentik.events.signals")
try:
from authentik.events.models import Event
date_from = now() - timedelta(days=1)
for event in Event.objects.filter(created__gte=date_from):
event._set_prom_metrics()
except ProgrammingError:
pass

View File

@ -0,0 +1,46 @@
# Generated by Django 3.2.6 on 2021-09-11 22:17
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0028_alter_token_intent"),
("authentik_events", "0017_alter_event_action"),
]
operations = [
migrations.CreateModel(
name="NotificationWebhookMapping",
fields=[
(
"propertymapping_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="authentik_core.propertymapping",
),
),
],
options={
"verbose_name": "Notification Webhook Mapping",
"verbose_name_plural": "Notification Webhook Mappings",
},
bases=("authentik_core.propertymapping",),
),
migrations.AddField(
model_name="notificationtransport",
name="webhook_mapping",
field=models.ForeignKey(
default=None,
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to="authentik_events.notificationwebhookmapping",
),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.7 on 2021-10-04 15:31
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_events", "0018_auto_20210911_2217"),
]
operations = [
migrations.AlterField(
model_name="notificationtransport",
name="webhook_url",
field=models.TextField(blank=True, validators=[django.core.validators.URLValidator()]),
),
]

View File

@ -2,25 +2,26 @@
from datetime import timedelta
from inspect import getmodule, stack
from smtplib import SMTPException
from typing import Optional, Union
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.http import HttpRequest
from django.http.request import QueryDict
from django.utils.timezone import now
from django.utils.translation import gettext as _
from prometheus_client import Gauge
from requests import RequestException, post
from requests import RequestException
from structlog.stdlib import get_logger
from authentik import __version__
from authentik.core.middleware import SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_USER
from authentik.core.models import ExpiringModel, Group, User
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.sentry import SentryIgnoredException
from authentik.lib.utils.http import get_client_ip
from authentik.lib.utils.http import get_client_ip, get_http_session
from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.models import PolicyBindingModel
from authentik.stages.email.utils import TemplateEmailMessage
@ -28,11 +29,8 @@ from authentik.tenants.models import Tenant
from authentik.tenants.utils import DEFAULT_TENANT
LOGGER = get_logger("authentik.events")
GAUGE_EVENTS = Gauge(
"authentik_events",
"Events in authentik",
["action", "user_username", "app", "client_ip"],
)
if TYPE_CHECKING:
from rest_framework.serializers import Serializer
def default_event_duration():
@ -143,8 +141,9 @@ class Event(ExpiringModel):
`user` arguments optionally overrides user from requests."""
if request:
self.context["http_request"] = {
"path": request.get_full_path(),
"path": request.path,
"method": request.method,
"args": QueryDict(request.META.get("QUERY_STRING", "")),
}
if hasattr(request, "tenant"):
tenant: Tenant = request.tenant
@ -182,14 +181,6 @@ class Event(ExpiringModel):
return
self.context["geo"] = city
def _set_prom_metrics(self):
GAUGE_EVENTS.labels(
action=self.action,
user_username=self.user.get("username"),
app=self.app,
client_ip=self.client_ip,
).set(self.created.timestamp())
def save(self, *args, **kwargs):
if self._state.adding:
LOGGER.debug(
@ -200,7 +191,6 @@ class Event(ExpiringModel):
user=self.user,
)
super().save(*args, **kwargs)
self._set_prom_metrics()
@property
def summary(self) -> str:
@ -234,7 +224,10 @@ class NotificationTransport(models.Model):
name = models.TextField(unique=True)
mode = models.TextField(choices=TransportMode.choices)
webhook_url = models.TextField(blank=True)
webhook_url = models.TextField(blank=True, validators=[URLValidator()])
webhook_mapping = models.ForeignKey(
"NotificationWebhookMapping", on_delete=models.SET_DEFAULT, null=True, default=None
)
send_once = models.BooleanField(
default=False,
help_text=_(
@ -254,15 +247,22 @@ class NotificationTransport(models.Model):
def send_webhook(self, notification: "Notification") -> list[str]:
"""Send notification to generic webhook"""
default_body = {
"body": notification.body,
"severity": notification.severity,
"user_email": notification.user.email,
"user_username": notification.user.username,
}
if self.webhook_mapping:
default_body = self.webhook_mapping.evaluate(
user=notification.user,
request=None,
notification=notification,
)
try:
response = post(
response = get_http_session().post(
self.webhook_url,
json={
"body": notification.body,
"severity": notification.severity,
"user_email": notification.user.email,
"user_username": notification.user.username,
},
json=default_body,
)
response.raise_for_status()
except RequestException as exc:
@ -312,7 +312,7 @@ class NotificationTransport(models.Model):
if notification.event:
body["attachments"][0]["title"] = notification.event.action
try:
response = post(self.webhook_url, json=body)
response = get_http_session().post(self.webhook_url, json=body)
response.raise_for_status()
except RequestException as exc:
text = exc.response.text if exc.response else str(exc)
@ -429,3 +429,25 @@ class NotificationRule(PolicyBindingModel):
verbose_name = _("Notification Rule")
verbose_name_plural = _("Notification Rules")
class NotificationWebhookMapping(PropertyMapping):
"""Modify the schema and layout of the webhook being sent"""
@property
def component(self) -> str:
return "ak-property-mapping-notification-form"
@property
def serializer(self) -> Type["Serializer"]:
from authentik.events.api.notification_mapping import NotificationWebhookMappingSerializer
return NotificationWebhookMappingSerializer
def __str__(self):
return f"Notification Webhook Mapping {self.name}"
class Meta:
verbose_name = _("Notification Webhook Mapping")
verbose_name_plural = _("Notification Webhook Mappings")

View File

@ -3,7 +3,6 @@ from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from timeit import default_timer
from traceback import format_tb
from typing import Any, Optional
from celery import Task
@ -11,6 +10,7 @@ from django.core.cache import cache
from prometheus_client import Gauge
from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string
GAUGE_TASKS = Gauge(
"authentik_system_tasks",
@ -41,8 +41,7 @@ class TaskResult:
def with_error(self, exc: Exception) -> "TaskResult":
"""Since errors might not always be pickle-able, set the traceback"""
self.messages.extend(format_tb(exc.__traceback__))
self.messages.append(str(exc))
self.messages.extend(exception_to_string(exc).splitlines())
return self
@ -174,9 +173,7 @@ class MonitoredTask(Task):
).save(self.result_timeout_hours)
Event.new(
EventAction.SYSTEM_TASK_EXCEPTION,
message=(
f"Task {self.__name__} encountered an error: " "\n".join(self._result.messages)
),
message=(f"Task {self.__name__} encountered an error: {exception_to_string(exc)}"),
).save()
return super().on_failure(exc, task_id, args, kwargs, einfo=einfo)

View File

@ -4,15 +4,21 @@ from django.urls import reverse
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.events.models import Event, EventAction
from authentik.events.models import (
Event,
EventAction,
Notification,
NotificationSeverity,
TransportMode,
)
class TestEventsAPI(APITestCase):
"""Test Event API"""
def setUp(self) -> None:
user = User.objects.get(username="akadmin")
self.client.force_login(user)
self.user = User.objects.get(username="akadmin")
self.client.force_login(self.user)
def test_top_n(self):
"""Test top_per_user"""
@ -30,3 +36,34 @@ class TestEventsAPI(APITestCase):
reverse("authentik_api:event-actions"),
)
self.assertEqual(response.status_code, 200)
def test_notifications(self):
"""Test notifications"""
notification = Notification.objects.create(
user=self.user, severity=NotificationSeverity.ALERT, body="", seen=False
)
self.client.post(
reverse("authentik_api:notification-mark-all-seen"),
)
notification.refresh_from_db()
self.assertTrue(notification.seen)
def test_transport(self):
"""Test transport API"""
response = self.client.post(
reverse("authentik_api:notificationtransport-list"),
data={
"name": "foo-with",
"mode": TransportMode.WEBHOOK,
"webhook_url": "http://foo.com",
},
)
self.assertEqual(response.status_code, 201)
response = self.client.post(
reverse("authentik_api:notificationtransport-list"),
data={
"name": "foo-without",
"mode": TransportMode.WEBHOOK,
},
)
self.assertEqual(response.status_code, 400)

View File

@ -77,7 +77,7 @@ def sanitize_dict(source: dict[Any, Any]) -> dict[Any, Any]:
final_dict = {}
for key, value in source.items():
if is_dataclass(value):
# Because asdict calls `copy.deepcopy(obj)` on everything thats not tuple/dict,
# Because asdict calls `copy.deepcopy(obj)` on everything that's not tuple/dict,
# and deepcopy doesn't work with HttpRequests (neither django nor rest_framework).
# Currently, the only dataclass that actually holds an http request is a PolicyRequest
if isinstance(value, PolicyRequest):

View File

@ -108,6 +108,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
queryset = Flow.objects.all()
serializer_class = FlowSerializer
lookup_field = "slug"
ordering = ["slug", "name"]
search_fields = ["name", "slug", "designation", "title"]
filterset_fields = ["flow_uuid", "name", "slug", "designation"]

View File

@ -86,7 +86,7 @@ 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()
_all_stages: Iterable[Stage] = Stage.objects.all().select_subclasses().order_by("name")
matching_stages: list[dict] = []
for stage in _all_stages:
user_settings = stage.ui_user_settings

View File

@ -31,6 +31,7 @@ class FlowPlanProcess(PROCESS_CLASS): # pragma: no cover
self.request = RequestFactory().get("/")
def run(self):
"""Execute 1000 flow plans"""
print(f"Proc {self.index} Running")
def test_inner():

View File

@ -0,0 +1,21 @@
# Generated by Django 3.2.6 on 2021-08-30 14:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_flows", "0023_alter_flow_background"),
]
operations = [
migrations.AlterField(
model_name="flow",
name="compatibility_mode",
field=models.BooleanField(
default=False,
help_text="Enable compatibility mode, increases compatibility with password managers on mobile devices.",
),
),
]

View File

@ -125,7 +125,7 @@ class Flow(SerializerModel, PolicyBindingModel):
)
compatibility_mode = models.BooleanField(
default=True,
default=False,
help_text=_(
"Enable compatibility mode, increases compatibility with "
"password managers on mobile devices."

View File

@ -57,11 +57,11 @@ class FlowPlan:
markers: list[StageMarker] = field(default_factory=list)
def append_stage(self, stage: Stage, marker: Optional[StageMarker] = None):
"""Append `stage` to all stages, optionall with stage marker"""
"""Append `stage` to all stages, optionally with stage marker"""
return self.append(FlowStageBinding(stage=stage), marker)
def append(self, binding: FlowStageBinding, marker: Optional[StageMarker] = None):
"""Append `stage` to all stages, optionall with stage marker"""
"""Append `stage` to all stages, optionally with stage marker"""
self.bindings.append(binding)
self.markers.append(marker or StageMarker())

View File

@ -0,0 +1,31 @@
"""stage view tests"""
from typing import Callable, Type
from django.test import RequestFactory, TestCase
from authentik.flows.stage import StageView
from authentik.flows.views import FlowExecutorView
from authentik.lib.utils.reflection import all_subclasses
class TestViews(TestCase):
"""Generic model properties tests"""
def setUp(self) -> None:
self.factory = RequestFactory()
self.exec = FlowExecutorView(request=self.factory.get("/"))
def view_tester_factory(view_class: Type[StageView]) -> Callable:
"""Test a form"""
def tester(self: TestViews):
model_class = view_class(self.exec)
self.assertIsNotNone(model_class.post)
self.assertIsNotNone(model_class.get)
return tester
for view in all_subclasses(StageView):
setattr(TestViews, f"test_view_{view.__name__}", view_tester_factory(view))

View File

@ -2,10 +2,10 @@
from unittest.mock import MagicMock, PropertyMock, patch
from django.http import HttpRequest, HttpResponse
from django.test import TestCase
from django.test.client import RequestFactory
from django.urls import reverse
from django.utils.encoding import force_str
from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.flows.challenge import ChallengeTypes
@ -37,7 +37,7 @@ def to_stage_response(request: HttpRequest, source: HttpResponse):
TO_STAGE_RESPONSE_MOCK = MagicMock(side_effect=to_stage_response)
class TestFlowExecutor(TestCase):
class TestFlowExecutor(APITestCase):
"""Test views logic"""
def setUp(self):
@ -438,7 +438,7 @@ class TestFlowExecutor(TestCase):
# third request, this should trigger the re-evaluate
# A get request will evaluate the policies and this will return stage 4
# but it won't save it, hence we cant' check the plan
# but it won't save it, hence we can't check the plan
response = self.client.get(exec_url)
self.assertEqual(response.status_code, 200)
self.assertJSONEqual(

View File

@ -1,5 +1,5 @@
"""flow views tests"""
from django.test import Client, TestCase
from django.test import TestCase
from django.urls import reverse
from authentik.flows.models import Flow, FlowDesignation
@ -10,9 +10,6 @@ from authentik.flows.views import SESSION_KEY_PLAN
class TestHelperView(TestCase):
"""Test helper views logic"""
def setUp(self):
self.client = Client()
def test_default_view(self):
"""Test that ToDefaultFlow returns the expected URL"""
flow = Flow.objects.filter(

View File

@ -11,7 +11,7 @@ from authentik.lib.sentry import SentryIgnoredException
def get_attrs(obj: SerializerModel) -> dict[str, Any]:
"""Get object's attributes via their serializer, and covert it to a normal dict"""
"""Get object's attributes via their serializer, and convert it to a normal dict"""
data = dict(obj.serializer(obj).data)
to_remove = (
"policies",

View File

@ -14,12 +14,7 @@ from django.utils.decorators import method_decorator
from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.generic import View
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import (
OpenApiParameter,
OpenApiResponse,
PolymorphicProxySerializer,
extend_schema,
)
from drf_spectacular.utils import OpenApiParameter, PolymorphicProxySerializer, extend_schema
from rest_framework.permissions import AllowAny
from rest_framework.views import APIView
from sentry_sdk import capture_exception
@ -131,12 +126,12 @@ class FlowExecutorView(APIView):
# pylint: disable=unused-argument, too-many-return-statements
def dispatch(self, request: HttpRequest, flow_slug: str) -> HttpResponse:
# Early check if theres an active Plan for the current session
# 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, deleteing plan",
"f(exec): Found existing plan for other flow, deleting plan",
)
# Existing plan is deleted from session and instance
self.plan = None
@ -213,9 +208,6 @@ class FlowExecutorView(APIView):
serializers=challenge_types(),
resource_type_field_name="component",
),
404: OpenApiResponse(
description="No Token found"
), # This error can be raised by the email stage
},
request=OpenApiTypes.NONE,
parameters=[
@ -441,7 +433,7 @@ class ToDefaultFlow(View):
plan: FlowPlan = self.request.session[SESSION_KEY_PLAN]
if plan.flow_pk != flow.pk.hex:
LOGGER.warning(
"f(def): Found existing plan for other flow, deleteing plan",
"f(def): Found existing plan for other flow, deleting plan",
flow_slug=flow.slug,
)
del self.request.session[SESSION_KEY_PLAN]

View File

@ -9,7 +9,9 @@ postgresql:
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:
host: localhost
@ -54,6 +56,7 @@ outposts:
# %(build_hash)s: Build hash if you're running a beta version
docker_image_base: "ghcr.io/goauthentik/%(type)s:%(version)s"
disable_update_check: false
avatars: env://AUTHENTIK_AUTHENTIK__AVATARS?gravatar
geoip: "./GeoLite2-City.mmdb"

View File

@ -4,13 +4,13 @@ from textwrap import indent
from typing import Any, Iterable, Optional
from django.core.exceptions import FieldError
from requests import Session
from rest_framework.serializers import ValidationError
from sentry_sdk.hub import Hub
from sentry_sdk.tracing import Span
from structlog.stdlib import get_logger
from authentik.core.models import User
from authentik.lib.utils.http import get_http_session
LOGGER = get_logger()
@ -35,7 +35,7 @@ class BaseEvaluator:
"ak_is_group_member": BaseEvaluator.expr_is_group_member,
"ak_user_by": BaseEvaluator.expr_user_by,
"ak_logger": get_logger(),
"requests": Session(),
"requests": get_http_session(),
}
self._context = {}
self._filename = "BaseEvalautor"

View File

@ -93,6 +93,7 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
if "exc_info" in hint:
_, exc_value, _ = hint["exc_info"]
if isinstance(exc_value, ignored_classes):
LOGGER.debug("dropping exception", exception=exc_value)
return None
if "logger" in event:
if event["logger"] in [

View File

@ -32,7 +32,7 @@ class TestConfig(TestCase):
config = ConfigLoader()
environ["foo"] = "bar"
self.assertEqual(config.parse_uri("env://foo"), "bar")
self.assertEqual(config.parse_uri("env://fo?bar"), "bar")
self.assertEqual(config.parse_uri("env://foo?bar"), "bar")
def test_uri_file(self):
"""Test URI parsing (file load)"""

View File

@ -27,7 +27,7 @@ class TestHTTP(TestCase):
token = Token.objects.create(
identifier="test", user=self.user, intent=TokenIntents.INTENT_API
)
# Invalid, non-existant token
# Invalid, non-existent token
request = self.factory.get(
"/",
**{
@ -36,7 +36,7 @@ class TestHTTP(TestCase):
},
)
self.assertEqual(get_client_ip(request), "127.0.0.1")
# Invalid, user doesn't have permisions
# Invalid, user doesn't have permissions
request = self.factory.get(
"/",
**{

View File

@ -1,9 +1,13 @@
"""http helpers"""
from os import environ
from typing import Any, Optional
from django.http import HttpRequest
from requests.sessions import Session
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
OUTPOST_REMOTE_IP_HEADER = "HTTP_X_AUTHENTIK_REMOTE_IP"
OUTPOST_TOKEN_HEADER = "HTTP_X_AUTHENTIK_OUTPOST_TOKEN" # nosec
DEFAULT_IP = "255.255.255.255"
@ -60,3 +64,16 @@ def get_client_ip(request: Optional[HttpRequest]) -> str:
if override:
return override
return _get_client_ip_from_meta(request.META)
def authentik_user_agent() -> str:
"""Get a common user agent"""
build = environ.get(ENV_GIT_HASH_KEY, "tagged")
return f"authentik@{__version__} (build={build})"
def get_http_session() -> Session:
"""Get a requests session with common headers"""
session = Session()
session.headers["User-Agent"] = authentik_user_agent()
return session

View File

@ -1,5 +1,6 @@
"""authentik lib reflection utilities"""
from importlib import import_module
from typing import Union
from django.conf import settings
@ -19,12 +20,12 @@ def all_subclasses(cls, sort=True):
return classes
def class_to_path(cls):
def class_to_path(cls: type) -> str:
"""Turn Class (Class or instance) into module path"""
return f"{cls.__module__}.{cls.__name__}"
def path_to_class(path):
def path_to_class(path: Union[str, None]) -> Union[type, None]:
"""Import module and return class"""
if not path:
return None

View File

@ -15,7 +15,7 @@ from authentik.core.channels import AuthJsonConsumer
from authentik.outposts.models import OUTPOST_HELLO_INTERVAL, Outpost, OutpostState
GAUGE_OUTPOSTS_CONNECTED = Gauge(
"authentik_outposts_connected", "Currently connected outposts", ["outpost", "uid"]
"authentik_outposts_connected", "Currently connected outposts", ["outpost", "uid", "expected"]
)
GAUGE_OUTPOSTS_LAST_UPDATE = Gauge(
"authentik_outposts_last_update",
@ -76,6 +76,7 @@ class OutpostConsumer(AuthJsonConsumer):
GAUGE_OUTPOSTS_CONNECTED.labels(
outpost=self.outpost.name,
uid=self.last_uid,
expected=self.outpost.config.kubernetes_replicas,
).dec()
LOGGER.debug(
"removed outpost instance from cache",
@ -100,9 +101,10 @@ class OutpostConsumer(AuthJsonConsumer):
GAUGE_OUTPOSTS_CONNECTED.labels(
outpost=self.outpost.name,
uid=self.last_uid,
expected=self.outpost.config.kubernetes_replicas,
).inc()
LOGGER.debug(
"added outpost instace to cache",
"added outpost instance to cache",
outpost=self.outpost,
instance_uuid=self.last_uid,
)

View File

@ -29,13 +29,16 @@ class DockerController(BaseController):
raise ControllerException from exc
def _get_labels(self) -> dict[str, str]:
return {}
return {
"io.goauthentik.outpost-uuid": self.outpost.pk.hex,
}
def _get_env(self) -> dict[str, str]:
return {
"AUTHENTIK_HOST": self.outpost.config.authentik_host.lower(),
"AUTHENTIK_INSECURE": str(self.outpost.config.authentik_host_insecure).lower(),
"AUTHENTIK_TOKEN": self.outpost.token.key,
"AUTHENTIK_HOST_BROWSER": self.outpost.config.authentik_host_browser,
}
def _comp_env(self, container: Container) -> bool:
@ -49,6 +52,17 @@ class DockerController(BaseController):
return True
return False
def _comp_labels(self, container: Container) -> bool:
"""Check if container's labels is equal to what we would set. Return true if container needs
to be rebuilt."""
should_be = self._get_labels()
for key, expected_value in should_be.items():
if key not in container.labels:
return True
if container.labels[key] != expected_value:
return True
return False
def _comp_ports(self, container: Container) -> bool:
"""Check that the container has the correct ports exposed. Return true if container needs
to be rebuilt."""
@ -62,6 +76,9 @@ class DockerController(BaseController):
# {'HostIp': '0.0.0.0', 'HostPort': '389'},
# {'HostIp': '::', 'HostPort': '389'}
# ]}
# If no ports are mapped (either mapping disabled, or host network)
if not container.ports:
return False
for port in self.deployment_ports:
key = f"{port.inner_port or port.port}/{port.protocol.lower()}"
if key not in container.ports:
@ -85,16 +102,19 @@ class DockerController(BaseController):
"image": image_name,
"name": container_name,
"detach": True,
"ports": {
f"{port.inner_port or port.port}/{port.protocol.lower()}": port.port
for port in self.deployment_ports
},
"environment": self._get_env(),
"labels": self._get_labels(),
"restart_policy": {"Name": "unless-stopped"},
"network": self.outpost.config.docker_network,
}
if self.outpost.config.docker_map_ports:
container_args["ports"] = {
f"{port.inner_port or port.port}/{port.protocol.lower()}": str(port.port)
for port in self.deployment_ports
}
if settings.TEST:
del container_args["ports"]
del container_args["network"]
container_args["network_mode"] = "host"
return (
self.client.containers.create(**container_args),
@ -133,6 +153,11 @@ class DockerController(BaseController):
self.logger.info("Container has outdated config, re-creating...")
self.down()
return self.up(depth + 1)
# Check that container values match our values
if self._comp_labels(container):
self.logger.info("Container has outdated labels, re-creating...")
self.down()
return self.up(depth + 1)
if (
container.attrs.get("HostConfig", {})
.get("RestartPolicy", {})
@ -144,11 +169,9 @@ class DockerController(BaseController):
self.down()
return self.up(depth + 1)
# Check that container is healthy
if (
container.status == "running"
and container.attrs.get("State", {}).get("Health", {}).get("Status", "")
!= "healthy"
):
if container.status == "running" and container.attrs.get("State", {}).get(
"Health", {}
).get("Status", "") not in ["healthy", "starting"]:
# At this point we know the config is correct, but the container isn't healthy,
# so we just restart it with the same config
if has_been_created:
@ -197,6 +220,7 @@ class DockerController(BaseController):
"AUTHENTIK_HOST": self.outpost.config.authentik_host,
"AUTHENTIK_INSECURE": str(self.outpost.config.authentik_host_insecure),
"AUTHENTIK_TOKEN": self.outpost.token.key,
"AUTHENTIK_HOST_BROWSER": self.outpost.config.authentik_host_browser,
},
"labels": self._get_labels(),
}

View File

@ -3,13 +3,14 @@ from typing import TYPE_CHECKING, Generic, TypeVar
from django.utils.text import slugify
from kubernetes.client import V1ObjectMeta
from kubernetes.client.exceptions import ApiException, OpenApiException
from kubernetes.client.models.v1_deployment import V1Deployment
from kubernetes.client.models.v1_pod import V1Pod
from kubernetes.client.rest import ApiException
from structlog.stdlib import get_logger
from urllib3.exceptions import HTTPError
from authentik import __version__
from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.controllers.k8s.triggers import NeedsRecreate, NeedsUpdate
from authentik.outposts.managed import MANAGED_OUTPOST
if TYPE_CHECKING:
@ -19,18 +20,6 @@ if TYPE_CHECKING:
T = TypeVar("T", V1Pod, V1Deployment)
class ReconcileTrigger(SentryIgnoredException):
"""Base trigger raised by child classes to notify us"""
class NeedsRecreate(ReconcileTrigger):
"""Exception to trigger a complete recreate of the Kubernetes Object"""
class NeedsUpdate(ReconcileTrigger):
"""Exception to trigger an update to the Kubernetes Object"""
class KubernetesObjectReconciler(Generic[T]):
"""Base Kubernetes Reconciler, handles the basic logic."""
@ -72,8 +61,9 @@ class KubernetesObjectReconciler(Generic[T]):
try:
try:
current = self.retrieve()
except ApiException as exc:
if exc.status == 404:
except (OpenApiException, HTTPError) as exc:
# pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, triggering recreate")
raise NeedsRecreate from exc
self.logger.debug("Other unhandled error", exc=exc)
@ -104,9 +94,10 @@ class KubernetesObjectReconciler(Generic[T]):
current = self.retrieve()
self.delete(current)
self.logger.debug("Removing")
except ApiException as exc:
if exc.status == 404:
self.logger.debug("Failed to get current, assuming non-existant")
except (OpenApiException, HTTPError) as exc:
# pylint: disable=no-member
if isinstance(exc, ApiException) and exc.status == 404:
self.logger.debug("Failed to get current, assuming non-existent")
return
self.logger.debug("Other unhandled error", exc=exc)
raise exc
@ -126,7 +117,7 @@ class KubernetesObjectReconciler(Generic[T]):
raise NotImplementedError
def retrieve(self) -> T:
"""API Wrapper to retrive object"""
"""API Wrapper to retrieve object"""
raise NotImplementedError
def delete(self, reference: T):

View File

@ -17,7 +17,9 @@ from kubernetes.client import (
)
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler, NeedsUpdate
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
from authentik.outposts.controllers.k8s.utils import compare_ports
from authentik.outposts.models import Outpost
if TYPE_CHECKING:
@ -35,7 +37,10 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
self.outpost = self.controller.outpost
def reconcile(self, current: V1Deployment, reference: V1Deployment):
super().reconcile(current, reference)
compare_ports(
current.spec.template.spec.containers[0].ports,
reference.spec.template.spec.containers[0].ports,
)
if current.spec.replicas != reference.spec.replicas:
raise NeedsUpdate()
if (
@ -43,6 +48,7 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
!= reference.spec.template.spec.containers[0].image
):
raise NeedsUpdate()
super().reconcile(current, reference)
def get_pod_meta(self) -> dict[str, str]:
"""Get common object metadata"""
@ -89,6 +95,15 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
)
),
),
V1EnvVar(
name="AUTHENTIK_HOST_BROWSER",
value_from=V1EnvVarSource(
secret_key_ref=V1SecretKeySelector(
name=self.name,
key="authentik_host_browser",
)
),
),
V1EnvVar(
name="AUTHENTIK_TOKEN",
value_from=V1EnvVarSource(

View File

@ -5,7 +5,8 @@ from typing import TYPE_CHECKING
from kubernetes.client import CoreV1Api, V1Secret
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler, NeedsUpdate
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
if TYPE_CHECKING:
from authentik.outposts.controllers.kubernetes import KubernetesController
@ -26,7 +27,7 @@ class SecretReconciler(KubernetesObjectReconciler[V1Secret]):
def reconcile(self, current: V1Secret, reference: V1Secret):
super().reconcile(current, reference)
for key in reference.data.keys():
if current.data[key] != reference.data[key]:
if key not in current.data or current.data[key] != reference.data[key]:
raise NeedsUpdate()
def get_reference_object(self) -> V1Secret:
@ -40,6 +41,9 @@ class SecretReconciler(KubernetesObjectReconciler[V1Secret]):
str(self.controller.outpost.config.authentik_host_insecure)
),
"token": b64string(self.controller.outpost.token.key),
"authentik_host_browser": b64string(
self.controller.outpost.config.authentik_host_browser
),
},
)

View File

@ -3,9 +3,10 @@ from typing import TYPE_CHECKING
from kubernetes.client import CoreV1Api, V1Service, V1ServicePort, V1ServiceSpec
from authentik.outposts.controllers.base import FIELD_MANAGER, DeploymentPort
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler, NeedsUpdate
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.utils import compare_ports
if TYPE_CHECKING:
from authentik.outposts.controllers.kubernetes import KubernetesController
@ -19,46 +20,15 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]):
self.api = CoreV1Api(controller.client)
def reconcile(self, current: V1Service, reference: V1Service):
compare_ports(current.spec.ports, reference.spec.ports)
# run the base reconcile last, as that will probably raise NeedsUpdate
# after an authentik update. However the ports might have also changed during
# the update, so this causes the service to be re-created with higher
# priority than being updated.
super().reconcile(current, reference)
if len(current.spec.ports) != len(reference.spec.ports):
raise NeedsUpdate()
for port in reference.spec.ports:
if port not in current.spec.ports:
raise NeedsUpdate()
def get_embedded_reference_object(self) -> V1Service:
"""Get Service for embedded outpost"""
selector_labels = {
"app.kubernetes.io/name": "authentik",
"app.kubernetes.io/component": "server",
}
meta = self.get_object_meta(name=self.name)
ports = []
for port in [
DeploymentPort(9000, "http", "tcp"),
DeploymentPort(9443, "https", "tcp"),
]:
ports.append(
V1ServicePort(
name=port.name,
port=port.port,
protocol=port.protocol.upper(),
target_port=port.inner_port or port.port,
)
)
return V1Service(
metadata=meta,
spec=V1ServiceSpec(
ports=ports,
selector=selector_labels,
type=self.controller.outpost.config.kubernetes_service_type,
),
)
def get_reference_object(self) -> V1Service:
"""Get deployment object for outpost"""
if self.is_embedded:
return self.get_embedded_reference_object()
meta = self.get_object_meta(name=self.name)
ports = []
for port in self.controller.deployment_ports:
@ -70,7 +40,13 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]):
target_port=port.inner_port or port.port,
)
)
selector_labels = DeploymentReconciler(self.controller).get_pod_meta()
if self.is_embedded:
selector_labels = {
"app.kubernetes.io/name": "authentik",
"app.kubernetes.io/component": "server",
}
else:
selector_labels = DeploymentReconciler(self.controller).get_pod_meta()
return V1Service(
metadata=meta,
spec=V1ServiceSpec(

View File

@ -0,0 +1,150 @@
"""Kubernetes Prometheus ServiceMonitor Reconciler"""
from dataclasses import asdict, dataclass, field
from typing import TYPE_CHECKING
from dacite import from_dict
from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
if TYPE_CHECKING:
from authentik.outposts.controllers.kubernetes import KubernetesController
@dataclass
class PrometheusServiceMonitorSpecEndpoint:
"""Prometheus ServiceMonitor endpoint spec"""
port: str
path: str = field(default="/metrics")
@dataclass
class PrometheusServiceMonitorSpecSelector:
"""Prometheus ServiceMonitor selector spec"""
# pylint: disable=invalid-name
matchLabels: dict
@dataclass
class PrometheusServiceMonitorSpec:
"""Prometheus ServiceMonitor spec"""
endpoints: list[PrometheusServiceMonitorSpecEndpoint]
# pylint: disable=invalid-name
selector: PrometheusServiceMonitorSpecSelector
@dataclass
class PrometheusServiceMonitorMetadata:
"""Prometheus ServiceMonitor metadata"""
name: str
namespace: str
labels: dict = field(default_factory=dict)
@dataclass
class PrometheusServiceMonitor:
"""Prometheus ServiceMonitor"""
# pylint: disable=invalid-name
apiVersion: str
kind: str
metadata: PrometheusServiceMonitorMetadata
spec: PrometheusServiceMonitorSpec
CRD_NAME = "servicemonitors.monitoring.coreos.com"
CRD_GROUP = "monitoring.coreos.com"
CRD_VERSION = "v1"
CRD_PLURAL = "servicemonitors"
class PrometheusServiceMonitorReconciler(KubernetesObjectReconciler[PrometheusServiceMonitor]):
"""Kubernetes Prometheus ServiceMonitor Reconciler"""
def __init__(self, controller: "KubernetesController") -> None:
super().__init__(controller)
self.api_ex = ApiextensionsV1Api(controller.client)
self.api = CustomObjectsApi(controller.client)
@property
def noop(self) -> bool:
return (not self._crd_exists()) or (self.is_embedded)
def _crd_exists(self) -> bool:
"""Check if the Prometheus ServiceMonitor exists"""
return bool(
len(
self.api_ex.list_custom_resource_definition(
field_selector=f"metadata.name={CRD_NAME}"
).items
)
)
def get_reference_object(self) -> PrometheusServiceMonitor:
"""Get service monitor object for outpost"""
return PrometheusServiceMonitor(
apiVersion=f"{CRD_GROUP}/{CRD_VERSION}",
kind="ServiceMonitor",
metadata=PrometheusServiceMonitorMetadata(
name=self.name,
namespace=self.namespace,
labels=self.get_object_meta().labels,
),
spec=PrometheusServiceMonitorSpec(
endpoints=[
PrometheusServiceMonitorSpecEndpoint(
port="http-metrics",
)
],
selector=PrometheusServiceMonitorSpecSelector(
matchLabels=self.get_object_meta(name=self.name).labels,
),
),
)
def create(self, reference: PrometheusServiceMonitor):
return self.api.create_namespaced_custom_object(
group=CRD_GROUP,
version=CRD_VERSION,
plural=CRD_PLURAL,
namespace=self.namespace,
body=asdict(reference),
field_manager=FIELD_MANAGER,
)
def delete(self, reference: PrometheusServiceMonitor):
return self.api.delete_namespaced_custom_object(
group=CRD_GROUP,
version=CRD_VERSION,
namespace=self.namespace,
plural=CRD_PLURAL,
name=self.name,
)
def retrieve(self) -> PrometheusServiceMonitor:
return from_dict(
PrometheusServiceMonitor,
self.api.get_namespaced_custom_object(
group=CRD_GROUP,
version=CRD_VERSION,
namespace=self.namespace,
plural=CRD_PLURAL,
name=self.name,
),
)
def update(self, current: PrometheusServiceMonitor, reference: PrometheusServiceMonitor):
return self.api.patch_namespaced_custom_object(
group=CRD_GROUP,
version=CRD_VERSION,
namespace=self.namespace,
plural=CRD_PLURAL,
name=self.name,
body=asdict(reference),
field_manager=FIELD_MANAGER,
)

View File

@ -0,0 +1,14 @@
"""exceptions used by the kubernetes reconciler to trigger updates"""
from authentik.lib.sentry import SentryIgnoredException
class ReconcileTrigger(SentryIgnoredException):
"""Base trigger raised by child classes to notify us"""
class NeedsRecreate(ReconcileTrigger):
"""Exception to trigger a complete recreate of the Kubernetes Object"""
class NeedsUpdate(ReconcileTrigger):
"""Exception to trigger an update to the Kubernetes Object"""

View File

@ -1,8 +1,11 @@
"""k8s utils"""
from pathlib import Path
from kubernetes.client.models.v1_container_port import V1ContainerPort
from kubernetes.config.incluster_config import SERVICE_TOKEN_FILENAME
from authentik.outposts.controllers.k8s.triggers import NeedsRecreate
def get_namespace() -> str:
"""Get the namespace if we're running in a pod, otherwise default to default"""
@ -11,3 +14,12 @@ def get_namespace() -> str:
with open(path, "r", encoding="utf8") as _namespace_file:
return _namespace_file.read()
return "default"
def compare_ports(current: list[V1ContainerPort], reference: list[V1ContainerPort]):
"""Compare ports of a list"""
if len(current) != len(reference):
raise NeedsRecreate()
for port in reference:
if port not in current:
raise NeedsRecreate()

View File

@ -3,8 +3,9 @@ from io import StringIO
from typing import Type
from kubernetes.client.api_client import ApiClient
from kubernetes.client.exceptions import ApiException
from kubernetes.client.exceptions import OpenApiException
from structlog.testing import capture_logs
from urllib3.exceptions import HTTPError
from yaml import dump_all
from authentik.outposts.controllers.base import BaseController, ControllerException
@ -12,7 +13,8 @@ from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.secret import SecretReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler
from authentik.outposts.models import KubernetesServiceConnection, Outpost
from authentik.outposts.controllers.k8s.service_monitor import PrometheusServiceMonitorReconciler
from authentik.outposts.models import KubernetesServiceConnection, Outpost, ServiceConnectionInvalid
class KubernetesController(BaseController):
@ -31,8 +33,9 @@ class KubernetesController(BaseController):
"secret": SecretReconciler,
"deployment": DeploymentReconciler,
"service": ServiceReconciler,
"prometheus servicemonitor": PrometheusServiceMonitorReconciler,
}
self.reconcile_order = ["secret", "deployment", "service"]
self.reconcile_order = ["secret", "deployment", "service", "prometheus servicemonitor"]
def up(self):
try:
@ -40,7 +43,7 @@ class KubernetesController(BaseController):
reconciler = self.reconcilers[reconcile_key](self)
reconciler.up()
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def up_with_logs(self) -> list[str]:
@ -55,7 +58,7 @@ class KubernetesController(BaseController):
reconciler.up()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def down(self):
@ -65,7 +68,7 @@ class KubernetesController(BaseController):
self.logger.debug("Tearing down object", name=reconcile_key)
reconciler.down()
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def down_with_logs(self) -> list[str]:
@ -80,7 +83,7 @@ class KubernetesController(BaseController):
reconciler.down()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
return all_logs
except ApiException as exc:
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def get_static_deployment(self) -> str:

View File

@ -30,7 +30,7 @@ class DockerInlineTLS:
return str(path)
def write(self) -> TLSConfig:
"""Create TLSConfig with Certificate Keypairs"""
"""Create TLSConfig with Certificate Key pairs"""
# So yes, this is quite ugly. But sadly, there is no clean way to pass
# docker-py (which is using requests (which is using urllib3)) a certificate
# for verification or authentication as string.

View File

@ -56,6 +56,7 @@ class ServiceConnectionInvalid(SentryIgnoredException):
@dataclass
# pylint: disable=too-many-instance-attributes
class OutpostConfig:
"""Configuration an outpost uses to configure it self"""
@ -63,12 +64,16 @@ class OutpostConfig:
authentik_host: str = ""
authentik_host_insecure: bool = False
authentik_host_browser: str = ""
log_level: str = CONFIG.y("log_level")
error_reporting_enabled: bool = CONFIG.y_bool("error_reporting.enabled")
error_reporting_environment: str = CONFIG.y("error_reporting.environment", "customer")
object_naming_template: str = field(default="ak-outpost-%(name)s")
docker_network: Optional[str] = field(default=None)
docker_map_ports: bool = field(default=True)
kubernetes_replicas: int = field(default=1)
kubernetes_namespace: str = field(default_factory=get_namespace)
kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict)
@ -336,19 +341,8 @@ class Outpost(ManagedModel):
"""Username for service user"""
return f"ak-outpost-{self.uuid.hex}"
@property
def user(self) -> User:
"""Get/create user with access to all required objects"""
users = User.objects.filter(username=self.user_identifier)
if not users.exists():
user: User = User.objects.create(username=self.user_identifier)
user.set_unusable_password()
user.save()
else:
user = users.first()
user.attributes[USER_ATTRIBUTE_SA] = True
user.attributes[USER_ATTRIBUTE_CAN_OVERRIDE_IP] = True
user.save()
def build_user_permissions(self, user: User):
"""Create per-object and global permissions for outpost service-account"""
# To ensure the user only has the correct permissions, we delete all of them and re-add
# the ones the user needs
with transaction.atomic():
@ -362,7 +356,7 @@ class Outpost(ManagedModel):
)
try:
assign_perm(code_name, user, model_or_perm)
except Permission.DoesNotExist as exc:
except (Permission.DoesNotExist, AttributeError) as exc:
LOGGER.warning(
"permission doesn't exist",
code_name=code_name,
@ -392,6 +386,23 @@ class Outpost(ManagedModel):
"Updated service account's permissions",
perms=UserObjectPermission.objects.filter(user=user),
)
@property
def user(self) -> User:
"""Get/create user with access to all required objects"""
users = User.objects.filter(username=self.user_identifier)
should_create_user = not users.exists()
if should_create_user:
user: User = User.objects.create(username=self.user_identifier)
user.set_unusable_password()
user.save()
else:
user = users.first()
user.attributes[USER_ATTRIBUTE_SA] = True
user.attributes[USER_ATTRIBUTE_CAN_OVERRIDE_IP] = True
user.save()
if should_create_user:
self.build_user_permissions(user)
return user
@property

View File

@ -100,7 +100,7 @@ def outpost_controller(
if from_cache:
outpost: Outpost = cache.get(CACHE_KEY_OUTPOST_DOWN % outpost_pk)
else:
outpost: Outpost = Outpost.objects.get(pk=outpost_pk)
outpost: Outpost = Outpost.objects.filter(pk=outpost_pk).first()
if not outpost:
return
self.set_uid(slugify(outpost.name))
@ -126,6 +126,7 @@ def outpost_token_ensurer(self: MonitoredTask):
all_outposts = Outpost.objects.all()
for outpost in all_outposts:
_ = outpost.token
outpost.build_user_permissions(outpost.user)
self.set_status(
TaskResult(
TaskResultStatus.SUCCESSFUL,
@ -148,10 +149,7 @@ def outpost_post_save(model_class: str, model_pk: Any):
return
if isinstance(instance, Outpost):
LOGGER.debug("Ensuring token and permissions for outpost", instance=instance)
_ = instance.token
_ = instance.user
LOGGER.debug("Trigger reconcile for outpost")
LOGGER.debug("Trigger reconcile for outpost", instance=instance)
outpost_controller.delay(instance.pk)
if isinstance(instance, (OutpostModel, Outpost)):
@ -184,7 +182,7 @@ def outpost_post_save(model_class: str, model_pk: Any):
def outpost_send_update(model_instace: Model):
"""Send outpost update to all registered outposts, irregardless to which authentik
"""Send outpost update to all registered outposts, regardless to which authentik
instance they are connected"""
channel_layer = get_channel_layer()
if isinstance(model_instace, OutpostModel):
@ -199,7 +197,7 @@ def _outpost_single_update(outpost: Outpost, layer=None):
# Ensure token again, because this function is called when anything related to an
# OutpostModel is saved, so we can be sure permissions are right
_ = outpost.token
_ = outpost.user
outpost.build_user_permissions(outpost.user)
if not layer: # pragma: no cover
layer = get_channel_layer()
for state in OutpostState.for_outpost(outpost):
@ -211,7 +209,7 @@ def _outpost_single_update(outpost: Outpost, layer=None):
@CELERY_APP.task()
def outpost_local_connection():
"""Checks the local environment and create Service connections."""
# Explicitly check against token filename, as thats
# Explicitly check against token filename, as that's
# only present when the integration is enabled
if Path(SERVICE_TOKEN_FILENAME).exists():
LOGGER.debug("Detected in-cluster Kubernetes Config")

View File

@ -87,6 +87,7 @@ class PolicyViewSet(
"promptstage": ["isnull"],
}
search_fields = ["name"]
ordering = ["name"]
def get_queryset(self): # pragma: no cover
return Policy.objects.select_subclasses().prefetch_related("bindings", "promptstage_set")

View File

@ -81,11 +81,11 @@ class PolicyEngine:
.iterator()
)
def _check_policy_type(self, policy: Policy):
def _check_policy_type(self, binding: PolicyBinding):
"""Check policy type, make sure it's not the root class as that has no logic implemented"""
# pyright: reportGeneralTypeIssues=false
if policy.__class__ == Policy:
raise TypeError(f"Policy '{policy}' is root type")
if binding.policy is not None and binding.policy.__class__ == Policy:
raise TypeError(f"Policy '{binding.policy}' is root type")
def build(self) -> "PolicyEngine":
"""Build wrapper which monitors performance"""
@ -102,7 +102,7 @@ class PolicyEngine:
for binding in self._iter_bindings():
self.__expected_result_count += 1
self._check_policy_type(binding.policy)
self._check_policy_type(binding)
key = cache_key(binding, self.request)
cached_policy = cache.get(key, None)
if cached_policy and self.use_cache:

View File

@ -3,8 +3,10 @@ from ipaddress import ip_address, ip_network
from typing import TYPE_CHECKING, Optional
from django.http import HttpRequest
from django_otp import devices_for_user
from structlog.stdlib import get_logger
from authentik.core.models import User
from authentik.flows.planner import PLAN_CONTEXT_SSO
from authentik.lib.expression.evaluator import BaseEvaluator
from authentik.lib.utils.http import get_client_ip
@ -28,6 +30,7 @@ class PolicyEvaluator(BaseEvaluator):
self._messages = []
self._context["ak_logger"] = get_logger(policy_name)
self._context["ak_message"] = self.expr_func_message
self._context["ak_user_has_authenticator"] = self.expr_func_user_has_authenticator
self._context["ip_address"] = ip_address
self._context["ip_network"] = ip_network
self._filename = policy_name or "PolicyEvaluator"
@ -36,6 +39,19 @@ class PolicyEvaluator(BaseEvaluator):
"""Wrapper to append to messages list, which is returned with PolicyResult"""
self._messages.append(message)
def expr_func_user_has_authenticator(
self, user: User, device_type: Optional[str] = None
) -> bool:
"""Check if a user has any authenticator devices, optionally matching *device_type*"""
user_devices = devices_for_user(user)
if device_type:
for device in user_devices:
device_class = device.__class__.__name__.lower().replace("device", "")
if device_class == device_type:
return True
return False
return len(user_devices) > 0
def set_policy_request(self, request: PolicyRequest):
"""Update context based on policy request (if http request is given, update that too)"""
# update website/docs/expressions/_objects.md

View File

@ -3,10 +3,10 @@ from hashlib import sha1
from django.db import models
from django.utils.translation import gettext as _
from requests import get
from rest_framework.serializers import BaseSerializer
from structlog.stdlib import get_logger
from authentik.lib.utils.http import get_http_session
from authentik.policies.models import Policy, PolicyResult
from authentik.policies.types import PolicyRequest
@ -49,7 +49,7 @@ class HaveIBeenPwendPolicy(Policy):
pw_hash = sha1(password.encode("utf-8")).hexdigest() # nosec
url = f"https://api.pwnedpasswords.com/range/{pw_hash[:5]}"
result = get(url).text
result = get_http_session().get(url).text
final_count = 0
for line in result.split("\r\n"):
full_hash, count = line.split(":")

View File

@ -8,8 +8,11 @@ from structlog.stdlib import get_logger
from authentik.policies.models import Policy
from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
LOGGER = get_logger()
RE_LOWER = re.compile("[a-z]")
RE_UPPER = re.compile("[A-Z]")
class PasswordPolicy(Policy):
@ -38,31 +41,42 @@ class PasswordPolicy(Policy):
return "ak-policy-password-form"
def passes(self, request: PolicyRequest) -> PolicyResult:
if self.password_field not in request.context:
if (
self.password_field not in request.context
and self.password_field not in request.context.get(PLAN_CONTEXT_PROMPT, {})
):
LOGGER.warning(
"Password field not set in Policy Request",
field=self.password_field,
fields=request.context.keys(),
prompt_fields=request.context.get(PLAN_CONTEXT_PROMPT, {}).keys(),
)
return PolicyResult(False, _("Password not set in context"))
password = request.context[self.password_field]
filter_regex = []
if self.amount_lowercase > 0:
filter_regex.append(r"[a-z]{%d,}" % self.amount_lowercase)
if self.amount_uppercase > 0:
filter_regex.append(r"[A-Z]{%d,}" % self.amount_uppercase)
if self.password_field in request.context:
password = request.context[self.password_field]
else:
password = request.context[PLAN_CONTEXT_PROMPT][self.password_field]
if len(password) < self.length_min:
LOGGER.debug("password failed", reason="length")
return PolicyResult(False, self.error_message)
if self.amount_lowercase > 0 and len(RE_LOWER.findall(password)) < self.amount_lowercase:
LOGGER.debug("password failed", reason="amount_lowercase")
return PolicyResult(False, self.error_message)
if self.amount_uppercase > 0 and len(RE_UPPER.findall(password)) < self.amount_lowercase:
LOGGER.debug("password failed", reason="amount_uppercase")
return PolicyResult(False, self.error_message)
if self.amount_symbols > 0:
filter_regex.append(r"[%s]{%d,}" % (self.symbol_charset, self.amount_symbols))
full_regex = "|".join(filter_regex)
LOGGER.debug("Built regex", regexp=full_regex)
result = bool(re.compile(full_regex).match(password))
count = 0
for symbol in self.symbol_charset:
count += password.count(symbol)
if count < self.amount_symbols:
LOGGER.debug("password failed", reason="amount_symbols")
return PolicyResult(False, self.error_message)
result = result and len(password) >= self.length_min
if not result:
return PolicyResult(result, self.error_message)
return PolicyResult(result)
return PolicyResult(True)
class Meta:

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