Compare commits
41 Commits
version/20
...
version/20
| Author | SHA1 | Date | |
|---|---|---|---|
| 0b7ebf0e07 | |||
| ddca8ef3ca | |||
| 709581f5a8 | |||
| 72e41c03f5 | |||
| 40503d06b7 | |||
| 1df8790050 | |||
| 3c23ad340f | |||
| f9f2e00913 | |||
| 8362507bdf | |||
| a2181c3bf0 | |||
| a07ded0dae | |||
| 3b0b9301ee | |||
| 919f293fc7 | |||
| c4df2e5a50 | |||
| 4d1500e0f3 | |||
| 281bd4c69a | |||
| e4678aa032 | |||
| ff1c4d555a | |||
| 4a3e34d40a | |||
| 6939898bbe | |||
| 549607c5ed | |||
| f61acdfbfd | |||
| e3572bad76 | |||
| 8f99891a9d | |||
| 99d5262d41 | |||
| 97a3c2d88b | |||
| e91ff4566d | |||
| dc942b2f4c | |||
| a3fccbdaff | |||
| bdf9f26d07 | |||
| 901cea1453 | |||
| 37b57ac28f | |||
| e9aa37ba67 | |||
| 9a0aa4c79b | |||
| 34ab68a169 | |||
| 52cf4890cf | |||
| 8e5d03cb86 | |||
| 2190fa555b | |||
| ae1edde17b | |||
| 3ad1c3f212 | |||
| 65ec444e52 |
@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 2021.5.1-rc8
|
current_version = 2021.5.1
|
||||||
tag = True
|
tag = True
|
||||||
commit = True
|
commit = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
|
||||||
|
|||||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@ -36,9 +36,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
push: ${{ github.event_name == 'release' }}
|
push: ${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
beryju/authentik:2021.5.1-rc8,
|
beryju/authentik:2021.5.1,
|
||||||
beryju/authentik:latest,
|
beryju/authentik:latest,
|
||||||
ghcr.io/goauthentik/server:2021.5.1-rc8,
|
ghcr.io/goauthentik/server:2021.5.1,
|
||||||
ghcr.io/goauthentik/server:latest
|
ghcr.io/goauthentik/server:latest
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
context: .
|
context: .
|
||||||
@ -75,9 +75,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
push: ${{ github.event_name == 'release' }}
|
push: ${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
beryju/authentik-proxy:2021.5.1-rc8,
|
beryju/authentik-proxy:2021.5.1,
|
||||||
beryju/authentik-proxy:latest,
|
beryju/authentik-proxy:latest,
|
||||||
ghcr.io/goauthentik/proxy:2021.5.1-rc8,
|
ghcr.io/goauthentik/proxy:2021.5.1,
|
||||||
ghcr.io/goauthentik/proxy:latest
|
ghcr.io/goauthentik/proxy:latest
|
||||||
context: outpost/
|
context: outpost/
|
||||||
file: outpost/proxy.Dockerfile
|
file: outpost/proxy.Dockerfile
|
||||||
@ -115,9 +115,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
push: ${{ github.event_name == 'release' }}
|
push: ${{ github.event_name == 'release' }}
|
||||||
tags: |
|
tags: |
|
||||||
beryju/authentik-ldap:2021.5.1-rc8,
|
beryju/authentik-ldap:2021.5.1,
|
||||||
beryju/authentik-ldap:latest,
|
beryju/authentik-ldap:latest,
|
||||||
ghcr.io/goauthentik/ldap:2021.5.1-rc8,
|
ghcr.io/goauthentik/ldap:2021.5.1,
|
||||||
ghcr.io/goauthentik/ldap:latest
|
ghcr.io/goauthentik/ldap:latest
|
||||||
context: outpost/
|
context: outpost/
|
||||||
file: outpost/ldap.Dockerfile
|
file: outpost/ldap.Dockerfile
|
||||||
@ -139,7 +139,7 @@ jobs:
|
|||||||
docker-compose pull -q
|
docker-compose pull -q
|
||||||
docker-compose up --no-start
|
docker-compose up --no-start
|
||||||
docker-compose start postgresql redis
|
docker-compose start postgresql redis
|
||||||
docker-compose run -u root --entrypoint /bin/bash server -c "pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
|
docker-compose run -u root --entrypoint /bin/bash server -c "apt-get update && apt-get install -y --no-install-recommends git && pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
|
||||||
sentry-release:
|
sentry-release:
|
||||||
if: ${{ github.event_name == 'release' }}
|
if: ${{ github.event_name == 'release' }}
|
||||||
needs:
|
needs:
|
||||||
@ -155,5 +155,5 @@ jobs:
|
|||||||
SENTRY_PROJECT: authentik
|
SENTRY_PROJECT: authentik
|
||||||
SENTRY_URL: https://sentry.beryju.org
|
SENTRY_URL: https://sentry.beryju.org
|
||||||
with:
|
with:
|
||||||
version: authentik@2021.5.1-rc8
|
version: authentik@2021.5.1
|
||||||
environment: beryjuorg-prod
|
environment: beryjuorg-prod
|
||||||
|
|||||||
6
.github/workflows/tag.yml
vendored
6
.github/workflows/tag.yml
vendored
@ -27,17 +27,17 @@ jobs:
|
|||||||
-f Dockerfile .
|
-f Dockerfile .
|
||||||
docker-compose up --no-start
|
docker-compose up --no-start
|
||||||
docker-compose start postgresql redis
|
docker-compose start postgresql redis
|
||||||
docker-compose run -u root --entrypoint /bin/bash server -c "pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
|
docker-compose run -u root --entrypoint /bin/bash server -c "apt-get update && apt-get install -y --no-install-recommends git && pip install --no-cache -r requirements-dev.txt && ./manage.py test authentik"
|
||||||
- name: Extract version number
|
- name: Extract version number
|
||||||
id: get_version
|
id: get_version
|
||||||
uses: actions/github-script@0.2.0
|
uses: actions/github-script@v4.0.2
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
return context.payload.ref.replace(/\/refs\/tags\/version\//, '');
|
return context.payload.ref.replace(/\/refs\/tags\/version\//, '');
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1.0.0
|
uses: actions/create-release@v1.1.4
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
10
Dockerfile
10
Dockerfile
@ -48,7 +48,7 @@ ARG GIT_BUILD_HASH
|
|||||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends curl ca-certificates gnupg git && \
|
apt-get install -y --no-install-recommends curl ca-certificates gnupg git runit && \
|
||||||
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
|
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - && \
|
||||||
echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
|
echo "deb http://apt.postgresql.org/pub/repos/apt buster-pgdg main" > /etc/apt/sources.list.d/pgdg.list && \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
@ -58,14 +58,7 @@ RUN apt-get update && \
|
|||||||
apt-get autoremove --purge -y && \
|
apt-get autoremove --purge -y && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \
|
rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \
|
||||||
# This is quite hacky, but docker has no guaranteed Group ID
|
|
||||||
# we could instead check for the GID of the socket and add the user dynamically,
|
|
||||||
# but then we have to drop permmissions later
|
|
||||||
groupadd -g 998 docker_998 && \
|
|
||||||
groupadd -g 999 docker_999 && \
|
|
||||||
adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \
|
adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \
|
||||||
usermod -a -G docker_998 authentik && \
|
|
||||||
usermod -a -G docker_999 authentik && \
|
|
||||||
mkdir /backups && \
|
mkdir /backups && \
|
||||||
chown authentik:authentik /backups
|
chown authentik:authentik /backups
|
||||||
|
|
||||||
@ -77,7 +70,6 @@ COPY ./lifecycle/ /lifecycle
|
|||||||
COPY --from=builder /work/authentik /authentik-proxy
|
COPY --from=builder /work/authentik /authentik-proxy
|
||||||
|
|
||||||
USER authentik
|
USER authentik
|
||||||
STOPSIGNAL SIGINT
|
|
||||||
ENV TMPDIR /dev/shm/
|
ENV TMPDIR /dev/shm/
|
||||||
ENV PYTHONUBUFFERED 1
|
ENV PYTHONUBUFFERED 1
|
||||||
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]
|
ENTRYPOINT [ "/lifecycle/bootstrap.sh" ]
|
||||||
|
|||||||
6
Makefile
6
Makefile
@ -36,11 +36,5 @@ gen:
|
|||||||
--additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0
|
--additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0
|
||||||
cd web/api && npx tsc
|
cd web/api && npx tsc
|
||||||
|
|
||||||
local-stack:
|
|
||||||
export AUTHENTIK_TAG=testing
|
|
||||||
docker build -t beryju/authentik:testng .
|
|
||||||
docker-compose up -d
|
|
||||||
docker-compose run --rm server migrate
|
|
||||||
|
|
||||||
run:
|
run:
|
||||||
go run -v cmd/server/main.go
|
go run -v cmd/server/main.go
|
||||||
|
|||||||
75
Pipfile.lock
generated
75
Pipfile.lock
generated
@ -122,19 +122,18 @@
|
|||||||
},
|
},
|
||||||
"boto3": {
|
"boto3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:bcb1b76ca5a60586181ad202b19f4c50cb7c22ac68cae20f997abe311e22bf2a",
|
"sha256:3317722a1e9acbfc0d30cdf273d1708c823ceb19309e9cd91cac8a3604762341",
|
||||||
"sha256:edf9b3b36e08cd575a9458bf59871852335aceb5db2d07bfc8530bae3a97d045"
|
"sha256:ee3317fd79b443ef102469fac393a1ffb650ea51ac4fc27464013872c5e1ce31"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==1.17.71"
|
"version": "==1.17.72"
|
||||||
},
|
},
|
||||||
"botocore": {
|
"botocore": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:414e1721d381095767db1cf673257fdfec639da3be9405a41d49cc859b817d68",
|
"sha256:0fa93a2e2daad5791c63ee526ada66896cc483d04cb2d32bfcadfeb881203453"
|
||||||
"sha256:b7afebca1fd6ca1f8af79f377a445d474e3bd2cf88e704169d6713a6362a304f"
|
|
||||||
],
|
],
|
||||||
"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.20.71"
|
"version": "==1.20.72"
|
||||||
},
|
},
|
||||||
"cachetools": {
|
"cachetools": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@ -323,11 +322,11 @@
|
|||||||
},
|
},
|
||||||
"django": {
|
"django": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0a1d195ad65c52bf275b8277b3d49680bd1137a5f55039a806f25f6b9752ce3d",
|
"sha256:13ac78dbfd189532cad8f383a27e58e18b3d33f80009ceb476d7fcbfc5dcebd8",
|
||||||
"sha256:18dd3145ddbd04bf189ff79b9954d08fda5171ea7b57bf705789fea766a07d50"
|
"sha256:7e0a1393d18c16b503663752a8b6790880c5084412618990ce8a81cc908b4962"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==3.2.2"
|
"version": "==3.2.3"
|
||||||
},
|
},
|
||||||
"django-dbbackup": {
|
"django-dbbackup": {
|
||||||
"git": "https://github.com/django-dbbackup/django-dbbackup.git",
|
"git": "https://github.com/django-dbbackup/django-dbbackup.git",
|
||||||
@ -441,11 +440,11 @@
|
|||||||
},
|
},
|
||||||
"geoip2": {
|
"geoip2": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:57d8d15de2527e0697bbef44fc16812bba709f03a07ef99297bd56c1df3b1efd",
|
"sha256:906a1dbf15a179a1af3522970e8420ab15bb3e0afc526942cc179e12146d9c1d",
|
||||||
"sha256:707025542ef076bd8fd80e97138bebdb7812527b2a007d141a27ad98b0370fff"
|
"sha256:b97b44031fdc463e84eb1316b4f19edd978cb1d78703465fcb1e36dc5a822ba6"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==4.1.0"
|
"version": "==4.2.0"
|
||||||
},
|
},
|
||||||
"google-auth": {
|
"google-auth": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
@ -607,19 +606,19 @@
|
|||||||
},
|
},
|
||||||
"kubernetes": {
|
"kubernetes": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:23c85d8571df8f56e773f1a413bc081537536dc47e2b5e8dc2e6262edb2c57ca",
|
"sha256:225a95a0aadbd5b645ab389d941a7980db8cdad2a776fde64d1b43fc3299bde9",
|
||||||
"sha256:ec52ea01d52e2ec3da255992f7e859f3a76f2bdb51cf65ba8cd71dfc309d8daa"
|
"sha256:c69b318696ba797dcf63eb928a8d4370c52319f4140023c502d7dfdf2080eb79"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==12.0.1"
|
"version": "==17.17.0"
|
||||||
},
|
},
|
||||||
"ldap3": {
|
"ldap3": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
"sha256:c1df41d89459be6f304e0ceec4b00fdea533dbbcd83c802b1272dcdb94620b57",
|
||||||
"sha256:18c3ee656a6775b9b0d60f7c6c5b094d878d1d90fc03d56731039f0a4b546a91",
|
"sha256:18c3ee656a6775b9b0d60f7c6c5b094d878d1d90fc03d56731039f0a4b546a91",
|
||||||
"sha256:4139c91f0eef9782df7b77c8cbc6243086affcb6a8a249b768a9658438e5da59",
|
|
||||||
"sha256:8c949edbad2be8a03e719ba48bd6779f327ec156929562814b3e84ab56889c8c",
|
"sha256:8c949edbad2be8a03e719ba48bd6779f327ec156929562814b3e84ab56889c8c",
|
||||||
"sha256:afc6fc0d01f02af82cd7bfabd3bbfd5dc96a6ae91e97db0a2dab8a0f1b436056",
|
"sha256:afc6fc0d01f02af82cd7bfabd3bbfd5dc96a6ae91e97db0a2dab8a0f1b436056",
|
||||||
"sha256:c1df41d89459be6f304e0ceec4b00fdea533dbbcd83c802b1272dcdb94620b57"
|
"sha256:4139c91f0eef9782df7b77c8cbc6243086affcb6a8a249b768a9658438e5da59"
|
||||||
],
|
],
|
||||||
"index": "pypi",
|
"index": "pypi",
|
||||||
"version": "==2.9"
|
"version": "==2.9"
|
||||||
@ -874,37 +873,37 @@
|
|||||||
},
|
},
|
||||||
"pyasn1": {
|
"pyasn1": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
|
|
||||||
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
|
|
||||||
"sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
|
"sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf",
|
||||||
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
|
|
||||||
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
|
"sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
|
||||||
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
|
"sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00",
|
||||||
"sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
|
|
||||||
"sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
|
|
||||||
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
|
|
||||||
"sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
|
"sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776",
|
||||||
|
"sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12",
|
||||||
|
"sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359",
|
||||||
|
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3",
|
||||||
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
|
"sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba",
|
||||||
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2",
|
"sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86",
|
||||||
"sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"
|
"sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576",
|
||||||
|
"sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8",
|
||||||
|
"sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7",
|
||||||
|
"sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"
|
||||||
],
|
],
|
||||||
"version": "==0.4.8"
|
"version": "==0.4.8"
|
||||||
},
|
},
|
||||||
"pyasn1-modules": {
|
"pyasn1-modules": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
|
"sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
|
||||||
"sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199",
|
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
|
||||||
"sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
|
|
||||||
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
|
|
||||||
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
|
"sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4",
|
||||||
|
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
|
||||||
|
"sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
|
||||||
|
"sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811",
|
||||||
|
"sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8",
|
||||||
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
|
"sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
|
||||||
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
|
"sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74",
|
||||||
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
|
"sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb",
|
||||||
"sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45",
|
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405",
|
||||||
"sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd",
|
"sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed",
|
||||||
"sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0",
|
"sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199"
|
||||||
"sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d",
|
|
||||||
"sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"
|
|
||||||
],
|
],
|
||||||
"version": "==0.2.8"
|
"version": "==0.2.8"
|
||||||
},
|
},
|
||||||
@ -1603,11 +1602,11 @@
|
|||||||
},
|
},
|
||||||
"gitpython": {
|
"gitpython": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:3283ae2fba31c913d857e12e5ba5f9a7772bbc064ae2bb09efafa71b0dd4939b",
|
"sha256:2bfcd25e6b81fe431fa3ab1f0975986cfddabf7870a323c183f3afbc9447c0c5",
|
||||||
"sha256:be27633e7509e58391f10207cd32b2a6cf5b908f92d9cd30da2e514e1137af61"
|
"sha256:37ac36cacf2e2be5e88f0810187c5833e71c1a2a8cf81588f5699d1b70183baa"
|
||||||
],
|
],
|
||||||
"markers": "python_version >= '3.4'",
|
"markers": "python_version >= '3.5'",
|
||||||
"version": "==3.1.14"
|
"version": "==3.1.16"
|
||||||
},
|
},
|
||||||
"idna": {
|
"idna": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
"""authentik"""
|
"""authentik"""
|
||||||
__version__ = "2021.5.1-rc8"
|
__version__ = "2021.5.1"
|
||||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||||
|
|||||||
@ -75,5 +75,6 @@ def backup_database(self: MonitoredTask): # pragma: no cover
|
|||||||
Boto3Error,
|
Boto3Error,
|
||||||
PermissionError,
|
PermissionError,
|
||||||
CommandConnectorError,
|
CommandConnectorError,
|
||||||
|
ValueError,
|
||||||
) as exc:
|
) as exc:
|
||||||
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
|
self.set_status(TaskResult(TaskResultStatus.ERROR).with_error(exc))
|
||||||
|
|||||||
@ -2,22 +2,25 @@
|
|||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
|
from authentik.core.api.groups import GroupSerializer
|
||||||
from authentik.events.models import NotificationRule
|
from authentik.events.models import NotificationRule
|
||||||
|
|
||||||
|
|
||||||
class NotificationRuleSerializer(ModelSerializer):
|
class NotificationRuleSerializer(ModelSerializer):
|
||||||
"""NotificationRule Serializer"""
|
"""NotificationRule Serializer"""
|
||||||
|
|
||||||
|
group_obj = GroupSerializer(read_only=True, source="group")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
||||||
model = NotificationRule
|
model = NotificationRule
|
||||||
depth = 2
|
|
||||||
fields = [
|
fields = [
|
||||||
"pk",
|
"pk",
|
||||||
"name",
|
"name",
|
||||||
"transports",
|
"transports",
|
||||||
"severity",
|
"severity",
|
||||||
"group",
|
"group",
|
||||||
|
"group_obj",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -210,6 +210,7 @@ class FlowViewSet(ModelViewSet):
|
|||||||
request.user, "authentik_policies.view_policybinding"
|
request.user, "authentik_policies.view_policybinding"
|
||||||
)
|
)
|
||||||
.filter(target=stage_binding)
|
.filter(target=stage_binding)
|
||||||
|
.exclude(policy__isnull=True)
|
||||||
.order_by("order")
|
.order_by("order")
|
||||||
):
|
):
|
||||||
body.append(
|
body.append(
|
||||||
|
|||||||
@ -42,7 +42,8 @@ outposts:
|
|||||||
# Placeholders:
|
# Placeholders:
|
||||||
# %(type)s: Outpost type; proxy, ldap, etc
|
# %(type)s: Outpost type; proxy, ldap, etc
|
||||||
# %(version)s: Current version; 2021.4.1
|
# %(version)s: Current version; 2021.4.1
|
||||||
docker_image_base: "beryju/authentik-%(type)s:%(version)s"
|
# %(build_hash)s: Build hash if you're running a beta version
|
||||||
|
docker_image_base: "ghcr.io/goauthentik/%(type)s:%(version)s"
|
||||||
|
|
||||||
authentik:
|
authentik:
|
||||||
avatars: gravatar # gravatar or none
|
avatars: gravatar # gravatar or none
|
||||||
|
|||||||
@ -4,6 +4,7 @@ from typing import Optional
|
|||||||
from aioredis.errors import ConnectionClosedError, ReplyError
|
from aioredis.errors import ConnectionClosedError, ReplyError
|
||||||
from billiard.exceptions import WorkerLostError
|
from billiard.exceptions import WorkerLostError
|
||||||
from botocore.client import ClientError
|
from botocore.client import ClientError
|
||||||
|
from botocore.exceptions import BotoCoreError
|
||||||
from celery.exceptions import CeleryError
|
from celery.exceptions import CeleryError
|
||||||
from channels.middleware import BaseMiddleware
|
from channels.middleware import BaseMiddleware
|
||||||
from channels_redis.core import ChannelFull
|
from channels_redis.core import ChannelFull
|
||||||
@ -72,6 +73,7 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
|
|||||||
WorkerLostError,
|
WorkerLostError,
|
||||||
CeleryError,
|
CeleryError,
|
||||||
# S3 errors
|
# S3 errors
|
||||||
|
BotoCoreError,
|
||||||
ClientError,
|
ClientError,
|
||||||
# custom baseclass
|
# custom baseclass
|
||||||
SentryIgnoredException,
|
SentryIgnoredException,
|
||||||
@ -87,6 +89,6 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
|
|||||||
if isinstance(exc_value, ignored_classes):
|
if isinstance(exc_value, ignored_classes):
|
||||||
return None
|
return None
|
||||||
if "logger" in event:
|
if "logger" in event:
|
||||||
if event["logger"] in ["dbbackup"]:
|
if event["logger"] in ["dbbackup", "botocore"]:
|
||||||
return None
|
return None
|
||||||
return event
|
return event
|
||||||
|
|||||||
@ -18,8 +18,6 @@ class OutpostSerializer(ModelSerializer):
|
|||||||
"""Outpost Serializer"""
|
"""Outpost Serializer"""
|
||||||
|
|
||||||
config = JSONField(validators=[is_dict], source="_config")
|
config = JSONField(validators=[is_dict], source="_config")
|
||||||
# TODO: Remove _config again, this is only here for legacy with older outposts
|
|
||||||
_config = JSONField(validators=[is_dict], read_only=True)
|
|
||||||
providers_obj = ProviderSerializer(source="providers", many=True, read_only=True)
|
providers_obj = ProviderSerializer(source="providers", many=True, read_only=True)
|
||||||
|
|
||||||
def validate_config(self, config) -> dict:
|
def validate_config(self, config) -> dict:
|
||||||
@ -42,7 +40,6 @@ class OutpostSerializer(ModelSerializer):
|
|||||||
"service_connection",
|
"service_connection",
|
||||||
"token_identifier",
|
"token_identifier",
|
||||||
"config",
|
"config",
|
||||||
"_config",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -82,6 +82,7 @@ class OutpostConsumer(AuthJsonConsumer):
|
|||||||
)
|
)
|
||||||
if msg.instruction == WebsocketMessageInstruction.HELLO:
|
if msg.instruction == WebsocketMessageInstruction.HELLO:
|
||||||
state.version = msg.args.get("version", None)
|
state.version = msg.args.get("version", None)
|
||||||
|
state.build_hash = msg.args.get("buildHash", "")
|
||||||
elif msg.instruction == WebsocketMessageInstruction.ACK:
|
elif msg.instruction == WebsocketMessageInstruction.ACK:
|
||||||
return
|
return
|
||||||
state.save(timeout=OUTPOST_HELLO_INTERVAL * 1.5)
|
state.save(timeout=OUTPOST_HELLO_INTERVAL * 1.5)
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
"""Base Controller"""
|
"""Base Controller"""
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from os import environ
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
from structlog.testing import capture_logs
|
from structlog.testing import capture_logs
|
||||||
|
|
||||||
from authentik import __version__
|
from authentik import ENV_GIT_HASH_KEY, __version__
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
from authentik.lib.sentry import SentryIgnoredException
|
from authentik.lib.sentry import SentryIgnoredException
|
||||||
from authentik.outposts.models import Outpost, OutpostServiceConnection
|
from authentik.outposts.models import Outpost, OutpostServiceConnection
|
||||||
@ -69,4 +70,8 @@ class BaseController:
|
|||||||
def get_container_image(self) -> str:
|
def get_container_image(self) -> str:
|
||||||
"""Get container image to use for this outpost"""
|
"""Get container image to use for this outpost"""
|
||||||
image_name_template: str = CONFIG.y("outposts.docker_image_base")
|
image_name_template: str = CONFIG.y("outposts.docker_image_base")
|
||||||
return image_name_template % {"type": self.outpost.type, "version": __version__}
|
return image_name_template % {
|
||||||
|
"type": self.outpost.type,
|
||||||
|
"version": __version__,
|
||||||
|
"build_hash": environ.get(ENV_GIT_HASH_KEY, ""),
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
"""Outpost models"""
|
"""Outpost models"""
|
||||||
from dataclasses import asdict, dataclass, field
|
from dataclasses import asdict, dataclass, field
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from os import environ
|
||||||
from typing import Iterable, Optional, Union
|
from typing import Iterable, Optional, Union
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ from packaging.version import LegacyVersion, Version, parse
|
|||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
from urllib3.exceptions import HTTPError
|
from urllib3.exceptions import HTTPError
|
||||||
|
|
||||||
from authentik import __version__
|
from authentik import ENV_GIT_HASH_KEY, __version__
|
||||||
from authentik.core.models import USER_ATTRIBUTE_SA, Provider, Token, TokenIntents, User
|
from authentik.core.models import USER_ATTRIBUTE_SA, Provider, Token, TokenIntents, User
|
||||||
from authentik.crypto.models import CertificateKeyPair
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
@ -411,6 +412,7 @@ class OutpostState:
|
|||||||
last_seen: Optional[datetime] = field(default=None)
|
last_seen: Optional[datetime] = field(default=None)
|
||||||
version: Optional[str] = field(default=None)
|
version: Optional[str] = field(default=None)
|
||||||
version_should: Union[Version, LegacyVersion] = field(default=OUR_VERSION)
|
version_should: Union[Version, LegacyVersion] = field(default=OUR_VERSION)
|
||||||
|
build_hash: str = field(default="")
|
||||||
|
|
||||||
_outpost: Optional[Outpost] = field(default=None)
|
_outpost: Optional[Outpost] = field(default=None)
|
||||||
|
|
||||||
@ -419,6 +421,8 @@ class OutpostState:
|
|||||||
"""Check if outpost version matches our version"""
|
"""Check if outpost version matches our version"""
|
||||||
if not self.version:
|
if not self.version:
|
||||||
return False
|
return False
|
||||||
|
if self.build_hash != environ.get(ENV_GIT_HASH_KEY, ""):
|
||||||
|
return False
|
||||||
return parse(self.version) < OUR_VERSION
|
return parse(self.version) < OUR_VERSION
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
@ -320,6 +320,7 @@ CELERY_RESULT_BACKEND = (
|
|||||||
# Database backup
|
# Database backup
|
||||||
DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage"
|
DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage"
|
||||||
DBBACKUP_STORAGE_OPTIONS = {"location": "./backups" if DEBUG else "/backups"}
|
DBBACKUP_STORAGE_OPTIONS = {"location": "./backups" if DEBUG else "/backups"}
|
||||||
|
DBBACKUP_FILENAME_TEMPLATE = "authentik-backup-{datetime}.sql"
|
||||||
if CONFIG.y("postgresql.s3_backup"):
|
if CONFIG.y("postgresql.s3_backup"):
|
||||||
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
|
DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
|
||||||
DBBACKUP_STORAGE_OPTIONS = {
|
DBBACKUP_STORAGE_OPTIONS = {
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
"""AuthenticatorStaticStage API Views"""
|
"""AuthenticatorStaticStage API Views"""
|
||||||
from django_filters import OrderingFilter
|
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from django_otp.plugins.otp_static.models import StaticDevice
|
from django_otp.plugins.otp_static.models import StaticDevice
|
||||||
from guardian.utils import get_anonymous_user
|
from guardian.utils import get_anonymous_user
|
||||||
from rest_framework.filters import SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
|
|||||||
@ -21,7 +21,7 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
server:
|
server:
|
||||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc8}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.1}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@ -52,7 +52,7 @@ services:
|
|||||||
- "0.0.0.0:9000:9000"
|
- "0.0.0.0:9000:9000"
|
||||||
- "0.0.0.0:9443:9443"
|
- "0.0.0.0:9443:9443"
|
||||||
worker:
|
worker:
|
||||||
image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc8}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.5.1}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
networks:
|
networks:
|
||||||
@ -64,8 +64,13 @@ services:
|
|||||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||||
# AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
|
# AUTHENTIK_ERROR_REPORTING__ENABLED: "true"
|
||||||
|
# This is optional, and can be removed. If you remove this, the following will happen
|
||||||
|
# - The permissions for the /backups and /media folders aren't fixed, so make sure they are 1000:1000
|
||||||
|
# - The docker socket can't be accessed anymore
|
||||||
|
user: root
|
||||||
volumes:
|
volumes:
|
||||||
- ./backups:/backups
|
- ./backups:/backups
|
||||||
|
- ./media:/media
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- ./custom-templates:/templates
|
- ./custom-templates:/templates
|
||||||
- geoip:/geoip
|
- geoip:/geoip
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
package constants
|
package constants
|
||||||
|
|
||||||
const VERSION = "2021.5.1-rc8"
|
const VERSION = "2021.5.1"
|
||||||
|
|||||||
@ -1,14 +1,29 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
python -m lifecycle.wait_for_db
|
python -m lifecycle.wait_for_db
|
||||||
printf '{"event": "Bootstrap completed", "level": "info", "logger": "bootstrap", "command": "%s"}\n' "$@" > /dev/stderr
|
printf '{"event": "Bootstrap completed", "level": "info", "logger": "bootstrap", "command": "%s"}\n' "$@" > /dev/stderr
|
||||||
|
|
||||||
|
function check_if_root {
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
printf '{"event": "Not running as root, disabling permission fixes", "level": "info", "logger": "bootstrap", "command": "%s"}\n' "$@" > /dev/stderr
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
SOCKET="/var/run/docker.sock"
|
||||||
|
if [[ -e "$SOCKET" ]]; then
|
||||||
|
# Get group ID of the docker socket, so we can create a matching group and
|
||||||
|
# add ourselves to it
|
||||||
|
DOCKER_GID=$(stat -c '%g' $SOCKET)
|
||||||
|
usermod -a -G $DOCKER_GID authentik
|
||||||
|
fi
|
||||||
|
# Fix permissions of backups and media
|
||||||
|
chown -R authentik:authentik /media /backups
|
||||||
|
}
|
||||||
|
|
||||||
if [[ "$1" == "server" ]]; then
|
if [[ "$1" == "server" ]]; then
|
||||||
python -m lifecycle.migrate
|
python -m lifecycle.migrate
|
||||||
/authentik-proxy
|
/authentik-proxy
|
||||||
elif [[ "$1" == "worker" ]]; then
|
elif [[ "$1" == "worker" ]]; then
|
||||||
celery -A authentik.root.celery worker --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events
|
check_if_root
|
||||||
elif [[ "$1" == "migrate" ]]; then
|
chpst -u authentik env HOME=/authentik celery -A authentik.root.celery worker --autoscale 3,1 -E -B -s /tmp/celerybeat-schedule -Q authentik,authentik_scheduled,authentik_events
|
||||||
printf "DEPERECATED: database migrations are now executed automatically on startup."
|
|
||||||
python -m lifecycle.migrate
|
|
||||||
elif [[ "$1" == "backup" ]]; then
|
elif [[ "$1" == "backup" ]]; then
|
||||||
python -m manage dbbackup --clean
|
python -m manage dbbackup --clean
|
||||||
elif [[ "$1" == "restore" ]]; then
|
elif [[ "$1" == "restore" ]]; then
|
||||||
|
|||||||
@ -113,10 +113,21 @@ stages:
|
|||||||
inputs:
|
inputs:
|
||||||
containerRegistry: 'beryjuorg-harbor'
|
containerRegistry: 'beryjuorg-harbor'
|
||||||
repository: 'authentik/outpost-proxy'
|
repository: 'authentik/outpost-proxy'
|
||||||
command: 'buildAndPush'
|
command: 'build'
|
||||||
Dockerfile: 'outpost/proxy.Dockerfile'
|
Dockerfile: 'outpost/proxy.Dockerfile'
|
||||||
buildContext: 'outpost/'
|
buildContext: 'outpost/'
|
||||||
tags: "gh-$(branchName)"
|
tags: |
|
||||||
|
gh-$(branchName)
|
||||||
|
gh-$(Build.SourceVersion)
|
||||||
|
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
|
||||||
|
- task: Docker@2
|
||||||
|
inputs:
|
||||||
|
containerRegistry: 'beryjuorg-harbor'
|
||||||
|
repository: 'authentik/outpost-proxy'
|
||||||
|
command: 'push'
|
||||||
|
tags: |
|
||||||
|
gh-$(branchName)
|
||||||
|
gh-$(Build.SourceVersion)
|
||||||
- job: ldap_build_docker
|
- job: ldap_build_docker
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
@ -138,7 +149,18 @@ stages:
|
|||||||
inputs:
|
inputs:
|
||||||
containerRegistry: 'beryjuorg-harbor'
|
containerRegistry: 'beryjuorg-harbor'
|
||||||
repository: 'authentik/outpost-ldap'
|
repository: 'authentik/outpost-ldap'
|
||||||
command: 'buildAndPush'
|
command: 'build'
|
||||||
Dockerfile: 'outpost/ldap.Dockerfile'
|
Dockerfile: 'outpost/ldap.Dockerfile'
|
||||||
buildContext: 'outpost/'
|
buildContext: 'outpost/'
|
||||||
tags: "gh-$(branchName)"
|
tags: |
|
||||||
|
gh-$(branchName)
|
||||||
|
gh-$(Build.SourceVersion)
|
||||||
|
arguments: '--build-arg GIT_BUILD_HASH=$(Build.SourceVersion)'
|
||||||
|
- task: Docker@2
|
||||||
|
inputs:
|
||||||
|
containerRegistry: 'beryjuorg-harbor'
|
||||||
|
repository: 'authentik/outpost-ldap'
|
||||||
|
command: 'push'
|
||||||
|
tags: |
|
||||||
|
gh-$(branchName)
|
||||||
|
gh-$(Build.SourceVersion)
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
FROM golang:1.16.4 AS builder
|
FROM golang:1.16.4 AS builder
|
||||||
|
ARG GIT_BUILD_HASH
|
||||||
|
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package ak
|
package ak
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -43,7 +42,7 @@ 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 {
|
||||||
transport := httptransport.New(akURL.Host, client.DefaultBasePath, []string{akURL.Scheme})
|
transport := httptransport.New(akURL.Host, client.DefaultBasePath, []string{akURL.Scheme})
|
||||||
transport.Transport = SetUserAgent(getTLSTransport(), fmt.Sprintf("authentik-proxy@%s", pkg.VERSION))
|
transport.Transport = SetUserAgent(getTLSTransport(), pkg.UserAgent())
|
||||||
|
|
||||||
// create the transport
|
// create the transport
|
||||||
auth := httptransport.BearerToken(token)
|
auth := httptransport.BearerToken(token)
|
||||||
|
|||||||
@ -23,7 +23,7 @@ func (ac *APIController) initWS(akURL url.URL, outpostUUID strfmt.UUID) {
|
|||||||
|
|
||||||
header := http.Header{
|
header := http.Header{
|
||||||
"Authorization": []string{authHeader},
|
"Authorization": []string{authHeader},
|
||||||
"User-Agent": []string{fmt.Sprintf("authentik-proxy@%s", pkg.VERSION)},
|
"User-Agent": []string{pkg.UserAgent()},
|
||||||
}
|
}
|
||||||
|
|
||||||
value, set := os.LookupEnv("AUTHENTIK_INSECURE")
|
value, set := os.LookupEnv("AUTHENTIK_INSECURE")
|
||||||
@ -46,8 +46,9 @@ func (ac *APIController) initWS(akURL url.URL, outpostUUID strfmt.UUID) {
|
|||||||
msg := websocketMessage{
|
msg := websocketMessage{
|
||||||
Instruction: WebsocketInstructionHello,
|
Instruction: WebsocketInstructionHello,
|
||||||
Args: map[string]interface{}{
|
Args: map[string]interface{}{
|
||||||
"version": pkg.VERSION,
|
"version": pkg.VERSION,
|
||||||
"uuid": ac.instanceUUID.String(),
|
"buildHash": pkg.BUILD(),
|
||||||
|
"uuid": ac.instanceUUID.String(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := ws.WriteJSON(msg)
|
err := ws.WriteJSON(msg)
|
||||||
@ -76,7 +77,7 @@ func (ac *APIController) startWSHandler() {
|
|||||||
var wsMsg websocketMessage
|
var wsMsg websocketMessage
|
||||||
err := ac.wsConn.ReadJSON(&wsMsg)
|
err := ac.wsConn.ReadJSON(&wsMsg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Println("read:", err)
|
logger.WithError(err).Warning("ws write error, reconnecting")
|
||||||
ac.wsConn.CloseAndReconnect()
|
ac.wsConn.CloseAndReconnect()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -100,14 +101,15 @@ func (ac *APIController) startWSHealth() {
|
|||||||
aliveMsg := websocketMessage{
|
aliveMsg := websocketMessage{
|
||||||
Instruction: WebsocketInstructionHello,
|
Instruction: WebsocketInstructionHello,
|
||||||
Args: map[string]interface{}{
|
Args: map[string]interface{}{
|
||||||
"version": pkg.VERSION,
|
"version": pkg.VERSION,
|
||||||
"uuid": ac.instanceUUID.String(),
|
"buildHash": pkg.BUILD(),
|
||||||
|
"uuid": ac.instanceUUID.String(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := ac.wsConn.WriteJSON(aliveMsg)
|
err := ac.wsConn.WriteJSON(aliveMsg)
|
||||||
ac.logger.WithField("loop", "ws-health").Trace("hello'd")
|
ac.logger.WithField("loop", "ws-health").Trace("hello'd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ac.logger.WithField("loop", "ws-health").Println("write:", err)
|
ac.logger.WithField("loop", "ws-health").WithError(err).Warning("ws write error, reconnecting")
|
||||||
ac.wsConn.CloseAndReconnect()
|
ac.wsConn.CloseAndReconnect()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func doGlobalSetup(config map[string]interface{}) {
|
|||||||
default:
|
default:
|
||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
}
|
}
|
||||||
log.WithField("version", pkg.VERSION).Info("Starting authentik outpost")
|
log.WithField("buildHash", pkg.BUILD()).WithField("version", pkg.VERSION).Info("Starting authentik outpost")
|
||||||
|
|
||||||
var dsn string
|
var dsn string
|
||||||
if config[ConfigErrorReportingEnabled].(bool) {
|
if config[ConfigErrorReportingEnabled].(bool) {
|
||||||
|
|||||||
@ -2,20 +2,22 @@ package ldap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/nmcclain/ldap"
|
"github.com/nmcclain/ldap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
|
func (ls *LDAPServer) Bind(bindDN string, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
|
||||||
ls.log.WithField("boundDN", bindDN).Info("bind")
|
ls.log.WithField("bindDN", bindDN).Info("bind")
|
||||||
|
bindDN = strings.ToLower(bindDN)
|
||||||
for _, instance := range ls.providers {
|
for _, instance := range ls.providers {
|
||||||
username, err := instance.getUsername(bindDN)
|
username, err := instance.getUsername(bindDN)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return instance.Bind(username, bindPW, conn)
|
return instance.Bind(username, bindDN, bindPW, conn)
|
||||||
} else {
|
} else {
|
||||||
ls.log.WithError(err).Debug("Username not for instance")
|
ls.log.WithError(err).Debug("Username not for instance")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ls.log.WithField("boundDN", bindDN).WithField("request", "bind").Warning("No provider found for request")
|
ls.log.WithField("bindDN", bindDN).WithField("request", "bind").Warning("No provider found for request")
|
||||||
return ldap.LDAPResultOperationsError, nil
|
return ldap.LDAPResultOperationsError, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,7 +47,7 @@ func (pi *ProviderInstance) getUsername(dn string) (string, error) {
|
|||||||
return "", errors.New("failed to find cn")
|
return "", errors.New("failed to find cn")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pi *ProviderInstance) Bind(username string, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
|
func (pi *ProviderInstance) Bind(username string, bindDN, bindPW string, conn net.Conn) (ldap.LDAPResultCode, error) {
|
||||||
jar, err := cookiejar.New(nil)
|
jar, err := cookiejar.New(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pi.log.WithError(err).Warning("Failed to create cookiejar")
|
pi.log.WithError(err).Warning("Failed to create cookiejar")
|
||||||
@ -67,9 +67,9 @@ func (pi *ProviderInstance) Bind(username string, bindPW string, conn net.Conn)
|
|||||||
}
|
}
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("goauthentik.io/outpost/ldap", "true")
|
params.Add("goauthentik.io/outpost/ldap", "true")
|
||||||
passed, err := pi.solveFlowChallenge(username, bindPW, client, params.Encode())
|
passed, err := pi.solveFlowChallenge(username, bindPW, client, params.Encode(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pi.log.WithField("boundDN", username).WithError(err).Warning("failed to solve challenge")
|
pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to solve challenge")
|
||||||
return ldap.LDAPResultOperationsError, nil
|
return ldap.LDAPResultOperationsError, nil
|
||||||
}
|
}
|
||||||
if !passed {
|
if !passed {
|
||||||
@ -82,25 +82,25 @@ func (pi *ProviderInstance) Bind(username string, bindPW string, conn net.Conn)
|
|||||||
}, httptransport.PassThroughAuth)
|
}, httptransport.PassThroughAuth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, denied := err.(*core.CoreApplicationsCheckAccessForbidden); denied {
|
if _, denied := err.(*core.CoreApplicationsCheckAccessForbidden); denied {
|
||||||
pi.log.WithField("boundDN", username).Info("Access denied for user")
|
pi.log.WithField("bindDN", bindDN).Info("Access denied for user")
|
||||||
return ldap.LDAPResultInsufficientAccessRights, nil
|
return ldap.LDAPResultInsufficientAccessRights, nil
|
||||||
}
|
}
|
||||||
pi.log.WithField("boundDN", username).WithError(err).Warning("failed to check access")
|
pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to check access")
|
||||||
return ldap.LDAPResultOperationsError, nil
|
return ldap.LDAPResultOperationsError, nil
|
||||||
}
|
}
|
||||||
pi.log.WithField("boundDN", username).Info("User has access")
|
pi.log.WithField("bindDN", bindDN).Info("User has access")
|
||||||
// Get user info to store in context
|
// Get user info to store in context
|
||||||
userInfo, err := pi.s.ac.Client.Core.CoreUsersMe(&core.CoreUsersMeParams{
|
userInfo, err := pi.s.ac.Client.Core.CoreUsersMe(&core.CoreUsersMeParams{
|
||||||
Context: context.Background(),
|
Context: context.Background(),
|
||||||
HTTPClient: client,
|
HTTPClient: client,
|
||||||
}, httptransport.PassThroughAuth)
|
}, httptransport.PassThroughAuth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pi.log.WithField("boundDN", username).WithError(err).Warning("failed to get user info")
|
pi.log.WithField("bindDN", bindDN).WithError(err).Warning("failed to get user info")
|
||||||
return ldap.LDAPResultOperationsError, nil
|
return ldap.LDAPResultOperationsError, nil
|
||||||
}
|
}
|
||||||
pi.boundUsersMutex.Lock()
|
pi.boundUsersMutex.Lock()
|
||||||
pi.boundUsers[username] = UserFlags{
|
pi.boundUsers[bindDN] = UserFlags{
|
||||||
UserInfo: userInfo.Payload.User,
|
UserInfo: *userInfo.Payload.User,
|
||||||
CanSearch: pi.SearchAccessCheck(userInfo.Payload.User),
|
CanSearch: pi.SearchAccessCheck(userInfo.Payload.User),
|
||||||
}
|
}
|
||||||
defer pi.boundUsersMutex.Unlock()
|
defer pi.boundUsersMutex.Unlock()
|
||||||
@ -112,7 +112,8 @@ func (pi *ProviderInstance) Bind(username string, bindPW string, conn net.Conn)
|
|||||||
func (pi *ProviderInstance) SearchAccessCheck(user *models.User) bool {
|
func (pi *ProviderInstance) SearchAccessCheck(user *models.User) bool {
|
||||||
for _, group := range user.Groups {
|
for _, group := range user.Groups {
|
||||||
for _, allowedGroup := range pi.searchAllowedGroups {
|
for _, allowedGroup := range pi.searchAllowedGroups {
|
||||||
if &group.Pk == allowedGroup {
|
pi.log.WithField("userGroup", group.Pk).WithField("allowedGroup", allowedGroup).Trace("Checking search access")
|
||||||
|
if group.Pk.String() == allowedGroup.String() {
|
||||||
pi.log.WithField("group", group.Name).Info("Allowed access to search")
|
pi.log.WithField("group", group.Name).Info("Allowed access to search")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -139,7 +140,7 @@ func (pi *ProviderInstance) delayDeleteUserInfo(dn string) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *http.Client, urlParams string) (bool, error) {
|
func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, client *http.Client, urlParams string, depth int) (bool, error) {
|
||||||
challenge, err := pi.s.ac.Client.Flows.FlowsExecutorGet(&flows.FlowsExecutorGetParams{
|
challenge, err := pi.s.ac.Client.Flows.FlowsExecutorGet(&flows.FlowsExecutorGetParams{
|
||||||
FlowSlug: pi.flowSlug,
|
FlowSlug: pi.flowSlug,
|
||||||
Query: urlParams,
|
Query: urlParams,
|
||||||
@ -169,6 +170,10 @@ func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, c
|
|||||||
}
|
}
|
||||||
response, err := pi.s.ac.Client.Flows.FlowsExecutorSolve(responseParams, pi.s.ac.Auth)
|
response, err := pi.s.ac.Client.Flows.FlowsExecutorSolve(responseParams, pi.s.ac.Auth)
|
||||||
pi.log.WithField("component", response.Payload.Component).WithField("type", *response.Payload.Type).Debug("Got response")
|
pi.log.WithField("component", response.Payload.Component).WithField("type", *response.Payload.Type).Debug("Got response")
|
||||||
|
switch response.Payload.Component {
|
||||||
|
case "ak-stage-access-denied":
|
||||||
|
return false, errors.New("got ak-stage-access-denied")
|
||||||
|
}
|
||||||
if *response.Payload.Type == "redirect" {
|
if *response.Payload.Type == "redirect" {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -184,5 +189,8 @@ func (pi *ProviderInstance) solveFlowChallenge(bindDN string, password string, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pi.solveFlowChallenge(bindDN, password, client, urlParams)
|
if depth >= 10 {
|
||||||
|
return false, errors.New("exceeded stage recursion depth")
|
||||||
|
}
|
||||||
|
return pi.solveFlowChallenge(bindDN, password, client, urlParams, depth+1)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,10 +29,13 @@ func (pi *ProviderInstance) Search(bindDN string, searchReq ldap.SearchRequest,
|
|||||||
pi.boundUsersMutex.RLock()
|
pi.boundUsersMutex.RLock()
|
||||||
defer pi.boundUsersMutex.RUnlock()
|
defer pi.boundUsersMutex.RUnlock()
|
||||||
flags, ok := pi.boundUsers[bindDN]
|
flags, ok := pi.boundUsers[bindDN]
|
||||||
|
pi.log.WithField("bindDN", bindDN).WithField("ok", ok).Debugf("%+v\n", flags)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
pi.log.Debug("User info not cached")
|
||||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
||||||
}
|
}
|
||||||
if !flags.CanSearch {
|
if !flags.CanSearch {
|
||||||
|
pi.log.Debug("User can't search")
|
||||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultInsufficientAccessRights}, errors.New("access denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,7 +31,7 @@ type ProviderInstance struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserFlags struct {
|
type UserFlags struct {
|
||||||
UserInfo *models.User
|
UserInfo models.User
|
||||||
CanSearch bool
|
CanSearch bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import (
|
|||||||
"github.com/nmcclain/ldap"
|
"github.com/nmcclain/ldap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ls *LDAPServer) Search(boundDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
|
func (ls *LDAPServer) Search(bindDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
|
||||||
ls.log.WithField("boundDN", boundDN).WithField("baseDN", searchReq.BaseDN).Info("search")
|
ls.log.WithField("bindDN", bindDN).WithField("baseDN", searchReq.BaseDN).Info("search")
|
||||||
if searchReq.BaseDN == "" {
|
if searchReq.BaseDN == "" {
|
||||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultSuccess}, nil
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultSuccess}, nil
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ func (ls *LDAPServer) Search(boundDN string, searchReq ldap.SearchRequest, conn
|
|||||||
for _, provider := range ls.providers {
|
for _, provider := range ls.providers {
|
||||||
providerBase, _ := goldap.ParseDN(provider.BaseDN)
|
providerBase, _ := goldap.ParseDN(provider.BaseDN)
|
||||||
if providerBase.AncestorOf(bd) {
|
if providerBase.AncestorOf(bd) {
|
||||||
return provider.Search(boundDN, searchReq, conn)
|
return provider.Search(bindDN, searchReq, conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, errors.New("no provider could handle request")
|
return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, errors.New("no provider could handle request")
|
||||||
|
|||||||
@ -161,7 +161,7 @@ func (p *OAuthProxy) OAuthStart(rw http.ResponseWriter, req *http.Request) {
|
|||||||
p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
|
p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
redirectURI := p.GetRedirectURI(getHost(req))
|
redirectURI := p.GetRedirectURI(req.Host)
|
||||||
http.Redirect(rw, req, p.provider.GetLoginURL(redirectURI, fmt.Sprintf("%v:%v", nonce, redirect)), http.StatusFound)
|
http.Redirect(rw, req, p.provider.GetLoginURL(redirectURI, fmt.Sprintf("%v:%v", nonce, redirect)), http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,16 @@
|
|||||||
package pkg
|
package pkg
|
||||||
|
|
||||||
const VERSION = "2021.5.1-rc8"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const VERSION = "2021.5.1"
|
||||||
|
|
||||||
|
func BUILD() string {
|
||||||
|
return os.Getenv("GIT_BUILD_HASH")
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserAgent() string {
|
||||||
|
return fmt.Sprintf("authentik-outpost@%s (%s)", VERSION, BUILD())
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
FROM golang:1.16.4 AS builder
|
FROM golang:1.16.4 AS builder
|
||||||
|
ARG GIT_BUILD_HASH
|
||||||
|
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
|
|||||||
99
swagger.yaml
99
swagger.yaml
@ -15694,6 +15694,7 @@ definitions:
|
|||||||
NotificationRule:
|
NotificationRule:
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
|
- transports
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
pk:
|
pk:
|
||||||
@ -15706,38 +15707,17 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
transports:
|
transports:
|
||||||
|
description: Select which transports should be used to notify the user. If
|
||||||
|
none are selected, the notification will only be shown in the authentik
|
||||||
|
UI.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
required:
|
description: Select which transports should be used to notify the user.
|
||||||
- name
|
If none are selected, the notification will only be shown in the authentik
|
||||||
- mode
|
UI.
|
||||||
type: object
|
type: string
|
||||||
properties:
|
format: uuid
|
||||||
uuid:
|
uniqueItems: true
|
||||||
title: Uuid
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
readOnly: true
|
|
||||||
name:
|
|
||||||
title: Name
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
mode:
|
|
||||||
title: Mode
|
|
||||||
type: string
|
|
||||||
enum:
|
|
||||||
- webhook
|
|
||||||
- webhook_slack
|
|
||||||
- email
|
|
||||||
webhook_url:
|
|
||||||
title: Webhook url
|
|
||||||
type: string
|
|
||||||
send_once:
|
|
||||||
title: Send once
|
|
||||||
description: Only send notification once, for example when sending a
|
|
||||||
webhook into a chat channel.
|
|
||||||
type: boolean
|
|
||||||
readOnly: true
|
|
||||||
severity:
|
severity:
|
||||||
title: Severity
|
title: Severity
|
||||||
description: Controls which severity level the created notifications will
|
description: Controls which severity level the created notifications will
|
||||||
@ -15748,57 +15728,14 @@ definitions:
|
|||||||
- warning
|
- warning
|
||||||
- alert
|
- alert
|
||||||
group:
|
group:
|
||||||
required:
|
title: Group
|
||||||
- name
|
description: Define which group of users this notification should be sent
|
||||||
type: object
|
and shown to. If left empty, Notification won't ben sent.
|
||||||
properties:
|
type: string
|
||||||
group_uuid:
|
format: uuid
|
||||||
title: Group uuid
|
x-nullable: true
|
||||||
type: string
|
group_obj:
|
||||||
format: uuid
|
$ref: '#/definitions/Group'
|
||||||
readOnly: true
|
|
||||||
name:
|
|
||||||
title: Name
|
|
||||||
type: string
|
|
||||||
maxLength: 80
|
|
||||||
minLength: 1
|
|
||||||
is_superuser:
|
|
||||||
title: Is superuser
|
|
||||||
description: Users added to this group will be superusers.
|
|
||||||
type: boolean
|
|
||||||
attributes:
|
|
||||||
title: Attributes
|
|
||||||
type: object
|
|
||||||
parent:
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
- parent
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
group_uuid:
|
|
||||||
title: Group uuid
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
readOnly: true
|
|
||||||
name:
|
|
||||||
title: Name
|
|
||||||
type: string
|
|
||||||
maxLength: 80
|
|
||||||
minLength: 1
|
|
||||||
is_superuser:
|
|
||||||
title: Is superuser
|
|
||||||
description: Users added to this group will be superusers.
|
|
||||||
type: boolean
|
|
||||||
attributes:
|
|
||||||
title: Attributes
|
|
||||||
type: object
|
|
||||||
parent:
|
|
||||||
title: Parent
|
|
||||||
type: string
|
|
||||||
format: uuid
|
|
||||||
x-nullable: true
|
|
||||||
readOnly: true
|
|
||||||
readOnly: true
|
|
||||||
NotificationTransport:
|
NotificationTransport:
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
|
|||||||
@ -70,7 +70,7 @@ class TestProviderProxy(SeleniumTestCase):
|
|||||||
authorization_flow=Flow.objects.get(
|
authorization_flow=Flow.objects.get(
|
||||||
slug="default-provider-authorization-implicit-consent"
|
slug="default-provider-authorization-implicit-consent"
|
||||||
),
|
),
|
||||||
internal_host="http://localhost:80",
|
internal_host="http://localhost",
|
||||||
external_host="http://localhost:4180",
|
external_host="http://localhost:4180",
|
||||||
)
|
)
|
||||||
# Ensure OAuth2 Params are set
|
# Ensure OAuth2 Params are set
|
||||||
@ -123,7 +123,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase):
|
|||||||
authorization_flow=Flow.objects.get(
|
authorization_flow=Flow.objects.get(
|
||||||
slug="default-provider-authorization-implicit-consent"
|
slug="default-provider-authorization-implicit-consent"
|
||||||
),
|
),
|
||||||
internal_host="http://localhost:80",
|
internal_host="http://localhost",
|
||||||
external_host="http://localhost:4180",
|
external_host="http://localhost:4180",
|
||||||
)
|
)
|
||||||
# Ensure OAuth2 Params are set
|
# Ensure OAuth2 Params are set
|
||||||
|
|||||||
@ -104,5 +104,5 @@ class OutpostDockerTests(TestCase):
|
|||||||
self.assertEqual(compose["version"], "3.5")
|
self.assertEqual(compose["version"], "3.5")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
compose["services"]["authentik_proxy"]["image"],
|
compose["services"]["authentik_proxy"]["image"],
|
||||||
f"beryju/authentik-proxy:{__version__}",
|
f"ghcr.io/goauthentik/proxy:{__version__}",
|
||||||
)
|
)
|
||||||
|
|||||||
@ -104,5 +104,5 @@ class TestProxyDocker(TestCase):
|
|||||||
self.assertEqual(compose["version"], "3.5")
|
self.assertEqual(compose["version"], "3.5")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
compose["services"]["authentik_proxy"]["image"],
|
compose["services"]["authentik_proxy"]["image"],
|
||||||
f"beryju/authentik-proxy:{__version__}",
|
f"ghcr.io/goauthentik/proxy:{__version__}",
|
||||||
)
|
)
|
||||||
|
|||||||
@ -81,7 +81,7 @@ http {
|
|||||||
location /static/ {
|
location /static/ {
|
||||||
expires 31d;
|
expires 31d;
|
||||||
add_header Cache-Control "public, no-transform";
|
add_header Cache-Control "public, no-transform";
|
||||||
add_header X-authentik-version "2021.5.1-rc8";
|
add_header X-authentik-version "2021.5.1";
|
||||||
add_header Vary X-authentik-version;
|
add_header Vary X-authentik-version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1379
web/package-lock.json
generated
1379
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -35,10 +35,10 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.14.0",
|
"@babel/core": "^7.14.2",
|
||||||
"@babel/plugin-proposal-decorators": "^7.13.15",
|
"@babel/plugin-proposal-decorators": "^7.14.2",
|
||||||
"@babel/plugin-transform-runtime": "^7.13.15",
|
"@babel/plugin-transform-runtime": "^7.14.2",
|
||||||
"@babel/preset-env": "^7.14.1",
|
"@babel/preset-env": "^7.14.2",
|
||||||
"@babel/preset-typescript": "^7.13.0",
|
"@babel/preset-typescript": "^7.13.0",
|
||||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||||
"@lingui/cli": "^3.8.10",
|
"@lingui/cli": "^3.8.10",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
|
|||||||
export const ERROR_CLASS = "pf-m-danger";
|
export const ERROR_CLASS = "pf-m-danger";
|
||||||
export const PROGRESS_CLASS = "pf-m-in-progress";
|
export const PROGRESS_CLASS = "pf-m-in-progress";
|
||||||
export const CURRENT_CLASS = "pf-m-current";
|
export const CURRENT_CLASS = "pf-m-current";
|
||||||
export const VERSION = "2021.5.1-rc8";
|
export const VERSION = "2021.5.1";
|
||||||
export const PAGE_SIZE = 20;
|
export const PAGE_SIZE = 20;
|
||||||
export const EVENT_REFRESH = "ak-refresh";
|
export const EVENT_REFRESH = "ak-refresh";
|
||||||
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
|
|||||||
<option value="" ?selected=${this.instance?.group === undefined}>---------</option>
|
<option value="" ?selected=${this.instance?.group === undefined}>---------</option>
|
||||||
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
|
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
|
||||||
return groups.results.map(group => {
|
return groups.results.map(group => {
|
||||||
return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.group?.groupUuid === group.pk}>${group.name}</option>`;
|
return html`<option value=${ifDefined(group.pk)} ?selected=${this.instance?.group === group.pk}>${group.name}</option>`;
|
||||||
});
|
});
|
||||||
}), html`<option>${t`Loading...`}</option>`)}
|
}), html`<option>${t`Loading...`}</option>`)}
|
||||||
</select>
|
</select>
|
||||||
@ -80,7 +80,7 @@ export class RuleForm extends ModelForm<NotificationRule, string> {
|
|||||||
${until(new EventsApi(DEFAULT_CONFIG).eventsTransportsList({}).then(transports => {
|
${until(new EventsApi(DEFAULT_CONFIG).eventsTransportsList({}).then(transports => {
|
||||||
return transports.results.map(transport => {
|
return transports.results.map(transport => {
|
||||||
const selected = Array.from(this.instance?.transports || []).some(su => {
|
const selected = Array.from(this.instance?.transports || []).some(su => {
|
||||||
return su.uuid == transport.pk;
|
return su == transport.pk;
|
||||||
});
|
});
|
||||||
return html`<option value=${ifDefined(transport.pk)} ?selected=${selected}>${transport.name}</option>`;
|
return html`<option value=${ifDefined(transport.pk)} ?selected=${selected}>${transport.name}</option>`;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -55,7 +55,7 @@ export class RuleListPage extends TablePage<NotificationRule> {
|
|||||||
return [
|
return [
|
||||||
html`${item.name}`,
|
html`${item.name}`,
|
||||||
html`${item.severity}`,
|
html`${item.severity}`,
|
||||||
html`${item.group?.name || t`None (rule disabled)`}`,
|
html`${item.groupObj?.name || t`None (rule disabled)`}`,
|
||||||
html`
|
html`
|
||||||
<ak-forms-modal>
|
<ak-forms-modal>
|
||||||
<span slot="submit">
|
<span slot="submit">
|
||||||
|
|||||||
@ -58,14 +58,6 @@ export class FlowViewPage extends LitElement {
|
|||||||
<ak-tabs>
|
<ak-tabs>
|
||||||
<div slot="page-overview" data-tab-title="${t`Flow Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
<div slot="page-overview" data-tab-title="${t`Flow Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||||
<div class="pf-l-gallery pf-m-gutter">
|
<div class="pf-l-gallery pf-m-gutter">
|
||||||
<div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 4;grid-row-end: span 2;">
|
|
||||||
<div class="pf-c-card">
|
|
||||||
<div class="pf-c-card__body">
|
|
||||||
<ak-flow-diagram flowSlug=${this.flow.slug}>
|
|
||||||
</ak-flow-diagram>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pf-c-card pf-l-gallery__item">
|
<div class="pf-c-card pf-l-gallery__item">
|
||||||
<div class="pf-c-card__title">${t`Related`}</div>
|
<div class="pf-c-card__title">${t`Related`}</div>
|
||||||
<div class="pf-c-card__body">
|
<div class="pf-c-card__body">
|
||||||
@ -94,6 +86,14 @@ export class FlowViewPage extends LitElement {
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 4;grid-row-end: span 2;">
|
||||||
|
<div class="pf-c-card">
|
||||||
|
<div class="pf-c-card__body">
|
||||||
|
<ak-flow-diagram flowSlug=${this.flow.slug}>
|
||||||
|
</ak-flow-diagram>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div slot="page-stage-bindings" data-tab-title="${t`Stage Bindings`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
<div slot="page-stage-bindings" data-tab-title="${t`Stage Bindings`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
|
||||||
|
|||||||
@ -42,13 +42,12 @@ export class OutpostHealthElement extends LitElement {
|
|||||||
return html`<ak-spinner></ak-spinner>`;
|
return html`<ak-spinner></ak-spinner>`;
|
||||||
}
|
}
|
||||||
if (this.outpostHealth.length === 0) {
|
if (this.outpostHealth.length === 0) {
|
||||||
return html`<li>
|
return html`
|
||||||
<ul>
|
<ul>
|
||||||
<li role="cell">
|
<li role="cell">
|
||||||
<ak-label color=${PFColor.Grey} text=${t`Not available`}></ak-label>
|
<ak-label color=${PFColor.Grey} text=${t`Not available`}></ak-label>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>`;
|
||||||
</li>`;
|
|
||||||
}
|
}
|
||||||
return html`<ul>${this.outpostHealth.map((h) => {
|
return html`<ul>${this.outpostHealth.map((h) => {
|
||||||
return html`<li>
|
return html`<li>
|
||||||
|
|||||||
@ -76,6 +76,40 @@ export class PlexSourceForm extends ModelForm<PlexSource, string> {
|
|||||||
this.plexResources = await new PlexAPIClient(this.plexToken).getServers();
|
this.plexResources = await new PlexAPIClient(this.plexToken).getServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderSettings(): TemplateResult {
|
||||||
|
if (!this.plexToken) {
|
||||||
|
return html`
|
||||||
|
<button class="pf-c-button pf-m-primary" type="button" @click=${() => {
|
||||||
|
this.doAuth();
|
||||||
|
}}>
|
||||||
|
${t`Load servers`}
|
||||||
|
</button>`;
|
||||||
|
}
|
||||||
|
return html`<ak-form-element-horizontal name="allowFriends">
|
||||||
|
<div class="pf-c-check">
|
||||||
|
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.allowFriends, true)}>
|
||||||
|
<label class="pf-c-check__label">
|
||||||
|
${t`Allow friends to authenticate via Plex, even if you don't share any servers`}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</ak-form-element-horizontal>
|
||||||
|
<ak-form-element-horizontal
|
||||||
|
label=${t`Allowed servers`}
|
||||||
|
?required=${true}
|
||||||
|
name="allowedServers">
|
||||||
|
<select class="pf-c-form-control" multiple>
|
||||||
|
${this.plexResources?.map(r => {
|
||||||
|
const selected = Array.from(this.instance?.allowedServers || []).some(server => {
|
||||||
|
return server == r.clientIdentifier;
|
||||||
|
});
|
||||||
|
return html`<option value=${r.clientIdentifier} ?selected=${selected}>${r.name}</option>`;
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
<p class="pf-c-form__helper-text">${t`Select which server a user has to be a member of to be allowed to authenticate.`}</p>
|
||||||
|
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
||||||
|
</ak-form-element-horizontal>`;
|
||||||
|
}
|
||||||
|
|
||||||
renderForm(): TemplateResult {
|
renderForm(): TemplateResult {
|
||||||
return html`<form class="pf-c-form pf-m-horizontal">
|
return html`<form class="pf-c-form pf-m-horizontal">
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
@ -132,36 +166,7 @@ export class PlexSourceForm extends ModelForm<PlexSource, string> {
|
|||||||
name="clientId">
|
name="clientId">
|
||||||
<input type="text" value="${first(this.instance?.clientId)}" class="pf-c-form-control" required>
|
<input type="text" value="${first(this.instance?.clientId)}" class="pf-c-form-control" required>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal name="allowFriends">
|
${this.renderSettings()}
|
||||||
<div class="pf-c-check">
|
|
||||||
<input type="checkbox" class="pf-c-check__input" ?checked=${first(this.instance?.allowFriends, true)}>
|
|
||||||
<label class="pf-c-check__label">
|
|
||||||
${t`Allow friends to authenticate via Plex, even if you don't share any servers`}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</ak-form-element-horizontal>
|
|
||||||
<ak-form-element-horizontal
|
|
||||||
label=${t`Allowed servers`}
|
|
||||||
?required=${true}
|
|
||||||
name="allowedServers">
|
|
||||||
<select class="pf-c-form-control" multiple>
|
|
||||||
${this.plexResources?.map(r => {
|
|
||||||
const selected = Array.from(this.instance?.allowedServers || []).some(server => {
|
|
||||||
return server == r.clientIdentifier;
|
|
||||||
});
|
|
||||||
return html`<option value=${r.clientIdentifier} ?selected=${selected}>${r.name}</option>`;
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
<p class="pf-c-form__helper-text">${t`Select which server a user has to be a member of to be allowed to authenticate.`}</p>
|
|
||||||
<p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
|
|
||||||
<p class="pf-c-form__helper-text">
|
|
||||||
<button class="pf-c-button pf-m-primary" type="button" @click=${() => {
|
|
||||||
this.doAuth();
|
|
||||||
}}>
|
|
||||||
${t`Load servers`}
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</ak-form-element-horizontal>
|
|
||||||
</div>
|
</div>
|
||||||
</ak-form-group>
|
</ak-form-group>
|
||||||
<ak-form-group>
|
<ak-form-group>
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
|||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${t`Not configured action`}
|
label=${t`Not configured action`}
|
||||||
?required=${true}
|
?required=${true}
|
||||||
name="mode">
|
name="notConfiguredAction">
|
||||||
<select class="pf-c-form-control" @change=${(ev: Event) => {
|
<select class="pf-c-form-control" @change=${(ev: Event) => {
|
||||||
const target = ev.target as HTMLSelectElement;
|
const target = ev.target as HTMLSelectElement;
|
||||||
if (target.selectedOptions[0].value === AuthenticatorValidateStageNotConfiguredActionEnum.Configure) {
|
if (target.selectedOptions[0].value === AuthenticatorValidateStageNotConfiguredActionEnum.Configure) {
|
||||||
|
|||||||
@ -16,7 +16,7 @@ Download the latest `docker-compose.yml` from [here](https://raw.githubuserconte
|
|||||||
|
|
||||||
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
|
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
|
||||||
|
|
||||||
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.1-rc8 >> .env`
|
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.1 >> .env`
|
||||||
|
|
||||||
If this is a fresh authentik install run the following commands to generate a password:
|
If this is a fresh authentik install run the following commands to generate a password:
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ version: "3.5"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
authentik_proxy:
|
authentik_proxy:
|
||||||
image: beryju/authentik-proxy:2021.5.1-rc8
|
image: beryju/authentik-proxy:2021.5.1
|
||||||
ports:
|
ports:
|
||||||
- 4180:4180
|
- 4180:4180
|
||||||
- 4443:4443
|
- 4443:4443
|
||||||
|
|||||||
@ -14,7 +14,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
name: authentik-outpost-api
|
name: authentik-outpost-api
|
||||||
stringData:
|
stringData:
|
||||||
authentik_host: "__AUTHENTIK_URL__"
|
authentik_host: "__AUTHENTIK_URL__"
|
||||||
@ -29,7 +29,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
name: authentik-outpost
|
name: authentik-outpost
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
@ -54,7 +54,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
name: authentik-outpost
|
name: authentik-outpost
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
@ -62,14 +62,14 @@ spec:
|
|||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- env:
|
||||||
@ -88,7 +88,7 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
key: authentik_host_insecure
|
key: authentik_host_insecure
|
||||||
name: authentik-outpost-api
|
name: authentik-outpost-api
|
||||||
image: beryju/authentik-proxy:2021.5.1-rc8
|
image: beryju/authentik-proxy:2021.5.1
|
||||||
name: proxy
|
name: proxy
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 4180
|
- containerPort: 4180
|
||||||
@ -110,7 +110,7 @@ metadata:
|
|||||||
app.kubernetes.io/instance: __OUTPOST_NAME__
|
app.kubernetes.io/instance: __OUTPOST_NAME__
|
||||||
app.kubernetes.io/managed-by: goauthentik.io
|
app.kubernetes.io/managed-by: goauthentik.io
|
||||||
app.kubernetes.io/name: authentik-proxy
|
app.kubernetes.io/name: authentik-proxy
|
||||||
app.kubernetes.io/version: 2021.5.1-rc8
|
app.kubernetes.io/version: 2021.5.1
|
||||||
name: authentik-outpost
|
name: authentik-outpost
|
||||||
spec:
|
spec:
|
||||||
rules:
|
rules:
|
||||||
|
|||||||
@ -34,7 +34,7 @@ module.exports = {
|
|||||||
position: "left",
|
position: "left",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "https://github.com/beryju/authentik",
|
href: "https://github.com/goauthentik/authentik",
|
||||||
label: "GitHub",
|
label: "GitHub",
|
||||||
position: "right",
|
position: "right",
|
||||||
},
|
},
|
||||||
@ -69,7 +69,7 @@ module.exports = {
|
|||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: "GitHub",
|
label: "GitHub",
|
||||||
href: "https://github.com/beryju/authentik",
|
href: "https://github.com/goauthentik/authentik",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Discord",
|
label: "Discord",
|
||||||
@ -95,7 +95,7 @@ module.exports = {
|
|||||||
docs: {
|
docs: {
|
||||||
id: "docs",
|
id: "docs",
|
||||||
sidebarPath: require.resolve("./sidebars.js"),
|
sidebarPath: require.resolve("./sidebars.js"),
|
||||||
editUrl: "https://github.com/beryju/authentik/edit/master/website/",
|
editUrl: "https://github.com/goauthentik/authentik/edit/master/website/",
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve("./src/css/custom.css"),
|
customCss: require.resolve("./src/css/custom.css"),
|
||||||
@ -111,7 +111,7 @@ module.exports = {
|
|||||||
path: 'developer-docs',
|
path: 'developer-docs',
|
||||||
routeBasePath: 'developer-docs',
|
routeBasePath: 'developer-docs',
|
||||||
sidebarPath: require.resolve('./sidebarsDev.js'),
|
sidebarPath: require.resolve('./sidebarsDev.js'),
|
||||||
editUrl: "https://github.com/beryju/authentik/edit/master/website/",
|
editUrl: "https://github.com/goauthentik/authentik/edit/master/website/",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|||||||
8127
website/package-lock.json
generated
8127
website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
|||||||
"serve": "docusaurus serve"
|
"serve": "docusaurus serve"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/preset-classic": "2.0.0-alpha.75",
|
"@docusaurus/preset-classic": "2.0.0-beta.0",
|
||||||
"@mdx-js/react": "^1.6.22",
|
"@mdx-js/react": "^1.6.22",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
"postcss": "^8.2.15",
|
"postcss": "^8.2.15",
|
||||||
|
|||||||
Reference in New Issue
Block a user