Merge branch 'master' into inbuilt-proxy
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> # Conflicts: # Dockerfile # internal/outpost/ak/api.go # internal/outpost/ak/api_uag.go # internal/outpost/ak/global.go # internal/outpost/ldap/api_tls.go # internal/outpost/ldap/instance_bind.go # internal/outpost/ldap/utils.go # internal/outpost/proxy/api_bundle.go # outpost/go.mod # outpost/go.sum # outpost/pkg/ak/cert.go
This commit is contained in:
commit
b3159a74e5
|
@ -3,3 +3,6 @@ static
|
||||||
htmlcov
|
htmlcov
|
||||||
*.env.yml
|
*.env.yml
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
dist/**
|
||||||
|
build/**
|
||||||
|
build_docs/**
|
||||||
|
|
26
Dockerfile
26
Dockerfile
|
@ -10,8 +10,16 @@ RUN pip install pipenv && \
|
||||||
pipenv lock -r > requirements.txt && \
|
pipenv lock -r > requirements.txt && \
|
||||||
pipenv lock -r --dev-only > requirements-dev.txt
|
pipenv lock -r --dev-only > requirements-dev.txt
|
||||||
|
|
||||||
# Stage 2: Build web API
|
# Stage 2: Build website
|
||||||
FROM openapitools/openapi-generator-cli as web-api-builder
|
FROM node as website-builder
|
||||||
|
|
||||||
|
COPY ./website /static/
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
RUN cd /static && npm i && npm run build-docs-only
|
||||||
|
|
||||||
|
# Stage 3: Build web API
|
||||||
|
FROM openapitools/openapi-generator-cli as api-builder
|
||||||
|
|
||||||
COPY ./schema.yml /local/schema.yml
|
COPY ./schema.yml /local/schema.yml
|
||||||
|
|
||||||
|
@ -37,7 +45,7 @@ RUN docker-entrypoint.sh generate \
|
||||||
rm -f /local/api/go.mod /local/api/go.sum
|
rm -f /local/api/go.mod /local/api/go.sum
|
||||||
|
|
||||||
# Stage 4: Build webui
|
# Stage 4: Build webui
|
||||||
FROM node as npm-builder
|
FROM node as web-builder
|
||||||
|
|
||||||
COPY ./web /static/
|
COPY ./web /static/
|
||||||
COPY --from=web-api-builder /local/web/api /static/api
|
COPY --from=web-api-builder /local/web/api /static/api
|
||||||
|
@ -46,18 +54,20 @@ ENV NODE_ENV=production
|
||||||
RUN cd /static && npm i && npm run build
|
RUN cd /static && npm i && npm run build
|
||||||
|
|
||||||
# Stage 5: Build go proxy
|
# Stage 5: Build go proxy
|
||||||
FROM golang:1.16.5 AS builder
|
FROM golang:1.16.6 AS builder
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
COPY --from=npm-builder /static/robots.txt /work/web/robots.txt
|
COPY --from=web-builder /static/robots.txt /work/web/robots.txt
|
||||||
COPY --from=npm-builder /static/security.txt /work/web/security.txt
|
COPY --from=web-builder /static/security.txt /work/web/security.txt
|
||||||
COPY --from=npm-builder /static/dist/ /work/web/dist/
|
COPY --from=web-builder /static/dist/ /work/web/dist/
|
||||||
COPY --from=npm-builder /static/authentik/ /work/web/authentik/
|
COPY --from=web-builder /static/authentik/ /work/web/authentik/
|
||||||
|
COPY --from=website-builder /static/help/ /work/website/help/
|
||||||
|
|
||||||
COPY --from=go-api-builder /local/api api
|
COPY --from=go-api-builder /local/api api
|
||||||
COPY ./cmd /work/cmd
|
COPY ./cmd /work/cmd
|
||||||
COPY ./web/static.go /work/web/static.go
|
COPY ./web/static.go /work/web/static.go
|
||||||
|
COPY ./website/static.go /work/website/static.go
|
||||||
COPY ./internal /work/internal
|
COPY ./internal /work/internal
|
||||||
COPY ./go.mod /work/go.mod
|
COPY ./go.mod /work/go.mod
|
||||||
COPY ./go.sum /work/go.sum
|
COPY ./go.sum /work/go.sum
|
||||||
|
|
1
Pipfile
1
Pipfile
|
@ -47,6 +47,7 @@ xmlsec = "*"
|
||||||
duo-client = "*"
|
duo-client = "*"
|
||||||
ua-parser = "*"
|
ua-parser = "*"
|
||||||
deepmerge = "*"
|
deepmerge = "*"
|
||||||
|
colorama = "*"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_version = "3.9"
|
python_version = "3.9"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "f90d9fb4713eaf9c5ffe6a3858e64843670f79ab5007e7debf914c1f094c8d63"
|
"sha256": "e4f2e57bd5c709809515ab2b95eb3f5fa337d4a9334f4110a24bf28c3f9d5f8f"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -122,19 +122,19 @@
|
||||||
},
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:10122ff0f942d7400b18b726edaead20600178f8246cb21b40420073350613b5",
|
"sha256:054e347824064b7cd77616f35596420eb4f6aca049ecc131a2aec23bcf4cf6ba",
|
||||||
"sha256:484bba256137c2d2f8351175553dee0e888e8bd5872f5406c8984e02715acf4d"
|
"sha256:22802b3b4806cafff41ed591e578f048789a8dd0deeff07d055cd6f59a7c6076"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==1.17.108"
|
"version": "==1.18.0"
|
||||||
},
|
},
|
||||||
"botocore": {
|
"botocore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:7667ef69001708afa796d2e79910230715e8542a910820581bf4623a5d3b0d47",
|
"sha256:0d46f0addc1d7930c42115a814e5e0c3399666f6d11c1e58d9ec726dfed02ada",
|
||||||
"sha256:f4686d2ccf68dfcd90d2591695938fd0906ae0a7121f792d193b0f000a5d8872"
|
"sha256:84ea51660c758416f75ac612374156f6423a1d1ade449d38944de6eb8493cca2"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
"markers": "python_version >= '3.6'",
|
||||||
"version": "==1.20.108"
|
"version": "==1.21.0"
|
||||||
},
|
},
|
||||||
"cachetools": {
|
"cachetools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -189,8 +189,10 @@
|
||||||
"sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202",
|
"sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202",
|
||||||
"sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5",
|
"sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5",
|
||||||
"sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548",
|
"sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548",
|
||||||
|
"sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a",
|
||||||
"sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f",
|
"sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f",
|
||||||
"sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20",
|
"sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20",
|
||||||
|
"sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218",
|
||||||
"sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c",
|
"sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c",
|
||||||
"sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e",
|
"sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e",
|
||||||
"sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56",
|
"sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56",
|
||||||
|
@ -202,6 +204,7 @@
|
||||||
"sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346",
|
"sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346",
|
||||||
"sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b",
|
"sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b",
|
||||||
"sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e",
|
"sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e",
|
||||||
|
"sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534",
|
||||||
"sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb",
|
"sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb",
|
||||||
"sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0",
|
"sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0",
|
||||||
"sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156",
|
"sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156",
|
||||||
|
@ -215,21 +218,23 @@
|
||||||
"sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd",
|
"sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd",
|
||||||
"sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728",
|
"sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728",
|
||||||
"sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7",
|
"sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7",
|
||||||
|
"sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca",
|
||||||
"sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99",
|
"sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99",
|
||||||
"sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf",
|
"sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf",
|
||||||
"sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e",
|
"sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e",
|
||||||
"sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c",
|
"sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c",
|
||||||
|
"sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5",
|
||||||
"sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"
|
"sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"
|
||||||
],
|
],
|
||||||
"version": "==1.14.6"
|
"version": "==1.14.6"
|
||||||
},
|
},
|
||||||
"channels": {
|
"channels": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:056b72e51080a517a0f33a0a30003e03833b551d75394d6636c885d4edb8188f",
|
"sha256:0ff0422b4224d10efac76e451575517f155fe7c97d369b5973b116f22eeaf86c",
|
||||||
"sha256:3f15bdd2138bb4796e76ea588a0a344b12a7964ea9b2e456f992fddb988a4317"
|
"sha256:fdd9a94987a23d8d7ebd97498ed8b8cc83163f37e53fc6c85098aba7a3bb8b75"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==3.0.3"
|
"version": "==3.0.4"
|
||||||
},
|
},
|
||||||
"channels-redis": {
|
"channels-redis": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -247,6 +252,14 @@
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||||
"version": "==4.0.0"
|
"version": "==4.0.0"
|
||||||
},
|
},
|
||||||
|
"charset-normalizer": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3c502a35807c9df35697b0f44b1d65008f83071ff29c69677c7c22573bc5a45a",
|
||||||
|
"sha256:951567c2f7433a70ab63f1be67e5ee05d3925d9423306ecb71a3b272757bcc95"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3'",
|
||||||
|
"version": "==2.0.2"
|
||||||
|
},
|
||||||
"click": {
|
"click": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||||
|
@ -275,6 +288,14 @@
|
||||||
],
|
],
|
||||||
"version": "==0.2.0"
|
"version": "==0.2.0"
|
||||||
},
|
},
|
||||||
|
"colorama": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b",
|
||||||
|
"sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.4.4"
|
||||||
|
},
|
||||||
"constantly": {
|
"constantly": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35",
|
"sha256:586372eb92059873e29eba4f9dec8381541b4d3834660707faf8ba59146dfc35",
|
||||||
|
@ -464,11 +485,11 @@
|
||||||
},
|
},
|
||||||
"google-auth": {
|
"google-auth": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:9266252e11393943410354cf14a77bcca24dd2ccd9c4e1aef23034fe0fbae630",
|
"sha256:9bd25d835c01ca3dd9045ea0b50f036e3fe3868ee2c5a9773a661925bbdf46ca",
|
||||||
"sha256:c7c215c74348ef24faef2f7b62f6d8e6b38824fe08b1e7b7b09a02d397eda7b3"
|
"sha256:a756a33978fac611e4f00b69715b80e35467c30cc6262132d29d33a0e398ac55"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||||
"version": "==1.32.1"
|
"version": "==1.33.0"
|
||||||
},
|
},
|
||||||
"gunicorn": {
|
"gunicorn": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -562,10 +583,10 @@
|
||||||
},
|
},
|
||||||
"idna": {
|
"idna": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
|
"sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
|
||||||
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
|
"sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
|
||||||
],
|
],
|
||||||
"version": "==2.10"
|
"version": "==3.2"
|
||||||
},
|
},
|
||||||
"incremental": {
|
"incremental": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -966,11 +987,11 @@
|
||||||
},
|
},
|
||||||
"python-dateutil": {
|
"python-dateutil": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
|
"sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
|
||||||
"sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
|
"sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==2.8.1"
|
"version": "==2.8.2"
|
||||||
},
|
},
|
||||||
"python-dotenv": {
|
"python-dotenv": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1031,11 +1052,11 @@
|
||||||
},
|
},
|
||||||
"requests": {
|
"requests": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
"sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
|
||||||
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
|
"sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||||
"version": "==2.25.1"
|
"version": "==2.26.0"
|
||||||
},
|
},
|
||||||
"requests-oauthlib": {
|
"requests-oauthlib": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1056,10 +1077,11 @@
|
||||||
},
|
},
|
||||||
"s3transfer": {
|
"s3transfer": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:9b3752887a2880690ce628bc263d6d13a3864083aeacff4890c1c9839a5eb0bc",
|
"sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c",
|
||||||
"sha256:cb022f4b16551edebbb31a377d3f09600dbada7363d8c5db7976e7f47732e1b2"
|
"sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803"
|
||||||
],
|
],
|
||||||
"version": "==0.4.2"
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==0.5.0"
|
||||||
},
|
},
|
||||||
"sentry-sdk": {
|
"sentry-sdk": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1197,18 +1219,18 @@
|
||||||
},
|
},
|
||||||
"uvloop": {
|
"uvloop": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:114543c84e95df1b4ff546e6e3a27521580466a30127f12172a3278172ad68bc",
|
"sha256:0de811931e90ae2da9e19ce70ffad73047ab0c1dba7c6e74f9ae1a3aabeb89bd",
|
||||||
"sha256:19fa1d56c91341318ac5d417e7b61c56e9a41183946cc70c411341173de02c69",
|
"sha256:1ff05116ede1ebdd81802df339e5b1d4cab1dfbd99295bf27e90b4cec64d70e9",
|
||||||
"sha256:2bb0624a8a70834e54dde8feed62ed63b50bad7a1265c40d6403a2ac447bce01",
|
"sha256:2d8ffe44ae709f839c54bacf14ed283f41bee90430c3b398e521e10f8d117b3a",
|
||||||
"sha256:42eda9f525a208fbc4f7cecd00fa15c57cc57646c76632b3ba2fe005004f051d",
|
"sha256:5cda65fc60a645470b8525ce014516b120b7057b576fa876cdfdd5e60ab1efbb",
|
||||||
"sha256:44cac8575bf168601424302045234d74e3561fbdbac39b2b54cc1d1d00b70760",
|
"sha256:63a3288abbc9c8ee979d7e34c34e780b2fbab3e7e53d00b6c80271119f277399",
|
||||||
"sha256:6de130d0cb78985a5d080e323b86c5ecaf3af82f4890492c05981707852f983c",
|
"sha256:7522df4e45e4f25b50adbbbeb5bb9847495c438a628177099d2721f2751ff825",
|
||||||
"sha256:7ae39b11a5f4cec1432d706c21ecc62f9e04d116883178b09671aa29c46f7a47",
|
"sha256:7f4b8a905df909a407c5791fb582f6c03b0d3b491ecdc1cdceaefbc9bf9e08f6",
|
||||||
"sha256:90e56f17755e41b425ad19a08c41dc358fa7bf1226c0f8e54d4d02d556f7af7c",
|
"sha256:905f0adb0c09c9f44222ee02f6b96fd88b493478fffb7a345287f9444e926030",
|
||||||
"sha256:b45218c99795803fb8bdbc9435ff7f54e3a591b44cd4c121b02fa83affb61c7c",
|
"sha256:ae2b325c0f6d748027f7463077e457006b4fdb35a8788f01754aadba825285ee",
|
||||||
"sha256:e5e5f855c9bf483ee6cd1eb9a179b740de80cb0ae2988e3fa22309b78e2ea0e7"
|
"sha256:e71fb9038bfcd7646ca126c5ef19b17e48d4af9e838b2bcfda7a9f55a6552a32"
|
||||||
],
|
],
|
||||||
"version": "==0.15.2"
|
"version": "==0.15.3"
|
||||||
},
|
},
|
||||||
"vine": {
|
"vine": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1459,13 +1481,13 @@
|
||||||
],
|
],
|
||||||
"version": "==2021.5.30"
|
"version": "==2021.5.30"
|
||||||
},
|
},
|
||||||
"chardet": {
|
"charset-normalizer": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa",
|
"sha256:3c502a35807c9df35697b0f44b1d65008f83071ff29c69677c7c22573bc5a45a",
|
||||||
"sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"
|
"sha256:951567c2f7433a70ab63f1be67e5ee05d3925d9423306ecb71a3b272757bcc95"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '3'",
|
||||||
"version": "==4.0.0"
|
"version": "==2.0.2"
|
||||||
},
|
},
|
||||||
"click": {
|
"click": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1559,10 +1581,10 @@
|
||||||
},
|
},
|
||||||
"idna": {
|
"idna": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6",
|
"sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a",
|
||||||
"sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"
|
"sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"
|
||||||
],
|
],
|
||||||
"version": "==2.10"
|
"version": "==3.2"
|
||||||
},
|
},
|
||||||
"iniconfig": {
|
"iniconfig": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
@ -1790,11 +1812,11 @@
|
||||||
},
|
},
|
||||||
"requests": {
|
"requests": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804",
|
"sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24",
|
||||||
"sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"
|
"sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
|
||||||
"version": "==2.25.1"
|
"version": "==2.26.0"
|
||||||
},
|
},
|
||||||
"requests-mock": {
|
"requests-mock": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ConfigView(APIView):
|
||||||
caps.append(Capabilities.CAN_GEO_IP)
|
caps.append(Capabilities.CAN_GEO_IP)
|
||||||
if SERVICE_HOST_ENV_NAME in environ:
|
if SERVICE_HOST_ENV_NAME in environ:
|
||||||
# Running in k8s, only s3 backup is supported
|
# Running in k8s, only s3 backup is supported
|
||||||
if CONFIG.y("postgresql.s3_backup"):
|
if CONFIG.y_bool("postgresql.s3_backup"):
|
||||||
caps.append(Capabilities.CAN_BACKUP)
|
caps.append(Capabilities.CAN_BACKUP)
|
||||||
else:
|
else:
|
||||||
# Running in compose, backup is always supported
|
# Running in compose, backup is always supported
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
"""Sentry tunnel"""
|
||||||
|
from json import loads
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.http.request import HttpRequest
|
||||||
|
from django.http.response import HttpResponse
|
||||||
|
from django.views.generic.base import View
|
||||||
|
from requests import post
|
||||||
|
from requests.exceptions import RequestException
|
||||||
|
|
||||||
|
from authentik.lib.config import CONFIG
|
||||||
|
|
||||||
|
|
||||||
|
class SentryTunnelView(View):
|
||||||
|
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
|
||||||
|
|
||||||
|
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||||
|
"""Sentry tunnel, to prevent ad blockers from blocking sentry"""
|
||||||
|
# Only allow usage of this endpoint when error reporting is enabled
|
||||||
|
if not CONFIG.y_bool("error_reporting.enabled", False):
|
||||||
|
return HttpResponse(status=400)
|
||||||
|
# Body is 2 json objects separated by \n
|
||||||
|
full_body = request.body
|
||||||
|
header = loads(full_body.splitlines()[0])
|
||||||
|
# Check that the DSN is what we expect
|
||||||
|
dsn = header.get("dsn", "")
|
||||||
|
if dsn != settings.SENTRY_DSN:
|
||||||
|
return HttpResponse(status=400)
|
||||||
|
response = post(
|
||||||
|
"https://sentry.beryju.org/api/8/envelope/",
|
||||||
|
data=full_body,
|
||||||
|
headers={"Content-Type": "application/octet-stream"},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
response.raise_for_status()
|
||||||
|
except RequestException:
|
||||||
|
return HttpResponse(status=500)
|
||||||
|
return HttpResponse(status=response.status_code)
|
|
@ -1,5 +1,6 @@
|
||||||
"""api v2 urls"""
|
"""api v2 urls"""
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from drf_spectacular.views import SpectacularAPIView
|
from drf_spectacular.views import SpectacularAPIView
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
|
|
||||||
|
@ -10,6 +11,7 @@ from authentik.admin.api.tasks import TaskViewSet
|
||||||
from authentik.admin.api.version import VersionView
|
from authentik.admin.api.version import VersionView
|
||||||
from authentik.admin.api.workers import WorkerView
|
from authentik.admin.api.workers import WorkerView
|
||||||
from authentik.api.v2.config import ConfigView
|
from authentik.api.v2.config import ConfigView
|
||||||
|
from authentik.api.v2.sentry import SentryTunnelView
|
||||||
from authentik.api.views import APIBrowserView
|
from authentik.api.views import APIBrowserView
|
||||||
from authentik.core.api.applications import ApplicationViewSet
|
from authentik.core.api.applications import ApplicationViewSet
|
||||||
from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet
|
from authentik.core.api.authenticated_sessions import AuthenticatedSessionViewSet
|
||||||
|
@ -235,6 +237,7 @@ urlpatterns = (
|
||||||
FlowExecutorView.as_view(),
|
FlowExecutorView.as_view(),
|
||||||
name="flow-executor",
|
name="flow-executor",
|
||||||
),
|
),
|
||||||
|
path("sentry/", csrf_exempt(SentryTunnelView.as_view()), name="sentry"),
|
||||||
path("schema/", SpectacularAPIView.as_view(), name="schema"),
|
path("schema/", SpectacularAPIView.as_view(), name="schema"),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,24 +1,60 @@
|
||||||
"""Groups API Viewset"""
|
"""Groups API Viewset"""
|
||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from rest_framework.fields import JSONField
|
from rest_framework.fields import BooleanField, CharField, JSONField
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ListSerializer, ModelSerializer
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
from rest_framework_guardian.filters import ObjectPermissionsFilter
|
from rest_framework_guardian.filters import ObjectPermissionsFilter
|
||||||
|
|
||||||
from authentik.core.api.used_by import UsedByMixin
|
from authentik.core.api.used_by import UsedByMixin
|
||||||
from authentik.core.api.utils import is_dict
|
from authentik.core.api.utils import is_dict
|
||||||
from authentik.core.models import Group
|
from authentik.core.models import Group, User
|
||||||
|
|
||||||
|
|
||||||
|
class GroupMemberSerializer(ModelSerializer):
|
||||||
|
"""Stripped down user serializer to show relevant users for groups"""
|
||||||
|
|
||||||
|
is_superuser = BooleanField(read_only=True)
|
||||||
|
avatar = CharField(read_only=True)
|
||||||
|
attributes = JSONField(validators=[is_dict], required=False)
|
||||||
|
uid = CharField(read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
|
||||||
|
model = User
|
||||||
|
fields = [
|
||||||
|
"pk",
|
||||||
|
"username",
|
||||||
|
"name",
|
||||||
|
"is_active",
|
||||||
|
"last_login",
|
||||||
|
"is_superuser",
|
||||||
|
"email",
|
||||||
|
"avatar",
|
||||||
|
"attributes",
|
||||||
|
"uid",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class GroupSerializer(ModelSerializer):
|
class GroupSerializer(ModelSerializer):
|
||||||
"""Group Serializer"""
|
"""Group Serializer"""
|
||||||
|
|
||||||
attributes = JSONField(validators=[is_dict], required=False)
|
attributes = JSONField(validators=[is_dict], required=False)
|
||||||
|
users_obj = ListSerializer(
|
||||||
|
child=GroupMemberSerializer(), read_only=True, source="users", required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
model = Group
|
model = Group
|
||||||
fields = ["pk", "name", "is_superuser", "parent", "users", "attributes"]
|
fields = [
|
||||||
|
"pk",
|
||||||
|
"name",
|
||||||
|
"is_superuser",
|
||||||
|
"parent",
|
||||||
|
"users",
|
||||||
|
"attributes",
|
||||||
|
"users_obj",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class GroupViewSet(UsedByMixin, ModelViewSet):
|
class GroupViewSet(UsedByMixin, ModelViewSet):
|
||||||
|
|
|
@ -12,7 +12,7 @@ from authentik.api.decorators import permission_required
|
||||||
from authentik.core.api.used_by import UsedByMixin
|
from authentik.core.api.used_by import UsedByMixin
|
||||||
from authentik.core.api.users import UserSerializer
|
from authentik.core.api.users import UserSerializer
|
||||||
from authentik.core.api.utils import PassiveSerializer
|
from authentik.core.api.utils import PassiveSerializer
|
||||||
from authentik.core.models import Token, TokenIntents
|
from authentik.core.models import USER_ATTRIBUTE_TOKEN_EXPIRING, Token, TokenIntents
|
||||||
from authentik.events.models import Event, EventAction
|
from authentik.events.models import Event, EventAction
|
||||||
from authentik.managed.api import ManagedSerializer
|
from authentik.managed.api import ManagedSerializer
|
||||||
|
|
||||||
|
@ -61,11 +61,19 @@ class TokenViewSet(UsedByMixin, ModelViewSet):
|
||||||
"intent",
|
"intent",
|
||||||
"user__username",
|
"user__username",
|
||||||
"description",
|
"description",
|
||||||
|
"expires",
|
||||||
|
"expiring",
|
||||||
]
|
]
|
||||||
ordering = ["expires"]
|
ordering = ["expires"]
|
||||||
|
|
||||||
def perform_create(self, serializer: TokenSerializer):
|
def perform_create(self, serializer: TokenSerializer):
|
||||||
serializer.save(user=self.request.user, intent=TokenIntents.INTENT_API)
|
serializer.save(
|
||||||
|
user=self.request.user,
|
||||||
|
intent=TokenIntents.INTENT_API,
|
||||||
|
expiring=self.request.user.attributes.get(
|
||||||
|
USER_ATTRIBUTE_TOKEN_EXPIRING, True
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
@permission_required("authentik_core.view_token_key")
|
@permission_required("authentik_core.view_token_key")
|
||||||
@extend_schema(
|
@extend_schema(
|
||||||
|
|
|
@ -37,6 +37,7 @@ LOGGER = get_logger()
|
||||||
USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug"
|
USER_ATTRIBUTE_DEBUG = "goauthentik.io/user/debug"
|
||||||
USER_ATTRIBUTE_SA = "goauthentik.io/user/service-account"
|
USER_ATTRIBUTE_SA = "goauthentik.io/user/service-account"
|
||||||
USER_ATTRIBUTE_SOURCES = "goauthentik.io/user/sources"
|
USER_ATTRIBUTE_SOURCES = "goauthentik.io/user/sources"
|
||||||
|
USER_ATTRIBUTE_TOKEN_EXPIRING = "goauthentik.io/user/token-expires" # nosec
|
||||||
|
|
||||||
GRAVATAR_URL = "https://secure.gravatar.com"
|
GRAVATAR_URL = "https://secure.gravatar.com"
|
||||||
DEFAULT_AVATAR = static("dist/assets/images/user_default.png")
|
DEFAULT_AVATAR = static("dist/assets/images/user_default.png")
|
||||||
|
@ -380,6 +381,13 @@ class ExpiringModel(models.Model):
|
||||||
expires = models.DateTimeField(default=default_token_duration)
|
expires = models.DateTimeField(default=default_token_duration)
|
||||||
expiring = models.BooleanField(default=True)
|
expiring = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
def expire_action(self, *args, **kwargs):
|
||||||
|
"""Handler which is called when this object is expired. By
|
||||||
|
default the object is deleted. This is less efficient compared
|
||||||
|
to bulk deleting objects, but classes like Token() need to change
|
||||||
|
values instead of being deleted."""
|
||||||
|
return self.delete(*args, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_not_expired(cls, **kwargs) -> QuerySet:
|
def filter_not_expired(cls, **kwargs) -> QuerySet:
|
||||||
"""Filer for tokens which are not expired yet or are not expiring,
|
"""Filer for tokens which are not expired yet or are not expiring,
|
||||||
|
@ -424,6 +432,18 @@ class Token(ManagedModel, ExpiringModel):
|
||||||
user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+")
|
user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="+")
|
||||||
description = models.TextField(default="", blank=True)
|
description = models.TextField(default="", blank=True)
|
||||||
|
|
||||||
|
def expire_action(self, *args, **kwargs):
|
||||||
|
"""Handler which is called when this object is expired."""
|
||||||
|
from authentik.events.models import Event, EventAction
|
||||||
|
|
||||||
|
self.key = default_token_key()
|
||||||
|
self.save(*args, **kwargs)
|
||||||
|
Event.new(
|
||||||
|
action=EventAction.SECRET_ROTATE,
|
||||||
|
token=self,
|
||||||
|
message=f"Token {self.identifier}'s secret was rotated.",
|
||||||
|
).save()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
description = f"{self.identifier}"
|
description = f"{self.identifier}"
|
||||||
if self.expiring:
|
if self.expiring:
|
||||||
|
|
|
@ -26,14 +26,16 @@ def clean_expired_models(self: MonitoredTask):
|
||||||
messages = []
|
messages = []
|
||||||
for cls in ExpiringModel.__subclasses__():
|
for cls in ExpiringModel.__subclasses__():
|
||||||
cls: ExpiringModel
|
cls: ExpiringModel
|
||||||
amount, _ = (
|
objects = (
|
||||||
cls.objects.all()
|
cls.objects.all()
|
||||||
.exclude(expiring=False)
|
.exclude(expiring=False)
|
||||||
.exclude(expiring=True, expires__gt=now())
|
.exclude(expiring=True, expires__gt=now())
|
||||||
.delete()
|
|
||||||
)
|
)
|
||||||
LOGGER.debug("Deleted expired models", model=cls, amount=amount)
|
for obj in objects:
|
||||||
messages.append(f"Deleted {amount} expired {cls._meta.verbose_name_plural}")
|
obj.expire_action()
|
||||||
|
amount = objects.count()
|
||||||
|
LOGGER.debug("Expired models", model=cls, amount=amount)
|
||||||
|
messages.append(f"Expired {amount} {cls._meta.verbose_name_plural}")
|
||||||
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, messages))
|
self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, messages))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
"""authentik core task tests"""
|
|
||||||
from django.test import TestCase
|
|
||||||
from django.utils.timezone import now
|
|
||||||
from guardian.shortcuts import get_anonymous_user
|
|
||||||
|
|
||||||
from authentik.core.models import Token
|
|
||||||
from authentik.core.tasks import clean_expired_models
|
|
||||||
|
|
||||||
|
|
||||||
class TestTasks(TestCase):
|
|
||||||
"""Test Tasks"""
|
|
||||||
|
|
||||||
def test_token_cleanup(self):
|
|
||||||
"""Test Token cleanup task"""
|
|
||||||
Token.objects.create(expires=now(), user=get_anonymous_user())
|
|
||||||
self.assertEqual(Token.objects.all().count(), 1)
|
|
||||||
clean_expired_models.delay().get()
|
|
||||||
self.assertEqual(Token.objects.all().count(), 0)
|
|
|
@ -1,8 +1,16 @@
|
||||||
"""Test token API"""
|
"""Test token API"""
|
||||||
from django.urls.base import reverse
|
from django.urls.base import reverse
|
||||||
|
from django.utils.timezone import now
|
||||||
|
from guardian.shortcuts import get_anonymous_user
|
||||||
from rest_framework.test import APITestCase
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
from authentik.core.models import Token, TokenIntents, User
|
from authentik.core.models import (
|
||||||
|
USER_ATTRIBUTE_TOKEN_EXPIRING,
|
||||||
|
Token,
|
||||||
|
TokenIntents,
|
||||||
|
User,
|
||||||
|
)
|
||||||
|
from authentik.core.tasks import clean_expired_models
|
||||||
|
|
||||||
|
|
||||||
class TestTokenAPI(APITestCase):
|
class TestTokenAPI(APITestCase):
|
||||||
|
@ -22,3 +30,25 @@ class TestTokenAPI(APITestCase):
|
||||||
token = Token.objects.get(identifier="test-token")
|
token = Token.objects.get(identifier="test-token")
|
||||||
self.assertEqual(token.user, self.user)
|
self.assertEqual(token.user, self.user)
|
||||||
self.assertEqual(token.intent, TokenIntents.INTENT_API)
|
self.assertEqual(token.intent, TokenIntents.INTENT_API)
|
||||||
|
self.assertEqual(token.expiring, True)
|
||||||
|
|
||||||
|
def test_token_create_non_expiring(self):
|
||||||
|
"""Test token creation endpoint"""
|
||||||
|
self.user.attributes[USER_ATTRIBUTE_TOKEN_EXPIRING] = False
|
||||||
|
self.user.save()
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("authentik_api:token-list"), {"identifier": "test-token"}
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 201)
|
||||||
|
token = Token.objects.get(identifier="test-token")
|
||||||
|
self.assertEqual(token.user, self.user)
|
||||||
|
self.assertEqual(token.intent, TokenIntents.INTENT_API)
|
||||||
|
self.assertEqual(token.expiring, False)
|
||||||
|
|
||||||
|
def test_token_expire(self):
|
||||||
|
"""Test Token expire task"""
|
||||||
|
token: Token = Token.objects.create(expires=now(), user=get_anonymous_user())
|
||||||
|
key = token.key
|
||||||
|
clean_expired_models.delay().get()
|
||||||
|
token.refresh_from_db()
|
||||||
|
self.assertNotEqual(key, token.key)
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Generated by Django 3.2.5 on 2021-07-14 19:15
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_events", "0016_add_tenant"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="event",
|
||||||
|
name="action",
|
||||||
|
field=models.TextField(
|
||||||
|
choices=[
|
||||||
|
("login", "Login"),
|
||||||
|
("login_failed", "Login Failed"),
|
||||||
|
("logout", "Logout"),
|
||||||
|
("user_write", "User Write"),
|
||||||
|
("suspicious_request", "Suspicious Request"),
|
||||||
|
("password_set", "Password Set"),
|
||||||
|
("secret_view", "Secret View"),
|
||||||
|
("secret_rotate", "Secret Rotate"),
|
||||||
|
("invitation_used", "Invite Used"),
|
||||||
|
("authorize_application", "Authorize Application"),
|
||||||
|
("source_linked", "Source Linked"),
|
||||||
|
("impersonation_started", "Impersonation Started"),
|
||||||
|
("impersonation_ended", "Impersonation Ended"),
|
||||||
|
("policy_execution", "Policy Execution"),
|
||||||
|
("policy_exception", "Policy Exception"),
|
||||||
|
("property_mapping_exception", "Property Mapping Exception"),
|
||||||
|
("system_task_execution", "System Task Execution"),
|
||||||
|
("system_task_exception", "System Task Exception"),
|
||||||
|
("system_exception", "System Exception"),
|
||||||
|
("configuration_error", "Configuration Error"),
|
||||||
|
("model_created", "Model Created"),
|
||||||
|
("model_updated", "Model Updated"),
|
||||||
|
("model_deleted", "Model Deleted"),
|
||||||
|
("email_sent", "Email Sent"),
|
||||||
|
("update_available", "Update Available"),
|
||||||
|
("custom_", "Custom Prefix"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -62,6 +62,7 @@ class EventAction(models.TextChoices):
|
||||||
PASSWORD_SET = "password_set" # noqa # nosec
|
PASSWORD_SET = "password_set" # noqa # nosec
|
||||||
|
|
||||||
SECRET_VIEW = "secret_view" # noqa # nosec
|
SECRET_VIEW = "secret_view" # noqa # nosec
|
||||||
|
SECRET_ROTATE = "secret_rotate" # noqa # nosec
|
||||||
|
|
||||||
INVITE_USED = "invitation_used"
|
INVITE_USED = "invitation_used"
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,10 @@ web:
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
host: localhost
|
host: localhost
|
||||||
|
port: 6379
|
||||||
password: ''
|
password: ''
|
||||||
|
tls: false
|
||||||
|
tls_reqs: "none"
|
||||||
cache_db: 0
|
cache_db: 0
|
||||||
message_queue_db: 1
|
message_queue_db: 1
|
||||||
ws_db: 2
|
ws_db: 2
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Generated by Django 3.2.5 on 2021-07-14 19:15
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_policies_event_matcher", "0017_alter_eventmatcherpolicy_action"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="eventmatcherpolicy",
|
||||||
|
name="action",
|
||||||
|
field=models.TextField(
|
||||||
|
blank=True,
|
||||||
|
choices=[
|
||||||
|
("login", "Login"),
|
||||||
|
("login_failed", "Login Failed"),
|
||||||
|
("logout", "Logout"),
|
||||||
|
("user_write", "User Write"),
|
||||||
|
("suspicious_request", "Suspicious Request"),
|
||||||
|
("password_set", "Password Set"),
|
||||||
|
("secret_view", "Secret View"),
|
||||||
|
("secret_rotate", "Secret Rotate"),
|
||||||
|
("invitation_used", "Invite Used"),
|
||||||
|
("authorize_application", "Authorize Application"),
|
||||||
|
("source_linked", "Source Linked"),
|
||||||
|
("impersonation_started", "Impersonation Started"),
|
||||||
|
("impersonation_ended", "Impersonation Ended"),
|
||||||
|
("policy_execution", "Policy Execution"),
|
||||||
|
("policy_exception", "Policy Exception"),
|
||||||
|
("property_mapping_exception", "Property Mapping Exception"),
|
||||||
|
("system_task_execution", "System Task Execution"),
|
||||||
|
("system_task_exception", "System Task Exception"),
|
||||||
|
("system_exception", "System Exception"),
|
||||||
|
("configuration_error", "Configuration Error"),
|
||||||
|
("model_created", "Model Created"),
|
||||||
|
("model_updated", "Model Updated"),
|
||||||
|
("model_deleted", "Model Deleted"),
|
||||||
|
("email_sent", "Email Sent"),
|
||||||
|
("update_available", "Update Available"),
|
||||||
|
("custom_", "Custom Prefix"),
|
||||||
|
],
|
||||||
|
help_text="Match created events with this action type. When left empty, all action types will be matched.",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -21,12 +21,15 @@ def update_score(request: HttpRequest, username: str, amount: int):
|
||||||
"""Update score for IP and User"""
|
"""Update score for IP and User"""
|
||||||
remote_ip = get_client_ip(request)
|
remote_ip = get_client_ip(request)
|
||||||
|
|
||||||
|
try:
|
||||||
# We only update the cache here, as its faster than writing to the DB
|
# We only update the cache here, as its faster than writing to the DB
|
||||||
cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0, CACHE_TIMEOUT)
|
cache.get_or_set(CACHE_KEY_IP_PREFIX + remote_ip, 0, CACHE_TIMEOUT)
|
||||||
cache.incr(CACHE_KEY_IP_PREFIX + remote_ip, amount)
|
cache.incr(CACHE_KEY_IP_PREFIX + remote_ip, amount)
|
||||||
|
|
||||||
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0, CACHE_TIMEOUT)
|
cache.get_or_set(CACHE_KEY_USER_PREFIX + username, 0, CACHE_TIMEOUT)
|
||||||
cache.incr(CACHE_KEY_USER_PREFIX + username, amount)
|
cache.incr(CACHE_KEY_USER_PREFIX + username, amount)
|
||||||
|
except ValueError as exc:
|
||||||
|
LOGGER.warning("failed to set reputation", exc=exc)
|
||||||
|
|
||||||
LOGGER.debug("Updated score", amount=amount, for_user=username, for_ip=remote_ip)
|
LOGGER.debug("Updated score", amount=amount, for_user=username, for_ip=remote_ip)
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,10 @@ class LDAPProviderSerializer(ProviderSerializer):
|
||||||
fields = ProviderSerializer.Meta.fields + [
|
fields = ProviderSerializer.Meta.fields + [
|
||||||
"base_dn",
|
"base_dn",
|
||||||
"search_group",
|
"search_group",
|
||||||
|
"certificate",
|
||||||
|
"tls_server_name",
|
||||||
|
"uid_start_number",
|
||||||
|
"gid_start_number",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,6 +48,10 @@ class LDAPOutpostConfigSerializer(ModelSerializer):
|
||||||
"bind_flow_slug",
|
"bind_flow_slug",
|
||||||
"application_slug",
|
"application_slug",
|
||||||
"search_group",
|
"search_group",
|
||||||
|
"certificate",
|
||||||
|
"tls_server_name",
|
||||||
|
"uid_start_number",
|
||||||
|
"gid_start_number",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,5 @@ class LDAPDockerController(DockerController):
|
||||||
super().__init__(outpost, connection)
|
super().__init__(outpost, connection)
|
||||||
self.deployment_ports = [
|
self.deployment_ports = [
|
||||||
DeploymentPort(389, "ldap", "tcp", 3389),
|
DeploymentPort(389, "ldap", "tcp", 3389),
|
||||||
|
DeploymentPort(636, "ldaps", "tcp", 6636),
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,4 +11,5 @@ class LDAPKubernetesController(KubernetesController):
|
||||||
super().__init__(outpost, connection)
|
super().__init__(outpost, connection)
|
||||||
self.deployment_ports = [
|
self.deployment_ports = [
|
||||||
DeploymentPort(389, "ldap", "tcp", 3389),
|
DeploymentPort(389, "ldap", "tcp", 3389),
|
||||||
|
DeploymentPort(636, "ldaps", "tcp", 6636),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Generated by Django 3.2.5 on 2021-07-13 11:38
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_crypto", "0002_create_self_signed_kp"),
|
||||||
|
("authentik_providers_ldap", "0002_ldapprovider_search_group"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="ldapprovider",
|
||||||
|
name="certificate",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="authentik_crypto.certificatekeypair",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="ldapprovider",
|
||||||
|
name="tls_server_name",
|
||||||
|
field=models.TextField(blank=True, default=""),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 3.2.5 on 2021-07-13 21:15
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_providers_ldap", "0003_auto_20210713_1138"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="ldapprovider",
|
||||||
|
name="gid_start_number",
|
||||||
|
field=models.IntegerField(
|
||||||
|
default=4000,
|
||||||
|
help_text="The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="ldapprovider",
|
||||||
|
name="uid_start_number",
|
||||||
|
field=models.IntegerField(
|
||||||
|
default=2000,
|
||||||
|
help_text="The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,6 +6,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from rest_framework.serializers import Serializer
|
from rest_framework.serializers import Serializer
|
||||||
|
|
||||||
from authentik.core.models import Group, Provider
|
from authentik.core.models import Group, Provider
|
||||||
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
from authentik.outposts.models import OutpostModel
|
from authentik.outposts.models import OutpostModel
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +29,36 @@ class LDAPProvider(OutpostModel, Provider):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tls_server_name = models.TextField(
|
||||||
|
default="",
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
certificate = models.ForeignKey(
|
||||||
|
CertificateKeyPair,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
uid_start_number = models.IntegerField(
|
||||||
|
default=2000,
|
||||||
|
help_text=_(
|
||||||
|
"The start for uidNumbers, this number is added to the user.Pk to make sure that the "
|
||||||
|
"numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't "
|
||||||
|
"collide with local users uidNumber"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
gid_start_number = models.IntegerField(
|
||||||
|
default=4000,
|
||||||
|
help_text=_(
|
||||||
|
"The start for gidNumbers, this number is added to a number generated from the "
|
||||||
|
"group.Pk to make sure that the numbers aren't too low for POSIX groups. Default "
|
||||||
|
"is 4000 to ensure that we don't collide with local groups or users "
|
||||||
|
"primary groups gidNumber"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def launch_url(self) -> Optional[str]:
|
def launch_url(self) -> Optional[str]:
|
||||||
"""LDAP never has a launch URL"""
|
"""LDAP never has a launch URL"""
|
||||||
|
|
|
@ -188,12 +188,19 @@ REST_FRAMEWORK = {
|
||||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
REDIS_PROTOCOL_PREFIX = "redis://"
|
||||||
|
REDIS_CELERY_TLS_REQUIREMENTS = ""
|
||||||
|
if CONFIG.y_bool("redis.tls", False):
|
||||||
|
REDIS_PROTOCOL_PREFIX = "rediss://"
|
||||||
|
REDIS_CELERY_TLS_REQUIREMENTS = f"?ssl_cert_reqs={CONFIG.y('redis.tls_reqs')}"
|
||||||
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
"BACKEND": "django_redis.cache.RedisCache",
|
||||||
"LOCATION": (
|
"LOCATION": (
|
||||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379"
|
f"{REDIS_PROTOCOL_PREFIX}:"
|
||||||
f"/{CONFIG.y('redis.cache_db')}"
|
f"{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:"
|
||||||
|
f"{int(CONFIG.y('redis.port'))}/{CONFIG.y('redis.cache_db')}"
|
||||||
),
|
),
|
||||||
"TIMEOUT": int(CONFIG.y("redis.cache_timeout", 300)),
|
"TIMEOUT": int(CONFIG.y("redis.cache_timeout", 300)),
|
||||||
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
"OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"},
|
||||||
|
@ -252,8 +259,9 @@ CHANNEL_LAYERS = {
|
||||||
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
"BACKEND": "channels_redis.core.RedisChannelLayer",
|
||||||
"CONFIG": {
|
"CONFIG": {
|
||||||
"hosts": [
|
"hosts": [
|
||||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379"
|
f"{REDIS_PROTOCOL_PREFIX}:"
|
||||||
f"/{CONFIG.y('redis.ws_db')}"
|
f"{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:"
|
||||||
|
f"{int(CONFIG.y('redis.port'))}/{CONFIG.y('redis.ws_db')}"
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -331,12 +339,16 @@ CELERY_BEAT_SCHEDULE = {
|
||||||
CELERY_TASK_CREATE_MISSING_QUEUES = True
|
CELERY_TASK_CREATE_MISSING_QUEUES = True
|
||||||
CELERY_TASK_DEFAULT_QUEUE = "authentik"
|
CELERY_TASK_DEFAULT_QUEUE = "authentik"
|
||||||
CELERY_BROKER_URL = (
|
CELERY_BROKER_URL = (
|
||||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}"
|
f"{REDIS_PROTOCOL_PREFIX}:"
|
||||||
f":6379/{CONFIG.y('redis.message_queue_db')}"
|
f"{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:"
|
||||||
|
f"{int(CONFIG.y('redis.port'))}/{CONFIG.y('redis.message_queue_db')}"
|
||||||
|
f"{REDIS_CELERY_TLS_REQUIREMENTS}"
|
||||||
)
|
)
|
||||||
CELERY_RESULT_BACKEND = (
|
CELERY_RESULT_BACKEND = (
|
||||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}"
|
f"{REDIS_PROTOCOL_PREFIX}:"
|
||||||
f":6379/{CONFIG.y('redis.message_queue_db')}"
|
f"{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:"
|
||||||
|
f"{int(CONFIG.y('redis.port'))}/{CONFIG.y('redis.message_queue_db')}"
|
||||||
|
f"{REDIS_CELERY_TLS_REQUIREMENTS}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Database backup
|
# Database backup
|
||||||
|
@ -364,11 +376,12 @@ if CONFIG.y("postgresql.s3_backup"):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Sentry integration
|
# Sentry integration
|
||||||
|
SENTRY_DSN = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8"
|
||||||
_ERROR_REPORTING = CONFIG.y_bool("error_reporting.enabled", False)
|
_ERROR_REPORTING = CONFIG.y_bool("error_reporting.enabled", False)
|
||||||
if _ERROR_REPORTING:
|
if _ERROR_REPORTING:
|
||||||
# pylint: disable=abstract-class-instantiated
|
# pylint: disable=abstract-class-instantiated
|
||||||
sentry_init(
|
sentry_init(
|
||||||
dsn="https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
dsn=SENTRY_DSN,
|
||||||
integrations=[
|
integrations=[
|
||||||
DjangoIntegration(transaction_style="function_name"),
|
DjangoIntegration(transaction_style="function_name"),
|
||||||
CeleryIntegration(),
|
CeleryIntegration(),
|
||||||
|
|
|
@ -46,7 +46,7 @@ func main() {
|
||||||
for {
|
for {
|
||||||
go attemptStartBackend(g, ex)
|
go attemptStartBackend(g, ex)
|
||||||
ws.Start()
|
ws.Start()
|
||||||
go attemptProxyStart(u, ex)
|
// go attemptProxyStart(u, ex)
|
||||||
|
|
||||||
<-ex
|
<-ex
|
||||||
log.WithField("logger", "authentik").Debug("shutting down webserver")
|
log.WithField("logger", "authentik").Debug("shutting down webserver")
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/recws-org/recws"
|
"github.com/recws-org/recws"
|
||||||
"goauthentik.io/internal/constants"
|
|
||||||
"goauthentik.io/api"
|
"goauthentik.io/api"
|
||||||
|
"goauthentik.io/internal/constants"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -40,10 +40,11 @@ type APIController struct {
|
||||||
// NewAPIController initialise new API Controller instance from URL and API token
|
// NewAPIController initialise new API Controller instance from URL and API token
|
||||||
func NewAPIController(akURL url.URL, token string) *APIController {
|
func NewAPIController(akURL url.URL, token string) *APIController {
|
||||||
config := api.NewConfiguration()
|
config := api.NewConfiguration()
|
||||||
|
config.UserAgent = constants.OutpostUserAgent()
|
||||||
config.Host = akURL.Host
|
config.Host = akURL.Host
|
||||||
config.Scheme = akURL.Scheme
|
config.Scheme = akURL.Scheme
|
||||||
config.HTTPClient = &http.Client{
|
config.HTTPClient = &http.Client{
|
||||||
Transport: SetUserAgent(GetTLSTransport(), constants.OutpostUserAgent()),
|
Transport: GetTLSTransport(),
|
||||||
}
|
}
|
||||||
config.AddDefaultHeader("Authorization", fmt.Sprintf("Bearer %s", token))
|
config.AddDefaultHeader("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
package ak
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
func SetUserAgent(inner http.RoundTripper, userAgent string) http.RoundTripper {
|
|
||||||
return &addUGA{
|
|
||||||
inner: inner,
|
|
||||||
Agent: userAgent,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type addUGA struct {
|
|
||||||
inner http.RoundTripper
|
|
||||||
Agent string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ug *addUGA) RoundTrip(r *http.Request) (*http.Response, error) {
|
|
||||||
r.Header.Set("User-Agent", ug.Agent)
|
|
||||||
return ug.inner.RoundTrip(r)
|
|
||||||
}
|
|
|
@ -1,6 +1,8 @@
|
||||||
package ak
|
package ak
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -9,6 +11,7 @@ import (
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
httptransport "github.com/go-openapi/runtime/client"
|
httptransport "github.com/go-openapi/runtime/client"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"goauthentik.io/api"
|
||||||
"goauthentik.io/internal/constants"
|
"goauthentik.io/internal/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,3 +69,21 @@ func GetTLSTransport() http.RoundTripper {
|
||||||
}
|
}
|
||||||
return tlsTransport
|
return tlsTransport
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseCertificate Load certificate from Keyepair UUID and parse it into a go Certificate
|
||||||
|
func ParseCertificate(kpUuid string, cryptoApi *api.CryptoApiService) (*tls.Certificate, error) {
|
||||||
|
cert, _, err := cryptoApi.CryptoCertificatekeypairsViewCertificateRetrieve(context.Background(), kpUuid).Execute()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, _, err := cryptoApi.CryptoCertificatekeypairsViewPrivateKeyRetrieve(context.Background(), kpUuid).Execute()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
x509cert, err := tls.X509KeyPair([]byte(cert.Data), []byte(key.Data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &x509cert, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -10,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"goauthentik.io/outpost/pkg/ak"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ls *LDAPServer) Refresh() error {
|
func (ls *LDAPServer) Refresh() error {
|
||||||
|
@ -24,6 +26,7 @@ func (ls *LDAPServer) Refresh() error {
|
||||||
for idx, provider := range outposts.Results {
|
for idx, provider := range outposts.Results {
|
||||||
userDN := strings.ToLower(fmt.Sprintf("ou=users,%s", *provider.BaseDn))
|
userDN := strings.ToLower(fmt.Sprintf("ou=users,%s", *provider.BaseDn))
|
||||||
groupDN := strings.ToLower(fmt.Sprintf("ou=groups,%s", *provider.BaseDn))
|
groupDN := strings.ToLower(fmt.Sprintf("ou=groups,%s", *provider.BaseDn))
|
||||||
|
logger := log.WithField("logger", "authentik.outpost.ldap").WithField("provider", provider.Name)
|
||||||
providers[idx] = &ProviderInstance{
|
providers[idx] = &ProviderInstance{
|
||||||
BaseDN: *provider.BaseDn,
|
BaseDN: *provider.BaseDn,
|
||||||
GroupDN: groupDN,
|
GroupDN: groupDN,
|
||||||
|
@ -35,6 +38,19 @@ func (ls *LDAPServer) Refresh() error {
|
||||||
boundUsers: make(map[string]UserFlags),
|
boundUsers: make(map[string]UserFlags),
|
||||||
s: ls,
|
s: ls,
|
||||||
log: log.WithField("logger", "authentik.outpost.ldap").WithField("provider", provider.Name),
|
log: log.WithField("logger", "authentik.outpost.ldap").WithField("provider", provider.Name),
|
||||||
|
tlsServerName: provider.TlsServerName,
|
||||||
|
uidStartNumber: *provider.UidStartNumber,
|
||||||
|
gidStartNumber: *provider.GidStartNumber,
|
||||||
|
}
|
||||||
|
if provider.Certificate.Get() != nil {
|
||||||
|
logger.WithField("provider", provider.Name).Debug("Enabling TLS")
|
||||||
|
cert, err := ak.ParseCertificate(*provider.Certificate.Get(), ls.ac.Client.CryptoApi)
|
||||||
|
if err != nil {
|
||||||
|
logger.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch certificate")
|
||||||
|
} else {
|
||||||
|
providers[idx].cert = cert
|
||||||
|
logger.WithField("provider", provider.Name).Debug("Loaded certificates")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ls.providers = providers
|
ls.providers = providers
|
||||||
|
@ -58,9 +74,30 @@ func (ls *LDAPServer) StartLDAPServer() error {
|
||||||
return ls.s.ListenAndServe(listen)
|
return ls.s.ListenAndServe(listen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ls *LDAPServer) StartLDAPTLSServer() error {
|
||||||
|
listen := "0.0.0.0:6636"
|
||||||
|
tlsConfig := &tls.Config{
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
MaxVersion: tls.VersionTLS12,
|
||||||
|
GetCertificate: ls.getCertificates,
|
||||||
|
}
|
||||||
|
|
||||||
|
ln, err := tls.Listen("tcp", listen, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
ls.log.Fatalf("FATAL: listen (%s) failed - %s", listen, err)
|
||||||
|
}
|
||||||
|
ls.log.WithField("listen", listen).Info("Starting ldap tls server")
|
||||||
|
err = ls.s.Serve(ln)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ls.log.Printf("closing %s", ln.Addr())
|
||||||
|
return ls.s.ListenAndServe(listen)
|
||||||
|
}
|
||||||
|
|
||||||
func (ls *LDAPServer) Start() error {
|
func (ls *LDAPServer) Start() error {
|
||||||
wg := sync.WaitGroup{}
|
wg := sync.WaitGroup{}
|
||||||
wg.Add(2)
|
wg.Add(3)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
err := ls.StartHTTPServer()
|
err := ls.StartHTTPServer()
|
||||||
|
@ -75,24 +112,13 @@ func (ls *LDAPServer) Start() error {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
err := ls.StartLDAPTLSServer()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type transport struct {
|
|
||||||
headers map[string]string
|
|
||||||
inner http.RoundTripper
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
|
||||||
for key, value := range t.headers {
|
|
||||||
req.Header.Add(key, value)
|
|
||||||
}
|
|
||||||
return t.inner.RoundTrip(req)
|
|
||||||
}
|
|
||||||
func newTransport(inner http.RoundTripper, headers map[string]string) *transport {
|
|
||||||
return &transport{
|
|
||||||
inner: inner,
|
|
||||||
headers: headers,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package ldap
|
||||||
|
|
||||||
|
import "crypto/tls"
|
||||||
|
|
||||||
|
func (ls *LDAPServer) getCertificates(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||||
|
if len(ls.providers) == 1 {
|
||||||
|
if ls.providers[0].cert != nil {
|
||||||
|
ls.log.WithField("server-name", info.ServerName).Debug("We only have a single provider, using their cert")
|
||||||
|
return ls.providers[0].cert, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, provider := range ls.providers {
|
||||||
|
if provider.tlsServerName == &info.ServerName {
|
||||||
|
if provider.cert == nil {
|
||||||
|
ls.log.WithField("server-name", info.ServerName).Debug("Handler does not have a certificate")
|
||||||
|
return ls.defaultCert, nil
|
||||||
|
}
|
||||||
|
return provider.cert, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ls.log.WithField("server-name", info.ServerName).Debug("Fallback to default cert")
|
||||||
|
return ls.defaultCert, nil
|
||||||
|
}
|
|
@ -54,12 +54,12 @@ func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn ne
|
||||||
config := api.NewConfiguration()
|
config := api.NewConfiguration()
|
||||||
config.Host = pi.s.ac.Client.GetConfig().Host
|
config.Host = pi.s.ac.Client.GetConfig().Host
|
||||||
config.Scheme = pi.s.ac.Client.GetConfig().Scheme
|
config.Scheme = pi.s.ac.Client.GetConfig().Scheme
|
||||||
|
config.UserAgent = constants.OutpostUserAgent()
|
||||||
config.HTTPClient = &http.Client{
|
config.HTTPClient = &http.Client{
|
||||||
Jar: jar,
|
Jar: jar,
|
||||||
Transport: newTransport(ak.SetUserAgent(ak.GetTLSTransport(), constants.OutpostUserAgent()), map[string]string{
|
Transport: ak.GetTLSTransport(),
|
||||||
"X-authentik-remote-ip": host,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
config.AddDefaultHeader("X-authentik-remote-ip", host)
|
||||||
// create the API client, with the transport
|
// create the API client, with the transport
|
||||||
apiClient := api.NewAPIClient(config)
|
apiClient := api.NewAPIClient(config)
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,18 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
|
||||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
|
||||||
}
|
}
|
||||||
pi.log.WithField("count", len(groups.Results)).Trace("Got results from API")
|
pi.log.WithField("count", len(groups.Results)).Trace("Got results from API")
|
||||||
|
|
||||||
for _, g := range groups.Results {
|
for _, g := range groups.Results {
|
||||||
entries = append(entries, pi.GroupEntry(g))
|
entries = append(entries, pi.GroupEntry(pi.APIGroupToLDAPGroup(g)))
|
||||||
|
}
|
||||||
|
|
||||||
|
users, _, err := pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()).Execute()
|
||||||
|
if err != nil {
|
||||||
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, fmt.Errorf("API Error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, u := range users.Results {
|
||||||
|
entries = append(entries, pi.GroupEntry(pi.APIUserToLDAPGroup(u)))
|
||||||
}
|
}
|
||||||
case UserObjectClass, "":
|
case UserObjectClass, "":
|
||||||
users, _, err := pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()).Execute()
|
users, _, err := pi.s.ac.Client.CoreApi.CoreUsersList(context.Background()).Execute()
|
||||||
|
@ -96,6 +106,14 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry {
|
||||||
Name: "objectClass",
|
Name: "objectClass",
|
||||||
Values: []string{UserObjectClass, "organizationalPerson", "goauthentik.io/ldap/user"},
|
Values: []string{UserObjectClass, "organizationalPerson", "goauthentik.io/ldap/user"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "uidNumber",
|
||||||
|
Values: []string{pi.GetUidNumber(u)},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "gidNumber",
|
||||||
|
Values: []string{pi.GetUidNumber(u)},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs = append(attrs, &ldap.EntryAttribute{Name: "memberOf", Values: pi.GroupsForUser(u)})
|
attrs = append(attrs, &ldap.EntryAttribute{Name: "memberOf", Values: pi.GroupsForUser(u)})
|
||||||
|
@ -109,28 +127,45 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry {
|
||||||
|
|
||||||
attrs = append(attrs, AKAttrsToLDAP(u.Attributes)...)
|
attrs = append(attrs, AKAttrsToLDAP(u.Attributes)...)
|
||||||
|
|
||||||
dn := fmt.Sprintf("cn=%s,%s", u.Username, pi.UserDN)
|
dn := pi.GetUserDN(u.Username)
|
||||||
|
|
||||||
return &ldap.Entry{DN: dn, Attributes: attrs}
|
return &ldap.Entry{DN: dn, Attributes: attrs}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pi *ProviderInstance) GroupEntry(g api.Group) *ldap.Entry {
|
func (pi *ProviderInstance) GroupEntry(g LDAPGroup) *ldap.Entry {
|
||||||
attrs := []*ldap.EntryAttribute{
|
attrs := []*ldap.EntryAttribute{
|
||||||
{
|
{
|
||||||
Name: "cn",
|
Name: "cn",
|
||||||
Values: []string{g.Name},
|
Values: []string{g.cn},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "uid",
|
Name: "uid",
|
||||||
Values: []string{string(g.Pk)},
|
Values: []string{g.uid},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "objectClass",
|
Name: "gidNumber",
|
||||||
Values: []string{GroupObjectClass, "goauthentik.io/ldap/group"},
|
Values: []string{g.gidNumber},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
attrs = append(attrs, AKAttrsToLDAP(g.Attributes)...)
|
|
||||||
|
|
||||||
dn := pi.GetGroupDN(g)
|
if g.isVirtualGroup {
|
||||||
return &ldap.Entry{DN: dn, Attributes: attrs}
|
attrs = append(attrs, &ldap.EntryAttribute{
|
||||||
|
Name: "objectClass",
|
||||||
|
Values: []string{GroupObjectClass, "goauthentik.io/ldap/group", "goauthentik.io/ldap/virtual-group"},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
attrs = append(attrs, &ldap.EntryAttribute{
|
||||||
|
Name: "objectClass",
|
||||||
|
Values: []string{GroupObjectClass, "goauthentik.io/ldap/group"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs = append(attrs, &ldap.EntryAttribute{Name: "member", Values: g.member})
|
||||||
|
attrs = append(attrs, &ldap.EntryAttribute{Name: "goauthentik.io/ldap/superuser", Values: []string{BoolToString(g.isSuperuser)}})
|
||||||
|
|
||||||
|
if g.akAttributes != nil {
|
||||||
|
attrs = append(attrs, AKAttrsToLDAP(g.akAttributes)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ldap.Entry{DN: g.dn, Attributes: attrs}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package ldap
|
package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/go-openapi/strfmt"
|
"github.com/go-openapi/strfmt"
|
||||||
|
@ -25,9 +26,15 @@ type ProviderInstance struct {
|
||||||
s *LDAPServer
|
s *LDAPServer
|
||||||
log *log.Entry
|
log *log.Entry
|
||||||
|
|
||||||
|
tlsServerName *string
|
||||||
|
cert *tls.Certificate
|
||||||
|
|
||||||
searchAllowedGroups []*strfmt.UUID
|
searchAllowedGroups []*strfmt.UUID
|
||||||
boundUsersMutex sync.RWMutex
|
boundUsersMutex sync.RWMutex
|
||||||
boundUsers map[string]UserFlags
|
boundUsers map[string]UserFlags
|
||||||
|
|
||||||
|
uidStartNumber int32
|
||||||
|
gidStartNumber int32
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserFlags struct {
|
type UserFlags struct {
|
||||||
|
@ -39,10 +46,21 @@ type LDAPServer struct {
|
||||||
s *ldap.Server
|
s *ldap.Server
|
||||||
log *log.Entry
|
log *log.Entry
|
||||||
ac *ak.APIController
|
ac *ak.APIController
|
||||||
|
defaultCert *tls.Certificate
|
||||||
providers []*ProviderInstance
|
providers []*ProviderInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LDAPGroup struct {
|
||||||
|
dn string
|
||||||
|
cn string
|
||||||
|
uid string
|
||||||
|
gidNumber string
|
||||||
|
member []string
|
||||||
|
isSuperuser bool
|
||||||
|
isVirtualGroup bool
|
||||||
|
akAttributes interface{}
|
||||||
|
}
|
||||||
|
|
||||||
func NewServer(ac *ak.APIController) *LDAPServer {
|
func NewServer(ac *ak.APIController) *LDAPServer {
|
||||||
s := ldap.NewServer()
|
s := ldap.NewServer()
|
||||||
s.EnforceLDAP = true
|
s.EnforceLDAP = true
|
||||||
|
@ -52,6 +70,11 @@ func NewServer(ac *ak.APIController) *LDAPServer {
|
||||||
ac: ac,
|
ac: ac,
|
||||||
providers: []*ProviderInstance{},
|
providers: []*ProviderInstance{},
|
||||||
}
|
}
|
||||||
|
defaultCert, err := ak.GenerateSelfSignedCert()
|
||||||
|
if err != nil {
|
||||||
|
log.Warning(err)
|
||||||
|
}
|
||||||
|
ls.defaultCert = &defaultCert
|
||||||
s.BindFunc("", ls)
|
s.BindFunc("", ls)
|
||||||
s.SearchFunc("", ls)
|
s.SearchFunc("", ls)
|
||||||
return ls
|
return ls
|
||||||
|
|
|
@ -2,8 +2,13 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/nmcclain/ldap"
|
"github.com/nmcclain/ldap"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"goauthentik.io/api"
|
"goauthentik.io/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,6 +19,24 @@ func BoolToString(in bool) string {
|
||||||
return "false"
|
return "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ldapResolveTypeSingle(in interface{}) *string {
|
||||||
|
switch t := in.(type) {
|
||||||
|
case string:
|
||||||
|
return &t
|
||||||
|
case *string:
|
||||||
|
return t
|
||||||
|
case bool:
|
||||||
|
s := BoolToString(t)
|
||||||
|
return &s
|
||||||
|
case *bool:
|
||||||
|
s := BoolToString(*t)
|
||||||
|
return &s
|
||||||
|
default:
|
||||||
|
log.WithField("type", reflect.TypeOf(in).String()).Warning("Type can't be mapped to LDAP yet")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
|
func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
|
||||||
attrList := []*ldap.EntryAttribute{}
|
attrList := []*ldap.EntryAttribute{}
|
||||||
a := attrs.(*map[string]interface{})
|
a := attrs.(*map[string]interface{})
|
||||||
|
@ -22,10 +45,19 @@ func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
|
||||||
switch t := attrValue.(type) {
|
switch t := attrValue.(type) {
|
||||||
case []string:
|
case []string:
|
||||||
entry.Values = t
|
entry.Values = t
|
||||||
case string:
|
case *[]string:
|
||||||
entry.Values = []string{t}
|
entry.Values = *t
|
||||||
case bool:
|
case []interface{}:
|
||||||
entry.Values = []string{BoolToString(t)}
|
entry.Values = make([]string, len(t))
|
||||||
|
for idx, v := range t {
|
||||||
|
v := ldapResolveTypeSingle(v)
|
||||||
|
entry.Values[idx] = *v
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
v := ldapResolveTypeSingle(t)
|
||||||
|
if v != nil {
|
||||||
|
entry.Values = []string{*v}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
attrList = append(attrList, entry)
|
attrList = append(attrList, entry)
|
||||||
}
|
}
|
||||||
|
@ -35,11 +67,72 @@ func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
|
||||||
func (pi *ProviderInstance) GroupsForUser(user api.User) []string {
|
func (pi *ProviderInstance) GroupsForUser(user api.User) []string {
|
||||||
groups := make([]string, len(user.Groups))
|
groups := make([]string, len(user.Groups))
|
||||||
for i, group := range user.Groups {
|
for i, group := range user.Groups {
|
||||||
groups[i] = pi.GetGroupDN(group)
|
groups[i] = pi.GetGroupDN(group.Name)
|
||||||
}
|
}
|
||||||
return groups
|
return groups
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pi *ProviderInstance) GetGroupDN(group api.Group) string {
|
func (pi *ProviderInstance) UsersForGroup(group api.Group) []string {
|
||||||
return fmt.Sprintf("cn=%s,%s", group.Name, pi.GroupDN)
|
users := make([]string, len(group.UsersObj))
|
||||||
|
for i, user := range group.UsersObj {
|
||||||
|
users[i] = pi.GetUserDN(user.Username)
|
||||||
|
}
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) APIGroupToLDAPGroup(g api.Group) LDAPGroup {
|
||||||
|
return LDAPGroup{
|
||||||
|
dn: pi.GetGroupDN(g.Name),
|
||||||
|
cn: g.Name,
|
||||||
|
uid: string(g.Pk),
|
||||||
|
gidNumber: pi.GetGidNumber(g),
|
||||||
|
member: pi.UsersForGroup(g),
|
||||||
|
isVirtualGroup: false,
|
||||||
|
isSuperuser: *g.IsSuperuser,
|
||||||
|
akAttributes: g.Attributes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) APIUserToLDAPGroup(u api.User) LDAPGroup {
|
||||||
|
return LDAPGroup{
|
||||||
|
dn: pi.GetGroupDN(u.Username),
|
||||||
|
cn: u.Username,
|
||||||
|
uid: u.Uid,
|
||||||
|
gidNumber: pi.GetUidNumber(u),
|
||||||
|
member: []string{pi.GetUserDN(u.Username)},
|
||||||
|
isVirtualGroup: true,
|
||||||
|
isSuperuser: false,
|
||||||
|
akAttributes: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) GetUserDN(user string) string {
|
||||||
|
return fmt.Sprintf("cn=%s,%s", user, pi.UserDN)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) GetGroupDN(group string) string {
|
||||||
|
return fmt.Sprintf("cn=%s,%s", group, pi.GroupDN)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) GetUidNumber(user api.User) string {
|
||||||
|
return strconv.FormatInt(int64(pi.uidStartNumber+user.Pk), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) GetGidNumber(group api.Group) string {
|
||||||
|
return strconv.FormatInt(int64(pi.gidStartNumber+pi.GetRIDForGroup(group.Pk)), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pi *ProviderInstance) GetRIDForGroup(uid string) int32 {
|
||||||
|
var i big.Int
|
||||||
|
i.SetString(strings.Replace(uid, "-", "", -1), 16)
|
||||||
|
intStr := i.String()
|
||||||
|
|
||||||
|
// Get the last 5 characters/digits of the int-version of the UUID
|
||||||
|
gid, err := strconv.Atoi(intStr[len(intStr)-5:])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return int32(gid)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package proxy
|
package proxy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -16,6 +15,7 @@ import (
|
||||||
"github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
|
"github.com/oauth2-proxy/oauth2-proxy/pkg/validation"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"goauthentik.io/api"
|
"goauthentik.io/api"
|
||||||
|
"goauthentik.io/internal/outpost/ak"
|
||||||
)
|
)
|
||||||
|
|
||||||
type providerBundle struct {
|
type providerBundle struct {
|
||||||
|
@ -90,23 +90,12 @@ func (pb *providerBundle) prepareOpts(provider api.ProxyOutpostConfig) *options.
|
||||||
|
|
||||||
if provider.Certificate.Get() != nil {
|
if provider.Certificate.Get() != nil {
|
||||||
pb.log.WithField("provider", provider.Name).Debug("Enabling TLS")
|
pb.log.WithField("provider", provider.Name).Debug("Enabling TLS")
|
||||||
cert, _, err := pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewCertificateRetrieve(context.Background(), *provider.Certificate.Get()).Execute()
|
cert, err := ak.ParseCertificate(*provider.Certificate.Get(), pb.s.ak.Client.CryptoApi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch certificate")
|
pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch certificate")
|
||||||
return providerOpts
|
return providerOpts
|
||||||
}
|
}
|
||||||
key, _, err := pb.s.ak.Client.CryptoApi.CryptoCertificatekeypairsViewPrivateKeyRetrieve(context.Background(), *provider.Certificate.Get()).Execute()
|
pb.cert = cert
|
||||||
if err != nil {
|
|
||||||
pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to fetch private key")
|
|
||||||
return providerOpts
|
|
||||||
}
|
|
||||||
|
|
||||||
x509cert, err := tls.X509KeyPair([]byte(cert.Data), []byte(key.Data))
|
|
||||||
if err != nil {
|
|
||||||
pb.log.WithField("provider", provider.Name).WithError(err).Warning("Failed to parse certificate")
|
|
||||||
return providerOpts
|
|
||||||
}
|
|
||||||
pb.cert = &x509cert
|
|
||||||
pb.log.WithField("provider", provider.Name).Debug("Loaded certificates")
|
pb.log.WithField("provider", provider.Name).Debug("Loaded certificates")
|
||||||
}
|
}
|
||||||
return providerOpts
|
return providerOpts
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"goauthentik.io/internal/config"
|
"goauthentik.io/internal/config"
|
||||||
"goauthentik.io/internal/constants"
|
"goauthentik.io/internal/constants"
|
||||||
staticWeb "goauthentik.io/web"
|
staticWeb "goauthentik.io/web"
|
||||||
|
staticDocs "goauthentik.io/website"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ws *WebServer) configureStatic() {
|
func (ws *WebServer) configureStatic() {
|
||||||
|
@ -16,14 +17,15 @@ func (ws *WebServer) configureStatic() {
|
||||||
ws.log.Debug("Using local static files")
|
ws.log.Debug("Using local static files")
|
||||||
statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static/dist", http.FileServer(http.Dir("./web/dist"))))
|
statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static/dist", http.FileServer(http.Dir("./web/dist"))))
|
||||||
statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static/authentik", http.FileServer(http.Dir("./web/authentik"))))
|
statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static/authentik", http.FileServer(http.Dir("./web/authentik"))))
|
||||||
statRouter.PathPrefix("/media").Handler(http.StripPrefix("/media", fs))
|
statRouter.PathPrefix("/help").Handler(http.StripPrefix("/help", http.FileServer(http.Dir("./website/help"))))
|
||||||
} else {
|
} else {
|
||||||
statRouter.Use(ws.staticHeaderMiddleware)
|
statRouter.Use(ws.staticHeaderMiddleware)
|
||||||
ws.log.Debug("Using packaged static files with aggressive caching")
|
ws.log.Debug("Using packaged static files with aggressive caching")
|
||||||
statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticDist))))
|
statRouter.PathPrefix("/static/dist").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticDist))))
|
||||||
statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticAuthentik))))
|
statRouter.PathPrefix("/static/authentik").Handler(http.StripPrefix("/static", http.FileServer(http.FS(staticWeb.StaticAuthentik))))
|
||||||
statRouter.PathPrefix("/media").Handler(http.StripPrefix("/media", fs))
|
statRouter.PathPrefix("/help").Handler(http.FileServer(http.FS(staticDocs.Help)))
|
||||||
}
|
}
|
||||||
|
statRouter.PathPrefix("/media").Handler(http.StripPrefix("/media", fs))
|
||||||
ws.lh.Path("/robots.txt").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
ws.lh.Path("/robots.txt").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||||
rw.Header()["Content-Type"] = []string{"text/plain"}
|
rw.Header()["Content-Type"] = []string{"text/plain"}
|
||||||
rw.WriteHeader(200)
|
rw.WriteHeader(200)
|
||||||
|
|
|
@ -14,7 +14,7 @@ RUN docker-entrypoint.sh generate \
|
||||||
rm -f /local/api/go.mod /local/api/go.sum
|
rm -f /local/api/go.mod /local/api/go.sum
|
||||||
|
|
||||||
# Stage 2: Build
|
# Stage 2: Build
|
||||||
FROM golang:1.16.5 AS builder
|
FROM golang:1.16.6 AS builder
|
||||||
ARG GIT_BUILD_HASH
|
ARG GIT_BUILD_HASH
|
||||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ if __name__ == "__main__":
|
||||||
user=CONFIG.y("postgresql.user"),
|
user=CONFIG.y("postgresql.user"),
|
||||||
password=CONFIG.y("postgresql.password"),
|
password=CONFIG.y("postgresql.password"),
|
||||||
host=CONFIG.y("postgresql.host"),
|
host=CONFIG.y("postgresql.host"),
|
||||||
|
port=int(CONFIG.y("postgresql.port")),
|
||||||
)
|
)
|
||||||
curr = conn.cursor()
|
curr = conn.cursor()
|
||||||
# lock an advisory lock to prevent multiple instances from migrating at once
|
# lock an advisory lock to prevent multiple instances from migrating at once
|
||||||
|
|
|
@ -40,11 +40,15 @@ while True:
|
||||||
sleep(1)
|
sleep(1)
|
||||||
j_print(f"PostgreSQL Connection failed, retrying... ({exc})")
|
j_print(f"PostgreSQL Connection failed, retrying... ({exc})")
|
||||||
|
|
||||||
|
REDIS_PROTOCOL_PREFIX = "redis://"
|
||||||
|
if CONFIG.y_bool("redis.tls", False):
|
||||||
|
REDIS_PROTOCOL_PREFIX = "rediss://"
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
redis = Redis.from_url(
|
redis = Redis.from_url(
|
||||||
f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379"
|
f"{REDIS_PROTOCOL_PREFIX}:"
|
||||||
f"/{CONFIG.y('redis.ws_db')}"
|
f"{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:"
|
||||||
|
f"{int(CONFIG.y('redis.port'))}/{CONFIG.y('redis.ws_db')}"
|
||||||
)
|
)
|
||||||
redis.ping()
|
redis.ping()
|
||||||
break
|
break
|
||||||
|
|
|
@ -14,7 +14,7 @@ RUN docker-entrypoint.sh generate \
|
||||||
rm -f /local/api/go.mod /local/api/go.sum
|
rm -f /local/api/go.mod /local/api/go.sum
|
||||||
|
|
||||||
# Stage 2: Build
|
# Stage 2: Build
|
||||||
FROM golang:1.16.5 AS builder
|
FROM golang:1.16.6 AS builder
|
||||||
ARG GIT_BUILD_HASH
|
ARG GIT_BUILD_HASH
|
||||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||||
|
|
||||||
|
|
183
schema.yml
183
schema.yml
|
@ -2429,6 +2429,15 @@ paths:
|
||||||
name: description
|
name: description
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: expires
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
- in: query
|
||||||
|
name: expiring
|
||||||
|
schema:
|
||||||
|
type: boolean
|
||||||
- in: query
|
- in: query
|
||||||
name: identifier
|
name: identifier
|
||||||
schema:
|
schema:
|
||||||
|
@ -19432,6 +19441,7 @@ components:
|
||||||
- suspicious_request
|
- suspicious_request
|
||||||
- password_set
|
- password_set
|
||||||
- secret_view
|
- secret_view
|
||||||
|
- secret_rotate
|
||||||
- invitation_used
|
- invitation_used
|
||||||
- authorize_application
|
- authorize_application
|
||||||
- source_linked
|
- source_linked
|
||||||
|
@ -19927,11 +19937,100 @@ components:
|
||||||
attributes:
|
attributes:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: {}
|
additionalProperties: {}
|
||||||
|
users_obj:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/GroupMember'
|
||||||
|
readOnly: true
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- parent
|
- parent
|
||||||
- pk
|
- pk
|
||||||
- users
|
- users
|
||||||
|
- users_obj
|
||||||
|
GroupMember:
|
||||||
|
type: object
|
||||||
|
description: Stripped down user serializer to show relevant users for groups
|
||||||
|
properties:
|
||||||
|
pk:
|
||||||
|
type: integer
|
||||||
|
readOnly: true
|
||||||
|
title: ID
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
|
||||||
|
only.
|
||||||
|
pattern: ^[\w.@+-]+$
|
||||||
|
maxLength: 150
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: User's display name.
|
||||||
|
is_active:
|
||||||
|
type: boolean
|
||||||
|
title: Active
|
||||||
|
description: Designates whether this user should be treated as active. Unselect
|
||||||
|
this instead of deleting accounts.
|
||||||
|
last_login:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
nullable: true
|
||||||
|
is_superuser:
|
||||||
|
type: boolean
|
||||||
|
readOnly: true
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
title: Email address
|
||||||
|
maxLength: 254
|
||||||
|
avatar:
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
attributes:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
|
uid:
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
required:
|
||||||
|
- avatar
|
||||||
|
- is_superuser
|
||||||
|
- name
|
||||||
|
- pk
|
||||||
|
- uid
|
||||||
|
- username
|
||||||
|
GroupMemberRequest:
|
||||||
|
type: object
|
||||||
|
description: Stripped down user serializer to show relevant users for groups
|
||||||
|
properties:
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
|
||||||
|
only.
|
||||||
|
pattern: ^[\w.@+-]+$
|
||||||
|
maxLength: 150
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: User's display name.
|
||||||
|
is_active:
|
||||||
|
type: boolean
|
||||||
|
title: Active
|
||||||
|
description: Designates whether this user should be treated as active. Unselect
|
||||||
|
this instead of deleting accounts.
|
||||||
|
last_login:
|
||||||
|
type: string
|
||||||
|
format: date-time
|
||||||
|
nullable: true
|
||||||
|
email:
|
||||||
|
type: string
|
||||||
|
format: email
|
||||||
|
title: Email address
|
||||||
|
maxLength: 254
|
||||||
|
attributes:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- username
|
||||||
GroupRequest:
|
GroupRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Group Serializer
|
description: Group Serializer
|
||||||
|
@ -20402,6 +20501,27 @@ components:
|
||||||
nullable: true
|
nullable: true
|
||||||
description: Users in this group can do search queries. If not set, every
|
description: Users in this group can do search queries. If not set, every
|
||||||
user can execute search queries.
|
user can execute search queries.
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
tls_server_name:
|
||||||
|
type: string
|
||||||
|
uid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for uidNumbers, this number is added to the user.Pk
|
||||||
|
to make sure that the numbers aren't too low for POSIX users. Default
|
||||||
|
is 2000 to ensure that we don't collide with local users uidNumber
|
||||||
|
gid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for gidNumbers, this number is added to a number
|
||||||
|
generated from the group.Pk to make sure that the numbers aren't too low
|
||||||
|
for POSIX groups. Default is 4000 to ensure that we don't collide with
|
||||||
|
local groups or users primary groups gidNumber
|
||||||
required:
|
required:
|
||||||
- application_slug
|
- application_slug
|
||||||
- bind_flow_slug
|
- bind_flow_slug
|
||||||
|
@ -20514,6 +20634,27 @@ components:
|
||||||
nullable: true
|
nullable: true
|
||||||
description: Users in this group can do search queries. If not set, every
|
description: Users in this group can do search queries. If not set, every
|
||||||
user can execute search queries.
|
user can execute search queries.
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
tls_server_name:
|
||||||
|
type: string
|
||||||
|
uid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for uidNumbers, this number is added to the user.Pk
|
||||||
|
to make sure that the numbers aren't too low for POSIX users. Default
|
||||||
|
is 2000 to ensure that we don't collide with local users uidNumber
|
||||||
|
gid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for gidNumbers, this number is added to a number
|
||||||
|
generated from the group.Pk to make sure that the numbers aren't too low
|
||||||
|
for POSIX groups. Default is 4000 to ensure that we don't collide with
|
||||||
|
local groups or users primary groups gidNumber
|
||||||
required:
|
required:
|
||||||
- assigned_application_name
|
- assigned_application_name
|
||||||
- assigned_application_slug
|
- assigned_application_slug
|
||||||
|
@ -20547,6 +20688,27 @@ components:
|
||||||
nullable: true
|
nullable: true
|
||||||
description: Users in this group can do search queries. If not set, every
|
description: Users in this group can do search queries. If not set, every
|
||||||
user can execute search queries.
|
user can execute search queries.
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
tls_server_name:
|
||||||
|
type: string
|
||||||
|
uid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for uidNumbers, this number is added to the user.Pk
|
||||||
|
to make sure that the numbers aren't too low for POSIX users. Default
|
||||||
|
is 2000 to ensure that we don't collide with local users uidNumber
|
||||||
|
gid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for gidNumbers, this number is added to a number
|
||||||
|
generated from the group.Pk to make sure that the numbers aren't too low
|
||||||
|
for POSIX groups. Default is 4000 to ensure that we don't collide with
|
||||||
|
local groups or users primary groups gidNumber
|
||||||
required:
|
required:
|
||||||
- authorization_flow
|
- authorization_flow
|
||||||
- name
|
- name
|
||||||
|
@ -24899,6 +25061,27 @@ components:
|
||||||
nullable: true
|
nullable: true
|
||||||
description: Users in this group can do search queries. If not set, every
|
description: Users in this group can do search queries. If not set, every
|
||||||
user can execute search queries.
|
user can execute search queries.
|
||||||
|
certificate:
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
|
nullable: true
|
||||||
|
tls_server_name:
|
||||||
|
type: string
|
||||||
|
uid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for uidNumbers, this number is added to the user.Pk
|
||||||
|
to make sure that the numbers aren't too low for POSIX users. Default
|
||||||
|
is 2000 to ensure that we don't collide with local users uidNumber
|
||||||
|
gid_start_number:
|
||||||
|
type: integer
|
||||||
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: The start for gidNumbers, this number is added to a number
|
||||||
|
generated from the group.Pk to make sure that the numbers aren't too low
|
||||||
|
for POSIX groups. Default is 4000 to ensure that we don't collide with
|
||||||
|
local groups or users primary groups gidNumber
|
||||||
PatchedLDAPSourceRequest:
|
PatchedLDAPSourceRequest:
|
||||||
type: object
|
type: object
|
||||||
description: LDAP Source Serializer
|
description: LDAP Source Serializer
|
||||||
|
|
|
@ -194,6 +194,8 @@ class TestProviderLDAP(SeleniumTestCase):
|
||||||
"organizationalPerson",
|
"organizationalPerson",
|
||||||
"goauthentik.io/ldap/user",
|
"goauthentik.io/ldap/user",
|
||||||
],
|
],
|
||||||
|
"uidNumber": [str(2000 + outpost_user.pk)],
|
||||||
|
"gidNumber": [str(2000 + outpost_user.pk)],
|
||||||
"memberOf": [],
|
"memberOf": [],
|
||||||
"accountStatus": ["true"],
|
"accountStatus": ["true"],
|
||||||
"superuser": ["false"],
|
"superuser": ["false"],
|
||||||
|
@ -217,6 +219,8 @@ class TestProviderLDAP(SeleniumTestCase):
|
||||||
"organizationalPerson",
|
"organizationalPerson",
|
||||||
"goauthentik.io/ldap/user",
|
"goauthentik.io/ldap/user",
|
||||||
],
|
],
|
||||||
|
"uidNumber": [str(2000 + USER().pk)],
|
||||||
|
"gidNumber": [str(2000 + USER().pk)],
|
||||||
"memberOf": [
|
"memberOf": [
|
||||||
"cn=authentik Admins,ou=groups,dc=ldap,dc=goauthentik,dc=io"
|
"cn=authentik Admins,ou=groups,dc=ldap,dc=goauthentik,dc=io"
|
||||||
],
|
],
|
||||||
|
|
|
@ -23,14 +23,14 @@
|
||||||
"@polymer/paper-input": "^3.2.1",
|
"@polymer/paper-input": "^3.2.1",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-replace": "^2.4.2",
|
"@rollup/plugin-replace": "^2.4.2",
|
||||||
"@rollup/plugin-typescript": "^8.2.1",
|
"@rollup/plugin-typescript": "^8.2.3",
|
||||||
"@sentry/browser": "^6.8.0",
|
"@sentry/browser": "^6.9.0",
|
||||||
"@sentry/tracing": "^6.8.0",
|
"@sentry/tracing": "^6.9.0",
|
||||||
"@types/chart.js": "^2.9.34",
|
"@types/chart.js": "^2.9.34",
|
||||||
"@types/codemirror": "5.60.2",
|
"@types/codemirror": "5.60.2",
|
||||||
"@types/grecaptcha": "^3.0.3",
|
"@types/grecaptcha": "^3.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
"@typescript-eslint/eslint-plugin": "^4.28.3",
|
||||||
"@typescript-eslint/parser": "^4.28.2",
|
"@typescript-eslint/parser": "^4.28.3",
|
||||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||||
"authentik-api": "file:api",
|
"authentik-api": "file:api",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
"lit-html": "^1.4.1",
|
"lit-html": "^1.4.1",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"rapidoc": "^9.0.0",
|
"rapidoc": "^9.0.0",
|
||||||
"rollup": "^2.52.8",
|
"rollup": "^2.53.2",
|
||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
"rollup-plugin-cssimport": "^1.0.2",
|
"rollup-plugin-cssimport": "^1.0.2",
|
||||||
|
@ -66,16 +66,15 @@
|
||||||
},
|
},
|
||||||
"api": {
|
"api": {
|
||||||
"name": "authentik-api",
|
"name": "authentik-api",
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"devDependencies": {
|
"dependencies": {
|
||||||
"typescript": "^3.6"
|
"typescript": "^3.9.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"api/node_modules/typescript": {
|
"api/node_modules/typescript": {
|
||||||
"version": "3.9.9",
|
"version": "3.9.9",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
|
||||||
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
|
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
@ -2299,15 +2298,20 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/plugin-typescript": {
|
"node_modules/@rollup/plugin-typescript": {
|
||||||
"version": "8.2.1",
|
"version": "8.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.3.tgz",
|
||||||
"integrity": "sha512-Qd2E1pleDR4bwyFxqbjt4eJf+wB0UKVMLc7/BAFDGVdAXQMCsD4DUv5/7/ww47BZCYxWtJqe1Lo0KVNswBJlRw==",
|
"integrity": "sha512-bSkd+DD3wP9OLU6lPet59B6jJF29/RlxHkbwvOVOcf1nk8eQYWw24HpldEdrPo/WG0QAPD7TqI7+2y5jtdqjww==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@rollup/pluginutils": "^3.1.0",
|
"@rollup/pluginutils": "^3.1.0",
|
||||||
"resolve": "^1.17.0"
|
"resolve": "^1.17.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"rollup": "^2.14.0",
|
||||||
|
"tslib": "*",
|
||||||
|
"typescript": ">=3.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/pluginutils": {
|
"node_modules/@rollup/pluginutils": {
|
||||||
|
@ -2334,13 +2338,13 @@
|
||||||
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="
|
"integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/browser": {
|
"node_modules/@sentry/browser": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.9.0.tgz",
|
||||||
"integrity": "sha512-nxa71csHlG5sMHUxI4e4xxuCWtbCv/QbBfMsYw7ncJSfCKG3yNlCVh8NJ7NS0rZW/MJUT6S6+r93zw0HetNDOA==",
|
"integrity": "sha512-4JnEPcwoNs6JqeEd4wscBq+hxpotEJ0DJ4eOIsaNZIMyqEHXBHTXCk/gfrSsiZFrkHM4PgvUHOxaC0HcZ92oBA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/core": "6.8.0",
|
"@sentry/core": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2353,14 +2357,14 @@
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/core": {
|
"node_modules/@sentry/core": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.9.0.tgz",
|
||||||
"integrity": "sha512-vJzWt/znEB+JqVwtwfjkRrAYRN+ep+l070Ti8GhJnvwU4IDtVlV3T/jVNrj6rl6UChcczaJQMxVxtG5x0crlAA==",
|
"integrity": "sha512-oFX2qQcMLujCeIuCQGlhpTUIOXiU5n6V2lqDnvMXUV8gKpplBPalwdlR9bgbSi+VO8u7LjHR1IKM0RAPWgNHWw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/minimal": "6.8.0",
|
"@sentry/minimal": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2373,12 +2377,12 @@
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/hub": {
|
"node_modules/@sentry/hub": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.9.0.tgz",
|
||||||
"integrity": "sha512-hFrI2Ss1fTov7CH64FJpigqRxH7YvSnGeqxT9Jc1BL7nzW/vgCK+Oh2mOZbosTcrzoDv+lE8ViOnSN3w/fo+rg==",
|
"integrity": "sha512-5mors7ojbo7G85ZmoVPQBgFBMONAJwyZfV0LNLy14GenoaVNuxTPyvAQiJb1FYq+x6YZ3CvqGX6r74KRKQU87w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2391,12 +2395,12 @@
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/minimal": {
|
"node_modules/@sentry/minimal": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.9.0.tgz",
|
||||||
"integrity": "sha512-MRxUKXiiYwKjp8mOQMpTpEuIby1Jh3zRTU0cmGZtfsZ38BC1JOle8xlwC4FdtOH+VvjSYnPBMya5lgNHNPUJDQ==",
|
"integrity": "sha512-GBZ6wG2Rc1wInYEl2BZTZc/t57O1Da876ifLsSPpEQAEnGWbqZWb8RLjZskH09ZIL/K4XCIDDi5ySzN8kFUWJw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2409,14 +2413,14 @@
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/tracing": {
|
"node_modules/@sentry/tracing": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.9.0.tgz",
|
||||||
"integrity": "sha512-3gDkQnmOuOjHz5rY7BOatLEUksANU3efR8wuBa2ujsPQvoLSLFuyZpRjPPsxuUHQOqAYIbSNAoDloXECvQeHjw==",
|
"integrity": "sha512-gogVTypolhPazXr3Lue8HgzBg5Sy1cQpEp5Iq9LtECs+TlOlxJ+S+P+EIjEZ0f1AHVu706jr5cY2G2Shluli9g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/minimal": "6.8.0",
|
"@sentry/minimal": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2429,19 +2433,19 @@
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/types": {
|
"node_modules/@sentry/types": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.9.0.tgz",
|
||||||
"integrity": "sha512-PbSxqlh6Fd5thNU5f8EVYBVvX+G7XdPA+ThNb2QvSK8yv3rIf0McHTyF6sIebgJ38OYN7ZFK7vvhC/RgSAfYTA==",
|
"integrity": "sha512-v52HJqLoLapEnqS2NdVtUXPvT+aezQgNXQkp8hiQ3RUdTm5cffwBVG7wlbpE6OsOOIZxd6p1zKylFkwCypiIIA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sentry/utils": {
|
"node_modules/@sentry/utils": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.9.0.tgz",
|
||||||
"integrity": "sha512-OYlI2JNrcWKMdvYbWNdQwR4QBVv2V0y5wK0U6f53nArv6RsyO5TzwRu5rMVSIZofUUqjoE5hl27jqnR+vpUrsA==",
|
"integrity": "sha512-PimDr6KAi4cCp5hQZ8Az2/pDcdfhTu7WAU30Dd9MZwknpHSTmD4G6QvkdrB5er6kMMnNQOC7rMo6w/Do3m6X3w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2537,9 +2541,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.7",
|
"version": "7.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz",
|
||||||
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA=="
|
"integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/minimatch": {
|
"node_modules/@types/minimatch": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
|
@ -2599,12 +2603,12 @@
|
||||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.3.tgz",
|
||||||
"integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==",
|
"integrity": "sha512-jW8sEFu1ZeaV8xzwsfi6Vgtty2jf7/lJmQmDkDruBjYAbx5DA8JtbcMnP0rNPUG+oH5GoQBTSp+9613BzuIpYg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/experimental-utils": "4.28.2",
|
"@typescript-eslint/experimental-utils": "4.28.3",
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"regexpp": "^3.1.0",
|
"regexpp": "^3.1.0",
|
||||||
|
@ -2629,14 +2633,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/experimental-utils": {
|
"node_modules/@typescript-eslint/experimental-utils": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.3.tgz",
|
||||||
"integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==",
|
"integrity": "sha512-zZYl9TnrxwEPi3FbyeX0ZnE8Hp7j3OCR+ELoUfbwGHGxWnHg9+OqSmkw2MoCVpZksPCZYpQzC559Ee9pJNHTQw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/typescript-estree": "4.28.2",
|
"@typescript-eslint/typescript-estree": "4.28.3",
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -2669,13 +2673,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.3.tgz",
|
||||||
"integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==",
|
"integrity": "sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/typescript-estree": "4.28.2",
|
"@typescript-eslint/typescript-estree": "4.28.3",
|
||||||
"debug": "^4.3.1"
|
"debug": "^4.3.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -2695,12 +2699,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz",
|
||||||
"integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==",
|
"integrity": "sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/visitor-keys": "4.28.2"
|
"@typescript-eslint/visitor-keys": "4.28.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||||
|
@ -2711,9 +2715,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.3.tgz",
|
||||||
"integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA==",
|
"integrity": "sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||||
},
|
},
|
||||||
|
@ -2723,12 +2727,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz",
|
||||||
"integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==",
|
"integrity": "sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/visitor-keys": "4.28.2",
|
"@typescript-eslint/visitor-keys": "4.28.3",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"globby": "^11.0.3",
|
"globby": "^11.0.3",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
|
@ -2768,11 +2772,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz",
|
||||||
"integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==",
|
"integrity": "sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -6791,9 +6795,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "2.52.8",
|
"version": "2.53.2",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.8.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.53.2.tgz",
|
||||||
"integrity": "sha512-IjAB0C6KK5/lvqzJWAzsvOik+jV5Bt907QdkQ/gDP4j+R9KYNI1tjqdxiPitGPVrWC21Mf/ucXgowUjN/VemaQ==",
|
"integrity": "sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"rollup": "dist/bin/rollup"
|
"rollup": "dist/bin/rollup"
|
||||||
},
|
},
|
||||||
|
@ -9675,9 +9679,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@rollup/plugin-typescript": {
|
"@rollup/plugin-typescript": {
|
||||||
"version": "8.2.1",
|
"version": "8.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.3.tgz",
|
||||||
"integrity": "sha512-Qd2E1pleDR4bwyFxqbjt4eJf+wB0UKVMLc7/BAFDGVdAXQMCsD4DUv5/7/ww47BZCYxWtJqe1Lo0KVNswBJlRw==",
|
"integrity": "sha512-bSkd+DD3wP9OLU6lPet59B6jJF29/RlxHkbwvOVOcf1nk8eQYWw24HpldEdrPo/WG0QAPD7TqI7+2y5jtdqjww==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@rollup/pluginutils": "^3.1.0",
|
"@rollup/pluginutils": "^3.1.0",
|
||||||
"resolve": "^1.17.0"
|
"resolve": "^1.17.0"
|
||||||
|
@ -9706,13 +9710,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/browser": {
|
"@sentry/browser": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.9.0.tgz",
|
||||||
"integrity": "sha512-nxa71csHlG5sMHUxI4e4xxuCWtbCv/QbBfMsYw7ncJSfCKG3yNlCVh8NJ7NS0rZW/MJUT6S6+r93zw0HetNDOA==",
|
"integrity": "sha512-4JnEPcwoNs6JqeEd4wscBq+hxpotEJ0DJ4eOIsaNZIMyqEHXBHTXCk/gfrSsiZFrkHM4PgvUHOxaC0HcZ92oBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/core": "6.8.0",
|
"@sentry/core": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9724,14 +9728,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/core": {
|
"@sentry/core": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.9.0.tgz",
|
||||||
"integrity": "sha512-vJzWt/znEB+JqVwtwfjkRrAYRN+ep+l070Ti8GhJnvwU4IDtVlV3T/jVNrj6rl6UChcczaJQMxVxtG5x0crlAA==",
|
"integrity": "sha512-oFX2qQcMLujCeIuCQGlhpTUIOXiU5n6V2lqDnvMXUV8gKpplBPalwdlR9bgbSi+VO8u7LjHR1IKM0RAPWgNHWw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/minimal": "6.8.0",
|
"@sentry/minimal": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9743,12 +9747,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/hub": {
|
"@sentry/hub": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.9.0.tgz",
|
||||||
"integrity": "sha512-hFrI2Ss1fTov7CH64FJpigqRxH7YvSnGeqxT9Jc1BL7nzW/vgCK+Oh2mOZbosTcrzoDv+lE8ViOnSN3w/fo+rg==",
|
"integrity": "sha512-5mors7ojbo7G85ZmoVPQBgFBMONAJwyZfV0LNLy14GenoaVNuxTPyvAQiJb1FYq+x6YZ3CvqGX6r74KRKQU87w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9760,12 +9764,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/minimal": {
|
"@sentry/minimal": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.9.0.tgz",
|
||||||
"integrity": "sha512-MRxUKXiiYwKjp8mOQMpTpEuIby1Jh3zRTU0cmGZtfsZ38BC1JOle8xlwC4FdtOH+VvjSYnPBMya5lgNHNPUJDQ==",
|
"integrity": "sha512-GBZ6wG2Rc1wInYEl2BZTZc/t57O1Da876ifLsSPpEQAEnGWbqZWb8RLjZskH09ZIL/K4XCIDDi5ySzN8kFUWJw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9777,14 +9781,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/tracing": {
|
"@sentry/tracing": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.9.0.tgz",
|
||||||
"integrity": "sha512-3gDkQnmOuOjHz5rY7BOatLEUksANU3efR8wuBa2ujsPQvoLSLFuyZpRjPPsxuUHQOqAYIbSNAoDloXECvQeHjw==",
|
"integrity": "sha512-gogVTypolhPazXr3Lue8HgzBg5Sy1cQpEp5Iq9LtECs+TlOlxJ+S+P+EIjEZ0f1AHVu706jr5cY2G2Shluli9g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/hub": "6.8.0",
|
"@sentry/hub": "6.9.0",
|
||||||
"@sentry/minimal": "6.8.0",
|
"@sentry/minimal": "6.9.0",
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"@sentry/utils": "6.8.0",
|
"@sentry/utils": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9796,16 +9800,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sentry/types": {
|
"@sentry/types": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.9.0.tgz",
|
||||||
"integrity": "sha512-PbSxqlh6Fd5thNU5f8EVYBVvX+G7XdPA+ThNb2QvSK8yv3rIf0McHTyF6sIebgJ38OYN7ZFK7vvhC/RgSAfYTA=="
|
"integrity": "sha512-v52HJqLoLapEnqS2NdVtUXPvT+aezQgNXQkp8hiQ3RUdTm5cffwBVG7wlbpE6OsOOIZxd6p1zKylFkwCypiIIA=="
|
||||||
},
|
},
|
||||||
"@sentry/utils": {
|
"@sentry/utils": {
|
||||||
"version": "6.8.0",
|
"version": "6.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.9.0.tgz",
|
||||||
"integrity": "sha512-OYlI2JNrcWKMdvYbWNdQwR4QBVv2V0y5wK0U6f53nArv6RsyO5TzwRu5rMVSIZofUUqjoE5hl27jqnR+vpUrsA==",
|
"integrity": "sha512-PimDr6KAi4cCp5hQZ8Az2/pDcdfhTu7WAU30Dd9MZwknpHSTmD4G6QvkdrB5er6kMMnNQOC7rMo6w/Do3m6X3w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sentry/types": "6.8.0",
|
"@sentry/types": "6.9.0",
|
||||||
"tslib": "^1.9.3"
|
"tslib": "^1.9.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -9900,9 +9904,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/json-schema": {
|
"@types/json-schema": {
|
||||||
"version": "7.0.7",
|
"version": "7.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz",
|
||||||
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA=="
|
"integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg=="
|
||||||
},
|
},
|
||||||
"@types/minimatch": {
|
"@types/minimatch": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
|
@ -9962,12 +9966,12 @@
|
||||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.28.3.tgz",
|
||||||
"integrity": "sha512-PGqpLLzHSxq956rzNGasO3GsAPf2lY9lDUBXhS++SKonglUmJypaUtcKzRtUte8CV7nruwnDxtLUKpVxs0wQBw==",
|
"integrity": "sha512-jW8sEFu1ZeaV8xzwsfi6Vgtty2jf7/lJmQmDkDruBjYAbx5DA8JtbcMnP0rNPUG+oH5GoQBTSp+9613BzuIpYg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/experimental-utils": "4.28.2",
|
"@typescript-eslint/experimental-utils": "4.28.3",
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"regexpp": "^3.1.0",
|
"regexpp": "^3.1.0",
|
||||||
|
@ -9976,14 +9980,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/experimental-utils": {
|
"@typescript-eslint/experimental-utils": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.28.3.tgz",
|
||||||
"integrity": "sha512-MwHPsL6qo98RC55IoWWP8/opTykjTp4JzfPu1VfO2Z0MshNP0UZ1GEV5rYSSnZSUI8VD7iHvtIPVGW5Nfh7klQ==",
|
"integrity": "sha512-zZYl9TnrxwEPi3FbyeX0ZnE8Hp7j3OCR+ELoUfbwGHGxWnHg9+OqSmkw2MoCVpZksPCZYpQzC559Ee9pJNHTQw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.7",
|
"@types/json-schema": "^7.0.7",
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/typescript-estree": "4.28.2",
|
"@typescript-eslint/typescript-estree": "4.28.3",
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -9999,37 +10003,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.3.tgz",
|
||||||
"integrity": "sha512-Q0gSCN51eikAgFGY+gnd5p9bhhCUAl0ERMiDKrTzpSoMYRubdB8MJrTTR/BBii8z+iFwz8oihxd0RAdP4l8w8w==",
|
"integrity": "sha512-ZyWEn34bJexn/JNYvLQab0Mo5e+qqQNhknxmc8azgNd4XqspVYR5oHq9O11fLwdZMRcj4by15ghSlIEq+H5ltQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/scope-manager": "4.28.2",
|
"@typescript-eslint/scope-manager": "4.28.3",
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/typescript-estree": "4.28.2",
|
"@typescript-eslint/typescript-estree": "4.28.3",
|
||||||
"debug": "^4.3.1"
|
"debug": "^4.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/scope-manager": {
|
"@typescript-eslint/scope-manager": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.3.tgz",
|
||||||
"integrity": "sha512-MqbypNjIkJFEFuOwPWNDjq0nqXAKZvDNNs9yNseoGBB1wYfz1G0WHC2AVOy4XD7di3KCcW3+nhZyN6zruqmp2A==",
|
"integrity": "sha512-/8lMisZ5NGIzGtJB+QizQ5eX4Xd8uxedFfMBXOKuJGP0oaBBVEMbJVddQKDXyyB0bPlmt8i6bHV89KbwOelJiQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/visitor-keys": "4.28.2"
|
"@typescript-eslint/visitor-keys": "4.28.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.3.tgz",
|
||||||
"integrity": "sha512-Gr15fuQVd93uD9zzxbApz3wf7ua3yk4ZujABZlZhaxxKY8ojo448u7XTm/+ETpy0V0dlMtj6t4VdDvdc0JmUhA=="
|
"integrity": "sha512-kQFaEsQBQVtA9VGVyciyTbIg7S3WoKHNuOp/UF5RG40900KtGqfoiETWD/v0lzRXc+euVE9NXmfer9dLkUJrkA=="
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.3.tgz",
|
||||||
"integrity": "sha512-86lLstLvK6QjNZjMoYUBMMsULFw0hPHJlk1fzhAVoNjDBuPVxiwvGuPQq3fsBMCxuDJwmX87tM/AXoadhHRljg==",
|
"integrity": "sha512-YAb1JED41kJsqCQt1NcnX5ZdTA93vKFCMP4lQYG6CFxd0VzDJcKttRlMrlG+1qiWAw8+zowmHU1H0OzjWJzR2w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"@typescript-eslint/visitor-keys": "4.28.2",
|
"@typescript-eslint/visitor-keys": "4.28.3",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"globby": "^11.0.3",
|
"globby": "^11.0.3",
|
||||||
"is-glob": "^4.0.1",
|
"is-glob": "^4.0.1",
|
||||||
|
@ -10053,11 +10057,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
"version": "4.28.2",
|
"version": "4.28.3",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.2.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.3.tgz",
|
||||||
"integrity": "sha512-aT2B4PLyyRDUVUafXzpZFoc0C9t0za4BJAKP5sgWIhG+jHECQZUEjuQSCIwZdiJJ4w4cgu5r3Kh20SOdtEBl0w==",
|
"integrity": "sha512-ri1OzcLnk1HH4gORmr1dllxDzzrN6goUIz/P4MHFV0YZJDCADPR3RvYNp0PW2SetKTThar6wlbFTL00hV2Q+fg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "4.28.2",
|
"@typescript-eslint/types": "4.28.3",
|
||||||
"eslint-visitor-keys": "^2.0.0"
|
"eslint-visitor-keys": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -10201,14 +10205,13 @@
|
||||||
"authentik-api": {
|
"authentik-api": {
|
||||||
"version": "file:api",
|
"version": "file:api",
|
||||||
"requires": {
|
"requires": {
|
||||||
"typescript": "^3.6"
|
"typescript": "^3.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "3.9.9",
|
"version": "3.9.9",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz",
|
||||||
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==",
|
"integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -13239,9 +13242,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rollup": {
|
"rollup": {
|
||||||
"version": "2.52.8",
|
"version": "2.53.2",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.8.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.53.2.tgz",
|
||||||
"integrity": "sha512-IjAB0C6KK5/lvqzJWAzsvOik+jV5Bt907QdkQ/gDP4j+R9KYNI1tjqdxiPitGPVrWC21Mf/ucXgowUjN/VemaQ==",
|
"integrity": "sha512-1CtEYuS5CRCzFZ7SNW5528SlDlk4VDXIRGwbm/2POQxA/G4+7/crIqJwkmnj8Q/74hGx4oVlNvh4E1CJQ5hZ6w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,14 +52,14 @@
|
||||||
"@polymer/paper-input": "^3.2.1",
|
"@polymer/paper-input": "^3.2.1",
|
||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-replace": "^2.4.2",
|
"@rollup/plugin-replace": "^2.4.2",
|
||||||
"@rollup/plugin-typescript": "^8.2.1",
|
"@rollup/plugin-typescript": "^8.2.3",
|
||||||
"@sentry/browser": "^6.8.0",
|
"@sentry/browser": "^6.9.0",
|
||||||
"@sentry/tracing": "^6.8.0",
|
"@sentry/tracing": "^6.9.0",
|
||||||
"@types/chart.js": "^2.9.34",
|
"@types/chart.js": "^2.9.34",
|
||||||
"@types/codemirror": "5.60.2",
|
"@types/codemirror": "5.60.2",
|
||||||
"@types/grecaptcha": "^3.0.3",
|
"@types/grecaptcha": "^3.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
"@typescript-eslint/eslint-plugin": "^4.28.3",
|
||||||
"@typescript-eslint/parser": "^4.28.2",
|
"@typescript-eslint/parser": "^4.28.3",
|
||||||
"@webcomponents/webcomponentsjs": "^2.5.0",
|
"@webcomponents/webcomponentsjs": "^2.5.0",
|
||||||
"authentik-api": "file:api",
|
"authentik-api": "file:api",
|
||||||
"babel-plugin-macros": "^3.1.0",
|
"babel-plugin-macros": "^3.1.0",
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
"lit-html": "^1.4.1",
|
"lit-html": "^1.4.1",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"rapidoc": "^9.0.0",
|
"rapidoc": "^9.0.0",
|
||||||
"rollup": "^2.52.8",
|
"rollup": "^2.53.2",
|
||||||
"rollup-plugin-commonjs": "^10.1.0",
|
"rollup-plugin-commonjs": "^10.1.0",
|
||||||
"rollup-plugin-copy": "^3.4.0",
|
"rollup-plugin-copy": "^3.4.0",
|
||||||
"rollup-plugin-cssimport": "^1.0.2",
|
"rollup-plugin-cssimport": "^1.0.2",
|
||||||
|
|
|
@ -15,6 +15,7 @@ export function configureSentry(canDoPpi: boolean = false): Promise<Config> {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
|
||||||
release: `authentik@${VERSION}`,
|
release: `authentik@${VERSION}`,
|
||||||
|
tunnel: "/api/v2beta/sentry/",
|
||||||
integrations: [
|
integrations: [
|
||||||
new Integrations.BrowserTracing({
|
new Integrations.BrowserTracing({
|
||||||
tracingOrigins: [window.location.host, "localhost"],
|
tracingOrigins: [window.location.host, "localhost"],
|
||||||
|
|
|
@ -483,6 +483,7 @@ msgid "Case insensitive matching"
|
||||||
msgstr "Case insensitive matching"
|
msgstr "Case insensitive matching"
|
||||||
|
|
||||||
#: src/pages/crypto/CertificateKeyPairForm.ts
|
#: src/pages/crypto/CertificateKeyPairForm.ts
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||||
msgid "Certificate"
|
msgid "Certificate"
|
||||||
msgstr "Certificate"
|
msgstr "Certificate"
|
||||||
|
@ -1669,6 +1670,10 @@ msgstr "From"
|
||||||
msgid "From address"
|
msgid "From address"
|
||||||
msgstr "From address"
|
msgstr "From address"
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "GID start number"
|
||||||
|
msgstr "GID start number"
|
||||||
|
|
||||||
#: src/pages/admin-overview/AdminOverviewPage.ts
|
#: src/pages/admin-overview/AdminOverviewPage.ts
|
||||||
msgid "General system status"
|
msgid "General system status"
|
||||||
msgstr "General system status"
|
msgstr "General system status"
|
||||||
|
@ -2079,6 +2084,7 @@ msgstr "Loading"
|
||||||
#: src/pages/property-mappings/PropertyMappingTestForm.ts
|
#: src/pages/property-mappings/PropertyMappingTestForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
|
@ -3222,6 +3228,10 @@ msgstr "Separator: Static Separator Line"
|
||||||
msgid "Server URI"
|
msgid "Server URI"
|
||||||
msgstr "Server URI"
|
msgstr "Server URI"
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "Server name for which this provider's certificate is valid for."
|
||||||
|
msgstr "Server name for which this provider's certificate is valid for."
|
||||||
|
|
||||||
#: src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
|
#: src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
|
||||||
msgid "Server validation of credential failed: {err}"
|
msgid "Server validation of credential failed: {err}"
|
||||||
msgstr "Server validation of credential failed: {err}"
|
msgstr "Server validation of credential failed: {err}"
|
||||||
|
@ -3791,6 +3801,10 @@ msgstr "System Tasks"
|
||||||
msgid "TLS Authentication Certificate"
|
msgid "TLS Authentication Certificate"
|
||||||
msgstr "TLS Authentication Certificate"
|
msgstr "TLS Authentication Certificate"
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "TLS Server name"
|
||||||
|
msgstr "TLS Server name"
|
||||||
|
|
||||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts
|
#: src/pages/outposts/ServiceConnectionDockerForm.ts
|
||||||
msgid "TLS Verification Certificate"
|
msgid "TLS Verification Certificate"
|
||||||
msgstr "TLS Verification Certificate"
|
msgstr "TLS Verification Certificate"
|
||||||
|
@ -3877,6 +3891,14 @@ msgstr ""
|
||||||
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
|
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
|
||||||
msgstr "The policy takes a random time to execute. This controls the minimum time it will take."
|
msgstr "The policy takes a random time to execute. This controls the minimum time it will take."
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber"
|
||||||
|
msgstr "The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber"
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
|
||||||
|
msgstr "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
|
||||||
|
|
||||||
#: src/pages/flows/BoundStagesList.ts
|
#: src/pages/flows/BoundStagesList.ts
|
||||||
msgid "These bindings control if this stage will be applied to the flow."
|
msgid "These bindings control if this stage will be applied to the flow."
|
||||||
msgstr "These bindings control if this stage will be applied to the flow."
|
msgstr "These bindings control if this stage will be applied to the flow."
|
||||||
|
@ -4035,6 +4057,10 @@ msgstr "UI settings"
|
||||||
msgid "UID"
|
msgid "UID"
|
||||||
msgstr "UID"
|
msgstr "UID"
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "UID start number"
|
||||||
|
msgstr "UID start number"
|
||||||
|
|
||||||
#: src/flows/stages/identification/IdentificationStage.ts
|
#: src/flows/stages/identification/IdentificationStage.ts
|
||||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||||
msgid "UPN"
|
msgid "UPN"
|
||||||
|
|
|
@ -479,6 +479,7 @@ msgid "Case insensitive matching"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/crypto/CertificateKeyPairForm.ts
|
#: src/pages/crypto/CertificateKeyPairForm.ts
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
#: src/pages/providers/proxy/ProxyProviderForm.ts
|
||||||
msgid "Certificate"
|
msgid "Certificate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1661,6 +1662,10 @@ msgstr ""
|
||||||
msgid "From address"
|
msgid "From address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "GID start number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/admin-overview/AdminOverviewPage.ts
|
#: src/pages/admin-overview/AdminOverviewPage.ts
|
||||||
msgid "General system status"
|
msgid "General system status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2071,6 +2076,7 @@ msgstr ""
|
||||||
#: src/pages/property-mappings/PropertyMappingTestForm.ts
|
#: src/pages/property-mappings/PropertyMappingTestForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
#: src/pages/providers/oauth2/OAuth2ProviderForm.ts
|
||||||
|
@ -3214,6 +3220,10 @@ msgstr ""
|
||||||
msgid "Server URI"
|
msgid "Server URI"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "Server name for which this provider's certificate is valid for."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
|
#: src/flows/stages/authenticator_webauthn/WebAuthnAuthenticatorRegisterStage.ts
|
||||||
msgid "Server validation of credential failed: {err}"
|
msgid "Server validation of credential failed: {err}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -3783,6 +3793,10 @@ msgstr ""
|
||||||
msgid "TLS Authentication Certificate"
|
msgid "TLS Authentication Certificate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "TLS Server name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/outposts/ServiceConnectionDockerForm.ts
|
#: src/pages/outposts/ServiceConnectionDockerForm.ts
|
||||||
msgid "TLS Verification Certificate"
|
msgid "TLS Verification Certificate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -3866,6 +3880,14 @@ msgstr ""
|
||||||
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
|
msgid "The policy takes a random time to execute. This controls the minimum time it will take."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/flows/BoundStagesList.ts
|
#: src/pages/flows/BoundStagesList.ts
|
||||||
msgid "These bindings control if this stage will be applied to the flow."
|
msgid "These bindings control if this stage will be applied to the flow."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -4020,6 +4042,10 @@ msgstr ""
|
||||||
msgid "UID"
|
msgid "UID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/pages/providers/ldap/LDAPProviderForm.ts
|
||||||
|
msgid "UID start number"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/flows/stages/identification/IdentificationStage.ts
|
#: src/flows/stages/identification/IdentificationStage.ts
|
||||||
#: src/pages/stages/identification/IdentificationStageForm.ts
|
#: src/pages/stages/identification/IdentificationStageForm.ts
|
||||||
msgid "UPN"
|
msgid "UPN"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { FlowsApi, ProvidersApi, LDAPProvider, CoreApi, FlowsInstancesListDesignationEnum } from "authentik-api";
|
import { FlowsApi, ProvidersApi, LDAPProvider, CoreApi, FlowsInstancesListDesignationEnum, CryptoApi } from "authentik-api";
|
||||||
import { t } from "@lingui/macro";
|
import { t } from "@lingui/macro";
|
||||||
import { customElement } from "lit-element";
|
import { customElement } from "lit-element";
|
||||||
import { html, TemplateResult } from "lit-html";
|
import { html, TemplateResult } from "lit-html";
|
||||||
|
@ -90,6 +90,41 @@ export class LDAPProviderFormPage extends ModelForm<LDAPProvider, number> {
|
||||||
<input type="text" value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}" class="pf-c-form-control" required>
|
<input type="text" value="${first(this.instance?.baseDn, "DC=ldap,DC=goauthentik,DC=io")}" class="pf-c-form-control" required>
|
||||||
<p class="pf-c-form__helper-text">${t`LDAP DN under which bind requests and search requests can be made.`}</p>
|
<p class="pf-c-form__helper-text">${t`LDAP DN under which bind requests and search requests can be made.`}</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${t`TLS Server name`}
|
||||||
|
name="tlsServerName">
|
||||||
|
<input type="text" value="${first(this.instance?.tlsServerName, "")}" class="pf-c-form-control">
|
||||||
|
<p class="pf-c-form__helper-text">${t`Server name for which this provider's certificate is valid for.`}</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${t`Certificate`}
|
||||||
|
name="certificate">
|
||||||
|
<select class="pf-c-form-control">
|
||||||
|
<option value="" ?selected=${this.instance?.certificate === undefined}>---------</option>
|
||||||
|
${until(new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsList({
|
||||||
|
ordering: "pk",
|
||||||
|
hasKey: true,
|
||||||
|
}).then(keys => {
|
||||||
|
return keys.results.map(key => {
|
||||||
|
return html`<option value=${ifDefined(key.pk)} ?selected=${this.instance?.certificate === key.pk}>${key.name}</option>`;
|
||||||
|
});
|
||||||
|
}), html`<option>${t`Loading...`}</option>`)}
|
||||||
|
</select>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${t`UID start number`}
|
||||||
|
?required=${true}
|
||||||
|
name="uidStartNumber">
|
||||||
|
<input type="number" value="${first(this.instance?.uidStartNumber, 2000)}" class="pf-c-form-control" required>
|
||||||
|
<p class="pf-c-form__helper-text">${t`The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber`}</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${t`GID start number`}
|
||||||
|
?required=${true}
|
||||||
|
name="gidStartNumber">
|
||||||
|
<input type="number" value="${first(this.instance?.gidStartNumber, 4000)}" class="pf-c-form-control" required>
|
||||||
|
<p class="pf-c-form__helper-text">${t`The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber`}</p>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
</div>
|
</div>
|
||||||
</ak-form-group>
|
</ak-form-group>
|
||||||
</form>`;
|
</form>`;
|
||||||
|
|
|
@ -47,9 +47,8 @@ export class UserTokenForm extends ModelForm<Token, string> {
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${t`Description`}
|
label=${t`Description`}
|
||||||
?required=${true}
|
|
||||||
name="description">
|
name="description">
|
||||||
<input type="text" value="${ifDefined(this.instance?.description)}" class="pf-c-form-control" required>
|
<input type="text" value="${ifDefined(this.instance?.description)}" class="pf-c-form-control">
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
</form>`;
|
</form>`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
# Production
|
# Production
|
||||||
/build
|
/build
|
||||||
|
/help
|
||||||
|
|
||||||
# Generated files
|
# Generated files
|
||||||
.docusaurus
|
.docusaurus
|
||||||
|
|
|
@ -5,7 +5,7 @@ title: Frontend-only development environment
|
||||||
If you want to only make changes on the UI, you don't need a backend running from source. You can user the docker-compose install with a few customizations.
|
If you want to only make changes on the UI, you don't need a backend running from source. You can user the docker-compose install with a few customizations.
|
||||||
|
|
||||||
1. Clone the git repo from https://github.com/goauthentik/authentik
|
1. Clone the git repo from https://github.com/goauthentik/authentik
|
||||||
2. In the cloned repository, follow the docker-compose installation instructions [here](../../docs/installation/docker-compose)
|
2. In the cloned repository, follow the docker-compose installation instructions [here](/docs/installation/docker-compose)
|
||||||
3. Add the following entry to your `.env` file:
|
3. Add the following entry to your `.env` file:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -22,7 +22,7 @@ You can bind using the DN `cn=<username>,ou=users,<base DN>`, or using the follo
|
||||||
ldapsearch \
|
ldapsearch \
|
||||||
-x \ # Only simple binds are currently supported
|
-x \ # Only simple binds are currently supported
|
||||||
-h *ip* \
|
-h *ip* \
|
||||||
-p 3389 \
|
-p 389 \
|
||||||
-D 'cn=*user*,ou=users,DC=ldap,DC=goauthentik,DC=io' \ # Bind user and password
|
-D 'cn=*user*,ou=users,DC=ldap,DC=goauthentik,DC=io' \ # Bind user and password
|
||||||
-w '*password*' \
|
-w '*password*' \
|
||||||
-b 'ou=users,DC=ldap,DC=goauthentik,DC=io' \ # The search base
|
-b 'ou=users,DC=ldap,DC=goauthentik,DC=io' \ # The search base
|
||||||
|
@ -33,6 +33,7 @@ The following fields are currently sent for users:
|
||||||
|
|
||||||
- `cn`: User's username
|
- `cn`: User's username
|
||||||
- `uid`: Unique user identifier
|
- `uid`: Unique user identifier
|
||||||
|
- `uidNumber`: A unique numeric identifier for the user
|
||||||
- `name`: User's name
|
- `name`: User's name
|
||||||
- `displayName`: User's name
|
- `displayName`: User's name
|
||||||
- `mail`: User's email address
|
- `mail`: User's email address
|
||||||
|
@ -48,8 +49,19 @@ The following fields are current set for groups:
|
||||||
|
|
||||||
- `cn`: The group's name
|
- `cn`: The group's name
|
||||||
- `uid`: Unique group identifier
|
- `uid`: Unique group identifier
|
||||||
|
- `gidNumber`: A unique numeric identifier for the group
|
||||||
|
- `member`: A list of all DNs of the groups members
|
||||||
- `objectClass`: A list of these strings:
|
- `objectClass`: A list of these strings:
|
||||||
- "group"
|
- "group"
|
||||||
- "goauthentik.io/ldap/group"
|
- "goauthentik.io/ldap/group"
|
||||||
|
|
||||||
**Additionally**, for both users and groups, any attributes you set are also present as LDAP Attributes.
|
A virtual group is also created for each user, they have the same fields as groups but have an additional objectClass: `goauthentik.io/ldap/virtual-group`.
|
||||||
|
The virtual groups gidNumber is equal to the uidNumber of the user.
|
||||||
|
|
||||||
|
**Additionally**, for both users and (non-virtual) groups, any attributes you set are also present as LDAP Attributes.
|
||||||
|
|
||||||
|
## SSL
|
||||||
|
|
||||||
|
You can also configure SSL for your LDAP Providers by selecting a certificate and a server name in the provider settings.
|
||||||
|
|
||||||
|
This enables you to bind on port 636 using LDAPS, StartTLS is not supported.
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
---
|
||||||
|
title: Release 2021.7
|
||||||
|
slug: "2021.7"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Headline Changes
|
||||||
|
|
||||||
|
- TLS Support for LDAP Providers
|
||||||
|
|
||||||
|
You can now configure certificates for your LDAP Providers, meaning that all communication will be done encrypted.
|
||||||
|
|
||||||
|
- Add bundeled docs
|
||||||
|
|
||||||
|
You can now browse the authentik docs for your version by browsing to `/help`. This means you don't have to rely on an
|
||||||
|
internet connection to check the logs, and you also have the correct logs for your currently running version.
|
||||||
|
|
||||||
|
## Minor changes
|
||||||
|
|
||||||
|
- Fix LDAP outpost not parsing arrays from user and group attributes correctly
|
||||||
|
- Fix LDAP outpost missing a `member` field on groups with all member DNs
|
||||||
|
- Allow configuration of Redis port
|
||||||
|
- Tunnel Sentry requests through authentik to prevent them being blocked by ad-blockers
|
||||||
|
- core: fix error when setting icon/background to url longer than 100 chars
|
||||||
|
- events: fix error when slack notification request failed without a response
|
||||||
|
- flows: allow variable substitution in flow titles
|
||||||
|
- providers/oauth2: allow blank redirect_uris to allow any redirect_uri
|
||||||
|
- providers/saml: fix parsing of POST bindings
|
||||||
|
- root: set samesite to None for SAML POST flows
|
||||||
|
- root: subclass SessionMiddleware to set Secure and SameSite flag depending on context
|
||||||
|
- web: fix error when showing error message of request
|
||||||
|
|
||||||
|
## Upgrading
|
||||||
|
|
||||||
|
This release does not introduce any new requirements.
|
||||||
|
|
||||||
|
### docker-compose
|
||||||
|
|
||||||
|
Download the docker-compose file for 2021.7 from [here](https://raw.githubusercontent.com/goauthentik/authentik/version-2021.7/docker-compose.yml). Afterwards, simply run `docker-compose up -d`.
|
||||||
|
|
||||||
|
### Kubernetes
|
||||||
|
|
||||||
|
Upgrade to the latest chart version to get the new images.
|
|
@ -0,0 +1,86 @@
|
||||||
|
const mainConfig = require("./docusaurus.config");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
title: "authentik",
|
||||||
|
tagline: "Making authentication simple.",
|
||||||
|
url: "https://goauthentik.io",
|
||||||
|
baseUrl: "/help/",
|
||||||
|
onBrokenLinks: "throw",
|
||||||
|
favicon: "img/icon.png",
|
||||||
|
organizationName: "BeryJu",
|
||||||
|
projectName: "authentik",
|
||||||
|
themeConfig: {
|
||||||
|
navbar: {
|
||||||
|
title: "authentik",
|
||||||
|
logo: {
|
||||||
|
alt: "authentik logo",
|
||||||
|
src: "img/icon_left_brand.svg",
|
||||||
|
},
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
to: "docs/",
|
||||||
|
activeBasePath: "docs",
|
||||||
|
label: "Docs",
|
||||||
|
position: "left",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: "developer-docs/",
|
||||||
|
activeBasePath: "developer-docs",
|
||||||
|
label: "Developer Docs",
|
||||||
|
position: "left",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://github.com/goauthentik/authentik",
|
||||||
|
label: "GitHub",
|
||||||
|
position: "right",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
href: "https://discord.gg/jg33eMhnj6",
|
||||||
|
label: "Discord",
|
||||||
|
position: "right",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
footer: mainConfig.themeConfig.footer,
|
||||||
|
colorMode: mainConfig.themeConfig.colorMode,
|
||||||
|
},
|
||||||
|
presets: [
|
||||||
|
[
|
||||||
|
"@docusaurus/preset-classic",
|
||||||
|
{
|
||||||
|
docs: {
|
||||||
|
id: "docs",
|
||||||
|
sidebarPath: require.resolve("./sidebars.js"),
|
||||||
|
editUrl: "https://github.com/goauthentik/authentik/edit/master/website/",
|
||||||
|
},
|
||||||
|
pages: false,
|
||||||
|
theme: {
|
||||||
|
customCss: require.resolve("./src/css/custom.css"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
'@docusaurus/plugin-content-docs',
|
||||||
|
{
|
||||||
|
id: 'docsDevelopers',
|
||||||
|
path: 'developer-docs',
|
||||||
|
routeBasePath: 'developer-docs',
|
||||||
|
sidebarPath: require.resolve('./sidebarsDev.js'),
|
||||||
|
editUrl: "https://github.com/goauthentik/authentik/edit/master/website/",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'@docusaurus/plugin-client-redirects',
|
||||||
|
{
|
||||||
|
redirects: [
|
||||||
|
{
|
||||||
|
to: '/docs/',
|
||||||
|
from: ['/'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
|
@ -6,18 +6,20 @@
|
||||||
"docusaurus": "docusaurus",
|
"docusaurus": "docusaurus",
|
||||||
"watch": "docusaurus start",
|
"watch": "docusaurus start",
|
||||||
"build": "docusaurus build",
|
"build": "docusaurus build",
|
||||||
|
"build-docs-only": "docusaurus build --config docusaurus.docs-only.js --out-dir help",
|
||||||
"swizzle": "docusaurus swizzle",
|
"swizzle": "docusaurus swizzle",
|
||||||
"deploy": "docusaurus deploy",
|
"deploy": "docusaurus deploy",
|
||||||
"serve": "docusaurus serve"
|
"serve": "docusaurus serve"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/preset-classic": "2.0.0-beta.0",
|
"@docusaurus/plugin-client-redirects": "2.0.0-beta.3",
|
||||||
|
"@docusaurus/preset-classic": "2.0.0-beta.3",
|
||||||
"@mdx-js/react": "^1.6.22",
|
"@mdx-js/react": "^1.6.22",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
"postcss": "^8.3.5",
|
"postcss": "^8.3.5",
|
||||||
"rapidoc": "^9.0.0",
|
"rapidoc": "^9.0.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-before-after-slider": "^1.0.4",
|
"react-before-after-slider-component": "^0.7.4",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-feather": "^2.0.9",
|
"react-feather": "^2.0.9",
|
||||||
"react-toggle": "^4.1.2"
|
"react-toggle": "^4.1.2"
|
||||||
|
|
|
@ -37,6 +37,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.before-after-slider img {
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,17 @@ import React from "react";
|
||||||
import Layout from "@theme/Layout";
|
import Layout from "@theme/Layout";
|
||||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||||
|
import BrowserOnly from "@docusaurus/core/lib/client/exports/BrowserOnly";
|
||||||
|
|
||||||
function APIBrowser() {
|
function APIBrowser() {
|
||||||
const context = useDocusaurusContext();
|
const context = useDocusaurusContext();
|
||||||
const { siteConfig = {} } = context;
|
const { siteConfig = {} } = context;
|
||||||
import('rapidoc');
|
|
||||||
return (
|
return (
|
||||||
<Layout title="API Browser" description={siteConfig.tagline}>
|
<Layout title="API Browser" description={siteConfig.tagline}>
|
||||||
<rapi-doc
|
<BrowserOnly>
|
||||||
|
{() => {
|
||||||
|
import('rapidoc');
|
||||||
|
return <rapi-doc
|
||||||
spec-url={useBaseUrl("schema.yaml")}
|
spec-url={useBaseUrl("schema.yaml")}
|
||||||
allow-try="false"
|
allow-try="false"
|
||||||
show-header="false"
|
show-header="false"
|
||||||
|
@ -19,6 +22,8 @@ function APIBrowser() {
|
||||||
allow-spec-url-load="false"
|
allow-spec-url-load="false"
|
||||||
allow-spec-file-load="false">
|
allow-spec-file-load="false">
|
||||||
</rapi-doc>
|
</rapi-doc>
|
||||||
|
}}
|
||||||
|
</BrowserOnly>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import BrowserOnly from "@docusaurus/core/lib/client/exports/BrowserOnly";
|
||||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||||
import useBaseUrl from "@docusaurus/useBaseUrl";
|
import useBaseUrl from "@docusaurus/useBaseUrl";
|
||||||
import styles from "./styles.module.css";
|
import styles from "./styles.module.css";
|
||||||
import BeforeAfterSlider from 'react-before-after-slider'
|
|
||||||
import Comparison from "../comparison";
|
import Comparison from "../comparison";
|
||||||
|
import 'react-before-after-slider-component/dist/build.css';
|
||||||
|
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
|
@ -105,12 +105,16 @@ function Home() {
|
||||||
<div>
|
<div>
|
||||||
<BrowserOnly>
|
<BrowserOnly>
|
||||||
{() => {
|
{() => {
|
||||||
return <BeforeAfterSlider
|
const ReactBeforeSliderComponent = require('react-before-after-slider-component');
|
||||||
className={styles.featureImage}
|
return <ReactBeforeSliderComponent
|
||||||
before={useBaseUrl("img/screen_apps_light.jpg")}
|
firstImage={{
|
||||||
after={useBaseUrl("img/screen_apps_dark.jpg")}
|
id: 1,
|
||||||
width={640}
|
imageUrl: useBaseUrl("img/screen_apps_light.jpg"),
|
||||||
height={480}
|
}}
|
||||||
|
secondImage={{
|
||||||
|
id: 2,
|
||||||
|
imageUrl: useBaseUrl("img/screen_apps_dark.jpg"),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
}}
|
}}
|
||||||
</BrowserOnly>
|
</BrowserOnly>
|
||||||
|
@ -146,12 +150,16 @@ function Home() {
|
||||||
<div>
|
<div>
|
||||||
<BrowserOnly>
|
<BrowserOnly>
|
||||||
{() => {
|
{() => {
|
||||||
return <BeforeAfterSlider
|
const ReactBeforeSliderComponent = require('react-before-after-slider-component');
|
||||||
className={styles.featureImage}
|
return <ReactBeforeSliderComponent
|
||||||
before={useBaseUrl("img/screen_admin_light.jpg")}
|
firstImage={{
|
||||||
after={useBaseUrl("img/screen_admin_dark.jpg")}
|
id: 1,
|
||||||
width={640}
|
imageUrl: useBaseUrl("img/screen_admin_light.jpg"),
|
||||||
height={480}
|
}}
|
||||||
|
secondImage={{
|
||||||
|
id: 2,
|
||||||
|
imageUrl: useBaseUrl("img/screen_admin_dark.jpg"),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
}}
|
}}
|
||||||
</BrowserOnly>
|
</BrowserOnly>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
//go:embed help/*
|
||||||
|
var Help embed.FS
|
Reference in New Issue