Compare commits

..

22 Commits

Author SHA1 Message Date
c77f4204c0 new release: 0.8.15-beta 2020-04-10 21:57:20 +02:00
5f4452470b providers/saml: fix metadata rendering when no singing keypair is selected
closes PASSBOOK-44
2020-04-10 21:54:23 +02:00
9a1270c693 providers/saml: fix wrong signing property being checked
closes PASSBOOK-45
2020-04-10 21:52:03 +02:00
7b9d1a1159 new release: 0.8.14-beta 2020-04-10 21:23:55 +02:00
cdbe1f6161 bump dependencies 2020-04-10 21:17:31 +02:00
e43db2e065 new release: 0.8.13-beta 2020-04-10 21:11:24 +02:00
d1c74d2160 lib: fix imports being changed every time 2020-03-05 17:28:03 +01:00
f2119ce567 providers/saml: fix signing_kp typo 2020-03-05 17:09:08 +01:00
2c4dcb9cf0 actions: remove cache 2020-03-04 21:15:44 +01:00
93b8266821 actions: install pipenv as root 2020-03-04 21:13:40 +01:00
443797d9b0 actions: install wheel package 2020-03-04 21:11:26 +01:00
a4365ca02c actions: don't update system pip 2020-03-04 21:09:46 +01:00
3750083667 actions: don't setup custom python, use system pip 2020-03-04 21:08:24 +01:00
66ef067ecf actions: don't update pip to fix CI 2020-03-04 20:10:46 +01:00
b489b0e691 Merge pull request #7 from BeryJu/crypto
generic cert management
2020-03-04 19:43:52 +01:00
f2154d9875 crypto: add property for private_key 2020-03-04 19:43:18 +01:00
80a50f9bdb providers/saml: switch to new crypto 2020-03-03 23:35:50 +01:00
dc8b89a6b9 sources/saml: switch to new crypto 2020-03-03 23:35:38 +01:00
8df55f22aa crypto: implement simple certificate-key pair for easier management 2020-03-03 23:35:25 +01:00
f6c322be27 providers/oidc: fix skip_authorization not being synced to oidc_client 2020-03-02 17:40:38 +01:00
a144552059 providers/oidc: fill claims with userinfo 2020-03-01 22:55:56 +01:00
535d529193 ui: fix title, fix navigation on user settings 2020-02-29 14:46:58 +01:00
45 changed files with 874 additions and 476 deletions

View File

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

View File

@ -15,14 +15,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev run: sudo pip install -U wheel pipenv && pipenv install --dev
- name: Lint with pylint - name: Lint with pylint
run: pipenv run pylint passbook run: pipenv run pylint passbook
black: black:
@ -32,14 +26,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev run: sudo pip install -U wheel pipenv && pipenv install --dev
- name: Lint with black - name: Lint with black
run: pipenv run black --check passbook run: pipenv run black --check passbook
prospector: prospector:
@ -49,14 +37,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev && pipenv install --dev prospector --skip-lock run: sudo pip install -U wheel pipenv && pipenv install --dev && pipenv install --dev prospector --skip-lock
- name: Lint with prospector - name: Lint with prospector
run: pipenv run prospector run: pipenv run prospector
bandit: bandit:
@ -66,14 +48,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev run: sudo pip install -U wheel pipenv && pipenv install --dev
- name: Lint with bandit - name: Lint with bandit
run: pipenv run bandit -r passbook run: pipenv run bandit -r passbook
# Actual CI tests # Actual CI tests
@ -101,14 +77,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev run: sudo pip install -U wheel pipenv && pipenv install --dev
- name: Run migrations - name: Run migrations
run: pipenv run ./manage.py migrate run: pipenv run ./manage.py migrate
coverage: coverage:
@ -135,14 +105,8 @@ jobs:
- uses: actions/setup-python@v1 - uses: actions/setup-python@v1
with: with:
python-version: '3.8' python-version: '3.8'
- uses: actions/cache@v1
with:
path: ~/.local/share/virtualenvs/
key: ${{ runner.os }}-pipenv-${{ hashFiles('Pipfile.lock') }}
restore-keys: |
${{ runner.os }}-pipenv-
- name: Install dependencies - name: Install dependencies
run: pip install -U pip pipenv && pipenv install --dev run: sudo pip install -U wheel pipenv && pipenv install --dev
- name: Run coverage - name: Run coverage
run: pipenv run ./scripts/coverage.sh run: pipenv run ./scripts/coverage.sh
# Build # Build

View File

@ -16,11 +16,11 @@ jobs:
- name: Building Docker Image - name: Building Docker Image
run: docker build run: docker build
--no-cache --no-cache
-t beryju/passbook:0.8.12-beta -t beryju/passbook:0.8.15-beta
-t beryju/passbook:latest -t beryju/passbook:latest
-f Dockerfile . -f Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/passbook:0.8.12-beta run: docker push beryju/passbook:0.8.15-beta
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/passbook:latest run: docker push beryju/passbook:latest
build-gatekeeper: build-gatekeeper:
@ -37,11 +37,11 @@ jobs:
cd gatekeeper cd gatekeeper
docker build \ docker build \
--no-cache \ --no-cache \
-t beryju/passbook-gatekeeper:0.8.12-beta \ -t beryju/passbook-gatekeeper:0.8.15-beta \
-t beryju/passbook-gatekeeper:latest \ -t beryju/passbook-gatekeeper:latest \
-f Dockerfile . -f Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/passbook-gatekeeper:0.8.12-beta run: docker push beryju/passbook-gatekeeper:0.8.15-beta
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/passbook-gatekeeper:latest run: docker push beryju/passbook-gatekeeper:latest
build-static: build-static:
@ -66,11 +66,11 @@ jobs:
run: docker build run: docker build
--no-cache --no-cache
--network=$(docker network ls | grep github | awk '{print $1}') --network=$(docker network ls | grep github | awk '{print $1}')
-t beryju/passbook-static:0.8.12-beta -t beryju/passbook-static:0.8.15-beta
-t beryju/passbook-static:latest -t beryju/passbook-static:latest
-f static.Dockerfile . -f static.Dockerfile .
- name: Push Docker Container to Registry (versioned) - name: Push Docker Container to Registry (versioned)
run: docker push beryju/passbook-static:0.8.12-beta run: docker push beryju/passbook-static:0.8.15-beta
- name: Push Docker Container to Registry (latest) - name: Push Docker Container to Registry (latest)
run: docker push beryju/passbook-static:latest run: docker push beryju/passbook-static:latest
test-release: test-release:

587
Pipfile.lock generated
View File

@ -25,10 +25,10 @@
}, },
"asgiref": { "asgiref": {
"hashes": [ "hashes": [
"sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0", "sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5",
"sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5" "sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c"
], ],
"version": "==3.2.3" "version": "==3.2.7"
}, },
"asn1crypto": { "asn1crypto": {
"hashes": [ "hashes": [
@ -46,40 +46,40 @@
}, },
"billiard": { "billiard": {
"hashes": [ "hashes": [
"sha256:26fd494dc3251f8ce1f5559744f18aeed427fdaf29a75d7baae26752a5d3816f", "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede",
"sha256:f4e09366653aa3cb3ae8ed16423f9ba1665ff426f087bcdbbed86bf3664fe02c" "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"
], ],
"version": "==3.6.2.0" "version": "==3.6.3.0"
}, },
"boto3": { "boto3": {
"hashes": [ "hashes": [
"sha256:33462a79d57c9c4a215e075472509537d03545f54566fc4f776fb0f4cfa616f6", "sha256:970bd7b332e73d7b51077ed36772c634811b38c81b0cc6ed0f910e50d7ebadf8",
"sha256:34f9a04f529dc849f0e427782d6f3c6b62f7fb734d8f4859b17e5dee0855323e" "sha256:cdd79a3a7bbe1f33a365f0acfcc75c4405b482b3eb9ce3f4e6b16c418e201ac3"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.12.0" "version": "==1.12.39"
}, },
"botocore": { "botocore": {
"hashes": [ "hashes": [
"sha256:055da4826f6c9158e4a61549d57a2ce449c27d44ce34ab4c96c7bb7b5c993efc", "sha256:94232b44e1540b7e043e220bd43f855400d0a243e926b26b3fb72994e971d518",
"sha256:1f7cecfcd38c7cac17b5386014eb04626d1c7559ee8d8ec1526058cd23f6d1d4" "sha256:e20ba56476b1031ce5ac8e22b59dabc75bd0e03231f124ed6b9ff99fe0b0c96b"
], ],
"version": "==1.15.0" "version": "==1.15.39"
}, },
"celery": { "celery": {
"hashes": [ "hashes": [
"sha256:7c544f37a84a5eadc44cab1aa8c9580dff94636bb81978cdf9bf8012d9ea7d8f", "sha256:108a0bf9018a871620936c33a3ee9f6336a89f8ef0a0f567a9001f4aa361415f",
"sha256:d3363bb5df72d74420986a435449f3c3979285941dff57d5d97ecba352a0e3e2" "sha256:5b4b37e276033fe47575107a2775469f0b721646a08c96ec2c61531e4fe45f2a"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.4.0" "version": "==4.4.2"
}, },
"certifi": { "certifi": {
"hashes": [ "hashes": [
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
], ],
"version": "==2019.11.28" "version": "==2020.4.5.1"
}, },
"cffi": { "cffi": {
"hashes": [ "hashes": [
@ -137,29 +137,27 @@
}, },
"cryptography": { "cryptography": {
"hashes": [ "hashes": [
"sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e",
"sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f",
"sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d",
"sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf",
"sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02",
"sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164",
"sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216",
"sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1",
"sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1",
"sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc",
"sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4",
"sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552",
"sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088",
"sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1",
"sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526",
"sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748",
"sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc",
"sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547",
"sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585"
"sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf",
"sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8"
], ],
"version": "==2.8" "version": "==2.9"
}, },
"defusedxml": { "defusedxml": {
"hashes": [ "hashes": [
@ -171,11 +169,11 @@
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:2f1ba1db8648484dd5c238fb62504777b7ad090c81c5f1fd8d5eb5ec21b5f283", "sha256:642d8eceab321ca743ae71e0f985ff8fdca59f07aab3a9fb362c617d23e33a76",
"sha256:c91c91a7ad6ef67a874a4f76f58ba534f9208412692a840e1d125eb5c279cb0a" "sha256:d4666c2edefa38c5ede0ec1655424c56dc47ceb04b6d8d62a7eac09db89545c1"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.0.3" "version": "==3.0.5"
}, },
"django-cors-middleware": { "django-cors-middleware": {
"hashes": [ "hashes": [
@ -218,10 +216,11 @@
}, },
"django-oauth-toolkit": { "django-oauth-toolkit": {
"hashes": [ "hashes": [
"sha256:ad1b76275950ebbff708222cec57bbdb879f89bac7df6b9dee0f4b9db485c264" "sha256:28508f83385ab4313936ddedfb310eaa8a1dcb737153d2956383ce47e75c2fab",
"sha256:d5a1044af9419ddc048390c5974777ea97874e5b78e33c609e17eebb8423afb2"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.2.0" "version": "==1.3.2"
}, },
"django-oidc-provider": { "django-oidc-provider": {
"hashes": [ "hashes": [
@ -240,11 +239,11 @@
}, },
"django-prometheus": { "django-prometheus": {
"hashes": [ "hashes": [
"sha256:362ea45e5ee26bdba85ce978aeb370659ca6bbc0d6bac69868a055179e053bd1", "sha256:1a8cb752ae4181e38df00e7bd7d5f6495cde18b8b3ff697c22f9d8d2fe48bf28",
"sha256:facaa677386899303ea26c45552371cc43f476e42a81c081011a49cb5564af0b" "sha256:9f024af5495447c8e309f07e5289e7bc1100c5a380ac7cd0afe3a1b2a0b3b534"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.1.0.dev5" "version": "==2.1.0.dev14"
}, },
"django-recaptcha": { "django-recaptcha": {
"hashes": [ "hashes": [
@ -322,16 +321,17 @@
}, },
"idna": { "idna": {
"hashes": [ "hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
], ],
"version": "==2.8" "version": "==2.9"
}, },
"inflection": { "inflection": {
"hashes": [ "hashes": [
"sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca" "sha256:32a5c3341d9583ec319548b9015b7fbdf8c429cbcb575d326c33ae3a0e90d52c",
"sha256:9a15d3598f01220e93f2207c432cfede50daff53137ce660fb8be838ef1ca6cc"
], ],
"version": "==0.3.1" "version": "==0.4.0"
}, },
"itypes": { "itypes": {
"hashes": [ "hashes": [
@ -349,10 +349,10 @@
}, },
"jmespath": { "jmespath": {
"hashes": [ "hashes": [
"sha256:3720a4b1bd659dd2eecad0666459b9788813e032b83e7ba58578e48254e0a0e6", "sha256:695cb76fa78a10663425d5b73ddc5714eb711157e52704d69be03b1a02ba4fec",
"sha256:bde2aef6f44302dfb30320115b17d030798de8c4110e28d5cf6cf91a7a31074c" "sha256:cca55c8d153173e21baa59983015ad0daf603f9cb799904ff057bfb8ff8dc2d9"
], ],
"version": "==0.9.4" "version": "==0.9.5"
}, },
"jsonschema": { "jsonschema": {
"hashes": [ "hashes": [
@ -363,19 +363,19 @@
}, },
"kombu": { "kombu": {
"hashes": [ "hashes": [
"sha256:2a9e7adff14d046c9996752b2c48b6d9185d0b992106d5160e1a179907a5d4ac", "sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76",
"sha256:67b32ccb6fea030f8799f8fd50dd08e03a4b99464ebc4952d71d8747b1a52ad1" "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.6.7" "version": "==4.6.8"
}, },
"ldap3": { "ldap3": {
"hashes": [ "hashes": [
"sha256:1898194d872539670a2f36d4b56fe5a35d4b9ead28103bec78f05a8993e8122f", "sha256:17f04298b70bf7ecaa5db8a7d8622b5a962ef7fc2b245b2eea705ac1c24338c0",
"sha256:27cb673e7afcb539f6adcae5a3ecac4e74eb37ca0a2d50dc98f29a3829eee529" "sha256:81df4ac8b6df10fb1f05b17c18d0cb8c4c344d5a03083c382824960ed959cf5b"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.6.1" "version": "==2.7"
}, },
"lxml": { "lxml": {
"hashes": [ "hashes": [
@ -458,11 +458,11 @@
}, },
"packaging": { "packaging": {
"hashes": [ "hashes": [
"sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73", "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
"sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334" "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
], ],
"index": "pypi", "index": "pypi",
"version": "==20.1" "version": "==20.3"
}, },
"prometheus-client": { "prometheus-client": {
"hashes": [ "hashes": [
@ -472,41 +472,39 @@
}, },
"psycopg2-binary": { "psycopg2-binary": {
"hashes": [ "hashes": [
"sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29", "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac",
"sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03", "sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a",
"sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039", "sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5",
"sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881", "sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04",
"sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309", "sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1",
"sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed", "sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5",
"sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b", "sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce",
"sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3", "sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434",
"sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7", "sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9",
"sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b", "sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057",
"sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03", "sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98",
"sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103", "sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522",
"sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d", "sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505",
"sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35", "sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa",
"sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b", "sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3",
"sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49", "sha256:96d3038f5bd061401996614f65d27a4ecb62d843eb4f48e212e6d129171a721f",
"sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70", "sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4",
"sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e", "sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4",
"sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e", "sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266",
"sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e", "sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66",
"sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103", "sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38",
"sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6", "sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3",
"sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1", "sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389",
"sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9", "sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab",
"sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e", "sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb",
"sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f", "sha256:ccdc6a87f32b491129ada4b87a43b1895cf2c20fdb7f98ad979647506ffc41b6",
"sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd", "sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d",
"sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8", "sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162",
"sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f", "sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e",
"sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4", "sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"
"sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
"sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.8.4" "version": "==2.8.5"
}, },
"pyasn1": { "pyasn1": {
"hashes": [ "hashes": [
@ -524,80 +522,81 @@
}, },
"pycparser": { "pycparser": {
"hashes": [ "hashes": [
"sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
], ],
"version": "==2.19" "version": "==2.20"
}, },
"pycryptodome": { "pycryptodome": {
"hashes": [ "hashes": [
"sha256:012ca77c2105600e3c6aef43188101ac1d95052c633a4ae8fbebffab20c25f8a", "sha256:07024fc364869eae8d6ac0d316e089956e6aeffe42dbdcf44fe1320d96becf7f",
"sha256:05b4d865710f9a6378d3ada28195ff78e52642d3ecffe6fa9d379d870b9bf29d", "sha256:09b6d6bcc01a4eb1a2b4deeff5aa602a108ec5aed8ac75ae554f97d1d7f0a5ad",
"sha256:07daddb98f98f771ba027f8f835bdb675aeb84effe41ed5221f520b267429354", "sha256:0e10f352ccbbcb5bb2dc4ecaf106564e65702a717d72ab260f9ac4c19753cfc2",
"sha256:09bf05a489fe10f9280a5e0163f195e7b9630cafb15f7d72fb9c8f5eb2afa84f", "sha256:1f4752186298caf2e9ff5354f2e694d607ca7342aa313a62005235d46e28cf04",
"sha256:0a8d5f2dbb4bbe830ace54286b829bfa529f0853bedaab6225fcb2e6d1f7e356", "sha256:2fbc472e0b567318fe2052281d5a8c0ae70099b446679815f655e9fbc18c3a65",
"sha256:1259b8ca49662b8a941177357f08147d858595c0042e63ff81e9628e925b5c9d", "sha256:3ec3dc2f80f71fd0c955ce48b81bfaf8914c6f63a41a738f28885a1c4892968a",
"sha256:238d8b6dd27bd1a04816a68aa90a739e6dd23b192fcd83b50f9360958bff192a", "sha256:426c188c83c10df71f053e04b4003b1437bae5cb37606440e498b00f160d71d0",
"sha256:2a57daef18a2022a5e4b6f7376c9ddd0c2d946e4b1f1e59b837f5bf295be7380", "sha256:626c0a1d4d83ec6303f970a17158114f75c3ba1736f7f2983f7b40a265861bd8",
"sha256:39e5ca2f66d1eac7abcba5ce1a03370d123dc6085620f1cd532dfee27e650178", "sha256:767ad0fb5d23efc36a4d5c2fc608ac603f3de028909bcf59abc943e0d0bc5a36",
"sha256:3d516df693c195b8da3795e381429bd420e87081b7e6c2871c62c9897c812cda", "sha256:7ac729d9091ed5478af2b4a4f44f5335a98febbc008af619e4569a59fe503e40",
"sha256:3e486c5b7228e864665fc479e9f596b2547b5fe29c6f5c8ed3807784d06faed7", "sha256:83295a3fb5cf50c48631eb5b440cb5e9832d8c14d81d1d45f4497b67a9987de8",
"sha256:5029c46b0d41dfb763c3981c0af68eab029f06fe2b94f2299112fc18cf9e8d6d", "sha256:8be56bde3312e022d9d1d6afa124556460ad5c844c2fc63642f6af723c098d35",
"sha256:5817c0b3c263025d851da96b90cbc7e95348008f88b990e90d10683dba376666", "sha256:8f06556a8f7ea7b1e42eff39726bb0dca1c251205debae64e6eebea3cd7b438a",
"sha256:79320f1fc5c9ca682869087c565bb29ca6f334692e940d7365771e9a94382e12", "sha256:9230fcb5d948c3fb40049bace4d33c5d254f8232c2c0bba05d2570aea3ba4520",
"sha256:887d08beca6368d3d70dc75126607ad76317a9fd07fe61323d8c3cb42add12b6", "sha256:9378c309aec1f8cd8bad361ed0816a440151b97a2a3f6ffdaba1d1a1fb76873a",
"sha256:9163fec630495c10c767991e3f8dab32f4427bfb2dfeaa59bb28fe3e52ba66f2", "sha256:9977086e0f93adb326379897437373871b80501e1d176fec63c7f46fb300c862",
"sha256:95d324e603c5cec5d89e8595236bbf59ade5fe3a72d100ce61eebb323d598750", "sha256:9a94fca11fdc161460bd8659c15b6adef45c1b20da86402256eaf3addfaab324",
"sha256:9927aa8a8cb4af681279b6f28a1dcb14e0eb556c1aea8413a1e27608a8516e0c", "sha256:9c739b7795ccf2ef1fdad8d44e539a39ad300ee6786e804ea7f0c6a786eb5343",
"sha256:9948c2d5c5c0ee45ed44cee0e2eba2ce60a03be006ed3074521f3da3be162e72", "sha256:b1e332587b3b195542e77681389c296e1837ca01240399d88803a075447d3557",
"sha256:a719bd708207fa219fcbf4c8ebbcbc52846045f78179d00445b429fdabdbc1c4", "sha256:c109a26a21f21f695d369ff9b87f5d43e0d6c768d8384e10bc74142bed2e092e",
"sha256:bc22ced26ebc46546798fa0141f4418f1db116dec517f0aeaecec87cf7b2416c", "sha256:c818dc1f3eace93ee50c2b6b5c2becf7c418fa5dd1ba6fc0ef7db279ea21d5e4",
"sha256:c41b7e10b72cef00cd63410f31fe50e72dc3a40eafbd146e288384fbe4208064", "sha256:cff31f5a8977534f255f729d5d2467526f2b10563a30bbdade92223e0bf264bd",
"sha256:cdb0ad83a5d6bac986a37fcb7562bcbef0aabae8ea19505bab5cf83c4d18af12", "sha256:d4f94368ce2d65873a87ad867eb3bf63f4ba81eb97a9ee66d38c2b71ce5a7439",
"sha256:d8e480f65ac7105cbc288eec2417dc61eaac6ed6e75595aa15b8c7c77c53a68b", "sha256:d61b012baa8c2b659e9890011358455c0019a4108536b811602d2f638c40802a",
"sha256:da2d581da279bc7408d38e16ff77754f5448c4352f2acfe530a5d14d8fc6934a", "sha256:d6e1bc5c94873bec742afe2dfadce0d20445b18e75c47afc0c115b19e5dd38dd",
"sha256:de61091dd68326b600422cf731eb4810c4c6363f18a65bccd6061784b7454f5b", "sha256:ea83bcd9d6c03248ebd46e71ac313858e0afd5aa2fa81478c0e653242f3eb476",
"sha256:ec7d39589f9cfc2a8b83b1d2fc673441757c99d43283e97b2dd46e0e23730db8", "sha256:ed5761b37615a1f222c5345bbf45272ae2cf8c7dff88a4f53a1e9f977cbb6d95",
"sha256:f3204006869ab037604b1d9f045c4e84882ddd365e4ee8caa5eb1ff47a59188e", "sha256:f011cd0062e54658b7086a76f8cf0f4222812acc66e219e196ea2d0a8849d0ed",
"sha256:f4d2174e168d0eabd1fffaf88b4f62c2b6f30a67b8816f31024b8e48be3e2d75", "sha256:f1add21b6d179179b3c177c33d18a2186a09cc0d3af41ff5ed3f377360b869f2",
"sha256:fcff8c9d88d58880f7eda2139c7c444552a38f98a9e77ba5970b6e78f54ac358" "sha256:f655addaaaa9974108d4808f4150652589cada96074c87115c52e575bfcd87d5"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.9.6" "version": "==3.9.7"
}, },
"pycryptodomex": { "pycryptodomex": {
"hashes": [ "hashes": [
"sha256:04646e40ef5788bad6d415e52862ffcdf2ac2d888ba4a5c82d5cb44607a042f7", "sha256:1537d2d15b604b303aef56e7f440895a1c81adbee786b91f1f06eddc34da5314",
"sha256:132f1e5fa84921f25695a313a6d4988847dfaee7fb1fd0d1fbe03ef678836f58", "sha256:1d20ab8369b7558168fc014a0745c678613f9f486dae468cca2d68145196b8a4",
"sha256:17ad1ebaa00806305d34550fe5d3c776e38a27b8a2678dfb7871ef0209d64e46", "sha256:1ecc9db7409db67765eb008e558879d298406642d33ade43a6488224d23e8081",
"sha256:27736fa02a2d3502e1ca4b150457e56ce3b98f132462f540073498884e5f8975", "sha256:37033976f72af829fe15f7fe5fe1dbed308cc43a98d9dd9d2a0a76de8ca5ee78",
"sha256:38050b3fd86c74c6c79e40bbe824bec6431c3e4e36f6080ed544673ba2dc133a", "sha256:3c3dd9d4c9c1e279d3945ae422895c901f98987333acc132dc094faf52afec35",
"sha256:3b9306b360bddbc8e098b16eab7adacf49389d212db9c3739588ab840a1ca868", "sha256:3c9b3fba037ea52c626060c5a87ee6de7e86c99e8a7c6ee07302539985d2bd64",
"sha256:466e36ba74a7e725625e717fad3f36e0b9293c247b7d0439c66528026ef2834f", "sha256:45ee555fc5e28c119a46d44ce373f5237e54a35c61b750fb3a94446b09855dbc",
"sha256:4f77360b23a21db32a4c35dacffac33dc30ac6a5a77162a34e99ab11ab631516", "sha256:4c93038ac011b36512cb0bf2ee3e2aec774e8bc81021d015917c89fe02bb0ee5",
"sha256:5002388178845683c330a02f4faeddfe7cd477b87824987cca4718fa0c4f2085", "sha256:50163324834edd0c9ce3e4512ded3e221c969086e10fdd5d3fdcaadac5e24a78",
"sha256:51be76756abfc1ddc97e1e2e3c38f4e62fb940161162368308ea9e5919e86c34", "sha256:59b0ea9cda5490f924771456912a225d8d9e678891f9f986661af718534719b2",
"sha256:544628ae67d61c31c28a60e621dadd738b303c5266492355d5ebdb6e7dd1e78f", "sha256:5cf306a17cccc327a33cdc3845629fa13f4573a4ec620ed607c79cf6785f2e27",
"sha256:6ff9d4a06bc40211eee05cd88436740d698a01233f4aaff9eb70d8a90e578966", "sha256:5fff8da399af16a1855f58771223acbbdac720b9969cd03fc5013d2e9a7bd9a4",
"sha256:718329c6ca60260f1c27b8392e372dd51e4e691f7dcb88adc53eb3b76af6363c", "sha256:68650ce5b9f7152b8283302a4617269f821695a612692640dd247bd12ab21c0b",
"sha256:918bc5a0170fe8ed7b72f202245b34f84a1997f5ca1520b9c7db71126e5acd62", "sha256:6b3a9a562688996f760b5077714c3ab8b62ca56061b6e9ab7906841e43e19f91",
"sha256:a8ea72adde0d010f89abece5f024b1be95a5c52472e9a57b3ac7d59aee3c8238", "sha256:7e938ed51a59e29431ea86fab60423ada2757728db0f78952329fa02a789bd31",
"sha256:a979d2c7bcc67282b7ec2600db384c63d37d74e250edb99168483605a380bf62", "sha256:87aa70daad6f039e814790a06422a3189311198b674b62f13933a2bdcb6b1bcc",
"sha256:b350f9ad09b692aed57e669fc3f8cf918557fae9f0229c6ce9286a6fe8c1b60f", "sha256:99be3a1df2b2b9f731ebe1c264a2c07c465e71cee68e35e1640b645b5213a755",
"sha256:be838abc8557a21a60d453c5a4e64c738966b8a0b7d7f8f97eb8bb44041ca452", "sha256:a3f2908666e6f74b8c4893f86dd02e16170f50e4a78ae7f3468b6208d54bc205",
"sha256:bfa99692d3c8f994c5850cc8a894cba001abd76d34069a8bfaad173dd46387d6", "sha256:ae3d44a639fd11dbdeca47e35e94febb1ee8bc15daf26673331add37146e0b85",
"sha256:c021b66f5b3c4ea0c45422ec3241bfea4a16651e1ee5459a136639d0716ccb3c", "sha256:afb4c2fa3c6f492fd9a8b38d76e13f32d429b8e5e1e00238309391b5591cde0d",
"sha256:c7babb64484080057a24c74a82dbf7997904b1710b74caf62e261610f989b437", "sha256:b1515ce3a8a2c3fa537d137c5ca5f8b7a902044d04e07d7c3aa26c3e026120fb",
"sha256:c96b7762b601dc8a58d7712235c3c152868116f58a7ffa40dcd1c6f6cd97405e", "sha256:bf391b377413a197000b43ef2b74359974d8927d329a897c9f5ba7b63dca7b9c",
"sha256:d67b6e0bae0777a2c6c83275fbd7cbf53cd5f23c2028f908b0f7d996466e5b15", "sha256:c436919117c23355740c669f89720673578b9aa4569bbfe105f6c10101fc1966",
"sha256:e15f39fcfb949cfd5536cc9647daba942b1a99b67e4d7211e3bdbcedbc2f823c", "sha256:d2c3c280975638e2a2c2fd9cb36ab111980219757fa163a2755594b9448e4138",
"sha256:e380448f1e39736f6230ec284cd6d771956ad802d6ce5bc56947a2481080cac1", "sha256:e585d530764c459cbd5d460aed0288807bb881f376ca9a20e653645217895961",
"sha256:e5236f2171b21e704d1854fd809a7228eb22e29c894af31459e41986e6a53f87", "sha256:e76e6638ead4a7d93262a24218f0ff3ff74de6b6c823b7e19dccb31b6a481978",
"sha256:ea7b48ce8dbbc86ebadcfe56ebc10d413bdd12c9a5ff0b9147a41993f12b80b3", "sha256:ebfc2f885cafda076c31ae30fa0dd81e7e919ec34059a88d3018ed66e83fcce3",
"sha256:f39f5b58d8fe348ed604bb44a89ca93b26130c275db2b249f718f1538cb70500", "sha256:f5797a39933a3d41526da60856735e6684b2b71a8ca99d5f79555ca121be2f4b",
"sha256:f545f776e45f74c41329e4020463fdd4d0cd0a7501bdf9e50251dafe7bd959a9", "sha256:f7e5fc5e124200b19a14be33fb0099e956e6ebb5e25d287b0829ef0a78ed76c7",
"sha256:f667ac7ae29c19530f199854635f1a97e73d0bfd24163e0db6bdba7dba04eb9f" "sha256:fb350e31e55211fec8ddc89fc0256f3b9bc3b44b68a8bde1cf44b3b4e80c0e42"
], ],
"version": "==3.9.6" "version": "==3.9.7"
}, },
"pyjwkest": { "pyjwkest": {
"hashes": [ "hashes": [
@ -614,16 +613,16 @@
}, },
"pyparsing": { "pyparsing": {
"hashes": [ "hashes": [
"sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f", "sha256:67199f0c41a9c702154efb0e7a8cc08accf830eb003b4d9fa42c4059002e2492",
"sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec" "sha256:700d17888d441604b0bd51535908dcb297561b040819cccde647a92439db5a2a"
], ],
"version": "==2.4.6" "version": "==3.0.0a1"
}, },
"pyrsistent": { "pyrsistent": {
"hashes": [ "hashes": [
"sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280" "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"
], ],
"version": "==0.15.7" "version": "==0.16.0"
}, },
"python-dateutil": { "python-dateutil": {
"hashes": [ "hashes": [
@ -673,20 +672,20 @@
}, },
"pyyaml": { "pyyaml": {
"hashes": [ "hashes": [
"sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
"sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
"sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
"sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
"sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
"sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
"sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
"sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
"sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
"sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
"sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.3" "version": "==5.3.1"
}, },
"qrcode": { "qrcode": {
"hashes": [ "hashes": [
@ -705,10 +704,10 @@
}, },
"requests": { "requests": {
"hashes": [ "hashes": [
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
], ],
"version": "==2.22.0" "version": "==2.23.0"
}, },
"requests-oauthlib": { "requests-oauthlib": {
"hashes": [ "hashes": [
@ -759,11 +758,11 @@
}, },
"sentry-sdk": { "sentry-sdk": {
"hashes": [ "hashes": [
"sha256:b06dd27391fd11fb32f84fe054e6a64736c469514a718a99fb5ce1dff95d6b28", "sha256:23808d571d2461a4ce3784ec12bbee5bdb8c026c143fe79d36cef8a6d653e71f",
"sha256:e023da07cfbead3868e1e2ba994160517885a32dfd994fc455b118e37989479b" "sha256:bb90a4e19c7233a580715fc986cc44be2c48fc10b31e71580a2037e1c94b6950"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.14.1" "version": "==0.14.3"
}, },
"service-identity": { "service-identity": {
"hashes": [ "hashes": [
@ -790,10 +789,10 @@
}, },
"sqlparse": { "sqlparse": {
"hashes": [ "hashes": [
"sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177", "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e",
"sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873" "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548"
], ],
"version": "==0.3.0" "version": "==0.3.1"
}, },
"structlog": { "structlog": {
"hashes": [ "hashes": [
@ -805,11 +804,11 @@
}, },
"swagger-spec-validator": { "swagger-spec-validator": {
"hashes": [ "hashes": [
"sha256:57e29feb3aa921a9fb98bd70af148746b27c77d3207266f5571cebcce211e685", "sha256:61f2d2a732b886cf33c2c24886565be9692e5814cacc17fd973e095b72b33e4f",
"sha256:62ef22eca3f429d93fddda5d793d2a1a9057d3732e7a14606e641805326ae4a6" "sha256:8eb82682871f8d63067b455e2e055c8dd953ca260e791635b58dfe0b73ba1f43"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.4.3" "version": "==2.5.0"
}, },
"uritemplate": { "uritemplate": {
"hashes": [ "hashes": [
@ -848,10 +847,10 @@
}, },
"asgiref": { "asgiref": {
"hashes": [ "hashes": [
"sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0", "sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5",
"sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5" "sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c"
], ],
"version": "==3.2.3" "version": "==3.2.7"
}, },
"astroid": { "astroid": {
"hashes": [ "hashes": [
@ -869,10 +868,10 @@
}, },
"autopep8": { "autopep8": {
"hashes": [ "hashes": [
"sha256:0f592a0447acea0c2b0a9602be1e4e3d86db52badd2e3c84f0193bfd89fd3a43" "sha256:cc6be1dfd46f2c7fa00e84a357f1a269683985b09eaffb47654ed551194399eb"
], ],
"index": "pypi", "index": "pypi",
"version": "==1.5" "version": "==1.5.1"
}, },
"bandit": { "bandit": {
"hashes": [ "hashes": [
@ -900,10 +899,10 @@
}, },
"click": { "click": {
"hashes": [ "hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
], ],
"version": "==7.0" "version": "==7.1.1"
}, },
"colorama": { "colorama": {
"hashes": [ "hashes": [
@ -915,48 +914,48 @@
}, },
"coverage": { "coverage": {
"hashes": [ "hashes": [
"sha256:15cf13a6896048d6d947bf7d222f36e4809ab926894beb748fc9caa14605d9c3", "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0",
"sha256:1daa3eceed220f9fdb80d5ff950dd95112cd27f70d004c7918ca6dfc6c47054c", "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30",
"sha256:1e44a022500d944d42f94df76727ba3fc0a5c0b672c358b61067abb88caee7a0", "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b",
"sha256:25dbf1110d70bab68a74b4b9d74f30e99b177cde3388e07cc7272f2168bd1477", "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0",
"sha256:3230d1003eec018ad4a472d254991e34241e0bbd513e97a29727c7c2f637bd2a", "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823",
"sha256:3dbb72eaeea5763676a1a1efd9b427a048c97c39ed92e13336e726117d0b72bf", "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe",
"sha256:5012d3b8d5a500834783689a5d2292fe06ec75dc86ee1ccdad04b6f5bf231691", "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037",
"sha256:51bc7710b13a2ae0c726f69756cf7ffd4362f4ac36546e243136187cfcc8aa73", "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6",
"sha256:527b4f316e6bf7755082a783726da20671a0cc388b786a64417780b90565b987", "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31",
"sha256:722e4557c8039aad9592c6a4213db75da08c2cd9945320220634f637251c3894", "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd",
"sha256:76e2057e8ffba5472fd28a3a010431fd9e928885ff480cb278877c6e9943cc2e", "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892",
"sha256:77afca04240c40450c331fa796b3eab6f1e15c5ecf8bf2b8bee9706cd5452fef", "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1",
"sha256:7afad9835e7a651d3551eab18cbc0fdb888f0a6136169fbef0662d9cdc9987cf", "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78",
"sha256:9bea19ac2f08672636350f203db89382121c9c2ade85d945953ef3c8cf9d2a68", "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac",
"sha256:a8b8ac7876bc3598e43e2603f772d2353d9931709345ad6c1149009fd1bc81b8", "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006",
"sha256:b0840b45187699affd4c6588286d429cd79a99d509fe3de0f209594669bb0954", "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014",
"sha256:b26aaf69713e5674efbde4d728fb7124e429c9466aeaf5f4a7e9e699b12c9fe2", "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2",
"sha256:b63dd43f455ba878e5e9f80ba4f748c0a2156dde6e0e6e690310e24d6e8caf40", "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7",
"sha256:be18f4ae5a9e46edae3f329de2191747966a34a3d93046dbdf897319923923bc", "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8",
"sha256:c312e57847db2526bc92b9bfa78266bfbaabac3fdcd751df4d062cd4c23e46dc", "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7",
"sha256:c60097190fe9dc2b329a0eb03393e2e0829156a589bd732e70794c0dd804258e", "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9",
"sha256:c62a2143e1313944bf4a5ab34fd3b4be15367a02e9478b0ce800cb510e3bbb9d", "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1",
"sha256:cc1109f54a14d940b8512ee9f1c3975c181bbb200306c6d8b87d93376538782f", "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307",
"sha256:cd60f507c125ac0ad83f05803063bed27e50fa903b9c2cfee3f8a6867ca600fc", "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a",
"sha256:d513cc3db248e566e07a0da99c230aca3556d9b09ed02f420664e2da97eac301", "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435",
"sha256:d649dc0bcace6fcdb446ae02b98798a856593b19b637c1b9af8edadf2b150bea", "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0",
"sha256:d7008a6796095a79544f4da1ee49418901961c97ca9e9d44904205ff7d6aa8cb", "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5",
"sha256:da93027835164b8223e8e5af2cf902a4c80ed93cb0909417234f4a9df3bcd9af", "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441",
"sha256:e69215621707119c6baf99bda014a45b999d37602cb7043d943c76a59b05bf52", "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732",
"sha256:ea9525e0fef2de9208250d6c5aeeee0138921057cd67fcef90fbed49c4d62d37", "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de",
"sha256:fca1669d464f0c9831fd10be2eef6b86f5ebd76c724d1e0706ebdff86bb4adf0" "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.0.3" "version": "==5.0.4"
}, },
"django": { "django": {
"hashes": [ "hashes": [
"sha256:2f1ba1db8648484dd5c238fb62504777b7ad090c81c5f1fd8d5eb5ec21b5f283", "sha256:642d8eceab321ca743ae71e0f985ff8fdca59f07aab3a9fb362c617d23e33a76",
"sha256:c91c91a7ad6ef67a874a4f76f58ba534f9208412692a840e1d125eb5c279cb0a" "sha256:d4666c2edefa38c5ede0ec1655424c56dc47ceb04b6d8d62a7eac09db89545c1"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.0.3" "version": "==3.0.5"
}, },
"django-debug-toolbar": { "django-debug-toolbar": {
"hashes": [ "hashes": [
@ -966,19 +965,19 @@
"index": "pypi", "index": "pypi",
"version": "==2.2" "version": "==2.2"
}, },
"gitdb2": { "gitdb": {
"hashes": [ "hashes": [
"sha256:0375d983fd887d03c8942e81b1b0abc6c320cfb500cd3fe0d9c0eac87fbf2b52", "sha256:284a6a4554f954d6e737cddcff946404393e030b76a282c6640df8efd6b3da5e",
"sha256:b2b3a67090c17dc61f8407ca485e79ae811225ab5ebcd98ac5ee01448e8987b5" "sha256:598e0096bb3175a0aab3a0b5aedaa18a9a25c6707e0eca0695ba1a0baf1b2150"
], ],
"version": "==3.0.2" "version": "==4.0.2"
}, },
"gitpython": { "gitpython": {
"hashes": [ "hashes": [
"sha256:620b3c729bbc143b498cfea77e302999deedc55faec5b1067086c9ef90e101bc", "sha256:43da89427bdf18bf07f1164c6d415750693b4d50e28fc9b68de706245147b9dd",
"sha256:a43a5d88a5bbc3cf32bb5223e4b4e68fd716db5e9996cad6e561bbfee6e5f4af" "sha256:e426c3b587bd58c482f0b7fe6145ff4ac7ae6c82673fc656f489719abca6f4cb"
], ],
"version": "==3.0.8" "version": "==3.1.0"
}, },
"isort": { "isort": {
"hashes": [ "hashes": [
@ -1022,17 +1021,17 @@
}, },
"pathspec": { "pathspec": {
"hashes": [ "hashes": [
"sha256:163b0632d4e31cef212976cf57b43d9fd6b0bac6e67c26015d611a647d5e7424", "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0",
"sha256:562aa70af2e0d434367d9790ad37aed893de47f1693e4201fd1d3dca15d19b96" "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"
], ],
"version": "==0.7.0" "version": "==0.8.0"
}, },
"pbr": { "pbr": {
"hashes": [ "hashes": [
"sha256:139d2625547dbfa5fb0b81daebb39601c478c21956dc57e2e07b74450a8c506b", "sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c",
"sha256:61aa52a0f18b71c5cc58232d2cf8f8d09cd67fcad60b742a60124cb8d6951488" "sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"
], ],
"version": "==5.4.4" "version": "==5.4.5"
}, },
"pycodestyle": { "pycodestyle": {
"hashes": [ "hashes": [
@ -1051,11 +1050,11 @@
}, },
"pylint-django": { "pylint-django": {
"hashes": [ "hashes": [
"sha256:440beb814464928aedd2e21196bb6e47a83b63e2cbe886a701ba0f4a64206bbb", "sha256:3a4cc19dd6301fc2d36c9fb6e15163001a6d12723c1f7f8c2249223c2a8c68f0",
"sha256:d5d113605a64cf0e638b707d4cb42106e626f8851bc30a44d5b22bd698ad8483" "sha256:c9bbcff6b87ee8466fae274fd7aae3d2d3d4c4d1ea20c48cbce673e837e36048"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.0.13" "version": "==2.0.14"
}, },
"pylint-plugin-utils": { "pylint-plugin-utils": {
"hashes": [ "hashes": [
@ -1073,46 +1072,46 @@
}, },
"pyyaml": { "pyyaml": {
"hashes": [ "hashes": [
"sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6", "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
"sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf", "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
"sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5", "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
"sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e", "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
"sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811", "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
"sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e", "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
"sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d", "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
"sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20", "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
"sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689", "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
"sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994", "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
"sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615" "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
], ],
"index": "pypi", "index": "pypi",
"version": "==5.3" "version": "==5.3.1"
}, },
"regex": { "regex": {
"hashes": [ "hashes": [
"sha256:07b39bf943d3d2fe63d46281d8504f8df0ff3fe4c57e13d1656737950e53e525", "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b",
"sha256:0932941cdfb3afcbc26cc3bcf7c3f3d73d5a9b9c56955d432dbf8bbc147d4c5b", "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8",
"sha256:0e182d2f097ea8549a249040922fa2b92ae28be4be4895933e369a525ba36576", "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3",
"sha256:10671601ee06cf4dc1bc0b4805309040bb34c9af423c12c379c83d7895622bb5", "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e",
"sha256:23e2c2c0ff50f44877f64780b815b8fd2e003cda9ce817a7fd00dea5600c84a0", "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683",
"sha256:26ff99c980f53b3191d8931b199b29d6787c059f2e029b2b0c694343b1708c35", "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1",
"sha256:27429b8d74ba683484a06b260b7bb00f312e7c757792628ea251afdbf1434003", "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142",
"sha256:3e77409b678b21a056415da3a56abfd7c3ad03da71f3051bbcdb68cf44d3c34d", "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3",
"sha256:4e8f02d3d72ca94efc8396f8036c0d3bcc812aefc28ec70f35bb888c74a25161", "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468",
"sha256:4eae742636aec40cf7ab98171ab9400393360b97e8f9da67b1867a9ee0889b26", "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e",
"sha256:6a6ae17bf8f2d82d1e8858a47757ce389b880083c4ff2498dba17c56e6c103b9", "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3",
"sha256:6a6ba91b94427cd49cd27764679024b14a96874e0dc638ae6bdd4b1a3ce97be1", "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a",
"sha256:7bcd322935377abcc79bfe5b63c44abd0b29387f267791d566bbb566edfdd146", "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f",
"sha256:98b8ed7bb2155e2cbb8b76f627b2fd12cf4b22ab6e14873e8641f266e0fb6d8f", "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6",
"sha256:bd25bb7980917e4e70ccccd7e3b5740614f1c408a642c245019cff9d7d1b6149", "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156",
"sha256:d0f424328f9822b0323b3b6f2e4b9c90960b24743d220763c7f07071e0778351", "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b",
"sha256:d58e4606da2a41659c84baeb3cfa2e4c87a74cec89a1e7c56bee4b956f9d7461", "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db",
"sha256:e3cd21cc2840ca67de0bbe4071f79f031c81418deb544ceda93ad75ca1ee9f7b", "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd",
"sha256:e6c02171d62ed6972ca8631f6f34fa3281d51db8b326ee397b9c83093a6b7242", "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a",
"sha256:e7c7661f7276507bce416eaae22040fd91ca471b5b33c13f8ff21137ed6f248c", "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948",
"sha256:ecc6de77df3ef68fee966bb8cb4e067e84d4d1f397d0ef6fce46913663540d77" "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"
], ],
"version": "==2020.1.8" "version": "==2020.4.4"
}, },
"six": { "six": {
"hashes": [ "hashes": [
@ -1121,19 +1120,19 @@
], ],
"version": "==1.14.0" "version": "==1.14.0"
}, },
"smmap2": { "smmap": {
"hashes": [ "hashes": [
"sha256:0555a7bf4df71d1ef4218e4807bbf9b201f910174e6e08af2e138d4e517b4dde", "sha256:171484fe62793e3626c8b05dd752eb2ca01854b0c55a1efc0dc4210fccb65446",
"sha256:29a9ffa0497e7f2be94ca0ed1ca1aa3cd4cf25a1f6b4f5f87f74b46ed91d609a" "sha256:5fead614cf2de17ee0707a8c6a5f2aa5a2fc6c698c70993ba42f515485ffda78"
], ],
"version": "==2.0.5" "version": "==3.0.1"
}, },
"sqlparse": { "sqlparse": {
"hashes": [ "hashes": [
"sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177", "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e",
"sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873" "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548"
], ],
"version": "==0.3.0" "version": "==0.3.1"
}, },
"stevedore": { "stevedore": {
"hashes": [ "hashes": [
@ -1177,11 +1176,11 @@
}, },
"unittest-xml-reporting": { "unittest-xml-reporting": {
"hashes": [ "hashes": [
"sha256:6584562cde8226fc79fa29e38903c669a02799074a563bb0b70fcd3a8e87829c", "sha256:74eaf7739a7957a74f52b8187c5616f61157372189bef0a32ba5c30bbc00e58a",
"sha256:dd8046a64dc62f3d30301523a54992e0be75a945194491e0a3b718130cb429e0" "sha256:e09b8ae70cce9904cdd331f53bf929150962869a5324ab7ff3dd6c8b87e01f7d"
], ],
"index": "pypi", "index": "pypi",
"version": "==3.0.1" "version": "==3.0.2"
}, },
"wrapt": { "wrapt": {
"hashes": [ "hashes": [

View File

@ -1,6 +1,6 @@
apiVersion: v1 apiVersion: v1
appVersion: "0.8.12-beta" appVersion: "0.8.15-beta"
description: A Helm chart for passbook. description: A Helm chart for passbook.
name: passbook name: passbook
version: "0.8.12-beta" version: "0.8.15-beta"
icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png icon: https://git.beryju.org/uploads/-/system/project/avatar/108/logo.png

View File

@ -2,7 +2,7 @@
# This is a YAML-formatted file. # This is a YAML-formatted file.
# Declare variables to be passed into your templates. # Declare variables to be passed into your templates.
image: image:
tag: 0.8.12-beta tag: 0.8.15-beta
nameOverride: "" nameOverride: ""

View File

@ -1,2 +1,2 @@
"""passbook""" """passbook"""
__version__ = "0.8.12-beta" __version__ = "0.8.15-beta"

View File

@ -64,6 +64,12 @@
{% trans 'Policies' %} {% trans 'Policies' %}
</a> </a>
</li> </li>
<li class="pf-c-nav__item">
<a href="{% url 'passbook_admin:certificate_key_pair' %}"
class="pf-c-nav__link {% is_active 'passbook_admin:certificate_key_pair' 'passbook_admin:certificatekeypair-create' 'passbook_admin:certificatekeypair-update' 'passbook_admin:certificatekeypair-delete' %}">
{% trans 'Certificates' %}
</a>
</li>
<li class="pf-c-nav__item"> <li class="pf-c-nav__item">
<a href="{% url 'passbook_admin:invitations' %}" <a href="{% url 'passbook_admin:invitations' %}"
class="pf-c-nav__link {% is_active 'passbook_admin:invitations' 'passbook_admin:invitation-create' 'passbook_admin:invitation-update' 'passbook_admin:invitation-delete' 'passbook_admin:invitation-test' %}"> class="pf-c-nav__link {% is_active 'passbook_admin:invitations' 'passbook_admin:invitation-create' 'passbook_admin:invitation-update' 'passbook_admin:invitation-delete' 'passbook_admin:invitation-test' %}">

View File

@ -0,0 +1,69 @@
{% extends "administration/base.html" %}
{% load i18n %}
{% load utils %}
{% block content %}
<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content">
<h1>
<i class="pf-icon pf-icon-key"></i>
{% trans 'Certificate-Key Pairs' %}
</h1>
<p>{% trans "Import certificates of external providers or create certificates to sign requests with." %}</p>
</div>
</section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">
<div class="pf-c-toolbar" id="page-layout-table-simple-toolbar-top">
<div class="pf-c-toolbar__action-group">
<a href="{% url 'passbook_admin:certificatekeypair-create' %}?back={{ request.get_full_path }}" class="pf-c-button pf-m-primary" type="button">{% trans 'Create' %}</a>
</div>
{% include 'partials/pagination.html' %}
</div>
<table class="pf-c-table pf-m-compact pf-m-grid-xl" role="grid">
<thead>
<tr role="row">
<th role="columnheader" scope="col">{% trans 'Name' %}</th>
<th role="columnheader" scope="col">{% trans 'Private Key available' %}</th>
<th role="columnheader" scope="col">{% trans 'Fingerprint' %}</th>
<th role="columnheader" scope="col">{% trans 'Provider Type' %}</th>
<th role="cell"></th>
</tr>
</thead>
<tbody role="rowgroup">
{% for kp in object_list %}
<tr role="row">
<th role="columnheader">
<div>
<div>{{ kp.name }}</div>
</div>
</th>
<td role="cell">
<span>
{% if kp.key_data is not None %}
{% trans 'Yes' %}
{% else %}
{% trans 'No' %}
{% endif %}
</span>
</td>
<td role="cell">
<span>
{{ kp.fingerprint }}
</span>
</td>
<td>
<a class="pf-c-button pf-m-secondary" href="{% url 'passbook_admin:certificatekeypair-update' pk=kp.pk %}?back={{ request.get_full_path }}">{% trans 'Edit' %}</a>
<a class="pf-c-button pf-m-danger" href="{% url 'passbook_admin:certificatekeypair-delete' pk=kp.pk %}?back={{ request.get_full_path }}">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pf-c-toolbar" id="page-layout-table-simple-toolbar-bottom">
{% include 'partials/pagination.html' %}
</div>
</div>
</section>
{% endblock %}

View File

@ -4,6 +4,7 @@ from django.urls import path
from passbook.admin.views import ( from passbook.admin.views import (
applications, applications,
audit, audit,
certificate_key_pair,
debug, debug,
factors, factors,
groups, groups,
@ -148,6 +149,27 @@ urlpatterns = [
path( path(
"group/<uuid:pk>/delete/", groups.GroupDeleteView.as_view(), name="group-delete" "group/<uuid:pk>/delete/", groups.GroupDeleteView.as_view(), name="group-delete"
), ),
# Certificate-Key Pairs
path(
"crypto/certificates/",
certificate_key_pair.CertificateKeyPairListView.as_view(),
name="certificate_key_pair",
),
path(
"crypto/certificates/create/",
certificate_key_pair.CertificateKeyPairCreateView.as_view(),
name="certificatekeypair-create",
),
path(
"crypto/certificates/<uuid:pk>/update/",
certificate_key_pair.CertificateKeyPairUpdateView.as_view(),
name="certificatekeypair-update",
),
path(
"crypto/certificates/<uuid:pk>/delete/",
certificate_key_pair.CertificateKeyPairDeleteView.as_view(),
name="certificatekeypair-delete",
),
# Audit Log # Audit Log
path("audit/", audit.EventListView.as_view(), name="audit-log"), path("audit/", audit.EventListView.as_view(), name="audit-log"),
# Groups # Groups

View File

@ -0,0 +1,77 @@
"""passbook CertificateKeyPair administration"""
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.mixins import (
PermissionRequiredMixin as DjangoPermissionRequiredMixin,
)
from django.contrib.messages.views import SuccessMessageMixin
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic import DeleteView, ListView, UpdateView
from guardian.mixins import PermissionListMixin, PermissionRequiredMixin
from passbook.crypto.forms import CertificateKeyPairForm
from passbook.crypto.models import CertificateKeyPair
from passbook.lib.views import CreateAssignPermView
class CertificateKeyPairListView(LoginRequiredMixin, PermissionListMixin, ListView):
"""Show list of all keypairs"""
model = CertificateKeyPair
permission_required = "passbook_crypto.view_certificatekeypair"
ordering = "name"
paginate_by = 40
template_name = "administration/certificatekeypair/list.html"
class CertificateKeyPairCreateView(
SuccessMessageMixin,
LoginRequiredMixin,
DjangoPermissionRequiredMixin,
CreateAssignPermView,
):
"""Create new CertificateKeyPair"""
model = CertificateKeyPair
form_class = CertificateKeyPairForm
permission_required = "passbook_crypto.add_certificatekeypair"
template_name = "generic/create.html"
success_url = reverse_lazy("passbook_admin:certificate_key_pair")
success_message = _("Successfully created CertificateKeyPair")
def get_context_data(self, **kwargs):
kwargs["type"] = "Certificate-Key Pair"
return super().get_context_data(**kwargs)
class CertificateKeyPairUpdateView(
SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView
):
"""Update certificatekeypair"""
model = CertificateKeyPair
form_class = CertificateKeyPairForm
permission_required = "passbook_crypto.change_certificatekeypair"
template_name = "generic/update.html"
success_url = reverse_lazy("passbook_admin:certificate_key_pair")
success_message = _("Successfully updated Certificate-Key Pair")
class CertificateKeyPairDeleteView(
SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView
):
"""Delete certificatekeypair"""
model = CertificateKeyPair
permission_required = "passbook_crypto.delete_certificatekeypair"
template_name = "generic/delete.html"
success_url = reverse_lazy("passbook_admin:certificate_key_pair")
success_message = _("Successfully deleted Certificate-Key Pair")
def delete(self, request, *args, **kwargs):
messages.success(self.request, self.success_message)
return super().delete(request, *args, **kwargs)

View File

@ -8,7 +8,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>{% block title %}{% trans title %}{% endblock %}</title> <title>{% block title %}{% trans title|default:"passbook" %}{% endblock %}</title>
<link rel="icon" type="image/png" href="{% static 'passbook/logo.png' %}"> <link rel="icon" type="image/png" href="{% static 'passbook/logo.png' %}">
<link rel="shortcut icon" type="image/png" href="{% static 'passbook/logo.png' %}"> <link rel="shortcut icon" type="image/png" href="{% static 'passbook/logo.png' %}">
<link rel="stylesheet" type="text/css" href="{% static 'node_modules/@patternfly/patternfly/patternfly.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'node_modules/@patternfly/patternfly/patternfly.css' %}">

View File

@ -7,7 +7,6 @@
{% load utils %} {% load utils %}
{% block page_content %} {% block page_content %}
{% include 'partials/messages.html' %}
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content"> <main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
{% block content %} {% block content %}
{% endblock %} {% endblock %}

View File

@ -1,67 +1,69 @@
{% extends "overview/base.html" %} {% extends "base/page.html" %}
{% load i18n %} {% load i18n %}
{% load is_active %} {% load is_active %}
{% load static %} {% load static %}
{% load passbook_user_settings %} {% load passbook_user_settings %}
{% block content %} {% block page_content %}
<section class="pf-c-page__main-section"> <div class="pf-c-page__sidebar">
<div class="pf-l-split pf-m-gutter"> <div class="pf-c-page__sidebar-body">
<div class="pf-l-split__item"> <nav class="pf-c-nav" id="page-default-nav-example-primary-nav" aria-label="Global">
<div class="pf-c-card"> <section class="pf-c-nav__section">
<div class="pf-c-card__body"> <h2 class="pf-c-nav__section-title">{% trans 'General Settings' %}</h2>
<nav class="pf-c-nav" aria-label="Global"> <ul class="pf-c-nav__list">
<section class="pf-c-nav__section"> <li class="pf-c-nav__item">
<h2 class="pf-c-nav__section-title">{% trans 'General Settings' %}</h2> <a href="{% url 'passbook_core:user-settings' %}"
<ul class="pf-c-nav__list"> class="pf-c-nav__link {% is_active 'passbook_core:user-settings' %}">{% trans 'User Details' %}</a>
<li class="pf-c-nav__item"> </li>
<a href="{% url 'passbook_core:user-settings' %}" class="pf-c-nav__link {% is_active 'passbook_core:user-settings' %}">{% trans 'User Details' %}</a> </ul>
</li> </section>
</ul> {% user_factors as user_factors_loc %}
</section> {% if user_factors_loc %}
{% user_factors as user_factors_loc %} <section class="pf-c-nav__section">
{% if user_factors_loc %} <h2 class="pf-c-nav__section-title">{% trans 'Factors' %}</h2>
<section class="pf-c-nav__section"> <ul class="pf-c-nav__list">
<h2 class="pf-c-nav__section-title">{% trans 'Factors' %}</h2> {% for factor in user_factors_loc %}
<ul class="pf-c-nav__list"> <li class="pf-c-nav__item">
{% for factor in user_factors_loc %} <a href="{% url factor.view_name %}" class="pf-c-nav__link {% is_active factor.view_name %}">
<li class="pf-c-nav__item"> <i class="{{ factor.icon }}"></i>
<a href="{% url factor.view_name %}" class="pf-c-nav__link {% is_active factor.view_name %}"> {{ factor.name }}
<i class="{{ factor.icon }}"></i> </a>
{{ factor.name }} </li>
</a> {% endfor %}
</li> </ul>
{% endfor %} </section>
</ul> {% endif %}
</section> {% user_sources as user_sources_loc %}
{% endif %} {% if user_sources_loc %}
{% user_sources as user_sources_loc %} <section class="pf-c-nav__section">
{% if user_sources_loc %} <h2 class="pf-c-nav__section-title">{% trans 'Sources' %}</h2>
<section class="pf-c-nav__section"> <ul class="pf-c-nav__list">
<h2 class="pf-c-nav__section-title">{% trans 'Sources' %}</h2> {% for source in user_sources_loc %}
<ul class="pf-c-nav__list"> <li class="pf-c-nav__item">
{% for source in user_sources_loc %} <a href="{{ source.view_name }}"
<li class="pf-c-nav__item"> class="pf-c-nav__link {% if user_settings.view_name == request.get_full_path %} pf-m-current {% endif %}">
<a href="{{ source.view_name }}" class="pf-c-nav__link {% if user_settings.view_name == request.get_full_path %} pf-m-current {% endif %}"> <i class="{{ source.icon }}"></i>
<i class="{{ source.icon }}"></i> {{ source.name }}
{{ source.name }} </a>
</a> </li>
</li> {% endfor %}
{% endfor %} </ul>
</ul> </section>
</section> {% endif %}
{% endif %} </nav>
</nav> </div>
</div>
<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
<section class="pf-c-page__main-section">
<div class="pf-l-split pf-m-gutter">
<div class="pf-l-split__item">
<div class="pf-c-card">
{% block page %}
{% endblock %}
</div> </div>
</div> </div>
</div> </div>
<div class="pf-l-split__item"> </section>
<div class="pf-c-card"> </main>
{% block page %}
{% endblock %}
</div>
</div>
</div>
</section>
{% endblock %} {% endblock %}

View File

5
passbook/crypto/admin.py Normal file
View File

@ -0,0 +1,5 @@
"""passbook crypto model admin"""
from passbook.lib.admin import admin_autoregister
admin_autoregister("passbook_crypto")

10
passbook/crypto/apps.py Normal file
View File

@ -0,0 +1,10 @@
"""passbook crypto app config"""
from django.apps import AppConfig
class PassbookCryptoConfig(AppConfig):
"""passbook crypto app config"""
name = "passbook.crypto"
label = "passbook_crypto"
verbose_name = "passbook Crypto"

View File

@ -36,8 +36,7 @@ class CertificateBuilder:
x509.Name( x509.Name(
[ [
x509.NameAttribute( x509.NameAttribute(
NameOID.COMMON_NAME, NameOID.COMMON_NAME, u"passbook Self-signed Certificate",
u"passbook Self-signed SAML Certificate",
), ),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"passbook"), x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"passbook"),
x509.NameAttribute( x509.NameAttribute(
@ -50,8 +49,7 @@ class CertificateBuilder:
x509.Name( x509.Name(
[ [
x509.NameAttribute( x509.NameAttribute(
NameOID.COMMON_NAME, NameOID.COMMON_NAME, u"passbook Self-signed Certificate",
u"passbook Self-signed SAML Certificate",
), ),
] ]
) )

27
passbook/crypto/forms.py Normal file
View File

@ -0,0 +1,27 @@
"""passbook Crypto forms"""
from django import forms
from django.utils.translation import gettext_lazy as _
from passbook.crypto.models import CertificateKeyPair
class CertificateKeyPairForm(forms.ModelForm):
"""CertificateKeyPair Form"""
class Meta:
model = CertificateKeyPair
fields = [
"name",
"certificate_data",
"key_data",
]
widgets = {
"name": forms.TextInput(),
"certificate_data": forms.Textarea(attrs={"class": "monospaced"}),
"key_data": forms.Textarea(attrs={"class": "monospaced"}),
}
labels = {
"certificate_data": _("Certificate"),
"key_data": _("Private Key"),
}

View File

@ -0,0 +1,67 @@
# Generated by Django 3.0.3 on 2020-03-03 21:45
import uuid
from django.db import migrations, models
def create_self_signed(apps, schema_editor):
CertificateKeyPair = apps.get_model("passbook_crypto", "CertificateKeyPair")
db_alias = schema_editor.connection.alias
from passbook.crypto.builder import CertificateBuilder
builder = CertificateBuilder()
builder.build()
CertificateKeyPair.objects.using(db_alias).create(
name="passbook Self-signed Certificate",
certificate_data=builder.certificate,
key_data=builder.private_key,
)
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="CertificateKeyPair",
fields=[
("created", models.DateTimeField(auto_now_add=True)),
("last_updated", models.DateTimeField(auto_now=True)),
(
"uuid",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("name", models.TextField()),
("certificate_data", models.TextField()),
("key_data", models.TextField(blank=True, default="")),
],
options={
"verbose_name": "Certificate-Key Pair",
"verbose_name_plural": "Certificate-Key Pairs",
},
),
migrations.RunPython(create_self_signed),
migrations.AlterField(
model_name="certificatekeypair",
name="certificate_data",
field=models.TextField(help_text="PEM-encoded Certificate data"),
),
migrations.AlterField(
model_name="certificatekeypair",
name="key_data",
field=models.TextField(
blank=True,
default="",
help_text="Optional Private Key. If this is set, you can use this keypair for encryption.",
),
),
]

View File

64
passbook/crypto/models.py Normal file
View File

@ -0,0 +1,64 @@
"""passbook crypto models"""
from binascii import hexlify
from typing import Optional
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.x509 import Certificate, load_pem_x509_certificate
from django.db import models
from django.utils.translation import gettext_lazy as _
from passbook.lib.models import CreatedUpdatedModel, UUIDModel
class CertificateKeyPair(UUIDModel, CreatedUpdatedModel):
"""CertificateKeyPair that can be used for signing or encrypting if `key_data`
is set, otherwise it can be used to verify remote data."""
name = models.TextField()
certificate_data = models.TextField(help_text=_("PEM-encoded Certificate data"))
key_data = models.TextField(
help_text=_(
"Optional Private Key. If this is set, you can use this keypair for encryption."
),
blank=True,
default="",
)
_cert: Optional[Certificate] = None
_key: Optional[RSAPrivateKey] = None
@property
def certificate(self) -> Certificate:
"""Get python cryptography Certificate instance"""
if not self._cert:
self._cert = load_pem_x509_certificate(
self.certificate_data.encode("utf-8"), default_backend()
)
return self._cert
@property
def private_key(self) -> Optional[RSAPrivateKey]:
"""Get python cryptography PrivateKey instance"""
if not self._key:
self._key = load_pem_private_key(
str.encode("\n".join([x.strip() for x in self.key_data.split("\n")])),
password=None,
backend=default_backend(),
)
return self._key
@property
def fingerprint(self) -> str:
"""Get SHA256 Fingerprint of certificate_data"""
return hexlify(self.certificate.fingerprint(hashes.SHA256())).decode("utf-8")
def __str__(self) -> str:
return f"Certificate-Key Pair {self.name} {self.fingerprint}"
class Meta:
verbose_name = _("Certificate-Key Pair")
verbose_name_plural = _("Certificate-Key Pairs")

View File

@ -1,10 +1,10 @@
"""passbook management command to bootstrap""" """passbook management command to bootstrap"""
from argparse import REMAINDER from argparse import REMAINDER
from subprocess import Popen # nosec from subprocess import Popen # nosec
from sys import exit as _exit
# pylint: disable=redefined-builtin from sys import stderr, stdin, stdout
from sys import exit, stderr, stdin, stdout
from time import sleep from time import sleep
from typing import List
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db import connection from django.db import connection
@ -54,13 +54,12 @@ class Command(BaseCommand):
should_check = not (self.check_database() and self.check_cache()) should_check = not (self.check_database() and self.check_cache())
sleep(1) sleep(1)
LOGGER.info("Dependencies are up, starting command...") LOGGER.info("Dependencies are up, starting command...")
proc = Popen( commands: List[str] = options.get("command", ["exit", "1"])
args=options.get("command"), stdout=stdout, stderr=stderr, stdin=stdin proc = Popen(args=commands, stdout=stdout, stderr=stderr, stdin=stdin) # nosec
) # nosec
try: try:
proc.wait() proc.wait()
exit(proc.returncode) _exit(proc.returncode)
except KeyboardInterrupt: except KeyboardInterrupt:
LOGGER.info("Killing process") LOGGER.info("Killing process")
proc.kill() proc.kill()
exit(254) _exit(254)

View File

@ -1,4 +1,6 @@
"""passbook auth oidc provider app config""" """passbook auth oidc provider app config"""
from importlib import import_module
from django.apps import AppConfig from django.apps import AppConfig
from django.db.utils import InternalError, OperationalError, ProgrammingError from django.db.utils import InternalError, OperationalError, ProgrammingError
from django.urls import include, path from django.urls import include, path
@ -34,3 +36,5 @@ class PassbookProviderOIDCConfig(AppConfig):
include("oidc_provider.urls", namespace="oidc_provider"), include("oidc_provider.urls", namespace="oidc_provider"),
), ),
) )
import_module("passbook.providers.oidc.signals")

View File

@ -0,0 +1,14 @@
"""passbook oidc claim helpers"""
from typing import Any, Dict
from passbook.core.models import User
def userinfo(claims: Dict[str, Any], user: User) -> Dict[str, Any]:
"""Populate claims from userdata"""
claims["name"] = user.name
claims["given_name"] = user.name
claims["family_name"] = user.name
claims["email"] = user.email
return claims

View File

@ -4,5 +4,6 @@ INSTALLED_APPS = [
"oidc_provider", "oidc_provider",
] ]
OIDC_AFTER_USERLOGIN_HOOK = "passbook.providers.oidc.lib.check_permissions" OIDC_AFTER_USERLOGIN_HOOK = "passbook.providers.oidc.auth.check_permissions"
OIDC_IDTOKEN_INCLUDE_CLAIMS = True OIDC_IDTOKEN_INCLUDE_CLAIMS = True
OIDC_USERINFO = "passbook.providers.oidc.claims.userinfo"

View File

@ -0,0 +1,16 @@
"""OIDC Provider signals"""
from django.db.models.signals import post_save
from django.dispatch import receiver
from passbook.core.models import Application
from passbook.providers.oidc.models import OpenIDProvider
@receiver(post_save, sender=Application)
# pylint: disable=unused-argument
def on_application_save(sender, instance: Application, **_):
"""Synchronize application's skip_authorization with oidc_client's require_consent"""
if isinstance(instance.provider, OpenIDProvider):
instance.provider.oidc_client.require_consent = not instance.skip_authorization
instance.provider.oidc_client.save()
print("updating skip_authz")

View File

@ -24,9 +24,7 @@ class SAMLProviderSerializer(ModelSerializer):
"property_mappings", "property_mappings",
"digest_algorithm", "digest_algorithm",
"signature_algorithm", "signature_algorithm",
"signing", "signing_kp",
"signing_cert",
"signing_key",
] ]

View File

@ -9,7 +9,6 @@ from passbook.providers.saml.models import (
SAMLProvider, SAMLProvider,
get_provider_choices, get_provider_choices,
) )
from passbook.providers.saml.utils.cert import CertificateBuilder
class SAMLProviderForm(forms.ModelForm): class SAMLProviderForm(forms.ModelForm):
@ -19,13 +18,6 @@ class SAMLProviderForm(forms.ModelForm):
choices=get_provider_choices(), label="Processor" choices=get_provider_choices(), label="Processor"
) )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
builder = CertificateBuilder()
builder.build()
self.fields["signing_cert"].initial = builder.certificate
self.fields["signing_key"].initial = builder.private_key
class Meta: class Meta:
model = SAMLProvider model = SAMLProvider
@ -41,9 +33,7 @@ class SAMLProviderForm(forms.ModelForm):
"property_mappings", "property_mappings",
"digest_algorithm", "digest_algorithm",
"signature_algorithm", "signature_algorithm",
"signing", "signing_kp",
"signing_cert",
"signing_key",
] ]
widgets = { widgets = {
"name": forms.TextInput(), "name": forms.TextInput(),

View File

@ -0,0 +1,29 @@
# Generated by Django 3.0.3 on 2020-03-03 21:57
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_crypto", "0001_initial"),
("passbook_providers_saml", "0006_auto_20200217_2031"),
]
operations = [
migrations.RemoveField(model_name="samlprovider", name="signing",),
migrations.RemoveField(model_name="samlprovider", name="signing_cert",),
migrations.RemoveField(model_name="samlprovider", name="signing_key",),
migrations.AddField(
model_name="samlprovider",
name="singing_kp",
field=models.ForeignKey(
default=None,
help_text="Singing is enabled upon selection of a Key Pair.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="passbook_crypto.CertificateKeyPair",
),
),
]

View File

@ -0,0 +1,16 @@
# Generated by Django 3.0.3 on 2020-03-05 16:06
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("passbook_providers_saml", "0007_auto_20200303_2157"),
]
operations = [
migrations.RenameField(
model_name="samlprovider", old_name="singing_kp", new_name="signing_kp",
),
]

View File

@ -8,6 +8,7 @@ from django.utils.translation import ugettext_lazy as _
from structlog import get_logger from structlog import get_logger
from passbook.core.models import PropertyMapping, Provider from passbook.core.models import PropertyMapping, Provider
from passbook.crypto.models import CertificateKeyPair
from passbook.lib.utils.reflection import class_to_path, path_to_class from passbook.lib.utils.reflection import class_to_path, path_to_class
from passbook.lib.utils.template import render_to_string from passbook.lib.utils.template import render_to_string
from passbook.providers.saml.processors.base import Processor from passbook.providers.saml.processors.base import Processor
@ -74,9 +75,13 @@ class SAMLProvider(Provider):
default="rsa-sha256", default="rsa-sha256",
) )
signing = models.BooleanField(default=True) signing_kp = models.ForeignKey(
signing_cert = models.TextField(verbose_name=_("Singing Certificate")) CertificateKeyPair,
signing_key = models.TextField() default=None,
null=True,
help_text=_("Singing is enabled upon selection of a Key Pair."),
on_delete=models.SET_NULL,
)
form = "passbook.providers.saml.forms.SAMLProviderForm" form = "passbook.providers.saml.forms.SAMLProviderForm"
_processor = None _processor = None

View File

@ -1,6 +1,7 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="{{ entity_id }}"> <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="{{ entity_id }}">
<md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
{% if cert_public_key %}
<md:KeyDescriptor use="signing"> <md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data> <ds:X509Data>
@ -8,13 +9,7 @@
</ds:X509Data> </ds:X509Data>
</ds:KeyInfo> </ds:KeyInfo>
</md:KeyDescriptor> </md:KeyDescriptor>
<md:KeyDescriptor use="encryption"> {% endif %}
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>{{ cert_public_key }}</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:NameIDFormat>{{ subject_format }}</md:NameIDFormat> <md:NameIDFormat>{{ subject_format }}</md:NameIDFormat>
<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="{{ slo_url }}"/> <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="{{ slo_url }}"/>
<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="{{ sso_post_url }}"/> <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="{{ sso_post_url }}"/>

View File

@ -82,7 +82,7 @@ def get_response_xml(parameters, saml_provider: SAMLProvider, assertion_id=""):
raw_response = render_to_string("saml/xml/response.xml", params) raw_response = render_to_string("saml/xml/response.xml", params)
if not saml_provider.signing: if not saml_provider.signing_kp:
return raw_response return raw_response
signature_xml = get_signature_xml() signature_xml = get_signature_xml()

View File

@ -1,8 +1,6 @@
"""Signing code goes here.""" """Signing code goes here."""
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from lxml import etree # nosec from lxml import etree # nosec
from signxml import XMLSigner, XMLVerifier from signxml import XMLSigner, XMLVerifier
from structlog import get_logger from structlog import get_logger
@ -17,11 +15,6 @@ LOGGER = get_logger()
def sign_with_signxml(data: str, provider: "SAMLProvider", reference_uri=None) -> str: def sign_with_signxml(data: str, provider: "SAMLProvider", reference_uri=None) -> str:
"""Sign Data with signxml""" """Sign Data with signxml"""
key = serialization.load_pem_private_key(
str.encode("\n".join([x.strip() for x in provider.signing_key.split("\n")])),
password=None,
backend=default_backend(),
)
# defused XML is not used here because it messes up XML namespaces # defused XML is not used here because it messes up XML namespaces
# Data is trusted, so lxml is ok # Data is trusted, so lxml is ok
root = etree.fromstring(data) # nosec root = etree.fromstring(data) # nosec
@ -31,9 +24,12 @@ def sign_with_signxml(data: str, provider: "SAMLProvider", reference_uri=None) -
digest_algorithm=provider.digest_algorithm, digest_algorithm=provider.digest_algorithm,
) )
signed = signer.sign( signed = signer.sign(
root, key=key, cert=[provider.signing_cert], reference_uri=reference_uri root,
key=provider.signing_kp.private_key,
cert=[provider.signing_kp.certificate_data],
reference_uri=reference_uri,
) )
XMLVerifier().verify(signed, x509_cert=provider.signing_cert) XMLVerifier().verify(signed, x509_cert=provider.signing_kp.certificate_data)
return etree.tostring(signed).decode("utf-8") # nosec return etree.tostring(signed).decode("utf-8") # nosec

View File

@ -274,19 +274,19 @@ class DescriptorDownloadView(AccessRequiredView):
kwargs={"application": provider.application.slug}, kwargs={"application": provider.application.slug},
) )
) )
pubkey = strip_pem_header(provider.signing_cert.replace("\r", "")).replace(
"\n", ""
)
subject_format = provider.processor.subject_format subject_format = provider.processor.subject_format
ctx = { ctx = {
"entity_id": entity_id, "entity_id": entity_id,
"cert_public_key": pubkey,
"slo_url": slo_url, "slo_url": slo_url,
# Currently, the same endpoint accepts POST and REDIRECT # Currently, the same endpoint accepts POST and REDIRECT
"sso_post_url": sso_post_url, "sso_post_url": sso_post_url,
"sso_redirect_url": sso_post_url, "sso_redirect_url": sso_post_url,
"subject_format": subject_format, "subject_format": subject_format,
} }
if provider.signing_kp:
ctx["cert_public_key"] = strip_pem_header(
provider.signing_kp.certificate_data.replace("\r", "")
).replace("\n", "")
return render_to_string("saml/xml/metadata.xml", ctx) return render_to_string("saml/xml/metadata.xml", ctx)
# pylint: disable=unused-argument # pylint: disable=unused-argument

View File

@ -85,6 +85,7 @@ INSTALLED_APPS = [
"passbook.api.apps.PassbookAPIConfig", "passbook.api.apps.PassbookAPIConfig",
"passbook.lib.apps.PassbookLibConfig", "passbook.lib.apps.PassbookLibConfig",
"passbook.audit.apps.PassbookAuditConfig", "passbook.audit.apps.PassbookAuditConfig",
"passbook.crypto.apps.PassbookCryptoConfig",
"passbook.recovery.apps.PassbookRecoveryConfig", "passbook.recovery.apps.PassbookRecoveryConfig",
"passbook.sources.saml.apps.PassbookSourceSAMLConfig", "passbook.sources.saml.apps.PassbookSourceSAMLConfig",
"passbook.sources.ldap.apps.PassbookSourceLDAPConfig", "passbook.sources.ldap.apps.PassbookSourceLDAPConfig",

View File

@ -17,7 +17,7 @@ class SAMLSourceSerializer(ModelSerializer):
"idp_url", "idp_url",
"idp_logout_url", "idp_logout_url",
"auto_logout", "auto_logout",
"signing_cert", "signing_kp",
] ]

View File

@ -5,19 +5,12 @@ from django.contrib.admin.widgets import FilteredSelectMultiple
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from passbook.admin.forms.source import SOURCE_FORM_FIELDS from passbook.admin.forms.source import SOURCE_FORM_FIELDS
from passbook.providers.saml.utils.cert import CertificateBuilder
from passbook.sources.saml.models import SAMLSource from passbook.sources.saml.models import SAMLSource
class SAMLSourceForm(forms.ModelForm): class SAMLSourceForm(forms.ModelForm):
"""SAML Provider form""" """SAML Provider form"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
builder = CertificateBuilder()
builder.build()
self.fields["signing_cert"].initial = builder.certificate
class Meta: class Meta:
model = SAMLSource model = SAMLSource
@ -26,7 +19,7 @@ class SAMLSourceForm(forms.ModelForm):
"idp_url", "idp_url",
"idp_logout_url", "idp_logout_url",
"auto_logout", "auto_logout",
"signing_cert", "signing_kp",
] ]
widgets = { widgets = {
"name": forms.TextInput(), "name": forms.TextInput(),

View File

@ -0,0 +1,27 @@
# Generated by Django 3.0.3 on 2020-03-03 22:01
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("passbook_crypto", "0001_initial"),
("passbook_sources_saml", "0005_auto_20200220_1621"),
]
operations = [
migrations.RemoveField(model_name="samlsource", name="signing_cert",),
migrations.AddField(
model_name="samlsource",
name="signing_kp",
field=models.ForeignKey(
default=None,
help_text="Certificate Key Pair of the IdP which Assertions are validated against.",
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="passbook_crypto.CertificateKeyPair",
),
),
]

View File

@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
from passbook.core.models import Source from passbook.core.models import Source
from passbook.core.types import UILoginButton from passbook.core.types import UILoginButton
from passbook.crypto.models import CertificateKeyPair
class SAMLSource(Source): class SAMLSource(Source):
@ -22,7 +23,16 @@ class SAMLSource(Source):
default=None, blank=True, null=True, verbose_name=_("IDP Logout URL") default=None, blank=True, null=True, verbose_name=_("IDP Logout URL")
) )
auto_logout = models.BooleanField(default=False) auto_logout = models.BooleanField(default=False)
signing_cert = models.TextField()
signing_kp = models.ForeignKey(
CertificateKeyPair,
default=None,
null=True,
help_text=_(
"Certificate Key Pair of the IdP which Assertions are validated against."
),
on_delete=models.SET_NULL,
)
form = "passbook.sources.saml.forms.SAMLSourceForm" form = "passbook.sources.saml.forms.SAMLSourceForm"

View File

@ -46,7 +46,7 @@ class Processor:
def _verify_signed(self): def _verify_signed(self):
"""Verify SAML Response's Signature""" """Verify SAML Response's Signature"""
verifier = XMLVerifier() verifier = XMLVerifier()
verifier.verify(self._root_xml, x509_cert=self._source.signing_cert) verifier.verify(self._root_xml, x509_cert=self._source.signing_kp.certificate)
def _get_email(self) -> Optional[str]: def _get_email(self) -> Optional[str]:
""" """

View File

@ -101,9 +101,9 @@ class MetadataView(View):
"""Replies with the XML Metadata SPSSODescriptor.""" """Replies with the XML Metadata SPSSODescriptor."""
source: SAMLSource = get_object_or_404(SAMLSource, slug=source_slug) source: SAMLSource = get_object_or_404(SAMLSource, slug=source_slug)
issuer = get_issuer(request, source) issuer = get_issuer(request, source)
cert_stripped = strip_pem_header(source.signing_cert.replace("\r", "")).replace( cert_stripped = strip_pem_header(
"\n", "" source.signing_kp.certificate_data.replace("\r", "")
) ).replace("\n", "")
return render_xml( return render_xml(
request, request,
"saml/sp/xml/sp_sso_descriptor.xml", "saml/sp/xml/sp_sso_descriptor.xml",

View File

@ -46,8 +46,3 @@ FROM nginx
COPY --from=static-build /app/static /usr/share/nginx/html/static COPY --from=static-build /app/static /usr/share/nginx/html/static
COPY --from=static-build /app/static/robots.txt /usr/share/nginx/html/robots.txt COPY --from=static-build /app/static/robots.txt /usr/share/nginx/html/robots.txt
COPY --from=npm-packager /static/node_modules /usr/share/nginx/html/static/node_modules COPY --from=npm-packager /static/node_modules /usr/share/nginx/html/static/node_modules
# FROM beryju/pixie:latest
# COPY --from=static-build /app/static /web-root/static/
# COPY --from=static-build /app/static/robots.txt /web-root/robots.txt