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")
 | 
				
			||||||
@ -47,6 +47,7 @@ func (ac *APIController) initWS(akURL url.URL, outpostUUID strfmt.UUID) {
 | 
				
			|||||||
		Instruction: WebsocketInstructionHello,
 | 
							Instruction: WebsocketInstructionHello,
 | 
				
			||||||
		Args: map[string]interface{}{
 | 
							Args: map[string]interface{}{
 | 
				
			||||||
			"version":   pkg.VERSION,
 | 
								"version":   pkg.VERSION,
 | 
				
			||||||
 | 
								"buildHash": pkg.BUILD(),
 | 
				
			||||||
			"uuid":      ac.instanceUUID.String(),
 | 
								"uuid":      ac.instanceUUID.String(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -101,13 +102,14 @@ func (ac *APIController) startWSHealth() {
 | 
				
			|||||||
			Instruction: WebsocketInstructionHello,
 | 
								Instruction: WebsocketInstructionHello,
 | 
				
			||||||
			Args: map[string]interface{}{
 | 
								Args: map[string]interface{}{
 | 
				
			||||||
				"version":   pkg.VERSION,
 | 
									"version":   pkg.VERSION,
 | 
				
			||||||
 | 
									"buildHash": pkg.BUILD(),
 | 
				
			||||||
				"uuid":      ac.instanceUUID.String(),
 | 
									"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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										89
									
								
								swagger.yaml
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								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
 | 
					 | 
				
			||||||
          properties:
 | 
					 | 
				
			||||||
            uuid:
 | 
					 | 
				
			||||||
              title: Uuid
 | 
					 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          format: uuid
 | 
					          format: uuid
 | 
				
			||||||
              readOnly: true
 | 
					        uniqueItems: 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:
 | 
					 | 
				
			||||||
          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:
 | 
					 | 
				
			||||||
            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
 | 
					        type: string
 | 
				
			||||||
        format: uuid
 | 
					        format: uuid
 | 
				
			||||||
        x-nullable: true
 | 
					        x-nullable: true
 | 
				
			||||||
            readOnly: true
 | 
					      group_obj:
 | 
				
			||||||
        readOnly: true
 | 
					        $ref: '#/definitions/Group'
 | 
				
			||||||
  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;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1377
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1377
									
								
								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/",
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8103
									
								
								website/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8103
									
								
								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