Compare commits

...

101 Commits

Author SHA1 Message Date
3d724db0e3 release: 2022.1.2 2022-01-24 11:28:00 +01:00
2997542114 lib: disable backup by default, add note to configuration 2022-01-24 10:00:15 +00:00
84b18fff96 ci: cache-v2
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-24 09:37:04 +01:00
1dce408c72 internal/proxyv2: only allow access to /akprox in nginx mode when forward url could be extracted
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-24 09:30:33 +01:00
e5ff47bf14 build(deps): bump @lingui/cli from 3.13.0 to 3.13.1 in /web (#2133) 2022-01-24 08:49:03 +01:00
b53bf331c3 build(deps): bump @lingui/macro from 3.13.0 to 3.13.1 in /web (#2135) 2022-01-24 08:48:51 +01:00
90e9a8b34c build(deps): bump rollup from 2.64.0 to 2.66.0 in /web (#2139) 2022-01-24 08:48:26 +01:00
845f842783 build(deps): bump @lingui/core from 3.13.0 to 3.13.1 in /web (#2136) 2022-01-24 08:48:17 +01:00
7397849c60 build(deps): bump rapidoc from 9.1.3 to 9.1.4 in /website (#2132) 2022-01-24 08:47:45 +01:00
6dd46b5fc5 build(deps): bump @babel/core from 7.16.10 to 7.16.12 in /web (#2134) 2022-01-24 08:47:35 +01:00
89ca79ed10 build(deps): bump @lingui/detect-locale from 3.13.0 to 3.13.1 in /web (#2137) 2022-01-24 08:47:15 +01:00
713bef895c build(deps): bump rapidoc from 9.1.3 to 9.1.4 in /web (#2138) 2022-01-24 08:46:37 +01:00
925115e9ce build(deps): bump github.com/go-openapi/runtime from 0.21.0 to 0.21.1 (#2140) 2022-01-24 08:46:17 +01:00
42f5cf8c93 outposts: allow custom label for docker containers
closes #2128

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-23 21:55:58 +01:00
82cc1d536a providers/proxy: add PathPrefix to auto-traefik labels
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2128
2022-01-23 21:55:46 +01:00
08af2fd46b website/docs: deprecate inbuilt backup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-23 21:51:22 +01:00
70e3b27a4d root: upgrade python dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-23 21:27:16 +01:00
6a411d7960 policies/hibp: ensure password is encodable
closes AUTHENTIK-1SA

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-23 21:23:24 +01:00
33567b56d7 lifecycle: replace lowercase, deprecated prometheus_multiproc_dir
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-23 21:21:06 +01:00
0c1954aeb7 web: Update Web API Client version (#2126)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-01-22 19:06:20 +01:00
f4a6c70e98 release: 2022.1.1 2022-01-22 18:28:40 +01:00
5f198e7fe4 website/docs: update 2022.1
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-22 12:29:20 +01:00
d172d32817 ci: bump golangci
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 23:22:59 +01:00
af3fb5c2cd internal: use math.MaxInt for compatibility
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#1819
2022-01-21 23:11:17 +01:00
885efb526e web/admin: also set embedded outpost host when it doesn't include scheme
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 13:51:34 +01:00
3bfb8b2cb2 outposts/proxyv2: allow access to /akprox urls in forward auth mode to make routing in nginx/traefik easier
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 13:43:16 +01:00
9fc5ff4b77 outposts/proxyv2: fix JWKS url pointing to localhost on embedded outpost
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 13:29:51 +01:00
dd8b579dd6 lib: ignore paramiko logger
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 10:46:33 +01:00
e12cbd8711 website/docs: add 2022.1
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-21 09:47:49 +01:00
62d35f8f8c build(deps): bump codemirror from 5.65.0 to 5.65.1 in /web (#2122) 2022-01-21 09:06:27 +01:00
49be504c13 build(deps): bump @babel/preset-env from 7.16.10 to 7.16.11 in /web (#2123) 2022-01-21 09:06:04 +01:00
edad55e51d build(deps): bump typescript from 4.5.4 to 4.5.5 in /web (#2124) 2022-01-21 09:05:51 +01:00
38086fa8bb build(deps): bump boto3 from 1.20.39 to 1.20.40 (#2125) 2022-01-21 09:05:32 +01:00
c4f9a3e9a7 build(deps): bump @babel/preset-env from 7.16.8 to 7.16.10 in /web (#2114) 2022-01-20 08:45:49 +01:00
930df791bd build(deps): bump python (#2113) 2022-01-20 08:45:28 +01:00
9a6086634c build(deps): bump boto3 from 1.20.38 to 1.20.39 (#2117) 2022-01-20 08:45:03 +01:00
b68e65355a build(deps): bump @babel/core from 7.16.7 to 7.16.10 in /web (#2115) 2022-01-20 08:44:47 +01:00
72d33a91dd build(deps): bump @babel/plugin-transform-runtime in /web (#2116) 2022-01-20 08:44:28 +01:00
7067e3d69a build(deps): bump github.com/prometheus/client_golang (#2118) 2022-01-20 08:44:01 +01:00
4db370d24e website/docs: add flow inspector docs
closes #2105

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-19 19:31:21 +01:00
41e7b9b73f outposts/proxyv2: fix before-redirect url not being saved in proxy mode
closes #2109

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-19 19:16:30 +01:00
7f47f93e4e internal: cleanup log messages
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-19 19:01:24 +01:00
89abd44b76 lifecycle: add early check for missing/invalid secret key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-19 09:53:53 +01:00
14c7d8c4f4 internal: route traffic to proxy providers based on cookie domain when multiple domain-level providers exist
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#2079
2022-01-18 23:19:43 +01:00
525976a81b root: upgrade python dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-18 21:35:07 +01:00
64a2126ea4 website/docs: fix typo in port mapping in manifest (#2103)
Otherwise it causes:

```
error: error validating "outpost.yaml": error validating data: ValidationError(Service.spec.ports[1].port): invalid type for io.k8s.api.core.v1.ServicePort.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
```
2022-01-18 19:57:55 +01:00
994c5882ab root: fix error if secret_key is purely numerical
closes #2099

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-18 09:17:33 +01:00
ad64d51e85 build(deps): bump @typescript-eslint/eslint-plugin in /web (#2100)
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 5.9.1 to 5.10.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.10.0/packages/eslint-plugin)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  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>
2022-01-18 09:16:54 +01:00
a184a7518a build(deps): bump @typescript-eslint/parser from 5.9.1 to 5.10.0 in /web (#2101)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.9.1 to 5.10.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.10.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  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>
2022-01-18 09:14:58 +01:00
943fd80920 web: ignore additional error
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-17 22:05:23 +01:00
01bb18b8c4 root: allow customisation of ports in compose without override
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-17 14:48:02 +01:00
94baaaa5a5 build(deps): bump eslint from 8.6.0 to 8.7.0 in /web (#2096) 2022-01-17 09:19:59 +01:00
40b164ce94 build(deps): bump rollup from 2.63.0 to 2.64.0 in /web (#2097) 2022-01-17 09:18:30 +01:00
1d7c7801e7 website/docs: prepare 2022.1 release
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-16 18:22:25 +01:00
0db0a12ef3 root: rename csrf header
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-16 16:17:44 +01:00
8008aba450 web: directly read csrf token before injecting into request
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-16 16:10:55 +01:00
eaeab27004 lib: add support for custom env
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-16 14:56:02 +01:00
111fbf119b *: refactor prometheus gauges to directly updating metrics view
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-16 13:57:07 +01:00
300ad88447 web: add polyfill for Intl.ListFormat
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-15 14:56:18 +01:00
92cc0c9c64 root: decrease to 10 backup history
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-14 19:59:50 +01:00
18ff803370 outposts: trigger service update on k8s when selector doesnt match
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-14 11:42:57 +01:00
819af78e2b internal: make internal go version match python version
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-14 10:45:37 +01:00
6338785ce1 outposts: change label app.kubernetes.io/name to include outpost type
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-14 10:34:54 +01:00
973e151dff outposts: add Additional version labels to managed k8s deployments
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-13 17:48:01 +01:00
fae6d83f27 *: simplify extracting current version info
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-13 17:47:31 +01:00
ed84fe0b8d root: set samesite for csrf cookie
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 23:14:14 +01:00
1ee603403e root: upgrade python dependencies
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 23:02:39 +01:00
7db7b7cc4d stages/authenticator_validate: fix lint
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 23:00:28 +01:00
68a98cd86c web: Update Web API Client version (#2091)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-01-12 22:59:59 +01:00
e758db5727 stages/authenticator_webauthn: make more WebAuthn options configurable
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 22:57:49 +01:00
4d7d700afa providers/oauth2: change default redirect uri behaviour; set first used url when blank and use star for wildcard
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 22:44:57 +01:00
f9a5add01d root: include build in analytics
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 22:18:52 +01:00
2986b56389 root: fix backups running every minute instead of once
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-12 22:09:44 +01:00
58f79b525d web/admin: fix invalid build due to wrong import
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-11 11:40:59 +01:00
0a1c0dae05 build(deps): bump @typescript-eslint/eslint-plugin in /web (#2085) 2022-01-11 08:59:13 +01:00
e18ef8dab6 build(deps): bump @babel/preset-env from 7.16.7 to 7.16.8 in /web (#2087) 2022-01-11 08:58:45 +01:00
3cacc59bec build(deps): bump @typescript-eslint/parser from 5.9.0 to 5.9.1 in /web (#2086) 2022-01-11 08:57:51 +01:00
4eea46d399 build(deps): bump @babel/plugin-transform-runtime in /web (#2088) 2022-01-11 08:57:28 +01:00
11e25617bd crypto: fully parse certificate on validation in serializer to prevent invalid certificates from being saved
closes #2082

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 20:36:50 +01:00
4817126811 website/integrations: fix synapse docs based on upstream docs
closes #2080

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 20:19:56 +01:00
0181361efa website/integrations: use Signing Key instead of RSA Key
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 20:18:05 +01:00
8ff8e1d5f7 web/admin: fix missing configure flow setting on webuahtn setup stage form
closes #2084

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 20:15:34 +01:00
19d5902a92 flows: handle error if flow title contains invalid format string
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 19:49:27 +01:00
71dffb21a9 outposts: improve error handling for outpost service connection state
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 19:44:13 +01:00
bd283c506d web/flows: remove node directly instead of using removeChild()
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 19:37:51 +01:00
ef564e5f1a web: fix double plural in label
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 18:58:56 +01:00
2543224c7c core: dont return 404 when trying to view key of expired token
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-10 17:53:09 +01:00
077eee9310 Revert "build(deps): bump goauthentik.io/api from 0.2021125.1 to 1.2021.9 (#2083)"
This reverts commit d894eeaa67.
2022-01-10 10:03:48 +01:00
d894eeaa67 build(deps): bump goauthentik.io/api from 0.2021125.1 to 1.2021.9 (#2083)
Bumps [goauthentik.io/api](https://github.com/goauthentik/client-go) from 0.2021125.1 to 1.2021.9.
- [Release notes](https://github.com/goauthentik/client-go/releases)
- [Commits](https://github.com/goauthentik/client-go/commits)

---
updated-dependencies:
- dependency-name: goauthentik.io/api
  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>
2022-01-10 09:39:30 +01:00
452bfb39bf Revert "web/elements: re-enable codemirror line numbers (fixed on firefox)"
This reverts commit 4c166dcf52.

closes #2081

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-09 22:24:32 +01:00
6b6702521f api: don't return error reporting enabled when debug is enabled
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-07 21:53:22 +01:00
c07b8d95d0 outposts/proxy: remove deprecated headers
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-07 17:01:23 +01:00
bf347730b3 outposts/ldap: remove deprecated fields
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-07 09:52:19 +01:00
ececfc3a30 internal: fix comment formatting for TODOs
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-07 09:51:41 +01:00
b76546de0c Translate /web/src/locales/en.po in tr (#2074) 2022-01-07 09:16:02 +01:00
424d490a60 build(deps): bump golang from 1.17.5-bullseye to 1.17.6-bullseye (#2075) 2022-01-07 09:14:44 +01:00
127dd85214 build(deps): bump lit from 2.1.0 to 2.1.1 in /web (#2076) 2022-01-07 09:14:23 +01:00
10570ac7f8 build(deps): bump goauthentik.io/api from 0.2021124.9 to 0.2021125.1 (#2077) 2022-01-07 09:14:07 +01:00
dc5667b0b8 web: Update Web API Client version (#2073)
Signed-off-by: GitHub <noreply@github.com>

Co-authored-by: BeryJu <BeryJu@users.noreply.github.com>
2022-01-06 22:23:23 +01:00
ec9cacb610 ci: post-release cleanup
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-06 22:22:50 +01:00
0027dbc0e5 root: remove old api path
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
2022-01-06 22:21:21 +01:00
118 changed files with 2167 additions and 1352 deletions

View File

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

View File

@ -40,7 +40,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
@ -56,7 +56,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
@ -79,7 +79,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: checkout stable
run: |
# Copy current, latest config to local
@ -95,11 +95,7 @@ jobs:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
run: |
scripts/ci_prepare.sh
# Sync anyways since stable will have different dependencies
# TODO: Remove after next stable release
if [[ -f "Pipfile.lock" ]]; then
pipenv install --dev
fi
# install anyways since stable will have different dependencies
poetry install
- name: run migrations to stable
run: poetry run python -m lifecycle.migrate
@ -108,13 +104,7 @@ jobs:
set -x
git fetch
git reset --hard HEAD
# TODO: Remove after next stable release
rm -f poetry.lock
git checkout $GITHUB_SHA
# TODO: Remove after next stable release
if [[ -f "Pipfile.lock" ]]; then
pipenv install --dev
fi
poetry install
- name: prepare
env:
@ -131,7 +121,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
@ -158,7 +148,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
@ -195,7 +185,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}
@ -240,7 +230,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}

View File

@ -28,7 +28,7 @@ jobs:
--rm \
-v $(pwd):/app \
-w /app \
golangci/golangci-lint:v1.39.0 \
golangci/golangci-lint:v1.43 \
golangci-lint run -v --timeout 200s
ci-outpost-mark:
needs:

View File

@ -30,14 +30,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.12.5,
beryju/authentik:2022.1.2,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.12.5,
ghcr.io/goauthentik/server:2022.1.2,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.12.5', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2022.1.2', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -78,14 +78,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-${{ matrix.type }}:2021.12.5,
beryju/authentik-${{ matrix.type }}:2022.1.2,
beryju/authentik-${{ matrix.type }}:latest,
ghcr.io/goauthentik/${{ matrix.type }}:2021.12.5,
ghcr.io/goauthentik/${{ matrix.type }}:2022.1.2,
ghcr.io/goauthentik/${{ matrix.type }}:latest
file: ${{ matrix.type }}.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.12.5', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2022.1.2', 'rc') }}
run: |
docker pull beryju/authentik-${{ matrix.type }}:latest
docker tag beryju/authentik-${{ matrix.type }}:latest beryju/authentik-${{ matrix.type }}:stable
@ -170,7 +170,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.12.5
version: authentik@2022.1.2
environment: beryjuorg-prod
sourcemaps: './web/dist'
url_prefix: '~/static/dist'

View File

@ -26,7 +26,7 @@ jobs:
uses: actions/cache@v2.1.7
with:
path: ~/.cache/pypoetry/virtualenvs
key: ${{ runner.os }}-poetry-cache-v3-${{ hashFiles('**/poetry.lock') }}
key: ${{ runner.os }}-poetry-cache-v2-${{ hashFiles('**/poetry.lock') }}
- name: prepare
env:
INSTALL: ${{ steps.cache-poetry.outputs.cache-hit }}

View File

@ -1 +0,0 @@
3.9.7

View File

@ -16,7 +16,7 @@ ENV NODE_ENV=production
RUN cd /work/web && npm i && npm run build
# Stage 3: Build go proxy
FROM docker.io/golang:1.17.5-bullseye AS builder
FROM docker.io/golang:1.17.6-bullseye AS builder
WORKDIR /work
@ -32,7 +32,7 @@ COPY ./go.sum /work/go.sum
RUN go build -o /work/authentik ./cmd/server/main.go
# Stage 4: Run
FROM docker.io/python:3.10.1-slim-bullseye
FROM docker.io/python:3.10.2-slim-bullseye
LABEL org.opencontainers.image.url https://goauthentik.io
LABEL org.opencontainers.image.description goauthentik.io Main server image, see https://goauthentik.io for more info.

View File

@ -1,3 +1,19 @@
"""authentik"""
__version__ = "2021.12.5"
from os import environ
from typing import Optional
__version__ = "2022.1.2"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
def get_build_hash(fallback: Optional[str] = None) -> str:
"""Get build hash"""
return environ.get(ENV_GIT_HASH_KEY, fallback if fallback else "")
def get_full_version() -> str:
"""Get full version, with build hash appended"""
version = __version__
if (build_hash := get_build_hash()) != "":
version += "." + build_hash
return version

View File

@ -1,6 +1,4 @@
"""authentik administration overview"""
from os import environ
from django.core.cache import cache
from drf_spectacular.utils import extend_schema
from packaging.version import parse
@ -10,7 +8,7 @@ from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import __version__, get_build_hash
from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version
from authentik.core.api.utils import PassiveSerializer
@ -25,7 +23,7 @@ class VersionSerializer(PassiveSerializer):
def get_build_hash(self, _) -> str:
"""Get build hash, if version is not latest or released"""
return environ.get(ENV_GIT_HASH_KEY, "")
return get_build_hash()
def get_version_current(self, _) -> str:
"""Get current version"""

View File

@ -1,4 +1,6 @@
"""authentik admin app config"""
from importlib import import_module
from django.apps import AppConfig
@ -13,3 +15,4 @@ class AuthentikAdminConfig(AppConfig):
from authentik.admin.tasks import clear_update_notifications
clear_update_notifications.delay()
import_module("authentik.admin.signals")

View File

@ -0,0 +1,23 @@
"""admin signals"""
from django.dispatch import receiver
from authentik.admin.api.tasks import TaskInfo
from authentik.admin.api.workers import GAUGE_WORKERS
from authentik.root.celery import CELERY_APP
from authentik.root.monitoring import monitoring_set
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_workers(sender, **kwargs):
"""Set worker gauge"""
count = len(CELERY_APP.control.ping(timeout=0.5))
GAUGE_WORKERS.set(count)
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_tasks(sender, **kwargs):
"""Set task gauges"""
for task in TaskInfo.all().values():
task.set_prom_metrics()

View File

@ -1,6 +1,5 @@
"""authentik admin tasks"""
import re
from os import environ
from django.core.cache import cache
from django.core.validators import URLValidator
@ -9,7 +8,7 @@ from prometheus_client import Info
from requests import RequestException
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import __version__, get_build_hash
from authentik.events.models import Event, EventAction, Notification
from authentik.events.monitored_tasks import (
MonitoredTask,
@ -36,7 +35,7 @@ def _set_prom_info():
{
"version": __version__,
"latest": cache.get(VERSION_CACHE_KEY, ""),
"build_hash": environ.get(ENV_GIT_HASH_KEY, ""),
"build_hash": get_build_hash(),
}
)

View File

@ -30,7 +30,7 @@ function getCookie(name) {
window.addEventListener('DOMContentLoaded', (event) => {
const rapidocEl = document.querySelector('rapi-doc');
rapidocEl.addEventListener('before-try', (e) => {
e.detail.request.headers.append('X-CSRFToken', getCookie("authentik_csrf"));
e.detail.request.headers.append('X-authentik-CSRF', getCookie("authentik_csrf"));
});
});
</script>

View File

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

View File

@ -80,7 +80,7 @@ class ConfigView(APIView):
config = ConfigSerializer(
{
"error_reporting": {
"enabled": CONFIG.y("error_reporting.enabled"),
"enabled": CONFIG.y("error_reporting.enabled") and not settings.DEBUG,
"environment": CONFIG.y("error_reporting.environment"),
"send_pii": CONFIG.y("error_reporting.send_pii"),
"traces_sample_rate": float(CONFIG.y("error_reporting.sample_rate", 0.4)),

View File

@ -1,7 +1,6 @@
"""Tokens API Viewset"""
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
@ -114,7 +113,5 @@ class TokenViewSet(UsedByMixin, ModelViewSet):
def view_key(self, request: Request, identifier: str) -> Response:
"""Return token key and log access"""
token: Token = self.get_object()
if token.is_expired:
raise Http404
Event.new(EventAction.SECRET_VIEW, secret=token).from_http(request) # noqa # nosec
return Response(TokenViewSerializer({"key": token.key}).data)

View File

@ -1,6 +1,7 @@
"""authentik core signals"""
from typing import TYPE_CHECKING
from django.apps import apps
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.contrib.sessions.backends.cache import KEY_PREFIX
from django.core.cache import cache
@ -11,6 +12,8 @@ from django.dispatch import receiver
from django.http.request import HttpRequest
from prometheus_client import Gauge
from authentik.root.monitoring import monitoring_set
# Arguments: user: User, password: str
password_changed = Signal()
@ -20,6 +23,17 @@ if TYPE_CHECKING:
from authentik.core.models import AuthenticatedSession, User
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_models(sender, **kwargs):
"""set models gauges"""
for model in apps.get_models():
GAUGE_MODELS.labels(
model_name=model._meta.model_name,
app=model._meta.app_label,
).set(model.objects.count())
@receiver(post_save)
# pylint: disable=unused-argument
def post_save_application(sender: type[Model], instance, created: bool, **_):
@ -27,11 +41,6 @@ def post_save_application(sender: type[Model], instance, created: bool, **_):
from authentik.core.api.applications import user_app_cache_key
from authentik.core.models import Application
GAUGE_MODELS.labels(
model_name=sender._meta.model_name,
app=sender._meta.app_label,
).set(sender.objects.count())
if sender != Application:
return
if not created: # pragma: no cover

View File

@ -17,6 +17,7 @@ from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
from authentik.api.decorators import permission_required
from authentik.core.api.used_by import UsedByMixin
@ -26,6 +27,8 @@ from authentik.crypto.managed import MANAGED_KEY
from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction
LOGGER = get_logger()
class CertificateKeyPairSerializer(ModelSerializer):
"""CertificateKeyPair Serializer"""
@ -76,8 +79,11 @@ class CertificateKeyPairSerializer(ModelSerializer):
def validate_certificate_data(self, value: str) -> str:
"""Verify that input is a valid PEM x509 Certificate"""
try:
load_pem_x509_certificate(value.encode("utf-8"), default_backend())
except ValueError:
# Cast to string to fully load and parse certificate
# Prevents issues like https://github.com/goauthentik/authentik/issues/2082
str(load_pem_x509_certificate(value.encode("utf-8"), default_backend()))
except ValueError as exc:
LOGGER.warning("Failed to load certificate", exc=exc)
raise ValidationError("Unable to load certificate.")
return value
@ -86,12 +92,17 @@ class CertificateKeyPairSerializer(ModelSerializer):
# Since this field is optional, data can be empty.
if value != "":
try:
load_pem_private_key(
str.encode("\n".join([x.strip() for x in value.split("\n")])),
password=None,
backend=default_backend(),
# Cast to string to fully load and parse certificate
# Prevents issues like https://github.com/goauthentik/authentik/issues/2082
str(
load_pem_private_key(
str.encode("\n".join([x.strip() for x in value.split("\n")])),
password=None,
backend=default_backend(),
)
)
except (ValueError, TypeError):
except (ValueError, TypeError) as exc:
LOGGER.warning("Failed to load private key", exc=exc)
raise ValidationError("Unable to load private key (possibly encrypted?).")
return value

View File

@ -4,7 +4,7 @@ from typing import Any, Optional
from django.core.cache import cache
from django.http import HttpRequest
from prometheus_client import Histogram
from prometheus_client import Gauge, Histogram
from sentry_sdk.hub import Hub
from sentry_sdk.tracing import Span
from structlog.stdlib import BoundLogger, get_logger
@ -16,7 +16,6 @@ from authentik.flows.markers import ReevaluateMarker, StageMarker
from authentik.flows.models import Flow, FlowStageBinding, Stage
from authentik.lib.config import CONFIG
from authentik.policies.engine import PolicyEngine
from authentik.root.monitoring import UpdatingGauge
LOGGER = get_logger()
PLAN_CONTEXT_PENDING_USER = "pending_user"
@ -27,10 +26,9 @@ PLAN_CONTEXT_SOURCE = "source"
# Is set by the Flow Planner when a FlowToken was used, and the currently active flow plan
# was restored.
PLAN_CONTEXT_IS_RESTORED = "is_restored"
GAUGE_FLOWS_CACHED = UpdatingGauge(
GAUGE_FLOWS_CACHED = Gauge(
"authentik_flows_cached",
"Cached flows",
update_func=lambda: len(cache.keys("flow_*") or []),
)
HIST_FLOWS_PLAN_TIME = Histogram(
"authentik_flows_plan_time",
@ -171,7 +169,6 @@ class FlowPlanner:
)
plan = self._build_plan(user, request, default_context)
cache.set(cache_key(self.flow, user), plan, CACHE_TIMEOUT)
GAUGE_FLOWS_CACHED.update()
if not plan.bindings and not self.allow_empty_flows:
raise EmptyFlowException()
return plan

View File

@ -4,6 +4,9 @@ from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from structlog.stdlib import get_logger
from authentik.flows.planner import GAUGE_FLOWS_CACHED
from authentik.root.monitoring import monitoring_set
LOGGER = get_logger()
@ -14,6 +17,13 @@ def delete_cache_prefix(prefix: str) -> int:
return len(keys)
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_flows(sender, **kwargs):
"""set flow gauges"""
GAUGE_FLOWS_CACHED.set(len(cache.keys("flow_*") or []))
@receiver(post_save)
@receiver(pre_delete)
# pylint: disable=unused-argument

View File

@ -118,9 +118,12 @@ class ChallengeStageView(StageView):
"""Allow usage of placeholder in flow title."""
if not self.executor.plan:
return self.executor.flow.title
return self.executor.flow.title % {
"app": self.executor.plan.context.get(PLAN_CONTEXT_APPLICATION, "")
}
try:
return self.executor.flow.title % {
"app": self.executor.plan.context.get(PLAN_CONTEXT_APPLICATION, "")
}
except ValueError:
return self.executor.flow.title
def _get_challenge(self, *args, **kwargs) -> Challenge:
with Hub.current.start_span(

View File

@ -6,7 +6,7 @@ postgresql:
port: 5432
password: 'env://POSTGRES_PASSWORD'
backup:
enabled: true
enabled: false
s3_backup:
access_key: ""
secret_key: ""

View File

@ -111,6 +111,7 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
"django_redis.cache",
"celery.backends.redis",
"celery.worker",
"paramiko.transport",
]:
return None
LOGGER.debug("sending event to sentry", exc=exc_value, source_logger=event.get("logger", None))

View File

@ -1,5 +1,4 @@
"""http helpers"""
from os import environ
from typing import Any, Optional
from django.http import HttpRequest
@ -7,7 +6,7 @@ from requests.sessions import Session
from sentry_sdk.hub import Hub
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import get_full_version
OUTPOST_REMOTE_IP_HEADER = "HTTP_X_AUTHENTIK_REMOTE_IP"
OUTPOST_TOKEN_HEADER = "HTTP_X_AUTHENTIK_OUTPOST_TOKEN" # nosec
@ -75,8 +74,7 @@ def get_client_ip(request: Optional[HttpRequest]) -> str:
def authentik_user_agent() -> str:
"""Get a common user agent"""
build = environ.get(ENV_GIT_HASH_KEY, "tagged")
return f"authentik@{__version__} (build={build})"
return f"authentik@{get_full_version()}"
def get_http_session() -> Session:

View File

@ -58,4 +58,6 @@ def get_env() -> str:
return "compose"
if CONFIG.y_bool("debug"):
return "dev"
if "AK_APPLIANCE" in os.environ:
return os.environ["AK_APPLIANCE"]
return "custom"

View File

@ -1,6 +1,4 @@
"""Outpost API Views"""
from os import environ
from dacite.core import from_dict
from dacite.exceptions import DaciteError
from django_filters.filters import ModelMultipleChoiceFilter
@ -14,7 +12,7 @@ from rest_framework.response import Response
from rest_framework.serializers import JSONField, ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from authentik import ENV_GIT_HASH_KEY
from authentik import get_build_hash
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer, is_dict
@ -154,7 +152,7 @@ class OutpostViewSet(UsedByMixin, ModelViewSet):
"version_should": state.version_should,
"version_outdated": state.version_outdated,
"build_hash": state.build_hash,
"build_hash_should": environ.get(ENV_GIT_HASH_KEY, ""),
"build_hash_should": get_build_hash(),
}
)
return Response(OutpostHealthSerializer(states, many=True).data)

View File

@ -1,12 +1,11 @@
"""Base Controller"""
from dataclasses import dataclass
from os import environ
from typing import Optional
from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import __version__, get_build_hash
from authentik.lib.config import CONFIG
from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.models import (
@ -102,5 +101,5 @@ class BaseController:
return image_name_template % {
"type": self.outpost.type,
"version": __version__,
"build_hash": environ.get(ENV_GIT_HASH_KEY, ""),
"build_hash": get_build_hash(),
}

View File

@ -9,6 +9,7 @@ from docker import DockerClient as UpstreamDockerClient
from docker.errors import DockerException, NotFound
from docker.models.containers import Container
from docker.utils.utils import kwargs_from_env
from paramiko.ssh_exception import SSHException
from structlog.stdlib import get_logger
from yaml import safe_dump
@ -49,10 +50,13 @@ class DockerClient(UpstreamDockerClient, BaseClient):
authentication_kp=connection.tls_authentication,
)
tls_config = self.tls.write()
super().__init__(
base_url=connection.url,
tls=tls_config,
)
try:
super().__init__(
base_url=connection.url,
tls=tls_config,
)
except SSHException as exc:
raise ServiceConnectionInvalid from exc
self.logger = get_logger()
# Ensure the client actually works
self.containers.list()
@ -102,9 +106,12 @@ class DockerController(BaseController):
).lower()
def _get_labels(self) -> dict[str, str]:
return {
labels = {
"io.goauthentik.outpost-uuid": self.outpost.pk.hex,
}
if self.outpost.config.docker_labels:
labels.update(self.outpost.config.docker_labels)
return labels
def _get_env(self) -> dict[str, str]:
return {

View File

@ -18,6 +18,7 @@ from kubernetes.client import (
V1SecretKeySelector,
)
from authentik import __version__, get_full_version
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
@ -52,15 +53,18 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
raise NeedsUpdate()
super().reconcile(current, reference)
def get_pod_meta(self) -> dict[str, str]:
def get_pod_meta(self, **kwargs) -> dict[str, str]:
"""Get common object metadata"""
return {
"app.kubernetes.io/name": "authentik-outpost",
"app.kubernetes.io/managed-by": "goauthentik.io",
"goauthentik.io/outpost-uuid": self.controller.outpost.uuid.hex,
"goauthentik.io/outpost-name": slugify(self.controller.outpost.name),
"goauthentik.io/outpost-type": str(self.controller.outpost.type),
}
kwargs.update(
{
"app.kubernetes.io/name": f"authentik-outpost-{self.outpost.type}",
"app.kubernetes.io/managed-by": "goauthentik.io",
"goauthentik.io/outpost-uuid": self.controller.outpost.uuid.hex,
"goauthentik.io/outpost-name": slugify(self.controller.outpost.name),
"goauthentik.io/outpost-type": str(self.controller.outpost.type),
}
)
return kwargs
def get_reference_object(self) -> V1Deployment:
"""Get deployment object for outpost"""
@ -77,13 +81,24 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
meta = self.get_object_meta(name=self.name)
image_name = self.controller.get_container_image()
image_pull_secrets = self.outpost.config.kubernetes_image_pull_secrets
version = get_full_version()
return V1Deployment(
metadata=meta,
spec=V1DeploymentSpec(
replicas=self.outpost.config.kubernetes_replicas,
selector=V1LabelSelector(match_labels=self.get_pod_meta()),
template=V1PodTemplateSpec(
metadata=V1ObjectMeta(labels=self.get_pod_meta()),
metadata=V1ObjectMeta(
labels=self.get_pod_meta(
**{
# Support istio-specific labels, but also use the standard k8s
# recommendations
"app.kubernetes.io/version": version,
"app": "authentik-outpost",
"version": version,
}
)
),
spec=V1PodSpec(
image_pull_secrets=[
V1ObjectReference(name=secret) for secret in image_pull_secrets

View File

@ -6,6 +6,7 @@ from kubernetes.client import CoreV1Api, V1Service, V1ServicePort, V1ServiceSpec
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.triggers import NeedsUpdate
from authentik.outposts.controllers.k8s.utils import compare_ports
if TYPE_CHECKING:
@ -25,6 +26,8 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]):
# 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.
if current.spec.selector != reference.spec.selector:
raise NeedsUpdate()
super().reconcile(current, reference)
def get_reference_object(self) -> V1Service:

View File

@ -1,7 +1,6 @@
"""Outpost models"""
from dataclasses import asdict, dataclass, field
from datetime import datetime
from os import environ
from typing import Iterable, Optional
from uuid import uuid4
@ -17,7 +16,7 @@ from model_utils.managers import InheritanceManager
from packaging.version import LegacyVersion, Version, parse
from structlog.stdlib import get_logger
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import __version__, get_build_hash
from authentik.core.models import (
USER_ATTRIBUTE_CAN_OVERRIDE_IP,
USER_ATTRIBUTE_SA,
@ -61,6 +60,7 @@ class OutpostConfig:
docker_network: Optional[str] = field(default=None)
docker_map_ports: bool = field(default=True)
docker_labels: Optional[dict[str, str]] = field(default=None)
container_image: Optional[str] = field(default=None)
@ -414,7 +414,7 @@ class OutpostState:
"""Check if outpost version matches our version"""
if not self.version:
return False
if self.build_hash != environ.get(ENV_GIT_HASH_KEY, ""):
if self.build_hash != get_build_hash():
return False
return parse(self.version) < OUR_VERSION

View File

@ -77,8 +77,12 @@ def outpost_service_connection_state(connection_pk: Any):
cls = DockerClient
if isinstance(connection, KubernetesServiceConnection):
cls = KubernetesClient
with cls(connection) as client:
state = client.fetch_state()
try:
with cls(connection) as client:
state = client.fetch_state()
except ServiceConnectionInvalid as exc:
LOGGER.warning("Failed to get client status", exc=exc)
return
cache.set(connection.state_key, state, timeout=None)

View File

@ -5,7 +5,7 @@ from typing import Iterator, Optional
from django.core.cache import cache
from django.http import HttpRequest
from prometheus_client import Histogram
from prometheus_client import Gauge, Histogram
from sentry_sdk.hub import Hub
from sentry_sdk.tracing import Span
from structlog.stdlib import BoundLogger, get_logger
@ -14,13 +14,11 @@ from authentik.core.models import User
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel, PolicyEngineMode
from authentik.policies.process import PolicyProcess, cache_key
from authentik.policies.types import PolicyRequest, PolicyResult
from authentik.root.monitoring import UpdatingGauge
CURRENT_PROCESS = current_process()
GAUGE_POLICIES_CACHED = UpdatingGauge(
GAUGE_POLICIES_CACHED = Gauge(
"authentik_policies_cached",
"Cached Policies",
update_func=lambda: len(cache.keys("policy_*") or []),
)
HIST_POLICIES_BUILD_TIME = Histogram(
"authentik_policies_build_time",

View File

@ -45,7 +45,7 @@ class HaveIBeenPwendPolicy(Policy):
fields=request.context.keys(),
)
return PolicyResult(False, _("Password not set in context"))
password = request.context[self.password_field]
password = str(request.context[self.password_field])
pw_hash = sha1(password.encode("utf-8")).hexdigest() # nosec
url = f"https://api.pwnedpasswords.com/range/{pw_hash[:5]}"

View File

@ -5,10 +5,19 @@ from django.dispatch import receiver
from structlog.stdlib import get_logger
from authentik.core.api.applications import user_app_cache_key
from authentik.policies.engine import GAUGE_POLICIES_CACHED
from authentik.root.monitoring import monitoring_set
LOGGER = get_logger()
@receiver(monitoring_set)
# pylint: disable=unused-argument
def monitoring_set_policies(sender, **kwargs):
"""set policy gauges"""
GAUGE_POLICIES_CACHED.set(len(cache.keys("policy_*") or []))
@receiver(post_save)
# pylint: disable=unused-argument
def invalidate_policy_cache(sender, instance, **_):

View File

@ -99,7 +99,7 @@ class OAuthAuthorizationParams:
# and POST request.
query_dict = request.POST if request.method == "POST" else request.GET
state = query_dict.get("state")
redirect_uri = query_dict.get("redirect_uri", "")
redirect_uri = query_dict.get("redirect_uri", "").lower()
response_type = query_dict.get("response_type", "")
grant_type = None
@ -156,13 +156,20 @@ class OAuthAuthorizationParams:
if not self.redirect_uri:
LOGGER.warning("Missing redirect uri.")
raise RedirectUriError("", allowed_redirect_urls)
if len(allowed_redirect_urls) < 1:
if self.provider.redirect_uris == "":
LOGGER.info("Setting redirect for blank redirect_uris", redirect=self.redirect_uri)
self.provider.redirect_uris = self.redirect_uri
self.provider.save()
allowed_redirect_urls = self.provider.redirect_uris.split()
if self.provider.redirect_uris == "*":
LOGGER.warning(
"Provider has no allowed redirect_uri set, allowing all.",
allow=self.redirect_uri.lower(),
"Provider has wildcard allowed redirect_uri set, allowing all.",
allow=self.redirect_uri,
)
return
if self.redirect_uri.lower() not in [x.lower() for x in allowed_redirect_urls]:
if self.redirect_uri not in [x.lower() for x in allowed_redirect_urls]:
LOGGER.warning(
"Invalid redirect uri",
redirect_uri=self.redirect_uri,

View File

@ -66,7 +66,7 @@ class TokenParams:
provider=provider,
client_id=client_id,
client_secret=client_secret,
redirect_uri=request.POST.get("redirect_uri", ""),
redirect_uri=request.POST.get("redirect_uri", "").lower(),
grant_type=request.POST.get("grant_type", ""),
state=request.POST.get("state", ""),
scope=request.POST.get("scope", "").split(),
@ -123,21 +123,23 @@ class TokenParams:
LOGGER.warning("Invalid grant type", grant_type=self.grant_type)
raise TokenError("unsupported_grant_type")
def __post_init_code(self, raw_code):
def __post_init_code(self, raw_code: str):
if not raw_code:
LOGGER.warning("Missing authorization code")
raise TokenError("invalid_grant")
allowed_redirect_urls = self.provider.redirect_uris.split()
if len(allowed_redirect_urls) < 1:
if self.provider.redirect_uris == "*":
LOGGER.warning(
"Provider has no allowed redirect_uri set, allowing all.",
allow=self.redirect_uri.lower(),
"Provider has wildcard allowed redirect_uri set, allowing all.",
redirect=self.redirect_uri,
)
elif self.redirect_uri.lower() not in [x.lower() for x in allowed_redirect_urls]:
# At this point, no provider should have a blank redirect_uri, in case they do
# this will check an empty array and raise an error
elif self.redirect_uri not in [x.lower() for x in allowed_redirect_urls]:
LOGGER.warning(
"Invalid redirect uri",
uri=self.redirect_uri,
redirect=self.redirect_uri,
expected=self.provider.redirect_uris.split(),
)
raise TokenError("invalid_client")

View File

@ -26,7 +26,9 @@ class ProxyDockerController(DockerController):
traefik_name = f"ak-outpost-{self.outpost.pk.hex}"
labels = super()._get_labels()
labels["traefik.enable"] = "true"
labels[f"traefik.http.routers.{traefik_name}-router.rule"] = f"Host({','.join(hosts)})"
labels[
f"traefik.http.routers.{traefik_name}-router.rule"
] = f"Host({','.join(hosts)}) && PathPrefix('/akprox')"
labels[f"traefik.http.routers.{traefik_name}-router.tls"] = "true"
labels[f"traefik.http.routers.{traefik_name}-router.service"] = f"{traefik_name}-service"
labels[

View File

@ -121,13 +121,6 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware])
forwardAuth=TraefikMiddlewareSpecForwardAuth(
address=f"http://{self.name}.{self.namespace}:9000/akprox/auth/traefik",
authResponseHeaders=[
# Legacy headers, remove after 2022.1
"X-Auth-Username",
"X-Auth-Groups",
"X-Forwarded-Email",
"X-Forwarded-Preferred-Username",
"X-Forwarded-User",
# New headers, unique prefix
"X-authentik-username",
"X-authentik-groups",
"X-authentik-email",

View File

@ -1,37 +1,17 @@
"""Metrics view"""
from base64 import b64encode
from typing import Callable
from django.conf import settings
from django.db import connections
from django.db.utils import OperationalError
from django.dispatch import Signal
from django.http import HttpRequest, HttpResponse
from django.views import View
from django_prometheus.exports import ExportToDjangoView
from django_redis import get_redis_connection
from prometheus_client import Gauge
from redis.exceptions import RedisError
from authentik.admin.api.workers import GAUGE_WORKERS
from authentik.events.monitored_tasks import TaskInfo
from authentik.root.celery import CELERY_APP
class UpdatingGauge(Gauge):
"""Gauge which fetches its own value from an update function.
Update function is called on instantiate"""
def __init__(self, *args, update_func: Callable, **kwargs):
super().__init__(*args, **kwargs)
self._update_func = update_func
self.update()
def update(self):
"""Set value from update function"""
val = self._update_func()
if val:
self.set(val)
monitoring_set = Signal()
class MetricsView(View):
@ -49,11 +29,7 @@ class MetricsView(View):
response["WWW-Authenticate"] = 'Basic realm="authentik-monitoring"'
return response
count = len(CELERY_APP.control.ping(timeout=0.5))
GAUGE_WORKERS.set(count)
for task in TaskInfo.all().values():
task.set_prom_metrics()
monitoring_set.send_robust(self)
return ExportToDjangoView(request)

View File

@ -30,7 +30,7 @@ from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.redis import RedisIntegration
from sentry_sdk.integrations.threading import ThreadingIntegration
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import ENV_GIT_HASH_KEY, __version__, get_build_hash, get_full_version
from authentik.core.middleware import structlog_add_request_id
from authentik.lib.config import CONFIG
from authentik.lib.logging import add_process_id
@ -75,6 +75,7 @@ AUTH_USER_MODEL = "authentik_core.User"
_cookie_suffix = "_debug" if DEBUG else ""
CSRF_COOKIE_NAME = "authentik_csrf"
CSRF_HEADER_NAME = "HTTP_X_AUTHENTIK_CSRF"
LANGUAGE_COOKIE_NAME = f"authentik_language{_cookie_suffix}"
SESSION_COOKIE_NAME = f"authentik_session{_cookie_suffix}"
SESSION_COOKIE_DOMAIN = CONFIG.y("cookie_domain", None)
@ -164,9 +165,6 @@ SPECTACULAR_SETTINGS = {
{
"url": "/api/v3/",
},
{
"url": "/api/v2beta/",
},
],
"CONTACT": {
"email": "hello@beryju.org",
@ -357,7 +355,7 @@ CELERY_BEAT_SCHEDULE = {
},
"db_backup": {
"task": "authentik.core.tasks.backup_database",
"schedule": crontab(hour="*/24"),
"schedule": crontab(hour="*/24", minute=0),
"options": {"queue": "authentik_scheduled"},
},
}
@ -378,7 +376,7 @@ DBBACKUP_CONNECTOR_MAPPING = {
"django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector",
}
DBBACKUP_TMP_DIR = gettempdir() if DEBUG else "/tmp" # nosec
DBBACKUP_CLEANUP_KEEP = 30
DBBACKUP_CLEANUP_KEEP = 10
if CONFIG.y("postgresql.s3_backup.bucket", "") != "":
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
DBBACKUP_STORAGE_OPTIONS = {
@ -398,10 +396,6 @@ if CONFIG.y("postgresql.s3_backup.bucket", "") != "":
# Sentry integration
SENTRY_DSN = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"
# Default to empty string as that is what docker has
build_hash = os.environ.get(ENV_GIT_HASH_KEY, "")
if build_hash == "":
build_hash = "tagged"
env = get_env()
_ERROR_REPORTING = CONFIG.y_bool("error_reporting.enabled", False)
@ -422,10 +416,10 @@ if _ERROR_REPORTING:
environment=CONFIG.y("error_reporting.environment", "customer"),
send_default_pii=CONFIG.y_bool("error_reporting.send_pii", False),
)
set_tag("authentik.build_hash", build_hash)
set_tag("authentik.build_hash", get_build_hash("tagged"))
set_tag("authentik.env", env)
set_tag("authentik.component", "backend")
set_tag("authentik.uuid", sha512(SECRET_KEY.encode("ascii")).hexdigest()[:16])
set_tag("authentik.uuid", sha512(str(SECRET_KEY).encode("ascii")).hexdigest()[:16])
j_print(
"Error reporting is enabled",
env=CONFIG.y("error_reporting.environment", "customer"),
@ -439,11 +433,13 @@ if not CONFIG.y_bool("disable_startup_analytics", False):
json={
"domain": "authentik",
"name": "pageview",
"referrer": f"{__version__} ({build_hash})",
"url": f"http://localhost/{env}?utm_source={__version__}&utm_medium={env}",
"referrer": get_full_version(),
"url": (
f"http://localhost/{env}?utm_source={get_full_version()}&utm_medium={env}"
),
},
headers={
"User-Agent": sha512(SECRET_KEY.encode("ascii")).hexdigest()[:16],
"User-Agent": sha512(str(SECRET_KEY).encode("ascii")).hexdigest()[:16],
"Content-Type": "application/json",
},
timeout=5,

View File

@ -18,7 +18,12 @@ class AuthenticateWebAuthnStageSerializer(StageSerializer):
class Meta:
model = AuthenticateWebAuthnStage
fields = StageSerializer.Meta.fields + ["configure_flow", "user_verification"]
fields = StageSerializer.Meta.fields + [
"configure_flow",
"user_verification",
"authenticator_attachment",
"resident_key_requirement",
]
class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet):

View File

@ -0,0 +1,37 @@
# Generated by Django 4.0.1 on 2022-01-12 21:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"authentik_stages_authenticator_webauthn",
"0005_authenticatewebauthnstage_user_verification",
),
]
operations = [
migrations.AddField(
model_name="authenticatewebauthnstage",
name="authenticator_attachment",
field=models.TextField(
choices=[("platform", "Platform"), ("cross-platform", "Cross Platform")],
default=None,
null=True,
),
),
migrations.AddField(
model_name="authenticatewebauthnstage",
name="resident_key_requirement",
field=models.TextField(
choices=[
("discouraged", "Discouraged"),
("preferred", "Preferred"),
("required", "Required"),
],
default="preferred",
),
),
]

View File

@ -31,6 +31,40 @@ class UserVerification(models.TextChoices):
DISCOURAGED = "discouraged"
class ResidentKeyRequirement(models.TextChoices):
"""The Relying Party's preference for the authenticator to create a dedicated "client-side"
credential for it. Requiring an authenticator to store a dedicated credential should not be
done lightly due to the limited storage capacity of some types of authenticators.
Members:
`DISCOURAGED`: The authenticator should not create a dedicated credential
`PREFERRED`: The authenticator can create and store a dedicated credential, but if it
doesn't that's alright too
`REQUIRED`: The authenticator MUST create a dedicated credential. If it cannot, the RP
is prepared for an error to occur.
https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement
"""
DISCOURAGED = "discouraged"
PREFERRED = "preferred"
REQUIRED = "required"
class AuthenticatorAttachment(models.TextChoices):
"""How an authenticator is connected to the client/browser.
Members:
`PLATFORM`: A non-removable authenticator, like TouchID or Windows Hello
`CROSS_PLATFORM`: A "roaming" authenticator, like a YubiKey
https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment
"""
PLATFORM = "platform"
CROSS_PLATFORM = "cross-platform"
class AuthenticateWebAuthnStage(ConfigurableStage, Stage):
"""WebAuthn stage"""
@ -38,6 +72,13 @@ class AuthenticateWebAuthnStage(ConfigurableStage, Stage):
choices=UserVerification.choices,
default=UserVerification.PREFERRED,
)
resident_key_requirement = models.TextField(
choices=ResidentKeyRequirement.choices,
default=ResidentKeyRequirement.PREFERRED,
)
authenticator_attachment = models.TextField(
choices=AuthenticatorAttachment.choices, default=None, null=True
)
@property
def serializer(self) -> BaseSerializer:

View File

@ -13,7 +13,6 @@ from webauthn.helpers.structs import (
AuthenticatorSelectionCriteria,
PublicKeyCredentialCreationOptions,
RegistrationCredential,
ResidentKeyRequirement,
)
from webauthn.registration.verify_registration_response import VerifiedRegistration
@ -85,6 +84,12 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
stage: AuthenticateWebAuthnStage = self.executor.current_stage
user = self.get_pending_user()
# library accepts none so we store null in the database, but if there is a value
# set, cast it to string to ensure it's not a django class
authenticator_attachment = stage.authenticator_attachment
if authenticator_attachment:
authenticator_attachment = str(authenticator_attachment)
registration_options: PublicKeyCredentialCreationOptions = generate_registration_options(
rp_id=get_rp_id(self.request),
rp_name=self.request.tenant.branding_title,
@ -92,8 +97,9 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
user_name=user.username,
user_display_name=user.name,
authenticator_selection=AuthenticatorSelectionCriteria(
resident_key=ResidentKeyRequirement.PREFERRED,
resident_key=str(stage.resident_key_requirement),
user_verification=str(stage.user_verification),
authenticator_attachment=authenticator_attachment,
),
)

View File

@ -17,7 +17,7 @@ services:
image: redis:alpine
restart: unless-stopped
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.12.5}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.2}
restart: unless-stopped
command: server
environment:
@ -35,10 +35,10 @@ services:
env_file:
- .env
ports:
- "0.0.0.0:9000:9000"
- "0.0.0.0:9443:9443"
- "0.0.0.0:${AUTHENTIK_PORT_HTTP:-9000}:9000"
- "0.0.0.0:${AUTHENTIK_PORT_HTTPS:-9443}:9443"
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.12.5}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2022.1.2}
restart: unless-stopped
command: worker
environment:

9
go.mod
View File

@ -9,10 +9,9 @@ require (
github.com/garyburd/redigo v1.6.2 // indirect
github.com/getsentry/sentry-go v0.12.0
github.com/go-ldap/ldap/v3 v3.4.1
github.com/go-openapi/runtime v0.21.0
github.com/go-openapi/runtime v0.21.1
github.com/go-openapi/strfmt v0.21.1
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/uuid v1.3.0
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
@ -26,10 +25,10 @@ require (
github.com/pires/go-proxyproto v0.6.1
github.com/pkg/errors v0.9.1
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/client_golang v1.12.0
github.com/sirupsen/logrus v1.8.1
goauthentik.io/api v0.2021124.9
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558
goauthentik.io/api v0.2021125.1
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/boj/redistore.v1 v1.0.0-20160128113310-fc113767cd6b

30
go.sum
View File

@ -70,8 +70,9 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@ -182,8 +183,8 @@ github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29g
github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo=
github.com/go-openapi/runtime v0.19.16/go.mod h1:5P9104EJgYcizotuXhEuUrzVc+j1RiSjahULvYmlv98=
github.com/go-openapi/runtime v0.19.24/go.mod h1:Lm9YGCeecBnUUkFTxPC4s1+lwrkJ0pthx8YvyjCfkgk=
github.com/go-openapi/runtime v0.21.0 h1:giZ8eT26R+/rx6RX2MkYjZPY8vPYVKDhP/mOazrQHzM=
github.com/go-openapi/runtime v0.21.0/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs=
github.com/go-openapi/runtime v0.21.1 h1:/KIG00BzA2x2HRStX2tnhbqbQdPcFlkgsYCiNY20FZs=
github.com/go-openapi/runtime v0.21.1/go.mod h1:aQg+kaIQEn+A2CRSY1TxbM8+sT9g2V3aLc1FbIAnbbs=
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
@ -360,6 +361,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@ -427,6 +429,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@ -467,8 +470,9 @@ github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoL
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.0 h1:C+UIj/QWtmqY13Arb8kwMt5j34/0Z2iKamrJ+ryC0Gg=
github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -476,13 +480,15 @@ github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -562,8 +568,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
goauthentik.io/api v0.2021124.9 h1:l6kzTggi8lt+Vmm5js7oxp9U/bXoOEIl4565bUeepuM=
goauthentik.io/api v0.2021124.9/go.mod h1:02nnD4FRd8lu8A1+ZuzqownBgvAhdCKzqkKX8v7JMTE=
goauthentik.io/api v0.2021125.1 h1:Ja00N1D1wjqFiR90JV8nDayhmm39uLudzsJhwCjoQJ4=
goauthentik.io/api v0.2021125.1/go.mod h1:02nnD4FRd8lu8A1+ZuzqownBgvAhdCKzqkKX8v7JMTE=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -655,6 +661,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f h1:1scJEYZBaF48BaG6tYbtxmLcXqwYGSfGcMoStTqkkIw=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -663,8 +670,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 h1:D7nTwh4J0i+5mW4Zjzn5omvlr6YBcWywE6KOcatyNxY=
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c h1:pkQiBZBvdos9qq4wBAHqlzuZHEXo07pqV06ef90u1WI=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -731,8 +738,9 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -5,16 +5,24 @@ import (
"os"
)
func BUILD() string {
func BUILD(def string) string {
build := os.Getenv("GIT_BUILD_HASH")
if build == "" {
return "tagged"
return def
}
return build
}
func OutpostUserAgent() string {
return fmt.Sprintf("authentik-outpost@%s (build=%s)", VERSION, BUILD())
func FullVersion() string {
ver := VERSION
if b := BUILD(""); b != "" {
ver = fmt.Sprintf("%s.%s", ver, b)
}
return ver
}
const VERSION = "2021.12.5"
func OutpostUserAgent() string {
return fmt.Sprintf("authentik-outpost@%s", FullVersion())
}
const VERSION = "2022.1.2"

View File

@ -171,7 +171,7 @@ func (a *APIController) StartBackgorundTasks() error {
"outpost_type": a.Server.Type(),
"uuid": a.instanceUUID.String(),
"version": constants.VERSION,
"build": constants.BUILD(),
"build": constants.BUILD("tagged"),
}).Set(1)
go func() {
a.logger.Debug("Starting WS Handler...")

View File

@ -51,7 +51,7 @@ func (ac *APIController) initWS(akURL url.URL, outpostUUID string) error {
Instruction: WebsocketInstructionHello,
Args: map[string]interface{}{
"version": constants.VERSION,
"buildHash": constants.BUILD(),
"buildHash": constants.BUILD("tagged"),
"uuid": ac.instanceUUID.String(),
},
}
@ -151,7 +151,7 @@ func (ac *APIController) startWSHandler() {
"outpost_type": ac.Server.Type(),
"uuid": ac.instanceUUID.String(),
"version": constants.VERSION,
"build": constants.BUILD(),
"build": constants.BUILD("tagged"),
}).SetToCurrentTime()
}
}
@ -165,7 +165,7 @@ func (ac *APIController) startWSHealth() {
Instruction: WebsocketInstructionHello,
Args: map[string]interface{}{
"version": constants.VERSION,
"buildHash": constants.BUILD(),
"buildHash": constants.BUILD("tagged"),
"uuid": ac.instanceUUID.String(),
},
}
@ -205,7 +205,7 @@ func (ac *APIController) startIntervalUpdater() {
"outpost_type": ac.Server.Type(),
"uuid": ac.instanceUUID.String(),
"version": constants.VERSION,
"build": constants.BUILD(),
"build": constants.BUILD("tagged"),
}).SetToCurrentTime()
}
}

View File

@ -34,7 +34,7 @@ func doGlobalSetup(outpost api.Outpost, globalConfig api.Config) {
} else {
l.Debug("Managed outpost, not setting global log level")
}
l.WithField("hash", constants.BUILD()).WithField("version", constants.VERSION).Info("Starting authentik outpost")
l.WithField("hash", constants.BUILD("tagged")).WithField("version", constants.VERSION).Info("Starting authentik outpost")
if globalConfig.ErrorReporting.Enabled {
dsn := "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"

View File

@ -12,11 +12,7 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry {
attrs := utils.AKAttrsToLDAP(u.Attributes)
attrs = utils.EnsureAttributes(attrs, map[string][]string{
"memberOf": pi.GroupsForUser(u),
// Old fields for backwards compatibility
"accountStatus": {utils.BoolToString(*u.IsActive)},
"superuser": {utils.BoolToString(u.IsSuperuser)},
// End old fields
"memberOf": pi.GroupsForUser(u),
"goauthentik.io/ldap/active": {utils.BoolToString(*u.IsActive)},
"goauthentik.io/ldap/superuser": {utils.BoolToString(u.IsSuperuser)},
"cn": {u.Username},

View File

@ -124,7 +124,7 @@ func (pi *ProviderInstance) GetBaseEntry() *ldap.Entry {
},
{
Name: "vendorVersion",
Values: []string{fmt.Sprintf("authentik LDAP Outpost Version %s (build %s)", constants.VERSION, constants.BUILD())},
Values: []string{fmt.Sprintf("authentik LDAP Outpost Version %s", constants.FullVersion())},
},
},
}

View File

@ -44,7 +44,7 @@ func (ds *DirectSearcher) SearchBase(req *search.Request, authz bool) (ldap.Serv
},
{
Name: "vendorVersion",
Values: []string{fmt.Sprintf("authentik LDAP Outpost Version %s (build %s)", constants.VERSION, constants.BUILD())},
Values: []string{fmt.Sprintf("authentik LDAP Outpost Version %s", constants.FullVersion())},
},
},
},

View File

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

View File

@ -61,7 +61,7 @@ func parseFilterForGroupSingle(req api.ApiCoreGroupsListRequest, f *ber.Packet)
}
return req.MembersByUsername([]string{username}), false
}
// TODO: Support int
//TODO: Support int
default:
return req, false
}

View File

@ -66,7 +66,7 @@ func parseFilterForUserSingle(req api.ApiCoreUsersListRequest, f *ber.Packet) (a
}
return req.GroupsByName([]string{name}), false
}
// TODO: Support int
//TODO: Support int
default:
return req, false
}

View File

@ -84,7 +84,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore
mux := mux.NewRouter()
a := &Application{
Host: externalHost.Host,
log: log.WithField("logger", "authentik.outpost.proxy.bundle").WithField("provider", p.Name),
log: muxLogger,
outpostName: ak.Outpost.Name,
endpint: endpoint,
oauthConfig: oauth2Config,
@ -172,7 +172,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, cs *ak.CryptoStore
for _, regex := range strings.Split(*p.SkipPathRegex, "\n") {
re, err := regexp.Compile(regex)
if err != nil {
// TODO: maybe create event for this?
//TODO: maybe create event for this?
a.log.WithError(err).Warning("failed to compile SkipPathRegex")
continue
} else {
@ -187,12 +187,16 @@ func (a *Application) Mode() api.ProxyMode {
return *a.proxyConfig.Mode
}
func (a *Application) ProxyConfig() api.ProxyOutpostConfig {
return a.proxyConfig
}
func (a *Application) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
a.mux.ServeHTTP(rw, r)
}
func (a *Application) handleSignOut(rw http.ResponseWriter, r *http.Request) {
// TODO: Token revocation
//TODO: Token revocation
s, err := a.sessions.Get(r, constants.SeesionName)
if err != nil {
http.Redirect(rw, r, a.endpint.EndSessionEndpoint, http.StatusFound)

View File

@ -13,15 +13,18 @@ import (
type OIDCEndpoint struct {
oauth2.Endpoint
EndSessionEndpoint string
JwksUri string
}
func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string) OIDCEndpoint {
authUrl := p.OidcConfiguration.AuthorizationEndpoint
endUrl := p.OidcConfiguration.EndSessionEndpoint
jwksUrl := p.OidcConfiguration.JwksUri
if browserHost, found := os.LookupEnv("AUTHENTIK_HOST_BROWSER"); found && browserHost != "" {
host := os.Getenv("AUTHENTIK_HOST")
authUrl = strings.ReplaceAll(authUrl, host, browserHost)
endUrl = strings.ReplaceAll(endUrl, host, browserHost)
jwksUrl = strings.ReplaceAll(jwksUrl, host, browserHost)
}
ep := OIDCEndpoint{
Endpoint: oauth2.Endpoint{
@ -30,6 +33,7 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string) OIDCEndpoin
AuthStyle: oauth2.AuthStyleInParams,
},
EndSessionEndpoint: endUrl,
JwksUri: jwksUrl,
}
authU, err := url.Parse(authUrl)
if err != nil {
@ -39,6 +43,10 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string) OIDCEndpoin
if err != nil {
return ep
}
jwksU, err := url.Parse(jwksUrl)
if err != nil {
return ep
}
if authU.Host != "localhost:8000" {
return ep
}
@ -54,7 +62,10 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string) OIDCEndpoin
authU.Scheme = aku.Scheme
endU.Host = aku.Host
endU.Scheme = aku.Scheme
jwksU.Host = aku.Host
jwksU.Scheme = aku.Scheme
ep.AuthURL = authU.String()
ep.EndSessionEndpoint = endU.String()
ep.JwksUri = jwksU.String()
return ep
}

View File

@ -14,14 +14,6 @@ import (
func (a *Application) addHeaders(headers http.Header, c *Claims) {
// https://goauthentik.io/docs/providers/proxy/proxy
// Legacy headers, remove after 2022.1
headers.Set("X-Auth-Username", c.PreferredUsername)
headers.Set("X-Auth-Groups", strings.Join(c.Groups, "|"))
headers.Set("X-Forwarded-Email", c.Email)
headers.Set("X-Forwarded-Preferred-Username", c.PreferredUsername)
headers.Set("X-Forwarded-User", c.Sub)
// New headers, unique prefix
headers.Set("X-authentik-username", c.PreferredUsername)
headers.Set("X-authentik-groups", strings.Join(c.Groups, "|"))
headers.Set("X-authentik-email", c.Email)
@ -30,7 +22,7 @@ func (a *Application) addHeaders(headers http.Header, c *Claims) {
headers.Set("X-authentik-jwt", c.RawToken)
// System headers
headers.Set("X-authentik-meta-jwks", a.proxyConfig.OidcConfiguration.JwksUri)
headers.Set("X-authentik-meta-jwks", a.endpint.JwksUri)
headers.Set("X-authentik-meta-outpost", a.outpostName)
headers.Set("X-authentik-meta-provider", a.proxyConfig.Name)
headers.Set("X-authentik-meta-app", a.proxyConfig.AssignedApplicationSlug)

View File

@ -4,6 +4,7 @@ import (
"fmt"
"net/http"
"net/url"
"strings"
"goauthentik.io/api"
"goauthentik.io/internal/outpost/proxyv2/constants"
@ -34,6 +35,10 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque
a.log.Trace("path can be accessed without authentication")
return
}
if strings.HasPrefix(r.Header.Get("X-Forwarded-Uri"), "/akprox") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access")
return
}
host := ""
s, _ := a.sessions.Get(r, constants.SeesionName)
// Optional suffix, which is appended to the URL
@ -49,14 +54,6 @@ func (a *Application) forwardHandleTraefik(rw http.ResponseWriter, r *http.Reque
// see https://doc.traefik.io/traefik/middlewares/forwardauth/
// X-Forwarded-Uri is only the path, so we need to build the entire URL
s.Values[constants.SessionRedirect] = a.getTraefikForwardUrl(r).String()
if r.Header.Get("X-Forwarded-Uri") == "/akprox/start" {
a.log.Info("Detected potential redirect loop")
if val, ok := s.Values[constants.SessionLoopDetection]; !ok {
s.Values[constants.SessionLoopDetection] = 1
} else {
s.Values[constants.SessionLoopDetection] = val.(int) + 1
}
}
err = s.Save(r, rw)
if err != nil {
a.log.WithError(err).Warning("failed to save session before redirect")
@ -83,5 +80,12 @@ func (a *Application) forwardHandleNginx(rw http.ResponseWriter, r *http.Request
a.log.Trace("path can be accessed without authentication")
return
}
fwu := a.getTraefikForwardUrl(r)
if fwu.String() != r.URL.String() {
if strings.HasPrefix(fwu.Path, "/akprox") {
a.log.WithField("url", r.URL.String()).Trace("path begins with /akprox, allowing access")
return
}
}
http.Error(rw, "unauthorized request", http.StatusUnauthorized)
}

View File

@ -25,13 +25,6 @@ func (a *Application) handleRedirect(rw http.ResponseWriter, r *http.Request) {
if err != nil {
a.log.WithError(err).Warning("failed to save session")
}
if loop, ok := s.Values[constants.SessionLoopDetection]; ok {
if loop.(int) > 10 {
rw.WriteHeader(http.StatusBadRequest)
a.ErrorPage(rw, r, "Detected redirect loop, make sure /akprox is accessible without authentication.")
return
}
}
http.Redirect(rw, r, a.oauthConfig.AuthCodeURL(newState), http.StatusFound)
}

View File

@ -19,7 +19,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig) sessions.Store {
if err != nil {
panic(err)
}
rs.SetMaxLength(math.MaxInt64)
rs.SetMaxLength(math.MaxInt)
if p.TokenValidity.IsSet() {
t := p.TokenValidity.Get()
// Add one to the validity to ensure we don't have a session with indefinite length
@ -39,7 +39,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig) sessions.Store {
// when using OpenID Connect , since this can contain a large amount of extra information in the id_token
// Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk
cs.MaxLength(math.MaxInt64)
cs.MaxLength(math.MaxInt)
if p.TokenValidity.IsSet() {
t := p.TokenValidity.Get()
// Add one to the validity to ensure we don't have a session with indefinite length

View File

@ -6,7 +6,9 @@ import (
"net/url"
"path"
"strconv"
"strings"
"goauthentik.io/api"
"goauthentik.io/internal/outpost/proxyv2/constants"
)
@ -20,6 +22,33 @@ func urlJoin(originalUrl string, newPath string) string {
}
func (a *Application) redirectToStart(rw http.ResponseWriter, r *http.Request) {
s, err := a.sessions.Get(r, constants.SeesionName)
if err == nil {
a.log.WithError(err).Warning("failed to decode session")
}
redirectUrl := r.URL.String()
// simple way to copy the URL
u, _ := url.Parse(redirectUrl)
// In proxy and forward_single mode we only have one URL that we route on
// if we somehow got here without that URL, make sure we're at least redirected back to it
if a.Mode() == api.PROXYMODE_PROXY || a.Mode() == api.PROXYMODE_FORWARD_SINGLE {
u.Host = a.proxyConfig.ExternalHost
}
if a.Mode() == api.PROXYMODE_FORWARD_DOMAIN {
dom := strings.TrimPrefix(*a.proxyConfig.CookieDomain, ".")
// In forward_domain we only check that the current URL's host
// ends with the cookie domain (remove the leading period if set)
if !strings.HasSuffix(r.URL.Hostname(), dom) {
a.log.WithField("url", r.URL.String()).WithField("cd", dom).Warning("Invalid redirect found")
redirectUrl = ""
}
}
s.Values[constants.SessionRedirect] = redirectUrl
err = s.Save(r, rw)
if err != nil {
a.log.WithError(err).Warning("failed to save session before redirect")
}
authUrl := urlJoin(a.proxyConfig.ExternalHost, "/akprox/start")
http.Redirect(rw, r, authUrl, http.StatusFound)
}

View File

@ -6,4 +6,3 @@ const SessionOAuthState = "oauth_state"
const SessionClaims = "claims"
const SessionRedirect = "redirect"
const SessionLoopDetection = "loop_detection"

View File

@ -8,6 +8,7 @@ import (
"time"
"github.com/prometheus/client_golang/prometheus"
"goauthentik.io/internal/outpost/proxyv2/application"
"goauthentik.io/internal/outpost/proxyv2/metrics"
"goauthentik.io/internal/utils/web"
staticWeb "goauthentik.io/web"
@ -43,6 +44,42 @@ func (ps *ProxyServer) HandleStatic(rw http.ResponseWriter, r *http.Request) {
}).Observe(float64(after))
}
func (ps *ProxyServer) lookupApp(r *http.Request) (*application.Application, string) {
host := web.GetHost(r)
// Try to find application by directly looking up host first (proxy, forward_auth_single)
a, ok := ps.apps[host]
if ok {
ps.log.WithField("host", host).WithField("app", a.ProxyConfig().Name).Debug("Found app based direct host match")
return a, host
}
// For forward_auth_domain, we don't have a direct app to domain relationship
// Check through all apps, and check how much of their cookie domain matches the host
// Return the application that has the longest match
var longestMatch *application.Application
longestMatchLength := 0
for _, app := range ps.apps {
// Check if the cookie domain has a leading period for a wildcard
// This will decrease the weight of a wildcard domain, but a request to example.com
// with the cookie domain set to example.com will still be routed correctly.
cd := strings.TrimPrefix(*app.ProxyConfig().CookieDomain, ".")
if !strings.HasSuffix(host, cd) {
continue
}
if len(cd) < longestMatchLength {
continue
}
longestMatch = app
longestMatchLength = len(cd)
}
// Check if our longes match is 0, in which case we didn't match, so we
// manually return no app
if longestMatchLength == 0 {
return nil, host
}
ps.log.WithField("host", host).WithField("app", longestMatch.ProxyConfig().Name).Debug("Found app based on cookie domain")
return longestMatch, host
}
func (ps *ProxyServer) Handle(rw http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/akprox/static") {
ps.HandleStatic(rw, r)
@ -52,9 +89,8 @@ func (ps *ProxyServer) Handle(rw http.ResponseWriter, r *http.Request) {
ps.HandlePing(rw, r)
return
}
host := web.GetHost(r)
a, ok := ps.apps[host]
if !ok {
a, host := ps.lookupApp(r)
if a == nil {
// If we only have one handler, host name switching doesn't matter
if len(ps.apps) == 1 {
ps.log.WithField("host", host).Trace("passing to single app mux")

View File

@ -70,11 +70,12 @@ func NewProxyServer(ac *ak.APIController, portOffset int) *ProxyServer {
return s
}
func (ps *ProxyServer) HandleHost(host string, rw http.ResponseWriter, r *http.Request) bool {
if app, ok := ps.apps[host]; ok {
if app.Mode() == api.PROXYMODE_PROXY {
func (ps *ProxyServer) HandleHost(rw http.ResponseWriter, r *http.Request) bool {
a, host := ps.lookupApp(r)
if a != nil {
if a.Mode() == api.PROXYMODE_PROXY {
ps.log.WithField("host", host).Trace("routing to proxy outpost")
app.ServeHTTP(rw, r)
a.ServeHTTP(rw, r)
return true
}
}

View File

@ -47,10 +47,9 @@ func (ws *WebServer) configureProxy() {
ws.proxyErrorHandler(rw, r, fmt.Errorf("authentik core not running yet"))
return
}
host := web.GetHost(r)
before := time.Now()
if ws.ProxyServer != nil {
if ws.ProxyServer.HandleHost(host, rw, r) {
if ws.ProxyServer.HandleHost(rw, r) {
Requests.With(prometheus.Labels{
"dest": "embedded_outpost",
}).Observe(float64(time.Since(before)))
@ -60,7 +59,7 @@ func (ws *WebServer) configureProxy() {
Requests.With(prometheus.Labels{
"dest": "py",
}).Observe(float64(time.Since(before)))
ws.log.WithField("host", host).Trace("routing to application server")
ws.log.WithField("host", web.GetHost(r)).Trace("routing to application server")
rp.ServeHTTP(rw, r)
})
}

View File

@ -1,5 +1,5 @@
# Stage 1: Build
FROM docker.io/golang:1.17.5-bullseye AS builder
FROM docker.io/golang:1.17.6-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View File

@ -61,8 +61,11 @@ MODE_FILE="/tmp/authentik-mode"
if [[ "$1" == "server" ]]; then
wait_for_db
echo "server" > $MODE_FILE
# We only set prometheus_multiproc_dir for serer, as with the worker it just fills up the disk
export prometheus_multiproc_dir=/dev/shm/
# We only set PROMETHEUS_MULTIPROC_DIR for serer, as with the worker it just fills up the disk
# as one file is created per process
#
# Set to TMPDIR instead hardcoded path so this can be used outside docker too
export PROMETHEUS_MULTIPROC_DIR=$TMPDIR
python -m lifecycle.migrate
/authentik-proxy
elif [[ "$1" == "worker" ]]; then

View File

@ -60,3 +60,10 @@ else:
workers = int(os.environ.get("WORKERS", default_workers))
threads = int(os.environ.get("THREADS", 4))
# pylint: disable=unused-argument
def worker_exit(server, worker):
"""Remove pid dbs when worker is shutdown"""
from prometheus_client import multiprocess
multiprocess.mark_process_dead(worker.pid)

View File

@ -2,6 +2,7 @@
"""This file needs to be run from the root of the project to correctly
import authentik. This is done by the dockerfile."""
from json import dumps
from sys import exit as sysexit
from sys import stderr
from time import sleep, time
@ -25,6 +26,12 @@ def j_print(event: str, log_level: str = "info", **kwargs):
print(dumps(data), file=stderr)
# Sanity check, ensure SECRET_KEY is set before we even check for database connectivity
if CONFIG.y("secret_key") is None or len(CONFIG.y("secret_key")) == 0:
j_print("Secret key missing, check https://goauthentik.io/docs/installation/.")
sysexit(1)
while True:
try:
conn = connect(

574
poetry.lock generated
View File

@ -54,11 +54,11 @@ vine = "5.0.0"
[[package]]
name = "asgiref"
version = "3.4.1"
version = "3.5.0"
description = "ASGI specs, helper code, and adapters"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[package.extras]
tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
@ -73,7 +73,7 @@ python-versions = "*"
[[package]]
name = "astroid"
version = "2.9.2"
version = "2.9.3"
description = "An abstract syntax tree for Python with inference support."
category = "dev"
optional = false
@ -227,14 +227,14 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "boto3"
version = "1.20.29"
version = "1.20.41"
description = "The AWS SDK for Python"
category = "main"
optional = false
python-versions = ">= 3.6"
[package.dependencies]
botocore = ">=1.23.29,<1.24.0"
botocore = ">=1.23.41,<1.24.0"
jmespath = ">=0.7.1,<1.0.0"
s3transfer = ">=0.5.0,<0.6.0"
@ -243,7 +243,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
version = "1.23.29"
version = "1.23.41"
description = "Low-level, data-driven core of boto 3."
category = "main"
optional = false
@ -267,11 +267,11 @@ python-versions = ">=3.5"
[[package]]
name = "cachetools"
version = "4.2.4"
version = "5.0.0"
description = "Extensible memoizing collections and decorators"
category = "main"
optional = false
python-versions = "~=3.5"
python-versions = "~=3.7"
[[package]]
name = "cattrs"
@ -800,11 +800,11 @@ tornado = ">=5.0.0,<7.0.0"
[[package]]
name = "frozenlist"
version = "1.2.0"
version = "1.3.0"
description = "A list-like structure which implements collections.abc.MutableSequence"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[[package]]
name = "geoip2"
@ -833,7 +833,7 @@ smmap = ">=3.0.1,<6"
[[package]]
name = "gitpython"
version = "3.1.24"
version = "3.1.26"
description = "GitPython is a python library used to interact with Git repositories"
category = "dev"
optional = false
@ -844,14 +844,14 @@ gitdb = ">=4.0.1,<5"
[[package]]
name = "google-auth"
version = "2.3.3"
version = "2.4.0"
description = "Google Authentication Library"
category = "main"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*"
[package.dependencies]
cachetools = ">=2.0.0,<5.0"
cachetools = ">=2.0.0,<6.0"
pyasn1-modules = ">=0.2.1"
rsa = {version = ">=3.1.4,<5", markers = "python_version >= \"3.6\""}
six = ">=1.9.0"
@ -877,7 +877,7 @@ tornado = ["tornado (>=0.2)"]
[[package]]
name = "h11"
version = "0.12.0"
version = "0.13.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
category = "main"
optional = false
@ -934,7 +934,7 @@ python-versions = ">=3.5"
[[package]]
name = "importlib-metadata"
version = "4.10.0"
version = "4.10.1"
description = "Read metadata from Python packages"
category = "dev"
optional = false
@ -999,7 +999,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "jsonschema"
version = "4.3.3"
version = "4.4.0"
description = "An implementation of JSON Schema validation for Python"
category = "main"
optional = false
@ -1122,11 +1122,11 @@ python-versions = "*"
[[package]]
name = "multidict"
version = "5.2.0"
version = "6.0.1"
description = "multidict implementation"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[[package]]
name = "mypy-extensions"
@ -1173,7 +1173,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
[[package]]
name = "paramiko"
version = "2.9.1"
version = "2.9.2"
description = "SSH2 protocol library"
category = "main"
optional = false
@ -1297,7 +1297,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[[package]]
name = "pycryptodome"
version = "3.12.0"
version = "3.13.0"
description = "Cryptographic library for Python"
category = "main"
optional = false
@ -1362,15 +1362,14 @@ pylint = ">=1.7"
[[package]]
name = "pynacl"
version = "1.4.0"
version = "1.5.0"
description = "Python binding to the Networking and Cryptography (NaCl) library"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
python-versions = ">=3.6"
[package.dependencies]
cffi = ">=1.4.1"
six = "*"
[package.extras]
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
@ -1394,7 +1393,7 @@ test = ["flaky", "pretend", "pytest (>=3.0.1)"]
[[package]]
name = "pyparsing"
version = "3.0.6"
version = "3.0.7"
description = "Python parsing module"
category = "main"
optional = false
@ -1405,11 +1404,11 @@ diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pyrsistent"
version = "0.18.0"
version = "0.18.1"
description = "Persistent/Functional/Immutable data structures"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[[package]]
name = "pytest"
@ -1449,11 +1448,11 @@ testing = ["django", "django-configurations (>=2.0)"]
[[package]]
name = "pytest-randomly"
version = "3.10.3"
version = "3.11.0"
description = "Pytest plugin to randomly order tests and control random.seed."
category = "dev"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.7"
[package.dependencies]
pytest = "*"
@ -1506,7 +1505,7 @@ python-versions = ">=3.6"
[[package]]
name = "redis"
version = "4.1.0"
version = "4.1.1"
description = "Python client for Redis database and key-value store"
category = "main"
optional = false
@ -1514,11 +1513,11 @@ python-versions = ">=3.6"
[package.dependencies]
deprecated = ">=1.2.3"
packaging = ">=21.3"
packaging = ">=20.4"
[package.extras]
cryptography = ["cryptography (>=36.0.1)", "requests (>=2.26.0)"]
hiredis = ["hiredis (>=1.0.0)"]
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
[[package]]
name = "requests"
@ -1609,39 +1608,33 @@ urllib3 = {version = ">=1.26,<2.0", extras = ["secure"]}
[[package]]
name = "sentry-sdk"
version = "1.5.0"
description = ""
version = "1.5.3"
description = "Python client for Sentry (https://sentry.io)"
category = "main"
optional = false
python-versions = "*"
develop = false
[package.dependencies]
certifi = "*"
urllib3 = ">=1.10.0"
[package.extras]
flask = ["flask (>=0.11)", "blinker (>=1.1)"]
bottle = ["bottle (>=0.12.13)"]
falcon = ["falcon (>=1.4)"]
django = ["django (>=1.8)"]
sanic = ["sanic (>=0.8)"]
celery = ["celery (>=3)"]
beam = ["apache-beam (>=2.12)"]
rq = ["rq (>=0.6)"]
aiohttp = ["aiohttp (>=3.5)"]
tornado = ["tornado (>=5)"]
sqlalchemy = ["sqlalchemy (>=1.2)"]
pyspark = ["pyspark (>=2.4.4)"]
pure_eval = ["pure-eval", "executing", "asttokens"]
beam = ["apache-beam (>=2.12)"]
bottle = ["bottle (>=0.12.13)"]
celery = ["celery (>=3)"]
chalice = ["chalice (>=1.16.0)"]
django = ["django (>=1.8)"]
falcon = ["falcon (>=1.4)"]
flask = ["flask (>=0.11)", "blinker (>=1.1)"]
httpx = ["httpx (>=0.16.0)"]
[package.source]
type = "git"
url = 'https://github.com/beryju/sentry-python.git'
reference = '379aee28b15d3b87b381317746c4efd24b3d7bc3'
resolved_reference = "379aee28b15d3b87b381317746c4efd24b3d7bc3"
pure_eval = ["pure-eval", "executing", "asttokens"]
pyspark = ["pyspark (>=2.4.4)"]
quart = ["quart (>=0.16.1)", "blinker (>=1.1)"]
rq = ["rq (>=0.6)"]
sanic = ["sanic (>=0.8)"]
sqlalchemy = ["sqlalchemy (>=1.2)"]
tornado = ["tornado (>=5)"]
[[package]]
name = "service-identity"
@ -1886,7 +1879,7 @@ python-versions = ">=3.6"
[[package]]
name = "urllib3"
version = "1.26.7"
version = "1.26.8"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
@ -1905,7 +1898,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "uvicorn"
version = "0.16.0"
version = "0.17.0"
description = "The lightning-fast ASGI server."
category = "main"
optional = false
@ -1921,10 +1914,10 @@ python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"stan
PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"standard\""}
uvloop = {version = ">=0.14.0,<0.15.0 || >0.15.0,<0.15.1 || >0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""}
watchgod = {version = ">=0.6", optional = true, markers = "extra == \"standard\""}
websockets = {version = ">=10.0", optional = true, markers = "python_version >= \"3.7\" and extra == \"standard\""}
websockets = {version = ">=10.0", optional = true, markers = "extra == \"standard\""}
[package.extras]
standard = ["httptools (>=0.2.0,<0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "websockets (>=9.1)", "websockets (>=10.0)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"]
standard = ["websockets (>=10.0)", "httptools (>=0.2.0,<0.4.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"]
[[package]]
name = "uvloop"
@ -1965,7 +1958,7 @@ python-versions = "*"
[[package]]
name = "webauthn"
version = "1.2.0"
version = "1.2.1"
description = "Pythonic WebAuthn"
category = "main"
optional = false
@ -2070,7 +2063,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
[metadata]
lock-version = "1.1"
python-versions = "^3.10"
content-hash = "b943f64c1111790d5534be74e941ce6880efb75cdf562993a66f138c082cd80f"
content-hash = "d3061d973ae4fd3ddea0bff63f1dbd615322546024b75dc6015ef5faf01d6368"
[metadata.files]
aiohttp = [
@ -2160,16 +2153,16 @@ amqp = [
{file = "amqp-5.0.9.tar.gz", hash = "sha256:1e5f707424e544078ca196e72ae6a14887ce74e02bd126be54b7c03c971bef18"},
]
asgiref = [
{file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"},
{file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"},
{file = "asgiref-3.5.0-py3-none-any.whl", hash = "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9"},
{file = "asgiref-3.5.0.tar.gz", hash = "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0"},
]
asn1crypto = [
{file = "asn1crypto-1.4.0-py2.py3-none-any.whl", hash = "sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8"},
{file = "asn1crypto-1.4.0.tar.gz", hash = "sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"},
]
astroid = [
{file = "astroid-2.9.2-py3-none-any.whl", hash = "sha256:aa296702f1a5c3102c860de49473aaa90a7f6d221555d5cf2678940a9be32a4e"},
{file = "astroid-2.9.2.tar.gz", hash = "sha256:72ace9c3333e274e9248168fc4f3e300da8545af1c303bd69197027f49e2bfff"},
{file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"},
{file = "astroid-2.9.3.tar.gz", hash = "sha256:1efdf4e867d4d8ba4a9f6cf9ce07cd182c4c41de77f23814feb27ca93ca9d877"},
]
async-generator = [
{file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"},
@ -2216,20 +2209,20 @@ black = [
{file = "black-21.12b0.tar.gz", hash = "sha256:77b80f693a569e2e527958459634f18df9b0ba2625ba4e0c2d5da5be42e6f2b3"},
]
boto3 = [
{file = "boto3-1.20.29-py3-none-any.whl", hash = "sha256:1955ec05e4a2cf8d503af72f5bb26e3a5526438c89ee875d77a2e8d082277589"},
{file = "boto3-1.20.29.tar.gz", hash = "sha256:ab0ca0d0dbb90a05b010bbcc038850f0b71979182b44bd88313eafb6ae8a26a3"},
{file = "boto3-1.20.41-py3-none-any.whl", hash = "sha256:aaddf6cf93568b734ad62fd96991775bccc7f016e93ff4e98dc1aa4f7586440c"},
{file = "boto3-1.20.41.tar.gz", hash = "sha256:fb02467a6e8109c7db994ba77fa2e8381ed129ce312988d8ef23edf6e3a3c7f1"},
]
botocore = [
{file = "botocore-1.23.29-py3-none-any.whl", hash = "sha256:d6706a8e72df56c5b25291cf5175b790bf1c71c740bdf8cb57f258b97ed39e2c"},
{file = "botocore-1.23.29.tar.gz", hash = "sha256:6ba08e8738b38b1c3cb11cd4d4ee1b4aa557511271071bdd7a9c41bc0b212eeb"},
{file = "botocore-1.23.41-py3-none-any.whl", hash = "sha256:41104e1c976c9c410387b3c7d265466b314f287a1c13fd4b543768135301058a"},
{file = "botocore-1.23.41.tar.gz", hash = "sha256:9137c59c4eb1dee60ae3c710e94f56119a1b33b0b17ff3ad878fc2f4ce77843a"},
]
bump2version = [
{file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"},
{file = "bump2version-1.0.1.tar.gz", hash = "sha256:762cb2bfad61f4ec8e2bdf452c7c267416f8c70dd9ecb1653fd0bbb01fa936e6"},
]
cachetools = [
{file = "cachetools-4.2.4-py3-none-any.whl", hash = "sha256:92971d3cb7d2a97efff7c7bb1657f21a8f5fb309a37530537c71b1774189f2d1"},
{file = "cachetools-4.2.4.tar.gz", hash = "sha256:89ea6f1b638d5a73a4f9226be57ac5e4f399d22770b92355f92dcb0f7f001693"},
{file = "cachetools-5.0.0-py3-none-any.whl", hash = "sha256:8fecd4203a38af17928be7b90689d8083603073622229ca7077b72d8e5a976e4"},
{file = "cachetools-5.0.0.tar.gz", hash = "sha256:486471dfa8799eb7ec503a8059e263db000cdda20075ce5e48903087f79d5fd6"},
]
cattrs = [
{file = "cattrs-1.10.0-py3-none-any.whl", hash = "sha256:35dd9063244263e63bd0bd24ea61e3015b00272cead084b2c40d788b0f857c46"},
@ -2506,78 +2499,65 @@ flower = [
{file = "flower-1.0.0.tar.gz", hash = "sha256:2e17c4fb55c569508f3bfee7fe41f44b8362d30dbdf77b604a9d9f4740fe8cbd"},
]
frozenlist = [
{file = "frozenlist-1.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:977a1438d0e0d96573fd679d291a1542097ea9f4918a8b6494b06610dfeefbf9"},
{file = "frozenlist-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8d86547a5e98d9edd47c432f7a14b0c5592624b496ae9880fb6332f34af1edc"},
{file = "frozenlist-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:181754275d5d32487431a0a29add4f897968b7157204bc1eaaf0a0ce80c5ba7d"},
{file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5df31bb2b974f379d230a25943d9bf0d3bc666b4b0807394b131a28fca2b0e5f"},
{file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4766632cd8a68e4f10f156a12c9acd7b1609941525569dd3636d859d79279ed3"},
{file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16eef427c51cb1203a7c0ab59d1b8abccaba9a4f58c4bfca6ed278fc896dc193"},
{file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:01d79515ed5aa3d699b05f6bdcf1fe9087d61d6b53882aa599a10853f0479c6c"},
{file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28e164722ea0df0cf6d48c4d5bdf3d19e87aaa6dfb39b0ba91153f224b912020"},
{file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e63ad0beef6ece06475d29f47d1f2f29727805376e09850ebf64f90777962792"},
{file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41de4db9b9501679cf7cddc16d07ac0f10ef7eb58c525a1c8cbff43022bddca4"},
{file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a9d84ee6427b65a81fc24e6ef589cb794009f5ca4150151251c062773e7ed2"},
{file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:f5f3b2942c3b8b9bfe76b408bbaba3d3bb305ee3693e8b1d631fe0a0d4f93673"},
{file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c98d3c04701773ad60d9545cd96df94d955329efc7743fdb96422c4b669c633b"},
{file = "frozenlist-1.2.0-cp310-cp310-win32.whl", hash = "sha256:72cfbeab7a920ea9e74b19aa0afe3b4ad9c89471e3badc985d08756efa9b813b"},
{file = "frozenlist-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:11ff401951b5ac8c0701a804f503d72c048173208490c54ebb8d7bb7c07a6d00"},
{file = "frozenlist-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b46f997d5ed6d222a863b02cdc9c299101ee27974d9bbb2fd1b3c8441311c408"},
{file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351686ca020d1bcd238596b1fa5c8efcbc21bffda9d0efe237aaa60348421e2a"},
{file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfbaa08cf1452acad9cb1c1d7b89394a41e712f88df522cea1a0f296b57782a0"},
{file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2ae2f5e9fa10805fb1c9adbfefaaecedd9e31849434be462c3960a0139ed729"},
{file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6790b8d96bbb74b7a6f4594b6f131bd23056c25f2aa5d816bd177d95245a30e3"},
{file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:41f62468af1bd4e4b42b5508a3fe8cc46a693f0cdd0ca2f443f51f207893d837"},
{file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:ec6cf345771cdb00791d271af9a0a6fbfc2b6dd44cb753f1eeaa256e21622adb"},
{file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:14a5cef795ae3e28fb504b73e797c1800e9249f950e1c964bb6bdc8d77871161"},
{file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8b54cdd2fda15467b9b0bfa78cee2ddf6dbb4585ef23a16e14926f4b076dfae4"},
{file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f025f1d6825725b09c0038775acab9ae94264453a696cc797ce20c0769a7b367"},
{file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:84e97f59211b5b9083a2e7a45abf91cfb441369e8bb6d1f5287382c1c526def3"},
{file = "frozenlist-1.2.0-cp36-cp36m-win32.whl", hash = "sha256:c5328ed53fdb0a73c8a50105306a3bc013e5ca36cca714ec4f7bd31d38d8a97f"},
{file = "frozenlist-1.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9ade70aea559ca98f4b1b1e5650c45678052e76a8ab2f76d90f2ac64180215a2"},
{file = "frozenlist-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0d3ffa8772464441b52489b985d46001e2853a3b082c655ec5fad9fb6a3d618"},
{file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3457f8cf86deb6ce1ba67e120f1b0128fcba1332a180722756597253c465fc1d"},
{file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a72eecf37eface331636951249d878750db84034927c997d47f7f78a573b72b"},
{file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:acc4614e8d1feb9f46dd829a8e771b8f5c4b1051365d02efb27a3229048ade8a"},
{file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:87521e32e18a2223311afc2492ef2d99946337da0779ddcda77b82ee7319df59"},
{file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b4c7665a17c3a5430edb663e4ad4e1ad457614d1b2f2b7f87052e2ef4fa45ca"},
{file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed58803563a8c87cf4c0771366cf0ad1aa265b6b0ae54cbbb53013480c7ad74d"},
{file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa44c4740b4e23fcfa259e9dd52315d2b1770064cde9507457e4c4a65a04c397"},
{file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:2de5b931701257d50771a032bba4e448ff958076380b049fd36ed8738fdb375b"},
{file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6e105013fa84623c057a4381dc8ea0361f4d682c11f3816cc80f49a1f3bc17c6"},
{file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:705c184b77565955a99dc360f359e8249580c6b7eaa4dc0227caa861ef46b27a"},
{file = "frozenlist-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:a37594ad6356e50073fe4f60aa4187b97d15329f2138124d252a5a19c8553ea4"},
{file = "frozenlist-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:25b358aaa7dba5891b05968dd539f5856d69f522b6de0bf34e61f133e077c1a4"},
{file = "frozenlist-1.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af2a51c8a381d76eabb76f228f565ed4c3701441ecec101dd18be70ebd483cfd"},
{file = "frozenlist-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:82d22f6e6f2916e837c91c860140ef9947e31194c82aaeda843d6551cec92f19"},
{file = "frozenlist-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cfe6fef507f8bac40f009c85c7eddfed88c1c0d38c75e72fe10476cef94e10f"},
{file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f602e380a5132880fa245c92030abb0fc6ff34e0c5500600366cedc6adb06a"},
{file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ad065b2ebd09f32511ff2be35c5dfafee6192978b5a1e9d279a5c6e121e3b03"},
{file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc93f5f62df3bdc1f677066327fc81f92b83644852a31c6aa9b32c2dde86ea7d"},
{file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:89fdfc84c6bf0bff2ff3170bb34ecba8a6911b260d318d377171429c4be18c73"},
{file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:47b2848e464883d0bbdcd9493c67443e5e695a84694efff0476f9059b4cb6257"},
{file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4f52d0732e56906f8ddea4bd856192984650282424049c956857fed43697ea43"},
{file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:16ef7dd5b7d17495404a2e7a49bac1bc13d6d20c16d11f4133c757dd94c4144c"},
{file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1cf63243bc5f5c19762943b0aa9e0d3fb3723d0c514d820a18a9b9a5ef864315"},
{file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:54a1e09ab7a69f843cd28fefd2bcaf23edb9e3a8d7680032c8968b8ac934587d"},
{file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:954b154a4533ef28bd3e83ffdf4eadf39deeda9e38fb8feaf066d6069885e034"},
{file = "frozenlist-1.2.0-cp38-cp38-win32.whl", hash = "sha256:cb3957c39668d10e2b486acc85f94153520a23263b6401e8f59422ef65b9520d"},
{file = "frozenlist-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0a7c7cce70e41bc13d7d50f0e5dd175f14a4f1837a8549b0936ed0cbe6170bf9"},
{file = "frozenlist-1.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4c457220468d734e3077580a3642b7f682f5fd9507f17ddf1029452450912cdc"},
{file = "frozenlist-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e74f8b4d8677ebb4015ac01fcaf05f34e8a1f22775db1f304f497f2f88fdc697"},
{file = "frozenlist-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fbd4844ff111449f3bbe20ba24fbb906b5b1c2384d0f3287c9f7da2354ce6d23"},
{file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0081a623c886197ff8de9e635528fd7e6a387dccef432149e25c13946cb0cd0"},
{file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b6e21e5770df2dea06cb7b6323fbc008b13c4a4e3b52cb54685276479ee7676"},
{file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:406aeb340613b4b559db78d86864485f68919b7141dec82aba24d1477fd2976f"},
{file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:878ebe074839d649a1cdb03a61077d05760624f36d196884a5cafb12290e187b"},
{file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1fef737fd1388f9b93bba8808c5f63058113c10f4e3c0763ced68431773f72f9"},
{file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a495c3d513573b0b3f935bfa887a85d9ae09f0627cf47cad17d0cc9b9ba5c38"},
{file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e7d0dd3e727c70c2680f5f09a0775525229809f1a35d8552b92ff10b2b14f2c2"},
{file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:66a518731a21a55b7d3e087b430f1956a36793acc15912e2878431c7aec54210"},
{file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94728f97ddf603d23c8c3dd5cae2644fa12d33116e69f49b1644a71bb77b89ae"},
{file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c1e8e9033d34c2c9e186e58279879d78c94dd365068a3607af33f2bc99357a53"},
{file = "frozenlist-1.2.0-cp39-cp39-win32.whl", hash = "sha256:83334e84a290a158c0c4cc4d22e8c7cfe0bba5b76d37f1c2509dabd22acafe15"},
{file = "frozenlist-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:735f386ec522e384f511614c01d2ef9cf799f051353876b4c6fb93ef67a6d1ee"},
{file = "frozenlist-1.2.0.tar.gz", hash = "sha256:68201be60ac56aff972dc18085800b6ee07973c49103a8aba669dee3d71079de"},
{file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3"},
{file = "frozenlist-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b"},
{file = "frozenlist-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868"},
{file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f"},
{file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b"},
{file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58"},
{file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02"},
{file = "frozenlist-1.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8"},
{file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e"},
{file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78"},
{file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa"},
{file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676"},
{file = "frozenlist-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d"},
{file = "frozenlist-1.3.0-cp310-cp310-win32.whl", hash = "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d"},
{file = "frozenlist-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c"},
{file = "frozenlist-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24"},
{file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa"},
{file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2"},
{file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f"},
{file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1"},
{file = "frozenlist-1.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93"},
{file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478"},
{file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141"},
{file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae"},
{file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01"},
{file = "frozenlist-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846"},
{file = "frozenlist-1.3.0-cp37-cp37m-win32.whl", hash = "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468"},
{file = "frozenlist-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1"},
{file = "frozenlist-1.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a"},
{file = "frozenlist-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d"},
{file = "frozenlist-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953"},
{file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f"},
{file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08"},
{file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274"},
{file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e"},
{file = "frozenlist-1.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8"},
{file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5"},
{file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1"},
{file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148"},
{file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0"},
{file = "frozenlist-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3"},
{file = "frozenlist-1.3.0-cp38-cp38-win32.whl", hash = "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07"},
{file = "frozenlist-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9"},
{file = "frozenlist-1.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486"},
{file = "frozenlist-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c"},
{file = "frozenlist-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f"},
{file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa"},
{file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d"},
{file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a"},
{file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b"},
{file = "frozenlist-1.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51"},
{file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a"},
{file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2"},
{file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed"},
{file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951"},
{file = "frozenlist-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b"},
{file = "frozenlist-1.3.0-cp39-cp39-win32.whl", hash = "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08"},
{file = "frozenlist-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab"},
{file = "frozenlist-1.3.0.tar.gz", hash = "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b"},
]
geoip2 = [
{file = "geoip2-4.5.0-py2.py3-none-any.whl", hash = "sha256:2aed03b45f8037b9e16f02567bcf3623801d6d20689c5fc5676d7c08ed067334"},
@ -2588,20 +2568,20 @@ gitdb = [
{file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
]
gitpython = [
{file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"},
{file = "GitPython-3.1.24.tar.gz", hash = "sha256:df83fdf5e684fef7c6ee2c02fc68a5ceb7e7e759d08b694088d0cacb4eba59e5"},
{file = "GitPython-3.1.26-py3-none-any.whl", hash = "sha256:26ac35c212d1f7b16036361ca5cff3ec66e11753a0d677fb6c48fa4e1a9dd8d6"},
{file = "GitPython-3.1.26.tar.gz", hash = "sha256:fc8868f63a2e6d268fb25f481995ba185a85a66fcad126f039323ff6635669ee"},
]
google-auth = [
{file = "google-auth-2.3.3.tar.gz", hash = "sha256:d83570a664c10b97a1dc6f8df87e5fdfff012f48f62be131e449c20dfc32630e"},
{file = "google_auth-2.3.3-py2.py3-none-any.whl", hash = "sha256:a348a50b027679cb7dae98043ac8dbcc1d7951f06d8387496071a1e05a2465c0"},
{file = "google-auth-2.4.0.tar.gz", hash = "sha256:ef6f4827f6a3f9c5ff884616e2ba779acb5d690486fb70ca5e3091ed85ad932a"},
{file = "google_auth-2.4.0-py2.py3-none-any.whl", hash = "sha256:d1fad279d9d97e7d6b4a09a53e851ab2ee6d36d5c19547354a3f47a8a6ae41b9"},
]
gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
{file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
]
h11 = [
{file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"},
{file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"},
{file = "h11-0.13.0-py3-none-any.whl", hash = "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442"},
{file = "h11-0.13.0.tar.gz", hash = "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06"},
]
hiredis = [
{file = "hiredis-2.0.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b4c8b0bc5841e578d5fb32a16e0c305359b987b850a06964bd5a62739d688048"},
@ -2685,8 +2665,8 @@ idna = [
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
]
importlib-metadata = [
{file = "importlib_metadata-4.10.0-py3-none-any.whl", hash = "sha256:b7cf7d3fef75f1e4c80a96ca660efbd51473d7e8f39b5ab9210febc7809012a4"},
{file = "importlib_metadata-4.10.0.tar.gz", hash = "sha256:92a8b58ce734b2a4494878e0ecf7d79ccd7a128b5fc6014c401e0b61f006f0f6"},
{file = "importlib_metadata-4.10.1-py3-none-any.whl", hash = "sha256:899e2a40a8c4a1aec681feef45733de8a6c58f3f6a0dbed2eb6574b4387a77b6"},
{file = "importlib_metadata-4.10.1.tar.gz", hash = "sha256:951f0d8a5b7260e9db5e41d429285b5f451e928479f19d80818878527d36e95e"},
]
incremental = [
{file = "incremental-21.3.0-py2.py3-none-any.whl", hash = "sha256:92014aebc6a20b78a8084cdd5645eeaa7f74b8933f70fa3ada2cfbd1e3b54321"},
@ -2709,8 +2689,8 @@ jmespath = [
{file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"},
]
jsonschema = [
{file = "jsonschema-4.3.3-py3-none-any.whl", hash = "sha256:eb7a69801beb7325653aa8fd373abbf9ff8f85b536ab2812e5e8287b522fb6a2"},
{file = "jsonschema-4.3.3.tar.gz", hash = "sha256:f210d4ce095ed1e8af635d15c8ee79b586f656ab54399ba87b8ab87e5bff0ade"},
{file = "jsonschema-4.4.0-py3-none-any.whl", hash = "sha256:77281a1f71684953ee8b3d488371b162419767973789272434bbc3f29d9c8823"},
{file = "jsonschema-4.4.0.tar.gz", hash = "sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83"},
]
kombu = [
{file = "kombu-5.2.3-py3-none-any.whl", hash = "sha256:eeaeb8024f3a5cfc71c9250e45cddb8493f269d74ada2f74909a93c59c4b4179"},
@ -2872,78 +2852,65 @@ msgpack = [
{file = "msgpack-1.0.3.tar.gz", hash = "sha256:51fdc7fb93615286428ee7758cecc2f374d5ff363bdd884c7ea622a7a327a81e"},
]
multidict = [
{file = "multidict-5.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55"},
{file = "multidict-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e"},
{file = "multidict-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7"},
{file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf"},
{file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b"},
{file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5"},
{file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f"},
{file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747"},
{file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52"},
{file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628"},
{file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda"},
{file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a"},
{file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86"},
{file = "multidict-5.2.0-cp310-cp310-win32.whl", hash = "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7"},
{file = "multidict-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f"},
{file = "multidict-5.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d"},
{file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37"},
{file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b"},
{file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1"},
{file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4"},
{file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02"},
{file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5"},
{file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858"},
{file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677"},
{file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded"},
{file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d"},
{file = "multidict-5.2.0-cp36-cp36m-win32.whl", hash = "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9"},
{file = "multidict-5.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0"},
{file = "multidict-5.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0"},
{file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11"},
{file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422"},
{file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3"},
{file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d"},
{file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac"},
{file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0"},
{file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704"},
{file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23"},
{file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d"},
{file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b"},
{file = "multidict-5.2.0-cp37-cp37m-win32.whl", hash = "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef"},
{file = "multidict-5.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a"},
{file = "multidict-5.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8"},
{file = "multidict-5.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6"},
{file = "multidict-5.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065"},
{file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e"},
{file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c"},
{file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64"},
{file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031"},
{file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d"},
{file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01"},
{file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4"},
{file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b"},
{file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac"},
{file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22"},
{file = "multidict-5.2.0-cp38-cp38-win32.whl", hash = "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940"},
{file = "multidict-5.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0"},
{file = "multidict-5.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24"},
{file = "multidict-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21"},
{file = "multidict-5.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae"},
{file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6"},
{file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c"},
{file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0"},
{file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17"},
{file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0"},
{file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1"},
{file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621"},
{file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341"},
{file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b"},
{file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5"},
{file = "multidict-5.2.0-cp39-cp39-win32.whl", hash = "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8"},
{file = "multidict-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac"},
{file = "multidict-5.2.0.tar.gz", hash = "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce"},
{file = "multidict-6.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05c3cca447fd39b566615d7cf918f0e83cd92f0549f8182a6cab6e4729c02566"},
{file = "multidict-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b487ad10f594e78e0e61662ff7643e1adc610919ea8a95dd976126bffc0256f"},
{file = "multidict-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d65b5bd50a5e1f4c6427ebcabb5acc62540301de733f81fd549cf7633826fccd"},
{file = "multidict-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a542ceca143e19c08715defe133475961d43d7bfb48dbdc3ac506548ec168f18"},
{file = "multidict-6.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:af441cfeb3003d96de8acdeb402187bc6a34f96e125618b8275bacfd29a6fad7"},
{file = "multidict-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f97f03d7dbc33e20a73428be93974e82762b393579d59053da1257c35bad13b"},
{file = "multidict-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c74c7a058a16b7dd24d030f0e8fe846f7d63f41cfeea89a804969cb129182a8"},
{file = "multidict-6.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a5210e5eca8f0fc0213da31cbc29587d15195b21f40ffd53ff513126c39be0e2"},
{file = "multidict-6.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:af1fdc8d25eb9e9998854e996bc982ae3be733590a9e8d6b179b28fd212ddf71"},
{file = "multidict-6.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ccf0aaaef2f8a4cf1973ebe17162b0c3016859eb706d55b328993b8fd8c3515c"},
{file = "multidict-6.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:1354127c9687d0abbaadfb26e35db247ef1c35f0271e8052afa98b34a9140445"},
{file = "multidict-6.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:2e82ac157bc0719b9802578964d4387e0d7dd530d1fd8949f3cef1c97f2e9d8a"},
{file = "multidict-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2f90eb274732fe0958f2d9d4cc7a608bf218e63dd554a690ccafa30f9d9d1b2d"},
{file = "multidict-6.0.1-cp310-cp310-win32.whl", hash = "sha256:593586d7ac76ab7a9f229c49d81136b8c1a78119d948ba2a672f4fa681ad54ce"},
{file = "multidict-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:f24b3d4405271d6d1b920261437f3acb7dd1c329b0ac782b8b4e0ee7ad187e5b"},
{file = "multidict-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9050a2487f9dee9b0abde090b2620a3ba57190d7fe1dc2932b32b9866f90df9e"},
{file = "multidict-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff8004ecfb2cc00cd4f063c5e8b3cfd7e544bf774f17c2a861067444532e4fbc"},
{file = "multidict-6.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b944477c1e7be8bea2ef819157fb01b79493af1a6dba83d315be63db2957af6"},
{file = "multidict-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70a5fff576fe9039550f8d6aacaa98ce26c41df97edc577688c563eb25bcbe83"},
{file = "multidict-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e545e5922a4ae99e680a96ed88d03007bd4208fc2599ff273eb2086051d3ef74"},
{file = "multidict-6.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502c1610c7737697108ba4717274cca01130ce3e23227034b1601fb9fa0a8aa"},
{file = "multidict-6.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:caa9f2874519e0fbb19b90380532e59ef9e07d8ed22d8f0e2e69af796bae2c78"},
{file = "multidict-6.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7c9213754993e0dcf70a4fffebef502daf9323fa8d56f0485f724bd4c2991667"},
{file = "multidict-6.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:0a9857789fd76e0394a5373598820bb2ea3dd113e2c0fb9a92248e3dadd81c5c"},
{file = "multidict-6.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:92ba0e4745937efef33399348f62a2dc98505dde4d0764061a34123a55fe02e9"},
{file = "multidict-6.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3424df56debab711f29c965cadb835dc3c702930265eae26f15ac784feb1dddd"},
{file = "multidict-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:d13af99bf380567ede69927d3188cfaccfde76e78e336151e42e60fe03ca5c00"},
{file = "multidict-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:37228376057f37fb013130e83e7ad0921598760fb75bd8f0da17403390241d20"},
{file = "multidict-6.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:1b469534be490ded141d74d7a158db284055b0d04991c2634a9d26d906e063dd"},
{file = "multidict-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6ee83096d27dfe52075385f5067d2a54fb227b41666b207e6a64f98ce9048266"},
{file = "multidict-6.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19c9c56ddca200f7ffbf376cf2d1a370e8f2e306ec16510a4d90b78a1a0be62"},
{file = "multidict-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a6da1575300e24011352c7c620d19b072a2c9498429d1f587e5090621e6f568"},
{file = "multidict-6.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48e0919ed5cc5e58c68f40b6516e3f1b0837580a7a8d51d9f99bf0f415d0b73a"},
{file = "multidict-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7c10ab3a1ad3188d9a4be01a10c0ddb67d6feaaea538781e73d6ba69fcafbbd"},
{file = "multidict-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17289c1ad70e1104ea25f560f6e2941718112d59616482589646aa01fcf4d0d1"},
{file = "multidict-6.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a701e9ad52e47b740b5b9aba627ac8fc4ee9e68682f0228fb4a7c4562631ffac"},
{file = "multidict-6.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:798dd2d825ce6c0699ce261fda90020562236480192604cfc5be4a315f806810"},
{file = "multidict-6.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:564ff7d88b4965cb5211ebf785bca409abbaac8dcca62b0fabe39d56a5ee7283"},
{file = "multidict-6.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:39d5424379505110d6ca64e927f8b2772c57b05a3d240e66805244ecc4402311"},
{file = "multidict-6.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:efeba14caaacb4a202d977aca63866069e8a57e632282caf971ce8ff472a49cd"},
{file = "multidict-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:241071469989c87da1835f3ccc4143a207b99a2ca27c19b7130a5edecc41a39e"},
{file = "multidict-6.0.1-cp38-cp38-win32.whl", hash = "sha256:7184dae6d519a8e629ef10e0e215dde022ee38d55254bea381ca0e61b8b197ea"},
{file = "multidict-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:666f78daccf8133ebfacb77e81f4077570b03641b49555ebb5e75797b72770e1"},
{file = "multidict-6.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a4fcf74d50a65fe99a68531d09f10ceef911992e0e64c1b2cf212effa075f8b"},
{file = "multidict-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a98ee92e96157a3c787c5aa156968ceffb6fb4548c5f74ff879884fed2f9752"},
{file = "multidict-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b6bfb0a4df79bd78907fff46c34ed47284d5eb459b096d2de896b0b1c31f3fa7"},
{file = "multidict-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbda7f3be5a75ee87a2649382e47f419374420ef244b372312e662637931399f"},
{file = "multidict-6.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f74a680ba9d6c543c1cdd8bcef464d58b933bed29edb89a0b3c0b33cc553181a"},
{file = "multidict-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:389a689aa3b657b87cb21f78468caa4dfccd758639ff4b37b6e2dceef7c5b12f"},
{file = "multidict-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36195396f2a76dd23a67ca2bdeb8589b6eaaef7e84c97cf90da3ede69f189baa"},
{file = "multidict-6.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02847aa3602e21c04ac6fdef6f7c6dc916de8cce49a9eb59aeffedd3365f196c"},
{file = "multidict-6.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bd21540c9cc9b90373b5a6aaed8f8d53815529e89210453e0566d00389034b82"},
{file = "multidict-6.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e037782357ddf6741023df1a84f17a3a1bb62abba52e41efa4014199f6338143"},
{file = "multidict-6.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ea08fb7383422148bcfc066c3d2dae03fcdb8bd06e7ce713badd86bc26c25179"},
{file = "multidict-6.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b85354b2d2fe38a3ab90348f8c9778a437d376252f62115cabea1106332bd1b6"},
{file = "multidict-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9c863a506466d64871c70e4204cecdcaf2c0c92d157683bb5d5b3e7b5aaea05a"},
{file = "multidict-6.0.1-cp39-cp39-win32.whl", hash = "sha256:d2cc15d2507b0d5f09726fd97bb9ffaa6bb47487fe77a208262cb6187fd9dcf3"},
{file = "multidict-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:38ada537db7f9089560cf16dc5b8b280096213bc5260970929aca43675682739"},
{file = "multidict-6.0.1.tar.gz", hash = "sha256:d40616f3f9326a18e1f2fa7c7e8e0e04a7e5228bfa2bd62c1e0d68fbc259b09b"},
]
mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
@ -2962,8 +2929,8 @@ packaging = [
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
]
paramiko = [
{file = "paramiko-2.9.1-py2.py3-none-any.whl", hash = "sha256:db5d3f19607941b1c90233588d60213c874392c4961c6297037da989c24f8070"},
{file = "paramiko-2.9.1.tar.gz", hash = "sha256:a1fdded3b55f61d23389e4fe52d9ae428960ac958d2edf50373faa5d8926edd0"},
{file = "paramiko-2.9.2-py2.py3-none-any.whl", hash = "sha256:04097dbd96871691cdb34c13db1883066b8a13a0df2afd4cb0a92221f51c2603"},
{file = "paramiko-2.9.2.tar.gz", hash = "sha256:944a9e5dbdd413ab6c7951ea46b0ab40713235a9c4c5ca81cfe45c6f14fa677b"},
]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
@ -3086,36 +3053,36 @@ pycparser = [
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
pycryptodome = [
{file = "pycryptodome-3.12.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:90ad3381ccdc6a24cc2841e295706a168f32abefe64c679695712acac71fd5da"},
{file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e80f7469b0b3ea0f694230477d8501dc5a30a717e94fddd4821e6721f3053eae"},
{file = "pycryptodome-3.12.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b91404611767a7485837a6f1fd20cf9a5ae0ad362040a022cd65827ecb1b0d00"},
{file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:db66ccda65d5d20c17b00768e462a86f6f540f9aea8419a7f76cc7d9effd82cd"},
{file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:dc88355c4b261ed259268e65705b28b44d99570337694d593f06e3b1698eaaf3"},
{file = "pycryptodome-3.12.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:6f8f5b7b53516da7511951910ab458e799173722c91fea54e2ba2f56d102e4aa"},
{file = "pycryptodome-3.12.0-cp27-cp27m-win32.whl", hash = "sha256:93acad54a72d81253242eb0a15064be559ec9d989e5173286dc21cad19f01765"},
{file = "pycryptodome-3.12.0-cp27-cp27m-win_amd64.whl", hash = "sha256:5a8c24d39d4a237dbfe181ea6593792bf9b5582c7fcfa7b8e0e12fda5eec07af"},
{file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:32d15da81959faea6cbed95df2bb44f7f796211c110cf90b5ad3b2aeeb97fc8e"},
{file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:aed7eb4b64c600fbc5e6d4238991ad1b4179a558401f203d1fcbd24883748982"},
{file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:341c6bbf932c406b4f3ee2372e8589b67ac0cf4e99e7dc081440f43a3cde9f0f"},
{file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:de0b711d673904dd6c65307ead36cb76622365a393569bf880895cba21195b7a"},
{file = "pycryptodome-3.12.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:3558616f45d8584aee3eba27559bc6fd0ba9be6c076610ed3cc62bd5229ffdc3"},
{file = "pycryptodome-3.12.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:a78e4324e566b5fbc2b51e9240950d82fa9e1c7eb77acdf27f58712f65622c1d"},
{file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:3f2f3dd596c6128d91314e60a6bcf4344610ef0e97f4ae4dd1770f86dd0748d8"},
{file = "pycryptodome-3.12.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:e05f994f30f1cda3cbe57441f41220d16731cf99d868bb02a8f6484c454c206b"},
{file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:4cded12e13785bbdf4ba1ff5fb9d261cd98162145f869e4fbc4a4b9083392f0b"},
{file = "pycryptodome-3.12.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:1181c90d1a6aee68a84826825548d0db1b58d8541101f908d779d601d1690586"},
{file = "pycryptodome-3.12.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:6bb0d340c93bcb674ea8899e2f6408ec64c6c21731a59481332b4b2a8143cc60"},
{file = "pycryptodome-3.12.0-cp35-abi3-win32.whl", hash = "sha256:39da5807aa1ff820799c928f745f89432908bf6624b9e981d2d7f9e55d91b860"},
{file = "pycryptodome-3.12.0-cp35-abi3-win_amd64.whl", hash = "sha256:212c7f7fe11cad9275fbcff50ca977f1c6643f13560d081e7b0f70596df447b8"},
{file = "pycryptodome-3.12.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:b07a4238465eb8c65dd5df2ab8ba6df127e412293c0ed7656c003336f557a100"},
{file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:a6e1bcd9d5855f1a3c0f8d585f44c81b08f39a02754007f374fb8db9605ba29c"},
{file = "pycryptodome-3.12.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:aceb1d217c3a025fb963849071446cf3aca1353282fe1c3cb7bd7339a4d47947"},
{file = "pycryptodome-3.12.0-pp27-pypy_73-win32.whl", hash = "sha256:f699360ae285fcae9c8f53ca6acf33796025a82bb0ccd7c1c551b04c1726def3"},
{file = "pycryptodome-3.12.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d845c587ceb82ac7cbac7d0bf8c62a1a0fe7190b028b322da5ca65f6e5a18b9e"},
{file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:d8083de50f6dec56c3c6f270fb193590999583a1b27c9c75bc0b5cac22d438cc"},
{file = "pycryptodome-3.12.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:9ea2f6674c803602a7c0437fccdc2ea036707e60456974fe26ca263bd501ec45"},
{file = "pycryptodome-3.12.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:5d4264039a2087977f50072aaff2346d1c1c101cb359f9444cf92e3d1f42b4cd"},
{file = "pycryptodome-3.12.0.zip", hash = "sha256:12c7343aec5a3b3df5c47265281b12b611f26ec9367b6129199d67da54b768c1"},
{file = "pycryptodome-3.13.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:e468724173df02f9d83f3fea830bf0d04aa291b5add22b4a78e01c97aab04873"},
{file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1fb7a6f222072412f320b9e48d3ce981920efbfce37b06d028ec9bd94093b37f"},
{file = "pycryptodome-3.13.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4f1b594d0cf35bd12ec4244df1155a7f565bf6e6245976ac36174c1564688c90"},
{file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9ea70f6c3f6566159e3798e4593a4a8016994a0080ac29a45200615b45091a1b"},
{file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f7aad304575d075faf2806977b726b67da7ba294adc97d878f92a062e357a56a"},
{file = "pycryptodome-3.13.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:702446a012fd9337b9327d168bb0c7dc714eb93ad361f6f61af9ca8305a301f1"},
{file = "pycryptodome-3.13.0-cp27-cp27m-win32.whl", hash = "sha256:681ac47c538c64305d710eaed2bb49532f62b3f4c93aa7c423c520df981392e5"},
{file = "pycryptodome-3.13.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7b3478a187d897f003b2aa1793bcc59463e8d57a42e2aafbcbbe9cd47ec46863"},
{file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:eec02d9199af4b1ccfe1f9c587691a07a1fa39d949d2c1dc69d079ab9af8212f"},
{file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9c8e0e6c5e982699801b20fa74f43c19aa080d2b53a39f3c132d35958e153bd4"},
{file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:f5457e44d3f26d9946091e92b28f3e970a56538b96c87b4b155a84e32a40b7b5"},
{file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:88d6d54e83cf9bbd665ce1e7b9079983ee2d97a05f42e0569ff00a70f1dd8b1e"},
{file = "pycryptodome-3.13.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:72de8c4d71e6b11d54528bb924447fa4fdabcbb3d76cc0e7f61d3b6075def6b3"},
{file = "pycryptodome-3.13.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:008ef2c631f112cd5a58736e0b29f4a28b4bb853e68878689f8b476fd56e0691"},
{file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:51ebe9624ad0a0b4da1aaaa2d43aabadf8537737fd494cee0ffa37cd6326de02"},
{file = "pycryptodome-3.13.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:deede160bdf87ddb71f0a1314ad5a267b1a960be314ea7dc6b7ad86da6da89a3"},
{file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:857c16bffd938254e3a834cd6b2a755ed24e1a953b1a86e33da136d3e4c16a6f"},
{file = "pycryptodome-3.13.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:ca6db61335d07220de0b665bfee7b8e9615b2dfc67a54016db4826dac34c2dd2"},
{file = "pycryptodome-3.13.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:073dedf0f9c490ae22ca081b86357646ac9b76f3e2bd89119d137fc697a9e3b6"},
{file = "pycryptodome-3.13.0-cp35-abi3-win32.whl", hash = "sha256:e3affa03c49cce7b0a9501cc7f608d4f8e61fb2522b276d599ac049b5955576d"},
{file = "pycryptodome-3.13.0-cp35-abi3-win_amd64.whl", hash = "sha256:e5d72be02b17e6bd7919555811264403468d1d052fa67c946e402257c3c29a27"},
{file = "pycryptodome-3.13.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0896d5d15ffe584d46cb9b69a75cf14a2bc8f6daf635b7bf16c1b041342a44b1"},
{file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux1_x86_64.whl", hash = "sha256:e420cdfca73f80fe15f79bb34756959945231a052440813e5fce531e6e96331a"},
{file = "pycryptodome-3.13.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:720fafdf3e5c5de93039d8308f765cc60b8e9e7e852ad7135aa65dd89238191f"},
{file = "pycryptodome-3.13.0-pp27-pypy_73-win32.whl", hash = "sha256:7a8b0e526ff239b4f4c61dd6898e2474d609843ffc437267f3a27ddff626e6f6"},
{file = "pycryptodome-3.13.0-pp36-pypy36_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d92a5eddffb0ad39f582f07c1de26e9daf6880e3e782a94bb7ebaf939567f8bf"},
{file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux1_x86_64.whl", hash = "sha256:cb9453c981554984c6f5c5ce7682d7286e65e2173d7416114c3593a977a01bf5"},
{file = "pycryptodome-3.13.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:765b8b16bc1fd699e183dde642c7f2653b8f3c9c1a50051139908e9683f97732"},
{file = "pycryptodome-3.13.0-pp36-pypy36_pp73-win32.whl", hash = "sha256:b3af53dddf848afb38b3ac2bae7159ddad1feb9bac14aa3acec6ef1797b82f8d"},
{file = "pycryptodome-3.13.0.tar.gz", hash = "sha256:95bacf9ff7d1b90bba537d3f5f6c834efe6bfbb1a0195cb3573f29e6716ef08d"},
]
pyjwt = [
{file = "PyJWT-2.3.0-py3-none-any.whl", hash = "sha256:e0c4bb8d9f0af0c7f5b1ec4c5036309617d03d56932877f2f7a0beeb5318322f"},
@ -3134,55 +3101,47 @@ pylint-plugin-utils = [
{file = "pylint_plugin_utils-0.7-py3-none-any.whl", hash = "sha256:b3d43e85ab74c4f48bb46ae4ce771e39c3a20f8b3d56982ab17aa73b4f98d535"},
]
pynacl = [
{file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
{file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"},
{file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"},
{file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"},
{file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"},
{file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"},
{file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"},
{file = "PyNaCl-1.4.0-cp35-abi3-win32.whl", hash = "sha256:4e10569f8cbed81cb7526ae137049759d2a8d57726d52c1a000a3ce366779634"},
{file = "PyNaCl-1.4.0-cp35-abi3-win_amd64.whl", hash = "sha256:c914f78da4953b33d4685e3cdc7ce63401247a21425c16a39760e282075ac4a6"},
{file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"},
{file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"},
{file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"},
{file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"},
{file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"},
{file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"},
{file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"},
{file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
{file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
{file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"},
{file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"},
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"},
{file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"},
{file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"},
{file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"},
{file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"},
]
pyopenssl = [
{file = "pyOpenSSL-21.0.0-py2.py3-none-any.whl", hash = "sha256:8935bd4920ab9abfebb07c41a4f58296407ed77f04bd1a92914044b848ba1ed6"},
{file = "pyOpenSSL-21.0.0.tar.gz", hash = "sha256:5e2d8c5e46d0d865ae933bef5230090bdaf5506281e9eec60fa250ee80600cb3"},
]
pyparsing = [
{file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
{file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
]
pyrsistent = [
{file = "pyrsistent-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f4c8cabb46ff8e5d61f56a037974228e978f26bfefce4f61a4b1ac0ba7a2ab72"},
{file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:da6e5e818d18459fa46fac0a4a4e543507fe1110e808101277c5a2b5bab0cd2d"},
{file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5e4395bbf841693eaebaa5bb5c8f5cdbb1d139e07c975c682ec4e4f8126e03d2"},
{file = "pyrsistent-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:527be2bfa8dc80f6f8ddd65242ba476a6c4fb4e3aedbf281dfbac1b1ed4165b1"},
{file = "pyrsistent-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2aaf19dc8ce517a8653746d98e962ef480ff34b6bc563fc067be6401ffb457c7"},
{file = "pyrsistent-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58a70d93fb79dc585b21f9d72487b929a6fe58da0754fa4cb9f279bb92369396"},
{file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4916c10896721e472ee12c95cdc2891ce5890898d2f9907b1b4ae0f53588b710"},
{file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:73ff61b1411e3fb0ba144b8f08d6749749775fe89688093e1efef9839d2dcc35"},
{file = "pyrsistent-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:b29b869cf58412ca5738d23691e96d8aff535e17390128a1a52717c9a109da4f"},
{file = "pyrsistent-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:097b96f129dd36a8c9e33594e7ebb151b1515eb52cceb08474c10a5479e799f2"},
{file = "pyrsistent-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:772e94c2c6864f2cd2ffbe58bb3bdefbe2a32afa0acb1a77e472aac831f83427"},
{file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c1a9ff320fa699337e05edcaae79ef8c2880b52720bc031b219e5b5008ebbdef"},
{file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd3caef37a415fd0dae6148a1b6957a8c5f275a62cca02e18474608cb263640c"},
{file = "pyrsistent-0.18.0-cp38-cp38-win32.whl", hash = "sha256:e79d94ca58fcafef6395f6352383fa1a76922268fa02caa2272fff501c2fdc78"},
{file = "pyrsistent-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:a0c772d791c38bbc77be659af29bb14c38ced151433592e326361610250c605b"},
{file = "pyrsistent-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d5ec194c9c573aafaceebf05fc400656722793dac57f254cd4741f3c27ae57b4"},
{file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b5eed00e597b5b5773b4ca30bd48a5774ef1e96f2a45d105db5b4ebb4bca680"},
{file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:48578680353f41dca1ca3dc48629fb77dfc745128b56fc01096b2530c13fd426"},
{file = "pyrsistent-0.18.0-cp39-cp39-win32.whl", hash = "sha256:f3ef98d7b76da5eb19c37fda834d50262ff9167c65658d1d8f974d2e4d90676b"},
{file = "pyrsistent-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:404e1f1d254d314d55adb8d87f4f465c8693d6f902f67eb6ef5b4526dc58e6ea"},
{file = "pyrsistent-0.18.0.tar.gz", hash = "sha256:773c781216f8c2900b42a7b638d5b517bb134ae1acbebe4d1e8f1f41ea60eb4b"},
{file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"},
{file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"},
{file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"},
{file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"},
{file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"},
{file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"},
{file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"},
{file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"},
{file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"},
{file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"},
{file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"},
{file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"},
{file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"},
{file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"},
{file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"},
{file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"},
{file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"},
{file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"},
{file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"},
{file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"},
{file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"},
]
pytest = [
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
@ -3193,8 +3152,8 @@ pytest-django = [
{file = "pytest_django-4.5.2-py3-none-any.whl", hash = "sha256:c60834861933773109334fe5a53e83d1ef4828f2203a1d6a0fa9972f4f75ab3e"},
]
pytest-randomly = [
{file = "pytest-randomly-3.10.3.tar.gz", hash = "sha256:22154cdcff7ba44e0599596490e6b75278ca973a33812ea6a54bf14d0b042ef1"},
{file = "pytest_randomly-3.10.3-py3-none-any.whl", hash = "sha256:b05a7a45f54cae2b5095752c6a10cb559df84448421b0420ae492dd2fb1727ef"},
{file = "pytest-randomly-3.11.0.tar.gz", hash = "sha256:9f013b8c1923130f3d0a286fde56e1fc52cfb3547b8eedf2765c460cee979c7f"},
{file = "pytest_randomly-3.11.0-py3-none-any.whl", hash = "sha256:a3c680d2b8150cf766311a80a1f92da64c3dd819045cda834fbf1b0ac4891610"},
]
python-dateutil = [
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
@ -3258,8 +3217,8 @@ pyyaml = [
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
redis = [
{file = "redis-4.1.0-py3-none-any.whl", hash = "sha256:e13fad67c098a33141bacde872786960e86a5c97a4255009bcd43c795fa1cc77"},
{file = "redis-4.1.0.tar.gz", hash = "sha256:21f0a23bce707909076e6ba2ce076cba59bff60d2ab22972e0647fdf620ffe47"},
{file = "redis-4.1.1-py3-none-any.whl", hash = "sha256:bc97d18938ca18d66737d0ef88584a2073069589e4026813cfba9ad6df9a9f40"},
{file = "redis-4.1.1.tar.gz", hash = "sha256:07420a3fbedd8e012c31d4fadac943fb81568946da202c5a5bc237774e5280a0"},
]
requests = [
{file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"},
@ -3285,7 +3244,10 @@ s3transfer = [
selenium = [
{file = "selenium-4.1.0-py3-none-any.whl", hash = "sha256:27e7b64df961d609f3d57237caa0df123abbbe22d038f2ec9e332fb90ec1a939"},
]
sentry-sdk = []
sentry-sdk = [
{file = "sentry-sdk-1.5.3.tar.gz", hash = "sha256:141da032f0fa4c56f9af6b361fda57360af1789576285bd1944561f9c274f9c0"},
{file = "sentry_sdk-1.5.3-py2.py3-none-any.whl", hash = "sha256:9aeff2a47f4038460296b920bf4d269284e8454e1c67547ee002ccafd9c2442b"},
]
service-identity = [
{file = "service-identity-21.1.0.tar.gz", hash = "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34"},
{file = "service_identity-21.1.0-py2.py3-none-any.whl", hash = "sha256:f0b0caac3d40627c3c04d7a51b6e06721857a0e10a8775f2d1d7e72901b3a7db"},
@ -3420,12 +3382,12 @@ uritemplate = [
{file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"},
]
urllib3 = [
{file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
{file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
{file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"},
{file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
]
uvicorn = [
{file = "uvicorn-0.16.0-py3-none-any.whl", hash = "sha256:d8c839231f270adaa6d338d525e2652a0b4a5f4c2430b5c4ef6ae4d11776b0d2"},
{file = "uvicorn-0.16.0.tar.gz", hash = "sha256:eacb66afa65e0648fcbce5e746b135d09722231ffffc61883d4fac2b62fbea8d"},
{file = "uvicorn-0.17.0-py3-none-any.whl", hash = "sha256:0b89c91bb8fe84c4bded9996af13c4b8c0de799d29bffeaa0c8ad298f2be0934"},
{file = "uvicorn-0.17.0.tar.gz", hash = "sha256:192c2422b056a3beb512c6c260bf77a7a884204a4ae41856719c1913ead63bbb"},
]
uvloop = [
{file = "uvloop-0.16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6224f1401025b748ffecb7a6e2652b17768f30b1a6a3f7b44660e5b5b690b12d"},
@ -3458,8 +3420,8 @@ wcwidth = [
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]
webauthn = [
{file = "webauthn-1.2.0-py3-none-any.whl", hash = "sha256:ecae0f99a6dc1a6d53e72f4be323cf58b418c02fe66dffae752eedc1d2ee6a70"},
{file = "webauthn-1.2.0.tar.gz", hash = "sha256:681b71d803c085d0911e29f2e2bbb0e49feda1ecdaa3982bae3d63b3377efdda"},
{file = "webauthn-1.2.1-py3-none-any.whl", hash = "sha256:024d0c54d1a11a1d95587745a0fea721cdb39ddc591ad0973bf93f55a123eb74"},
{file = "webauthn-1.2.1.tar.gz", hash = "sha256:3a9565e4587d6322a2c69c92faa89f40e211893f41b5993a410cdef7bc43d06b"},
]
websocket-client = [
{file = "websocket-client-1.2.3.tar.gz", hash = "sha256:1315816c0acc508997eb3ae03b9d3ff619c9d12d544c9a9b553704b1cc4f6af5"},

View File

@ -7,7 +7,7 @@ ENV NODE_ENV=production
RUN cd /static && npm i && npm run build-proxy
# Stage 2: Build
FROM docker.io/golang:1.17.5-bullseye AS builder
FROM docker.io/golang:1.17.6-bullseye AS builder
WORKDIR /go/src/goauthentik.io

View File

@ -92,7 +92,7 @@ addopts = "-p no:celery --junitxml=unittest.xml"
[tool.poetry]
name = "authentik"
version = "2021.12.5"
version = "2022.1.2"
description = ""
authors = ["Jens Langhammer <jens.langhammer@beryju.org>"]
@ -135,7 +135,7 @@ pyjwt = "*"
python = "^3.10"
pyyaml = "*"
requests-oauthlib = "*"
sentry-sdk = { git = 'https://github.com/beryju/sentry-python.git', rev = '379aee28b15d3b87b381317746c4efd24b3d7bc3' }
sentry-sdk = "*"
service_identity = "*"
structlog = "*"
swagger-spec-validator = "*"

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2021.12.5
version: 2022.1.2
description: Making authentication simple.
contact:
email: hello@beryju.org
@ -15270,6 +15270,14 @@ paths:
operationId: stages_authenticator_webauthn_list
description: AuthenticateWebAuthnStage Viewset
parameters:
- in: query
name: authenticator_attachment
schema:
type: string
nullable: true
enum:
- cross-platform
- platform
- in: query
name: configure_flow
schema:
@ -15297,6 +15305,14 @@ paths:
description: Number of results to return per page.
schema:
type: integer
- in: query
name: resident_key_requirement
schema:
type: string
enum:
- discouraged
- preferred
- required
- name: search
required: false
in: query
@ -19174,6 +19190,12 @@ components:
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
authenticator_attachment:
allOf:
- $ref: '#/components/schemas/AuthenticatorAttachmentEnum'
nullable: true
resident_key_requirement:
$ref: '#/components/schemas/ResidentKeyRequirementEnum'
required:
- component
- meta_model_name
@ -19200,6 +19222,12 @@ components:
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
authenticator_attachment:
allOf:
- $ref: '#/components/schemas/AuthenticatorAttachmentEnum'
nullable: true
resident_key_requirement:
$ref: '#/components/schemas/ResidentKeyRequirementEnum'
required:
- name
AuthenticatedSession:
@ -19288,6 +19316,11 @@ components:
- last_used
- user
- user_agent
AuthenticatorAttachmentEnum:
enum:
- platform
- cross-platform
type: string
AuthenticatorDuoChallenge:
type: object
description: Duo Challenge
@ -26519,6 +26552,12 @@ components:
If empty, user will not be able to configure this stage.
user_verification:
$ref: '#/components/schemas/UserVerificationEnum'
authenticator_attachment:
allOf:
- $ref: '#/components/schemas/AuthenticatorAttachmentEnum'
nullable: true
resident_key_requirement:
$ref: '#/components/schemas/ResidentKeyRequirementEnum'
PatchedAuthenticatorDuoStageRequest:
type: object
description: AuthenticatorDuoStage Serializer
@ -29376,6 +29415,12 @@ components:
type: integer
maximum: 2147483647
minimum: -2147483648
ResidentKeyRequirementEnum:
enum:
- discouraged
- preferred
- required
type: string
SAMLMetadata:
type: object
description: SAML Provider Metadata serializer
@ -31331,4 +31376,3 @@ components:
name: Authorization
servers:
- url: /api/v3/
- url: /api/v2beta/

View File

@ -24,7 +24,7 @@ export const DEFAULT_CONFIG = new Configuration({
// Required for POST/PUT/DELETE requests
// getCookie function must return the cookie's contents
headers: {
"X-CSRFToken": getCookie("authentik_csrf"),
"X-authentik-CSRF": getCookie("authentik_csrf"),
},
});
```

View File

@ -215,8 +215,6 @@ class TestProviderLDAP(SeleniumTestCase):
"uidNumber": [str(2000 + o_user.pk)],
"gidNumber": [str(2000 + o_user.pk)],
"memberOf": [],
"accountStatus": ["true"],
"superuser": ["false"],
"goauthentik.io/ldap/active": ["true"],
"goauthentik.io/ldap/superuser": ["false"],
"goauthentik.io/user/override-ips": ["true"],
@ -242,8 +240,6 @@ class TestProviderLDAP(SeleniumTestCase):
"uidNumber": [str(2000 + embedded_account.pk)],
"gidNumber": [str(2000 + embedded_account.pk)],
"memberOf": [],
"accountStatus": ["true"],
"superuser": ["false"],
"goauthentik.io/ldap/active": ["true"],
"goauthentik.io/ldap/superuser": ["false"],
"goauthentik.io/user/override-ips": ["true"],
@ -272,8 +268,6 @@ class TestProviderLDAP(SeleniumTestCase):
f"cn={group.name},ou=groups,dc=ldap,dc=goauthentik,dc=io"
for group in self.user.ak_groups.all()
],
"accountStatus": ["true"],
"superuser": ["true"],
"goauthentik.io/ldap/active": ["true"],
"goauthentik.io/ldap/superuser": ["true"],
"extraAttribute": ["bar"],

1363
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -46,18 +46,19 @@
]
},
"dependencies": {
"@babel/core": "^7.16.7",
"@babel/core": "^7.16.12",
"@babel/plugin-proposal-decorators": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.16.7",
"@babel/preset-env": "^7.16.7",
"@babel/plugin-transform-runtime": "^7.16.10",
"@babel/preset-env": "^7.16.11",
"@babel/preset-typescript": "^7.16.7",
"@formatjs/intl-listformat": "^6.5.0",
"@fortawesome/fontawesome-free": "^5.15.4",
"@goauthentik/api": "^2021.12.4-1641413678",
"@goauthentik/api": "^2022.1.1-1642874681",
"@jackfranklin/rollup-plugin-markdown": "^0.3.0",
"@lingui/cli": "^3.13.0",
"@lingui/core": "^3.13.0",
"@lingui/detect-locale": "^3.13.0",
"@lingui/macro": "^3.13.0",
"@lingui/cli": "^3.13.1",
"@lingui/core": "^3.13.1",
"@lingui/detect-locale": "^3.13.1",
"@lingui/macro": "^3.13.1",
"@patternfly/patternfly": "^4.164.2",
"@polymer/iron-form": "^3.0.1",
"@polymer/paper-input": "^3.2.1",
@ -73,27 +74,27 @@
"@types/chart.js": "^2.9.35",
"@types/codemirror": "5.60.5",
"@types/grecaptcha": "^3.0.3",
"@typescript-eslint/eslint-plugin": "^5.9.0",
"@typescript-eslint/parser": "^5.9.0",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"@webcomponents/webcomponentsjs": "^2.6.0",
"babel-plugin-macros": "^3.1.0",
"base64-js": "^1.5.1",
"chart.js": "^3.7.0",
"chartjs-adapter-moment": "^1.0.0",
"codemirror": "^5.65.0",
"codemirror": "^5.65.1",
"construct-style-sheets-polyfill": "^3.0.5",
"country-flag-icons": "^1.4.19",
"eslint": "^8.6.0",
"eslint": "^8.7.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.4",
"eslint-plugin-lit": "^1.6.1",
"flowchart.js": "^1.17.0",
"fuse.js": "^6.5.3",
"lit": "^2.1.0",
"lit": "^2.1.1",
"moment": "^2.29.1",
"prettier": "^2.5.1",
"rapidoc": "^9.1.3",
"rollup": "^2.63.0",
"rapidoc": "^9.1.4",
"rollup": "^2.66.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2",
"rollup-plugin-minify-html-literals": "^1.2.6",
@ -101,7 +102,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.3.1",
"typescript": "^4.5.4",
"typescript": "^4.5.5",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
}

View File

@ -3,3 +3,6 @@ window["polymerSkipLoadingFontRoboto"] = true;
import "construct-style-sheets-polyfill";
import "@webcomponents/webcomponentsjs";
import "lit/polyfill-support.js";
import "@formatjs/intl-listformat/polyfill.js";
import "@formatjs/intl-listformat/locale-data/en.js";

View File

@ -1,4 +1,4 @@
import { Config, Configuration, CoreApi, CurrentTenant, Middleware, ResponseContext, RootApi } from "@goauthentik/api";
import { Config, Configuration, CoreApi, CurrentTenant, FetchParams, Middleware, RequestContext, ResponseContext, RootApi } from "@goauthentik/api";
import { getCookie } from "../utils";
import { APIMiddleware } from "../elements/notifications/APIDrawer";
import { MessageMiddleware } from "../elements/messages/Middleware";
@ -50,13 +50,21 @@ export function tenant(): Promise<CurrentTenant> {
return globalTenantPromise;
}
export class CSRFMiddleware implements Middleware {
pre?(context: RequestContext): Promise<FetchParams | void> {
// @ts-ignore
context.init.headers["X-authentik-CSRF"] = getCookie("authentik_csrf");
return Promise.resolve(context);
}
}
export const DEFAULT_CONFIG = new Configuration({
basePath: process.env.AK_API_BASE_PATH + "/api/v3",
headers: {
"X-CSRFToken": getCookie("authentik_csrf"),
"sentry-trace": getMetaContent("sentry-trace") || "",
},
middleware: [
new CSRFMiddleware(),
new APIMiddleware(),
new MessageMiddleware(),
new LoggingMiddleware(),

View File

@ -20,6 +20,8 @@ export function configureSentry(canDoPpi: boolean = false): Promise<Config> {
// Error on edge on ios,
// https://stackoverflow.com/questions/69261499/what-is-instantsearchsdkjsbridgeclearhighlight
/instantSearchSDKJSBridgeClearHighlight/ig,
// Seems to be an issue in Safari and Firefox
/MutationObserver.observe/ig,
],
release: `authentik@${VERSION}`,
tunnel: "/api/v3/sentry/",

View File

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

View File

@ -107,7 +107,7 @@ export class CodeMirrorTextarea extends LitElement {
this.editor = CodeMirror.fromTextArea(textarea, {
mode: this.mode,
theme: "monokai",
lineNumbers: true,
lineNumbers: false, // Line Numbers seem to be broken on firefox?
readOnly: this.readOnly,
autoRefresh: true,
lineWrapping: true,

View File

@ -150,7 +150,7 @@ export class IdentificationStage extends BaseStage<
cleanup(): void {
if (this.form) {
document.documentElement.removeChild(this.form);
this.form.remove();
}
}

View File

@ -62,6 +62,10 @@ msgstr "6 digits, widely compatible"
msgid "8 digits, not compatible with apps like Google Authenticator"
msgstr "8 digits, not compatible with apps like Google Authenticator"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A \"roaming\" authenticator, like a YubiKey"
msgstr "A \"roaming\" authenticator, like a YubiKey"
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
msgid "A code has been sent to you via SMS."
msgstr "A code has been sent to you via SMS."
@ -70,6 +74,10 @@ msgstr "A code has been sent to you via SMS."
msgid "A newer version of the frontend is available."
msgstr "A newer version of the frontend is available."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A non-removable authenticator, like TouchID or Windows Hello"
msgstr "A non-removable authenticator, like TouchID or Windows Hello"
#: src/pages/policies/dummy/DummyPolicyForm.ts
msgid "A policy used for testing. Always returns the same result as specified below after waiting a random duration."
msgstr "A policy used for testing. Always returns the same result as specified below after waiting a random duration."
@ -488,6 +496,10 @@ msgstr "Authentication flow"
msgid "Authenticator"
msgstr "Authenticator"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Authenticator Attachment"
msgstr "Authenticator Attachment"
#: src/pages/flows/utils.ts
msgid "Authorization"
msgstr "Authorization"
@ -930,6 +942,7 @@ msgstr "Configuration error"
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/password/PasswordStageForm.ts
msgid "Configuration flow"
msgstr "Configuration flow"
@ -2064,6 +2077,7 @@ msgstr "Flow used by an authenticated user to configure their password. If empty
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
msgstr "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
@ -2380,8 +2394,12 @@ msgid "If multiple providers share an outpost, a self-signed certificate is used
msgstr "If multiple providers share an outpost, a self-signed certificate is used."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
msgstr "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgstr "If no explicit redirect URIs are specified, any redirect URI is allowed."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved."
msgstr "If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved."
#: src/pages/tenants/TenantForm.ts
msgid "If set, users are able to unenroll themselves using this flow. If no flow is set, option is not shown."
@ -2739,6 +2757,7 @@ msgstr "Loading"
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
@ -3140,6 +3159,10 @@ msgstr "No objects found."
msgid "No policies are currently bound to this object."
msgstr "No policies are currently bound to this object."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "No preference is sent"
msgstr "No preference is sent"
#: src/pages/users/UserListPage.ts
msgid "No recovery flow is configured."
msgstr "No recovery flow is configured."
@ -3227,8 +3250,12 @@ msgid "Notification rule(s)"
msgstr "Notification rule(s)"
#: src/pages/events/TransportListPage.ts
msgid "Notification transports(s)"
msgstr "Notification transports(s)"
msgid "Notification transport(s)"
msgstr "Notification transport(s)"
#: src/pages/events/TransportListPage.ts
#~ msgid "Notification transports(s)"
#~ msgstr "Notification transports(s)"
#: src/elements/notifications/NotificationDrawer.ts
msgid "Notifications"
@ -3929,6 +3956,10 @@ msgstr "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
msgid "Reset Password"
msgstr "Reset Password"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Resident key requirement"
msgstr "Resident key requirement"
#: src/interfaces/AdminInterface.ts
#~ msgid "Resources"
#~ msgstr "Resources"
@ -5034,6 +5065,18 @@ msgstr "The Host IP of the docker host"
msgid "The URL \"{0}\" was not found."
msgstr "The URL \"{0}\" was not found."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur"
msgstr "The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator can create and store a dedicated credential, but if it doesn't that's alright too"
msgstr "The authenticator can create and store a dedicated credential, but if it doesn't that's alright too"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator should not create a dedicated credential"
msgstr "The authenticator should not create a dedicated credential"
#: src/pages/providers/proxy/ProxyProviderForm.ts
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "The external URL you'll access the application at. Include any non-standard port."
@ -5180,6 +5223,10 @@ msgstr "Title"
msgid "To"
msgstr "To"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "To allow any redirect URI, set this value to \"*\". Be aware of the possible security implications this can have."
msgstr "To allow any redirect URI, set this value to \"*\". Be aware of the possible security implications this can have."
#: src/pages/users/UserViewPage.ts
msgid "To create a recovery link, the current tenant needs to have a recovery flow configured."
msgstr "To create a recovery link, the current tenant needs to have a recovery flow configured."

View File

@ -68,6 +68,10 @@ msgstr "6 chiffres, compatibilité large"
msgid "8 digits, not compatible with apps like Google Authenticator"
msgstr "8 chiffres, incompatible avec certaines applications telles que Google Authenticator"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A \"roaming\" authenticator, like a YubiKey"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
msgid "A code has been sent to you via SMS."
msgstr ""
@ -76,6 +80,10 @@ msgstr ""
msgid "A newer version of the frontend is available."
msgstr "Une nouvelle version de l'interface est disponible."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A non-removable authenticator, like TouchID or Windows Hello"
msgstr ""
#: src/pages/policies/dummy/DummyPolicyForm.ts
msgid "A policy used for testing. Always returns the same result as specified below after waiting a random duration."
msgstr "Une politique utilisée pour les tests. Retourne toujours la même valeur telle qu'indiquée ci-dessous après une attente aléatoire."
@ -493,6 +501,10 @@ msgstr "Flux d'authentification"
msgid "Authenticator"
msgstr "Authentificateur"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Authenticator Attachment"
msgstr ""
#: src/pages/flows/utils.ts
msgid "Authorization"
msgstr "Authorisation"
@ -932,6 +944,7 @@ msgstr "Erreur de configuration"
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/password/PasswordStageForm.ts
msgid "Configuration flow"
msgstr "Flux de configuration"
@ -2050,6 +2063,7 @@ msgstr "Flux utilisé par un utilisateur authentifié pour configurer son mot de
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
msgstr "Flux utilisé par un utilisateur authentifié pour configurer cette étape. S'il est vide, l'utilisateur ne sera pas en mesure de le configurer."
@ -2364,8 +2378,12 @@ msgid "If multiple providers share an outpost, a self-signed certificate is used
msgstr "Si plusieurs fournisseurs partagent un avant-poste, un certificat auto-signé est utilisé."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
msgstr "Si aucune URL de redirection explicite n'est spécifié, toute URL de redirection est autorisé."
#~ msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgstr "Si aucune URL de redirection explicite n'est spécifié, toute URL de redirection est autorisé."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved."
msgstr ""
#: src/pages/tenants/TenantForm.ts
msgid "If set, users are able to unenroll themselves using this flow. If no flow is set, option is not shown."
@ -2719,6 +2737,7 @@ msgstr "Chargement en cours"
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
@ -3119,6 +3138,10 @@ msgstr "Aucun objet trouvé."
msgid "No policies are currently bound to this object."
msgstr "Aucune politique n'est actuellement lié à cet objet."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "No preference is sent"
msgstr ""
#: src/pages/users/UserListPage.ts
msgid "No recovery flow is configured."
msgstr "Aucun flux de récupération n'est configuré."
@ -3205,8 +3228,12 @@ msgid "Notification rule(s)"
msgstr "Règle(s) de notification"
#: src/pages/events/TransportListPage.ts
msgid "Notification transports(s)"
msgstr "Transport(s) de notification"
msgid "Notification transport(s)"
msgstr ""
#: src/pages/events/TransportListPage.ts
#~ msgid "Notification transports(s)"
#~ msgstr "Transport(s) de notification"
#: src/elements/notifications/NotificationDrawer.ts
msgid "Notifications"
@ -3901,6 +3928,10 @@ msgstr "Obligatoire. 150 caractères ou moins. Lettres, chiffres et @/./+/-/_ un
msgid "Reset Password"
msgstr "Réinitialiser le mot de passe"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Resident key requirement"
msgstr ""
#: src/interfaces/AdminInterface.ts
#~ msgid "Resources"
#~ msgstr "Ressources"
@ -4989,6 +5020,18 @@ msgstr ""
msgid "The URL \"{0}\" was not found."
msgstr "L'URL \"{0}\" est introuvable."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator can create and store a dedicated credential, but if it doesn't that's alright too"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator should not create a dedicated credential"
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "The external URL you'll access the application at. Include any non-standard port."
@ -5124,6 +5167,10 @@ msgstr "Titre"
msgid "To"
msgstr "À"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "To allow any redirect URI, set this value to \"*\". Be aware of the possible security implications this can have."
msgstr ""
#: src/pages/users/UserViewPage.ts
msgid "To create a recovery link, the current tenant needs to have a recovery flow configured."
msgstr "Pour créer un lien de récupération, le locataire actuel doit avoir un flux de récupération configuré."

View File

@ -62,6 +62,10 @@ msgstr ""
msgid "8 digits, not compatible with apps like Google Authenticator"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A \"roaming\" authenticator, like a YubiKey"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
msgid "A code has been sent to you via SMS."
msgstr ""
@ -70,6 +74,10 @@ msgstr ""
msgid "A newer version of the frontend is available."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A non-removable authenticator, like TouchID or Windows Hello"
msgstr ""
#: src/pages/policies/dummy/DummyPolicyForm.ts
msgid "A policy used for testing. Always returns the same result as specified below after waiting a random duration."
msgstr ""
@ -484,6 +492,10 @@ msgstr ""
msgid "Authenticator"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Authenticator Attachment"
msgstr ""
#: src/pages/flows/utils.ts
msgid "Authorization"
msgstr ""
@ -924,6 +936,7 @@ msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/password/PasswordStageForm.ts
msgid "Configuration flow"
msgstr ""
@ -2056,6 +2069,7 @@ msgstr ""
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
msgstr ""
@ -2372,7 +2386,11 @@ msgid "If multiple providers share an outpost, a self-signed certificate is used
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved."
msgstr ""
#: src/pages/tenants/TenantForm.ts
@ -2729,6 +2747,7 @@ msgstr ""
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
@ -3130,6 +3149,10 @@ msgstr ""
msgid "No policies are currently bound to this object."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "No preference is sent"
msgstr ""
#: src/pages/users/UserListPage.ts
msgid "No recovery flow is configured."
msgstr ""
@ -3217,9 +3240,13 @@ msgid "Notification rule(s)"
msgstr ""
#: src/pages/events/TransportListPage.ts
msgid "Notification transports(s)"
msgid "Notification transport(s)"
msgstr ""
#: src/pages/events/TransportListPage.ts
#~ msgid "Notification transports(s)"
#~ msgstr ""
#: src/elements/notifications/NotificationDrawer.ts
msgid "Notifications"
msgstr ""
@ -3919,6 +3946,10 @@ msgstr ""
msgid "Reset Password"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Resident key requirement"
msgstr ""
#: src/interfaces/AdminInterface.ts
#~ msgid "Resources"
#~ msgstr ""
@ -5024,6 +5055,18 @@ msgstr ""
msgid "The URL \"{0}\" was not found."
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator can create and store a dedicated credential, but if it doesn't that's alright too"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator should not create a dedicated credential"
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "The external URL you'll access the application at. Include any non-standard port."
@ -5160,6 +5203,10 @@ msgstr ""
msgid "To"
msgstr ""
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "To allow any redirect URI, set this value to \"*\". Be aware of the possible security implications this can have."
msgstr ""
#: src/pages/users/UserViewPage.ts
msgid "To create a recovery link, the current tenant needs to have a recovery flow configured."
msgstr ""

View File

@ -65,6 +65,10 @@ msgstr "6 basamaklı, yaygın olarak uyumlu"
msgid "8 digits, not compatible with apps like Google Authenticator"
msgstr "Google Authenticator gibi uygulamalarla uyumlu olmayan 8 haneli"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A \"roaming\" authenticator, like a YubiKey"
msgstr ""
#: src/flows/stages/authenticator_validate/AuthenticatorValidateStageCode.ts
msgid "A code has been sent to you via SMS."
msgstr "SMS ile size bir kod gönderildi."
@ -73,6 +77,10 @@ msgstr "SMS ile size bir kod gönderildi."
msgid "A newer version of the frontend is available."
msgstr "Ön yüzün daha yeni bir sürümü mevcuttur."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "A non-removable authenticator, like TouchID or Windows Hello"
msgstr ""
#: src/pages/policies/dummy/DummyPolicyForm.ts
msgid "A policy used for testing. Always returns the same result as specified below after waiting a random duration."
msgstr "Test için kullanılan bir ilke. Her zaman rastgele bir süre bekledikten sonra aşağıda belirtilen sonucu döndürür."
@ -487,6 +495,10 @@ msgstr "Kimlik doğrulama akışı"
msgid "Authenticator"
msgstr "Kimlik Doğrulayıcı"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Authenticator Attachment"
msgstr ""
#: src/pages/flows/utils.ts
msgid "Authorization"
msgstr "Yetkilendirme"
@ -924,6 +936,7 @@ msgstr "Yapılandırma hatası"
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/password/PasswordStageForm.ts
msgid "Configuration flow"
msgstr "Yapılandırma akışı"
@ -2025,6 +2038,7 @@ msgstr "Kimliği doğrulanmış bir kullanıcı tarafından parolasını yapıla
#: src/pages/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage."
msgstr "Bu Aşama'yı yapılandırmak için kimliği doğrulanmış bir kullanıcı tarafından kullanılan akış. Boşsa, kullanıcı bu aşamayı yapılandıramaz."
@ -2292,8 +2306,6 @@ msgstr "Kimlik Belirteci"
msgid "IP"
msgstr "İP"
#: src/pages/policies/reputation/IPReputationListPage.ts
#: src/pages/policies/reputation/IPReputationListPage.ts
#~ msgid "IP Reputation"
#~ msgstr "IP İtibar"
@ -2337,8 +2349,12 @@ msgid "If multiple providers share an outpost, a self-signed certificate is used
msgstr "Birden çok sağlayıcı bir üssü paylaşıyorsa, otomatik olarak imzalanan bir sertifika kullanılır."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
msgstr "Açık bir yeniden yönlendirme URI'leri belirtilmezse, herhangi bir yeniden yönlendirme URI'sine izin verilir."
#~ msgid "If no explicit redirect URIs are specified, any redirect URI is allowed."
#~ msgstr "Açık bir yeniden yönlendirme URI'leri belirtilmezse, herhangi bir yeniden yönlendirme URI'sine izin verilir."
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved."
msgstr ""
#: src/pages/tenants/TenantForm.ts
msgid "If set, users are able to unenroll themselves using this flow. If no flow is set, option is not shown."
@ -2573,7 +2589,7 @@ msgstr "Son senkronizasyon: {0}"
#: src/pages/applications/ApplicationViewPage.ts
#: src/pages/applications/ApplicationViewPage.ts
msgid "Launch"
msgstr "Lansman"
msgstr "Eriş"
#: src/pages/applications/ApplicationForm.ts
msgid "Launch URL"
@ -2691,6 +2707,7 @@ msgstr "Yükleniyor"
#: src/pages/stages/authenticator_static/AuthenticatorStaticStageForm.ts
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
#: src/pages/stages/email/EmailStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
#: src/pages/stages/identification/IdentificationStageForm.ts
@ -2721,7 +2738,7 @@ msgstr "Yerel"
#: src/user/user-settings/details/UserDetailsForm.ts
msgid "Locale"
msgstr "Yerel"
msgstr "Yerelleştirme"
#: src/pages/stages/user_login/UserLoginStageForm.ts
msgid "Log the currently pending user in."
@ -3091,6 +3108,10 @@ msgstr "Nesne bulunamadı."
msgid "No policies are currently bound to this object."
msgstr "Hiçbir ilke şu anda bu nesneye bağlı değildir."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "No preference is sent"
msgstr ""
#: src/pages/users/UserListPage.ts
msgid "No recovery flow is configured."
msgstr "Kurtarma akışı yapılandırılmamış."
@ -3175,8 +3196,12 @@ msgid "Notification rule(s)"
msgstr "Bildirim kuralları"
#: src/pages/events/TransportListPage.ts
msgid "Notification transports(s)"
msgstr "Bildirim aktarıcıları"
msgid "Notification transport(s)"
msgstr ""
#: src/pages/events/TransportListPage.ts
#~ msgid "Notification transports(s)"
#~ msgstr "Bildirim aktarıcıları"
#: src/elements/notifications/NotificationDrawer.ts
msgid "Notifications"
@ -3804,32 +3829,28 @@ msgstr "Kullanıcıyı geçerli oturumdan kaldırın."
#: src/pages/policies/reputation/ReputationListPage.ts
msgid "Reputation"
msgstr ""
msgstr "İtibar"
#: src/pages/policies/reputation/ReputationListPage.ts
msgid "Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login."
msgstr ""
msgstr "IP ve kullanıcı tanımlayıcıları için itibar. Başarısız olan her giriş için puan azaltılır ve her başarılı oturum açma için artırılır."
#: src/pages/policies/reputation/IPReputationListPage.ts
#~ msgid "Reputation for IPs. Scores are decreased for each failed login and increased for each successful login."
#~ msgstr "IP'lerin itibarı. Başarısız olan her giriş için puanlar azaltılır ve her başarılı oturum açma için artırılır."
#: src/pages/policies/reputation/UserReputationListPage.ts
#~ msgid "Reputation for usernames. Scores are decreased for each failed login and increased for each successful login."
#~ msgstr "Kullanıcı adları için itibar. Başarısız olan her giriş için puanlar azaltılır ve her başarılı oturum açma için artırılır."
#: src/interfaces/AdminInterface.ts
#~ msgid "Reputation policy - IPs"
#~ msgstr "İtibar ilkesi - IP'ler"
#: src/interfaces/AdminInterface.ts
#~ msgid "Reputation policy - Users"
#~ msgstr "İtibar ilkesi- Kullanıcılar"
#: src/interfaces/AdminInterface.ts
#: src/pages/policies/reputation/ReputationListPage.ts
msgid "Reputation scores"
msgstr ""
msgstr "İtibar puanları"
#: src/pages/events/EventInfo.ts
#: src/pages/events/EventInfo.ts
@ -3862,6 +3883,10 @@ msgstr "Gerekli. 150 karakter veya daha az. Harfler, rakamlar ve yalnızca @/./+
msgid "Reset Password"
msgstr "Parolayı Sıfırla"
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "Resident key requirement"
msgstr ""
#~ msgid "Resources"
#~ msgstr "Kaynaklar"
@ -4933,6 +4958,18 @@ msgstr "Docker ana bilgisayarının Ana Bilgisayar IP'si"
msgid "The URL \"{0}\" was not found."
msgstr "“{0}” URL'si bulunamadı."
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator can create and store a dedicated credential, but if it doesn't that's alright too"
msgstr ""
#: src/pages/stages/authenticator_webauthn/AuthenticateWebAuthnStageForm.ts
msgid "The authenticator should not create a dedicated credential"
msgstr ""
#: src/pages/providers/proxy/ProxyProviderForm.ts
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "The external URL you'll access the application at. Include any non-standard port."
@ -5075,6 +5112,10 @@ msgstr "Başlık"
msgid "To"
msgstr "Kime"
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
msgid "To allow any redirect URI, set this value to \"*\". Be aware of the possible security implications this can have."
msgstr ""
#: src/pages/users/UserViewPage.ts
msgid "To create a recovery link, the current tenant needs to have a recovery flow configured."
msgstr "Kurtarma bağlantısı oluşturmak için geçerli sakinin yapılandırılmış bir kurtarma akışı olması gerekir."
@ -5464,7 +5505,7 @@ msgstr "Güncelleme {0}"
#: src/pages/policies/reputation/ReputationListPage.ts
msgid "Updated"
msgstr ""
msgstr "Güncellendi"
#: src/pages/providers/proxy/ProxyProviderForm.ts
msgid "Upstream host that the requests are forwarded to."
@ -5545,8 +5586,6 @@ msgstr "Kullanıcı Bilgileri"
msgid "User Property Mappings"
msgstr "Kullanıcı Özellik Eşlemeleri"
#: src/pages/policies/reputation/UserReputationListPage.ts
#: src/pages/policies/reputation/UserReputationListPage.ts
#~ msgid "User Reputation"
#~ msgstr "Kullanıcı İtibar"

View File

@ -17,8 +17,10 @@ export class SystemStatusCard extends AdminStatusCard<System> {
async getPrimaryValue(): Promise<System> {
this.now = new Date();
let status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
if (status.embeddedOutpostHost === "") {
if (status.embeddedOutpostHost === "" || !status.embeddedOutpostHost.includes("http")) {
// First install, ensure the embedded outpost host is set
// also run when outpost host does not contain http
// (yes it's called host and requires a URL, i know)
await this.setOutpostHost();
status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
}

View File

@ -56,7 +56,7 @@ export class TransportListPage extends TablePage<NotificationTransport> {
renderToolbarSelected(): TemplateResult {
const disabled = this.selectedElements.length < 1;
return html`<ak-forms-delete-bulk
objectLabel=${t`Notification transports(s)`}
objectLabel=${t`Notification transport(s)`}
.objects=${this.selectedElements}
.usedBy=${(item: NotificationTransport) => {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsUsedByList({

View File

@ -171,7 +171,10 @@ ${this.instance?.redirectUris}</textarea
${t`Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.`}
</p>
<p class="pf-c-form__helper-text">
${t`If no explicit redirect URIs are specified, any redirect URI is allowed.`}
${t`If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved.`}
</p>
<p class="pf-c-form__helper-text">
${t`To allow any redirect URI, set this value to "*". Be aware of the possible security implications this can have.`}
</p>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Signing Key`} name="signingKey">

View File

@ -5,8 +5,16 @@ import { t } from "@lingui/macro";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { until } from "lit/directives/until.js";
import { AuthenticateWebAuthnStage, StagesApi } from "@goauthentik/api";
import {
AuthenticateWebAuthnStage,
AuthenticatorAttachmentEnum,
FlowsApi,
FlowsInstancesListDesignationEnum,
ResidentKeyRequirementEnum,
StagesApi,
} from "@goauthentik/api";
import { DEFAULT_CONFIG } from "../../../api/Config";
import "../../../elements/forms/HorizontalFormElement";
@ -29,6 +37,9 @@ export class AuthenticateWebAuthnStageForm extends ModelForm<AuthenticateWebAuth
}
send = (data: AuthenticateWebAuthnStage): Promise<AuthenticateWebAuthnStage> => {
if (data.authenticatorAttachment?.toString() === "") {
data.authenticatorAttachment = null;
}
if (this.instance) {
return new StagesApi(DEFAULT_CONFIG).stagesAuthenticatorWebauthnUpdate({
stageUuid: this.instance.pk || "",
@ -62,7 +73,7 @@ export class AuthenticateWebAuthnStageForm extends ModelForm<AuthenticateWebAuth
?required=${true}
name="userVerification"
>
<select name="users" class="pf-c-form-control">
<select class="pf-c-form-control">
<option
value="${UserVerificationEnum.Required}"
?selected=${this.instance?.userVerification ===
@ -86,6 +97,103 @@ export class AuthenticateWebAuthnStageForm extends ModelForm<AuthenticateWebAuth
</option>
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Resident key requirement`}
?required=${true}
name="residentKeyRequirement"
>
<select class="pf-c-form-control">
<option
value="${ResidentKeyRequirementEnum.Discouraged}"
?selected=${this.instance?.residentKeyRequirement ===
ResidentKeyRequirementEnum.Discouraged}
>
${t`The authenticator should not create a dedicated credential`}
</option>
<option
value="${ResidentKeyRequirementEnum.Preferred}"
?selected=${this.instance?.residentKeyRequirement ===
ResidentKeyRequirementEnum.Preferred}
>
${t`The authenticator can create and store a dedicated credential, but if it doesn't that's alright too`}
</option>
<option
value="${ResidentKeyRequirementEnum.Required}"
?selected=${this.instance?.residentKeyRequirement ===
ResidentKeyRequirementEnum.Required}
>
${t`The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur`}
</option>
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Authenticator Attachment`}
?required=${true}
name="authenticatorAttachment"
>
<select class="pf-c-form-control">
<option
value=""
?selected=${this.instance?.authenticatorAttachment === null}
>
${t`No preference is sent`}
</option>
<option
value="${AuthenticatorAttachmentEnum.Platform}"
?selected=${this.instance?.authenticatorAttachment ===
AuthenticatorAttachmentEnum.Platform}
>
${t`A non-removable authenticator, like TouchID or Windows Hello`}
</option>
<option
value="${AuthenticatorAttachmentEnum.CrossPlatform}"
?selected=${this.instance?.authenticatorAttachment ===
AuthenticatorAttachmentEnum.CrossPlatform}
>
${t`A "roaming" authenticator, like a YubiKey`}
</option>
</select>
</ak-form-element-horizontal>
<ak-form-element-horizontal label=${t`Configuration flow`} name="configureFlow">
<select class="pf-c-form-control">
<option
value=""
?selected=${this.instance?.configureFlow === undefined}
>
---------
</option>
${until(
new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesList({
ordering: "slug",
designation:
FlowsInstancesListDesignationEnum.StageConfiguration,
})
.then((flows) => {
return flows.results.map((flow) => {
let selected = this.instance?.configureFlow === flow.pk;
if (
!this.instance?.pk &&
!this.instance?.configureFlow &&
flow.slug === "default-otp-time-configure"
) {
selected = true;
}
return html`<option
value=${ifDefined(flow.pk)}
?selected=${selected}
>
${flow.name} (${flow.slug})
</option>`;
});
}),
html`<option>${t`Loading...`}</option>`,
)}
</select>
<p class="pf-c-form__helper-text">
${t`Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage.`}
</p>
</ak-form-element-horizontal>
</div>
</ak-form-group>
</form>`;

View File

@ -0,0 +1,33 @@
---
title: Inspector
---
The flow inspector, introduced in 2021.10, allows administrators to easily figure out how custom flows work, inspect the current context and debug issues.
:::info
When running a flow with the inspector enabled, the flow is still executed normally. This means that for example, a `user_write` stage will _actually_ write user data.
:::
![](./inspector.png)
The following infos are shown in the inspector
## Next stage
This is the currently planned next stage. If you have stage bindings configured to evaluate on plan (default), then you will see the result here. If you however have them configured to re-evaluate, then this will not show up here, since the results will vary based on your input.
Shown is the name and kind of the stage, as well as the unique ID.
## Plan history
Here you can see an overview of which stages have run, which is currently active, and which is planned to come next. Same caveats as above apply.
## Current plan context
This shows you the current context. This will contain fields depending on the same, after an identification stage for example you would see "pending_user" be set.
This data is not cleaned, so if your flow involves inputting a password, it will be shown here too.
## Session ID
The unique ID for the currently used session. This can be used to debug issues with flows restarting/losing state.

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -25,7 +25,11 @@ All of these variables can be set to values, but you can also use a URI-like for
### PostgreSQL Backup Settings
- `AUTHENTIK_POSTGRESQL__BACKUP__ENABLED`: Controls if the inbuilt backup-mechanism is enabled, defaults to true (new in 2021.10).
:::info
The integrated backup is deprecated in 2022.1 and will be removed in a future version.
:::
- `AUTHENTIK_POSTGRESQL__BACKUP__ENABLED`: Controls if the inbuilt backup-mechanism is enabled, defaults to false (new in 2021.10).
Optionally enable automated database backups to S3 or S3-compatible storages.

View File

@ -67,20 +67,15 @@ The GeoIP database will automatically be updated every 8 hours.
## Running on Port 80/443
By default, authentik listens on port 9000 for HTTP and 9443 for HTTPS. To change this, you can use a [docker-compose override file](https://docs.docker.com/compose/extends/#adding-and-overriding-configuration).
By default, authentik listens on port 9000 for HTTP and 9443 for HTTPS. To change this, you can set the following variables in `.env`:
Create a file called `docker-compose.override.yml` with the following contents:
```yaml
version: '3.2'
services:
server:
ports:
- "0.0.0.0:80:9000"
- "0.0.0.0:443:9443"
```shell
AUTHENTIK_PORT_HTTP=80
AUTHENTIK_PORT_HTTPS=443
```
Afterwards, make sure to run `docker-compose up -d`.
## Startup
Afterwards, run these commands to finish

View File

@ -2,6 +2,10 @@
title: Backup and restore
---
:::error
Integrated backups are deprecated and will be removed in a future authentik release.
:::
:::warning
Local backups are only supported for docker-compose installs. If you want to backup a Kubernetes instance locally, use an S3-compatible server such as [minio](https://min.io/)
:::

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