Merge branch 'master' into inbuilt-proxy

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

# Conflicts:
#	internal/constants/constants.go
#	outpost/pkg/version.go
This commit is contained in:
Jens Langhammer 2021-07-02 16:23:30 +02:00
commit 3dc9e247d5
42 changed files with 481 additions and 227 deletions

View file

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2021.6.2
current_version = 2021.6.3
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)\-?(?P<release>.*)
@ -21,6 +21,8 @@ values =
[bumpversion:file:docker-compose.yml]
[bumpversion:file:schema.yml]
[bumpversion:file:.github/workflows/release.yml]
[bumpversion:file:authentik/__init__.py]

View file

@ -33,14 +33,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik:2021.6.2,
beryju/authentik:2021.6.3,
beryju/authentik:latest,
ghcr.io/goauthentik/server:2021.6.2,
ghcr.io/goauthentik/server:2021.6.3,
ghcr.io/goauthentik/server:latest
platforms: linux/amd64,linux/arm64
context: .
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.6.3', 'rc') }}
run: |
docker pull beryju/authentik:latest
docker tag beryju/authentik:latest beryju/authentik:stable
@ -75,14 +75,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-proxy:2021.6.2,
beryju/authentik-proxy:2021.6.3,
beryju/authentik-proxy:latest,
ghcr.io/goauthentik/proxy:2021.6.2,
ghcr.io/goauthentik/proxy:2021.6.3,
ghcr.io/goauthentik/proxy:latest
file: proxy.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.6.3', 'rc') }}
run: |
docker pull beryju/authentik-proxy:latest
docker tag beryju/authentik-proxy:latest beryju/authentik-proxy:stable
@ -117,14 +117,14 @@ jobs:
with:
push: ${{ github.event_name == 'release' }}
tags: |
beryju/authentik-ldap:2021.6.2,
beryju/authentik-ldap:2021.6.3,
beryju/authentik-ldap:latest,
ghcr.io/goauthentik/ldap:2021.6.2,
ghcr.io/goauthentik/ldap:2021.6.3,
ghcr.io/goauthentik/ldap:latest
file: ldap.Dockerfile
platforms: linux/amd64,linux/arm64
- name: Building Docker Image (stable)
if: ${{ github.event_name == 'release' && !contains('2021.6.2', 'rc') }}
if: ${{ github.event_name == 'release' && !contains('2021.6.3', 'rc') }}
run: |
docker pull beryju/authentik-ldap:latest
docker tag beryju/authentik-ldap:latest beryju/authentik-ldap:stable
@ -157,7 +157,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Setup Node.js environment
uses: actions/setup-node@v2.1.5
uses: actions/setup-node@v2.2.0
with:
node-version: 12.x
- name: Build web api client and web ui
@ -176,6 +176,7 @@ jobs:
SENTRY_PROJECT: authentik
SENTRY_URL: https://sentry.beryju.org
with:
version: authentik@2021.6.2
version: authentik@2021.6.3
environment: beryjuorg-prod
sourcemaps: './web/dist'
finalize: false

128
Pipfile.lock generated
View file

@ -76,11 +76,11 @@
},
"asgiref": {
"hashes": [
"sha256:05914d0fa65a21711e732adc6572edad6c8da5f1435c3f0c060689ced5e85195",
"sha256:d36fa91dd90e3aa3c81a6bd426ccc8fb20bd3d22b0cf14a12800289e9c3e2563"
"sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9",
"sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"
],
"markers": "python_version >= '3.6'",
"version": "==3.4.0"
"version": "==3.4.1"
},
"async-timeout": {
"hashes": [
@ -122,19 +122,19 @@
},
"boto3": {
"hashes": [
"sha256:6300e9ee9a404038113250bd218e2c4827f5e676efb14e77de2ad2dcb67679bc",
"sha256:be4714f0475c1f5183eea09ddbf568ced6fa41b0fc9976f2698b8442e1b17303"
"sha256:055f9dc07f95f202a4dc25196a3a9f1e2f137171ee364cf980e4673de75fb529",
"sha256:bc9b278e362ec9b531511a498262297f074c4f5ca9560455919a0af1a4698615"
],
"index": "pypi",
"version": "==1.17.102"
"version": "==1.17.104"
},
"botocore": {
"hashes": [
"sha256:2f57f7ceed1598d96cc497aeb45317db5d3b21a5aafea4732d0e561d0fc2a8fa",
"sha256:bdf08a4f7f01ead00d386848f089c08270499711447569c18d0db60023619c06"
"sha256:23aa3238c004319f78423eb8cbba2813b62ee64d0e3bab04e0a00e067f99542a",
"sha256:95ab472c8254b8d2cfa6d719b433e511fbcf80895b4cd18e4219c1efa0b78270"
],
"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.102"
"version": "==1.20.104"
},
"cachetools": {
"hashes": [
@ -242,11 +242,11 @@
},
"channels-redis": {
"hashes": [
"sha256:18d63f6462a58011740dc8eeb57ea4b31ec220eb551cb71b27de9c6779a549de",
"sha256:2fb31a63b05373f6402da2e6a91a22b9e66eb8b56626c6bfc93e156c734c5ae6"
"sha256:0a18ce279c15ba79b7985bb12b2d6dd0ac8a14e4ad6952681f4422a4cc4a5ea9",
"sha256:1abd5820ff1ed4ac627f8a219ad389e4c87e52e47a230929a7a474e95dd2c6c2"
],
"index": "pypi",
"version": "==3.2.0"
"version": "==3.3.0"
},
"chardet": {
"hashes": [
@ -342,11 +342,11 @@
},
"django": {
"hashes": [
"sha256:66c9d8db8cc6fe938a28b7887c1596e42d522e27618562517cc8929eb7e7f296",
"sha256:ea735cbbbb3b2fba6d4da4784a0043d84c67c92f1fdf15ad6db69900e792c10f"
"sha256:3da05fea54fdec2315b54a563d5b59f3b4e2b1e69c3a5841dda35019c01855cd",
"sha256:c58b5f19c5ae0afe6d75cbdd7df561e6eb929339985dbbda2565e1cabb19a62e"
],
"index": "pypi",
"version": "==3.2.4"
"version": "==3.2.5"
},
"django-dbbackup": {
"git": "https://github.com/django-dbbackup/django-dbbackup.git",
@ -473,11 +473,11 @@
},
"google-auth": {
"hashes": [
"sha256:b3a67fa9ba5b768861dacf374c2135eb09fa14a0e40c851c3b8ea7abe6fc8fef",
"sha256:e34e5f5de5610b202f9b40ebd9f8b27571d5c5537db9afed3a72b2db5a345039"
"sha256:9266252e11393943410354cf14a77bcca24dd2ccd9c4e1aef23034fe0fbae630",
"sha256:c7c215c74348ef24faef2f7b62f6d8e6b38824fe08b1e7b7b09a02d397eda7b3"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'",
"version": "==1.32.0"
"version": "==1.32.1"
},
"gunicorn": {
"hashes": [
@ -1423,11 +1423,11 @@
},
"astroid": {
"hashes": [
"sha256:4db03ab5fc3340cf619dbc25e42c2cc3755154ce6009469766d7143d1fc2ee4e",
"sha256:8a398dfce302c13f14bab13e2b14fe385d32b73f4e4853b9bdfb64598baa1975"
"sha256:38b95085e9d92e2ca06cf8b35c12a74fa81da395a6f9e65803742e6509c05892",
"sha256:606b2911d10c3dcf35e58d2ee5c97360e8477d7b9f3efc3f24811c93e6fc2cd9"
],
"markers": "python_version ~= '3.6'",
"version": "==2.5.6"
"version": "==2.6.2"
},
"attrs": {
"hashes": [
@ -1671,11 +1671,11 @@
},
"pylint": {
"hashes": [
"sha256:0a049c5d47b629d9070c3932d13bff482b12119b6a241a93bc460b0be16953c8",
"sha256:792b38ff30903884e4a9eab814ee3523731abd3c463f3ba48d7b627e87013484"
"sha256:23a1dc8b30459d78e9ff25942c61bb936108ccbe29dd9e71c01dc8274961709a",
"sha256:5d46330e6b8886c31b5e3aba5ff48c10f4aa5e76cbf9002c6544306221e63fbc"
],
"index": "pypi",
"version": "==2.8.3"
"version": "==2.9.3"
},
"pylint-django": {
"hashes": [
@ -1753,49 +1753,45 @@
},
"regex": {
"hashes": [
"sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5",
"sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79",
"sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31",
"sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500",
"sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11",
"sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14",
"sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3",
"sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439",
"sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c",
"sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82",
"sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711",
"sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093",
"sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a",
"sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb",
"sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8",
"sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17",
"sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000",
"sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d",
"sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480",
"sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc",
"sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0",
"sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9",
"sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765",
"sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e",
"sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a",
"sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07",
"sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f",
"sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac",
"sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7",
"sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed",
"sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968",
"sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7",
"sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2",
"sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4",
"sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87",
"sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8",
"sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10",
"sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29",
"sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605",
"sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6",
"sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"
"sha256:0e46c1191b2eb293a6912269ed08b4512e7e241bbf591f97e527492e04c77e93",
"sha256:18040755606b0c21281493ec309214bd61e41a170509e5014f41d6a5a586e161",
"sha256:1806370b2bef4d4193eebe8ee59a9fd7547836a34917b7badbe6561a8594d9cb",
"sha256:1ccbd41dbee3a31e18938096510b7d4ee53aa9fce2ee3dcc8ec82ae264f6acfd",
"sha256:1d386402ae7f3c9b107ae5863f7ecccb0167762c82a687ae6526b040feaa5ac6",
"sha256:210c359e6ee5b83f7d8c529ba3c75ba405481d50f35a420609b0db827e2e3bb5",
"sha256:268fe9dd1deb4a30c8593cabd63f7a241dfdc5bd9dd0233906c718db22cdd49a",
"sha256:361be4d311ac995a8c7ad577025a3ae3a538531b1f2cf32efd8b7e5d33a13e5a",
"sha256:3f7a92e60930f8fca2623d9e326c173b7cf2c8b7e4fdcf984b75a1d2fb08114d",
"sha256:444723ebaeb7fa8125f29c01a31101a3854ac3de293e317944022ae5effa53a4",
"sha256:494d0172774dc0beeea984b94c95389143db029575f7ca908edd74469321ea99",
"sha256:4b1999ef60c45357598935c12508abf56edbbb9c380df6f336de38a6c3a294ae",
"sha256:4fc86b729ab88fe8ac3ec92287df253c64aa71560d76da5acd8a2e245839c629",
"sha256:5049d00dbb78f9d166d1c704e93934d42cce0570842bb1a61695123d6b01de09",
"sha256:56bef6b414949e2c9acf96cb5d78de8b529c7b99752619494e78dc76f99fd005",
"sha256:59845101de68fd5d3a1145df9ea022e85ecd1b49300ea68307ad4302320f6f61",
"sha256:6b8b629f93246e507287ee07e26744beaffb4c56ed520576deac8b615bd76012",
"sha256:6c72ebb72e64e9bd195cb35a9b9bbfb955fd953b295255b8ae3e4ad4a146b615",
"sha256:7743798dfb573d006f1143d745bf17efad39775a5190b347da5d83079646be56",
"sha256:78a2a885345a2d60b5e68099e877757d5ed12e46ba1e87507175f14f80892af3",
"sha256:849802379a660206277675aa5a5c327f5c910c690649535863ddf329b0ba8c87",
"sha256:8cf6728f89b071bd3ab37cb8a0e306f4de897553a0ed07442015ee65fbf53d62",
"sha256:a1b6a3f600d6aff97e3f28c34192c9ed93fee293bd96ef327b64adb51a74b2f6",
"sha256:a548bb51c4476332ce4139df8e637386730f79a92652a907d12c696b6252b64d",
"sha256:a8a5826d8a1b64e2ff9af488cc179e1a4d0f144d11ce486a9f34ea38ccedf4ef",
"sha256:b024ee43ee6b310fad5acaee23e6485b21468718cb792a9d1693eecacc3f0b7e",
"sha256:b092754c06852e8a8b022004aff56c24b06310189186805800d09313c37ce1f8",
"sha256:b1dbeef938281f240347d50f28ae53c4b046a23389cd1fc4acec5ea0eae646a1",
"sha256:bf819c5b77ff44accc9a24e31f1f7ceaaf6c960816913ed3ef8443b9d20d81b6",
"sha256:c11f2fca544b5e30a0e813023196a63b1cb9869106ef9a26e9dae28bce3e4e26",
"sha256:ce269e903b00d1ab4746793e9c50a57eec5d5388681abef074d7b9a65748fca5",
"sha256:d0cf2651a8804f6325747c7e55e3be0f90ee2848e25d6b817aa2728d263f9abb",
"sha256:e07e92935040c67f49571779d115ecb3e727016d42fb36ee0d8757db4ca12ee0",
"sha256:e80d2851109e56420b71f9702ad1646e2f0364528adbf6af85527bc61e49f394",
"sha256:ed77b97896312bc2deafe137ca2626e8b63808f5bedb944f73665c68093688a7",
"sha256:f32f47fb22c988c0b35756024b61d156e5c4011cb8004aa53d93b03323c45657",
"sha256:fdad3122b69cdabdb3da4c2a4107875913ac78dab0117fc73f988ad589c66b66"
],
"version": "==2021.4.4"
"version": "==2021.7.1"
},
"requests": {
"hashes": [

View file

@ -1,3 +1,3 @@
"""authentik"""
__version__ = "2021.6.2"
__version__ = "2021.6.3"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View file

@ -5,14 +5,13 @@ from typing import Any, Optional, Type
from urllib.parse import urlencode
from uuid import uuid4
import django.db.models.options as options
from deepmerge import always_merger
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager as DjangoUserManager
from django.core import validators
from django.db import models
from django.db.models import Q, QuerySet
from django.db.models import Q, QuerySet, options
from django.http import HttpRequest
from django.templatetags.static import static
from django.utils.functional import cached_property

View file

@ -16,11 +16,6 @@ from authentik.crypto.models import CertificateKeyPair
class CertificateBuilder:
"""Build self-signed certificates"""
__public_key = None
__private_key = None
__builder = None
__certificate = None
common_name: str
def __init__(self):

View file

@ -46,7 +46,7 @@ class NotificationTransportTestSerializer(Serializer):
messages = ListField(child=CharField())
def create(self, request: Request) -> Response:
def create(self, validated_data: Request) -> Response:
raise NotImplementedError
def update(self, request: Request) -> Response:

View file

@ -27,10 +27,9 @@ class GeoIPDict(TypedDict):
class GeoIPReader:
"""Slim wrapper around GeoIP API"""
__reader: Optional[Reader] = None
__last_mtime: float = 0.0
def __init__(self):
self.__reader: Optional[Reader] = None
self.__last_mtime: float = 0.0
self.__open()
def __open(self):

View file

@ -40,15 +40,11 @@ def transaction_rollback():
class FlowImporter:
"""Import Flow from json"""
__import: FlowBundle
__pk_map: dict[Any, Model]
logger: BoundLogger
def __init__(self, json_input: str):
self.__pk_map: dict[Any, Model] = {}
self.logger = get_logger()
self.__pk_map = {}
import_dict = loads(json_input)
try:
self.__import = from_dict(FlowBundle, import_dict)

View file

@ -26,10 +26,9 @@ class ConfigLoader:
loaded_file = []
__config = {}
def __init__(self):
super().__init__()
self.__config = {}
base_dir = os.path.realpath(os.path.join(os.path.dirname(__file__), "../.."))
for path in SEARCH_PATHS:
# Check if path is relative, and if so join with base_dir

View file

@ -69,7 +69,7 @@ class OutpostConsumer(AuthJsonConsumer):
self.last_uid = self.channel_name
# pylint: disable=unused-argument
def disconnect(self, close_code):
def disconnect(self, code):
if self.outpost and self.last_uid:
state = OutpostState.for_instance_uid(self.outpost, self.last_uid)
if self.channel_name in state.channel_ids:

View file

@ -82,13 +82,13 @@ class PolicyBindingSerializer(ModelSerializer):
"timeout",
]
def validate(self, data: OrderedDict) -> OrderedDict:
def validate(self, attrs: OrderedDict) -> OrderedDict:
"""Check that either policy, group or user is set."""
count = sum(
[
bool(data.get("policy", None)),
bool(data.get("group", None)),
bool(data.get("user", None)),
bool(attrs.get("policy", None)),
bool(attrs.get("group", None)),
bool(attrs.get("user", None)),
]
)
invalid = count > 1
@ -97,7 +97,7 @@ class PolicyBindingSerializer(ModelSerializer):
raise ValidationError("Only one of 'policy', 'group' or 'user' can be set.")
if empty:
raise ValidationError("One of 'policy', 'group' or 'user' must be set.")
return data
return attrs
class PolicyBindingViewSet(UsedByMixin, ModelViewSet):

View file

@ -62,12 +62,6 @@ class PolicyEngine:
# Allow objects with no policies attached to pass
empty_result: bool
__pbm: PolicyBindingModel
__cached_policies: list[PolicyResult]
__processes: list[PolicyProcessInfo]
__expected_result_count: int
def __init__(
self, pbm: PolicyBindingModel, user: User, request: HttpRequest = None
):
@ -83,8 +77,8 @@ class PolicyEngine:
self.request.obj = pbm
if request:
self.request.set_http_request(request)
self.__cached_policies = []
self.__processes = []
self.__cached_policies: list[PolicyResult] = []
self.__processes: list[PolicyProcessInfo] = []
self.use_cache = True
self.__expected_result_count = 0

View file

@ -278,7 +278,7 @@ class OAuth2Provider(Provider):
"""Guess launch_url based on first redirect_uri"""
if self.redirect_uris == "":
return None
main_url = self.redirect_uris.split("\n")[0]
main_url = self.redirect_uris.split("\n", maxsplit=1)[0]
launch_url = urlparse(main_url)
return main_url.replace(launch_url.path, "")

View file

@ -1,6 +1,7 @@
"""authentik OAuth2 OpenID Userinfo views"""
from typing import Any, Optional
from deepmerge import always_merger
from django.http import HttpRequest, HttpResponse
from django.http.response import HttpResponseBadRequest
from django.views import View
@ -78,7 +79,7 @@ class UserInfoView(View):
)
continue
LOGGER.debug("updated scope", scope=scope)
final_claims.update(value)
always_merger.merge(final_claims, value)
return final_claims
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:

View file

@ -15,7 +15,7 @@ class MessageConsumer(JsonWebsocketConsumer):
cache.set(f"user_{self.session_key}_messages_{self.channel_name}", True, None)
# pylint: disable=unused-argument
def disconnect(self, close_code):
def disconnect(self, code):
cache.delete(f"user_{self.session_key}_messages_{self.channel_name}")
def event_update(self, event: dict):

View file

@ -36,7 +36,8 @@ class SourceType:
class SourceTypeManager:
"""Manager to hold all Source types."""
__sources: list[SourceType] = []
def __init__(self) -> None:
self.__sources: list[SourceType] = []
def type(self):
"""Class decorator to register classes inline."""

View file

@ -74,12 +74,12 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
duo, self.stage.request, self.stage.get_pending_user()
)
def validate(self, data: dict):
def validate(self, attrs: dict):
# Checking if the given data is from a valid device class is done above
# Here we only check if the any data was sent at all
if "code" not in data and "webauthn" not in data and "duo" not in data:
if "code" not in attrs and "webauthn" not in attrs and "duo" not in attrs:
raise ValidationError("Empty response")
return data
return attrs
class AuthenticatorValidateStageView(ChallengeStageView):
@ -163,7 +163,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
# pylint: disable=unused-argument
def challenge_valid(
self, challenge: AuthenticatorValidationChallengeResponse
self, response: AuthenticatorValidationChallengeResponse
) -> HttpResponse:
# All validation is done by the serializer
return self.executor.stage_ok()

View file

@ -38,7 +38,7 @@ class EmailChallengeResponse(ChallengeResponse):
component = CharField(default="ak-stage-email")
def validate(self, data):
def validate(self, attrs):
raise ValidationError("")

View file

@ -73,9 +73,9 @@ class IdentificationChallengeResponse(ChallengeResponse):
pre_user: Optional[User] = None
def validate(self, data: dict[str, Any]) -> dict[str, Any]:
def validate(self, attrs: dict[str, Any]) -> dict[str, Any]:
"""Validate that user exists, and optionally their password"""
uid_field = data["uid_field"]
uid_field = attrs["uid_field"]
current_stage: IdentificationStage = self.stage.executor.current_stage
pre_user = self.stage.get_user(uid_field)
@ -101,9 +101,9 @@ class IdentificationChallengeResponse(ChallengeResponse):
self.pre_user = pre_user
if not current_stage.password_stage:
# No password stage select, don't validate the password
return data
return attrs
password = data["password"]
password = attrs["password"]
try:
user = authenticate(
self.stage.request,
@ -116,7 +116,7 @@ class IdentificationChallengeResponse(ChallengeResponse):
self.pre_user = user
except PermissionDenied as exc:
raise ValidationError(str(exc)) from exc
return data
return attrs
class IdentificationStageView(ChallengeStageView):

View file

@ -146,8 +146,6 @@ def password_single_validator_factory() -> Callable[[PromptChallenge, str], Any]
class ListPolicyEngine(PolicyEngine):
"""Slightly modified policy engine, which uses a list instead of a PolicyBindingModel"""
__list: list[Policy]
def __init__(
self, policies: list[Policy], user: User, request: HttpRequest = None
) -> None:

View file

@ -21,7 +21,7 @@ services:
networks:
- internal
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.3}
restart: unless-stopped
command: server
environment:
@ -44,7 +44,7 @@ services:
- "0.0.0.0:9000:9000"
- "0.0.0.0:9443:9443"
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2021.6.3}
restart: unless-stopped
command: worker
networks:

View file

@ -5,8 +5,6 @@ import (
"os"
)
const VERSION = "2021.6.2"
func BUILD() string {
build := os.Getenv("GIT_BUILD_HASH")
if build == "" {
@ -18,3 +16,5 @@ func BUILD() string {
func OutpostUserAgent() string {
return fmt.Sprintf("authentik-outpost@%s (%s)", VERSION, BUILD())
}
const VERSION = "2021.6.3"

View file

@ -98,19 +98,9 @@ func (pi *ProviderInstance) UserEntry(u api.User) *ldap.Entry {
},
}
if *u.IsActive {
attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"active"}})
} else {
attrs = append(attrs, &ldap.EntryAttribute{Name: "accountStatus", Values: []string{"inactive"}})
}
if u.IsSuperuser {
attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"active"}})
} else {
attrs = append(attrs, &ldap.EntryAttribute{Name: "superuser", Values: []string{"inactive"}})
}
attrs = append(attrs, &ldap.EntryAttribute{Name: "memberOf", Values: pi.GroupsForUser(u)})
attrs = append(attrs, &ldap.EntryAttribute{Name: "goauthentik.io/ldap/active", Values: []string{BoolToString(*u.IsActive)}})
attrs = append(attrs, &ldap.EntryAttribute{Name: "goauthentik.io/ldap/superuser", Values: []string{BoolToString(u.IsSuperuser)}})
attrs = append(attrs, AKAttrsToLDAP(u.Attributes)...)

View file

@ -7,6 +7,13 @@ import (
"goauthentik.io/api"
)
func BoolToString(in bool) string {
if in {
return "true"
}
return "false"
}
func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
attrList := []*ldap.EntryAttribute{}
a := attrs.(*map[string]interface{})
@ -17,6 +24,8 @@ func AKAttrsToLDAP(attrs interface{}) []*ldap.EntryAttribute {
entry.Values = t
case string:
entry.Values = []string{t}
case bool:
entry.Values = []string{BoolToString(t)}
}
attrList = append(attrList, entry)
}

View file

@ -29,9 +29,10 @@ func (s *Server) bundleProviders(providers []api.ProxyOutpostConfig) []*provider
log.WithError(err).Warning("Failed to parse URL, skipping provider")
}
bundles[idx] = &providerBundle{
s: s,
Host: externalHost.Host,
log: log.WithField("logger", "authentik.outpost.proxy-bundle").WithField("provider", provider.Name),
s: s,
Host: externalHost.Host,
log: log.WithField("logger", "authentik.outpost.proxy-bundle").WithField("provider", provider.Name),
endSessionUrl: provider.OidcConfiguration.EndSessionEndpoint,
}
bundles[idx].Build(provider)
}

View file

@ -25,6 +25,8 @@ type providerBundle struct {
proxy *OAuthProxy
Host string
endSessionUrl string
cert *tls.Certificate
log *log.Entry
@ -58,6 +60,8 @@ func (pb *providerBundle) prepareOpts(provider api.ProxyOutpostConfig) *options.
providerOpts.RedeemURL = provider.OidcConfiguration.TokenEndpoint
providerOpts.OIDCJwksURL = provider.OidcConfiguration.JwksUri
providerOpts.ProfileURL = provider.OidcConfiguration.UserinfoEndpoint
providerOpts.ValidateURL = provider.OidcConfiguration.UserinfoEndpoint
providerOpts.AcrValues = "goauthentik.io/providers/oauth2/default"
if *provider.SkipPathRegex != "" {
skipRegexes := strings.Split(*provider.SkipPathRegex, "\n")
@ -153,6 +157,7 @@ func (pb *providerBundle) Build(provider api.ProxyOutpostConfig) {
oauthproxy.BasicAuthPasswordAttribute = *provider.BasicAuthPasswordAttribute
}
oauthproxy.endSessionEndpoint = pb.endSessionUrl
oauthproxy.ExternalHost = pb.Host
pb.proxy = oauthproxy

View file

@ -65,31 +65,33 @@ type OAuthProxy struct {
AuthOnlyPath string
UserInfoPath string
endSessionEndpoint string
mode api.ProxyMode
redirectURL *url.URL // the url to receive requests at
whitelistDomains []string
provider providers.Provider
sessionStore sessionsapi.SessionStore
ProxyPrefix string
serveMux http.Handler
SetXAuthRequest bool
SetBasicAuth bool
PassUserHeaders bool
BasicAuthUserAttribute string
BasicAuthPasswordAttribute string
ExternalHost string
PassAccessToken bool
SetAuthorization bool
PassAuthorization bool
PreferEmailToUser bool
skipAuthRegex []string
skipAuthPreflight bool
skipAuthStripHeaders bool
mainJwtBearerVerifier *oidc.IDTokenVerifier
extraJwtBearerVerifiers []*oidc.IDTokenVerifier
compiledRegex []*regexp.Regexp
templates *template.Template
realClientIPParser ipapi.RealClientIPParser
redirectURL *url.URL // the url to receive requests at
whitelistDomains []string
provider providers.Provider
sessionStore sessionsapi.SessionStore
ProxyPrefix string
serveMux http.Handler
SetXAuthRequest bool
SetBasicAuth bool
PassUserHeaders bool
PassAccessToken bool
SetAuthorization bool
PassAuthorization bool
PreferEmailToUser bool
skipAuthRegex []string
skipAuthPreflight bool
skipAuthStripHeaders bool
mainJwtBearerVerifier *oidc.IDTokenVerifier
extraJwtBearerVerifiers []*oidc.IDTokenVerifier
compiledRegex []*regexp.Regexp
templates *template.Template
realClientIPParser ipapi.RealClientIPParser
sessionChain alice.Chain
@ -285,19 +287,13 @@ func (p *OAuthProxy) UserInfo(rw http.ResponseWriter, req *http.Request) {
// SignOut sends a response to clear the authentication cookie
func (p *OAuthProxy) SignOut(rw http.ResponseWriter, req *http.Request) {
redirect, err := p.GetRedirect(req)
if err != nil {
p.logger.Errorf("Error obtaining redirect: %v", err)
p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
return
}
err = p.ClearSessionCookie(rw, req)
err := p.ClearSessionCookie(rw, req)
if err != nil {
p.logger.Errorf("Error clearing session cookie: %v", err)
p.ErrorPage(rw, http.StatusInternalServerError, "Internal Server Error", err.Error())
return
}
http.Redirect(rw, req, redirect, http.StatusFound)
http.Redirect(rw, req, p.endSessionEndpoint, http.StatusFound)
}
// AuthenticateOnly checks whether the user is currently logged in

View file

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2021.6.2
version: 2021.6.3
description: Making authentication simple.
contact:
email: hello@beryju.org

View file

@ -0,0 +1,228 @@
"""LDAP and Outpost e2e tests"""
from sys import platform
from time import sleep
from unittest.case import skipUnless
from docker.client import DockerClient, from_env
from docker.models.containers import Container
from guardian.shortcuts import get_anonymous_user
from ldap3 import (
ALL,
ALL_ATTRIBUTES,
ALL_OPERATIONAL_ATTRIBUTES,
SUBTREE,
Connection,
Server,
)
from ldap3.core.exceptions import LDAPInsufficientAccessRightsResult
from authentik.core.models import Application, Group, User
from authentik.events.models import Event, EventAction
from authentik.flows.models import Flow
from authentik.outposts.models import Outpost, OutpostType
from authentik.providers.ldap.models import LDAPProvider
from tests.e2e.utils import (
USER,
SeleniumTestCase,
apply_migration,
object_manager,
retry,
)
@skipUnless(platform.startswith("linux"), "requires local docker")
class TestProviderLDAP(SeleniumTestCase):
"""LDAP and Outpost e2e tests"""
ldap_container: Container
def tearDown(self) -> None:
super().tearDown()
self.output_container_logs(self.ldap_container)
self.ldap_container.kill()
def start_ldap(self, outpost: Outpost) -> Container:
"""Start ldap container based on outpost created"""
client: DockerClient = from_env()
container = client.containers.run(
image="beryju.org/authentik/outpost-ldap:gh-master",
detach=True,
network_mode="host",
auto_remove=True,
environment={
"AUTHENTIK_HOST": self.live_server_url,
"AUTHENTIK_TOKEN": outpost.token.key,
},
)
return container
def _prepare(self) -> User:
"""prepare user, provider, app and container"""
# set additionalHeaders to test later
user = USER()
user.attributes["extraAttribute"] = "bar"
user.save()
ldap: LDAPProvider = LDAPProvider.objects.create(
name="ldap_provider",
authorization_flow=Flow.objects.get(slug="default-authentication-flow"),
search_group=Group.objects.first(),
)
# we need to create an application to actually access the ldap
Application.objects.create(name="ldap", slug="ldap", provider=ldap)
outpost: Outpost = Outpost.objects.create(
name="ldap_outpost",
type=OutpostType.LDAP,
)
outpost.providers.add(ldap)
outpost.save()
user = outpost.user
self.ldap_container = self.start_ldap(outpost)
# Wait until outpost healthcheck succeeds
healthcheck_retries = 0
while healthcheck_retries < 50:
if len(outpost.state) > 0:
state = outpost.state[0]
if state.last_seen:
break
healthcheck_retries += 1
sleep(0.5)
return user
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@object_manager
def test_ldap_bind_success(self):
"""Test simple bind"""
self._prepare()
server = Server("ldap://localhost:3389", get_info=ALL)
_connection = Connection(
server,
raise_exceptions=True,
user=f"cn={USER().username},ou=users,DC=ldap,DC=goauthentik,DC=io",
password=USER().username,
)
_connection.bind()
self.assertTrue(
Event.objects.filter(
action=EventAction.LOGIN,
user={
"pk": USER().pk,
"email": USER().email,
"username": USER().username,
},
)
)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_flows", "0008_default_flows")
@object_manager
def test_ldap_bind_fail(self):
"""Test simple bind (failed)"""
self._prepare()
server = Server("ldap://localhost:3389", get_info=ALL)
_connection = Connection(
server,
raise_exceptions=True,
user=f"cn={USER().username},ou=users,DC=ldap,DC=goauthentik,DC=io",
password=USER().username + "fqwerwqer",
)
with self.assertRaises(LDAPInsufficientAccessRightsResult):
_connection.bind()
anon = get_anonymous_user()
self.assertTrue(
Event.objects.filter(
action=EventAction.LOGIN_FAILED,
user={"pk": anon.pk, "email": anon.email, "username": anon.username},
)
)
@retry()
@apply_migration("authentik_core", "0003_default_user")
@apply_migration("authentik_core", "0009_group_is_superuser")
@apply_migration("authentik_flows", "0008_default_flows")
@object_manager
def test_ldap_bind_search(self):
"""Test simple bind + search"""
outpost_user = self._prepare()
server = Server("ldap://localhost:3389", get_info=ALL)
_connection = Connection(
server,
raise_exceptions=True,
user=f"cn={USER().username},ou=users,dc=ldap,dc=goauthentik,dc=io",
password=USER().username,
)
_connection.bind()
self.assertTrue(
Event.objects.filter(
action=EventAction.LOGIN,
user={
"pk": USER().pk,
"email": USER().email,
"username": USER().username,
},
)
)
_connection.search(
"ou=users,dc=ldap,dc=goauthentik,dc=io",
"(objectClass=user)",
search_scope=SUBTREE,
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES],
)
response = _connection.response
# Remove raw_attributes to make checking easier
for obj in response:
del obj["raw_attributes"]
del obj["raw_dn"]
self.assertCountEqual(
response,
[
{
"dn": f"cn={outpost_user.username},ou=users,dc=ldap,dc=goauthentik,dc=io",
"attributes": {
"cn": [outpost_user.username],
"uid": [outpost_user.uid],
"name": [""],
"displayName": [""],
"mail": [""],
"objectClass": [
"user",
"organizationalPerson",
"goauthentik.io/ldap/user",
],
"memberOf": [],
"goauthentik.io/ldap/active": ["true"],
"goauthentik.io/ldap/superuser": ["false"],
"goauthentik.io/user/override-ips": ["true"],
"goauthentik.io/user/service-account": ["true"],
},
"type": "searchResEntry",
},
{
"dn": f"cn={USER().username},ou=users,dc=ldap,dc=goauthentik,dc=io",
"attributes": {
"cn": [USER().username],
"uid": [USER().uid],
"name": [USER().name],
"displayName": [USER().name],
"mail": [USER().email],
"objectClass": [
"user",
"organizationalPerson",
"goauthentik.io/ldap/user",
],
"memberOf": [
"cn=authentik Admins,ou=groups,dc=ldap,dc=goauthentik,dc=io"
],
"goauthentik.io/ldap/active": ["true"],
"goauthentik.io/ldap/superuser": ["true"],
"extraAttribute": ["bar"],
},
"type": "searchResEntry",
},
],
)

View file

@ -119,6 +119,13 @@ class TestProviderProxy(SeleniumTestCase):
self.assertIn("X-Forwarded-Preferred-Username: akadmin", full_body_text)
self.assertIn("X-Foo: bar", full_body_text)
self.driver.get("http://localhost:4180/akprox/sign_out")
sleep(2)
full_body_text = self.driver.find_element(
By.CSS_SELECTOR, ".pf-c-title.pf-m-3xl"
).text
self.assertIn("You've logged out of proxy.", full_body_text)
@skipUnless(platform.startswith("linux"), "requires local docker")
class TestProviderProxyConnect(ChannelsLiveServerTestCase):

View file

@ -62,11 +62,14 @@ class OutpostDockerTests(TestCase):
)
authentication_kp = CertificateKeyPair.objects.create(
name="docker-authentication",
# pylint: disable=consider-using-with
certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(),
# pylint: disable=consider-using-with
key_data=open(f"{self.ssl_folder}/client/key.pem").read(),
)
verification_kp = CertificateKeyPair.objects.create(
name="docker-verification",
# pylint: disable=consider-using-with
certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(),
)
self.service_connection = DockerServiceConnection.objects.create(

View file

@ -62,11 +62,14 @@ class TestProxyDocker(TestCase):
)
authentication_kp = CertificateKeyPair.objects.create(
name="docker-authentication",
# pylint: disable=consider-using-with
certificate_data=open(f"{self.ssl_folder}/client/cert.pem").read(),
# pylint: disable=consider-using-with
key_data=open(f"{self.ssl_folder}/client/key.pem").read(),
)
verification_kp = CertificateKeyPair.objects.create(
name="docker-verification",
# pylint: disable=consider-using-with
certificate_data=open(f"{self.ssl_folder}/client/ca.pem").read(),
)
self.service_connection = DockerServiceConnection.objects.create(

28
web/package-lock.json generated
View file

@ -48,7 +48,7 @@
"lit-html": "^1.4.1",
"moment": "^2.29.1",
"rapidoc": "^9.0.0",
"rollup": "^2.52.3",
"rollup": "^2.52.7",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2",
@ -58,7 +58,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.3.0",
"typescript": "^4.3.4",
"typescript": "^4.3.5",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
}
@ -6770,9 +6770,9 @@
}
},
"node_modules/rollup": {
"version": "2.52.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.3.tgz",
"integrity": "sha512-QF3Sju8Kl2z0osI4unyOLyUudyhOMK6G0AeqJWgfiyigqLAlnNrfBcDWDx+f1cqn+JU2iIYVkDrgQ6/KtwEfrg==",
"version": "2.52.7",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.7.tgz",
"integrity": "sha512-55cSH4CCU6MaPr9TAOyrIC+7qFCHscL7tkNsm1MBfIJRRqRbCEY0mmeFn4Wg8FKsHtEH8r389Fz38r/o+kgXLg==",
"bin": {
"rollup": "dist/bin/rollup"
},
@ -7604,9 +7604,9 @@
}
},
"node_modules/typescript": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz",
"integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==",
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -13200,9 +13200,9 @@
}
},
"rollup": {
"version": "2.52.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.3.tgz",
"integrity": "sha512-QF3Sju8Kl2z0osI4unyOLyUudyhOMK6G0AeqJWgfiyigqLAlnNrfBcDWDx+f1cqn+JU2iIYVkDrgQ6/KtwEfrg==",
"version": "2.52.7",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.7.tgz",
"integrity": "sha512-55cSH4CCU6MaPr9TAOyrIC+7qFCHscL7tkNsm1MBfIJRRqRbCEY0mmeFn4Wg8FKsHtEH8r389Fz38r/o+kgXLg==",
"requires": {
"fsevents": "~2.3.2"
}
@ -13896,9 +13896,9 @@
}
},
"typescript": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz",
"integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew=="
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA=="
},
"uglify-js": {
"version": "3.13.0",

View file

@ -77,7 +77,7 @@
"lit-html": "^1.4.1",
"moment": "^2.29.1",
"rapidoc": "^9.0.0",
"rollup": "^2.52.3",
"rollup": "^2.52.7",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2",
@ -87,7 +87,7 @@
"rollup-plugin-terser": "^7.0.2",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.3.0",
"typescript": "^4.3.4",
"typescript": "^4.3.5",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
},

View file

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2021.6.2";
export const VERSION = "2021.6.3";
export const PAGE_SIZE = 20;
export const EVENT_REFRESH = "ak-refresh";
export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle";

View file

@ -12,11 +12,11 @@ This installation method is for test-setups and small-scale productive setups.
## Preparation
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.6.2/docker-compose.yml). Place it in a directory of your choice.
Download the latest `docker-compose.yml` from [here](https://raw.githubusercontent.com/goauthentik/authentik/version/2021.6.3/docker-compose.yml). Place it in a directory of your choice.
To optionally enable error-reporting, run `echo AUTHENTIK_ERROR_REPORTING__ENABLED=true >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.6.2 >> .env`
To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.6.3 >> .env`
If this is a fresh authentik install run the following commands to generate a password:

View file

@ -16,6 +16,8 @@ Local backups can be created by running the following command in your authentik
```
docker-compose run --rm worker backup
# Or for kubernetes
kubectl exec -it authentik-worker-.... -- ./lifecycle/bootstrap.sh backup
```
This will dump the current database into the `./backups` folder. By defaults, the last 10 Backups are kept.
@ -26,15 +28,19 @@ Run this command in your authentik installation directory
```
docker-compose run --rm worker restore
# Or for kubernetes
kubectl exec -it authentik-worker-.... -- ./lifecycle/bootstrap.sh restore
```
This will prompt you to restore from your last backup. If you want to restore from a specific file, use the `-i` flag with the filename:
```
docker-compose run --rm worker restore -i default-2020-10-03-115557.psql
# Or for kubernetes
kubectl exec -it authentik-worker-.... -- ./lifecycle/bootstrap.sh restore -i default-2020-10-03-115557.psql
```
After you've restored the backup, it is recommended to restart all services with `docker-compose restart`.
After you've restored the backup, it is recommended to restart all services with `docker-compose restart` or `kubectl restart deployment --all`.
### S3 Configuration
@ -92,12 +98,15 @@ Simply enable these options in your values.yaml file
```yaml
# Enable Database Backups to S3
backup:
accessKey: access-key
secretKey: secret-key
bucket: s3-bucket
region: eu-central-1
host: s3-host
authentik:
postgresql:
s3_backup:
bucket: "authentik-backup"
access_key: foo
secret_key: bar
region: eu-central-1
# Optional S3 host
# host: "https://backup-s3.beryju.org"
```
Afterwards, run a `helm upgrade` to update the ConfigMap. Backups are done automatically as above, at 00:00 every day.

View file

@ -40,9 +40,9 @@ The following fields are currently sent for users:
- "user"
- "organizationalPerson"
- "goauthentik.io/ldap/user"
- `accountStatus`: "active" if the account is active, otherwise "inactive"
- `superuser`: "active" if the account is part of a group with superuser permissions, otherwise "inactive"
- `memberOf`: A list of all DNs that the user is a member of
- `goauthentik.io/ldap/active`: "true" if the account is active, otherwise "false"
- `goauthentik.io/ldap/superuser`: "true" if the account is part of a group with superuser permissions, otherwise "false"
The following fields are current set for groups:

View file

@ -11,7 +11,7 @@ version: "3.5"
services:
authentik_proxy:
image: ghcr.io/goauthentik/proxy:2021.6.2
image: ghcr.io/goauthentik/proxy:2021.6.3
ports:
- 4180:4180
- 4443:4443
@ -21,7 +21,7 @@ services:
AUTHENTIK_TOKEN: token-generated-by-authentik
# Or, for the LDAP Outpost
authentik_proxy:
image: ghcr.io/goauthentik/ldap:2021.6.2
image: ghcr.io/goauthentik/ldap:2021.6.3
ports:
- 389:3389
environment:

View file

@ -14,7 +14,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
name: authentik-outpost-api
stringData:
authentik_host: "__AUTHENTIK_URL__"
@ -29,7 +29,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
name: authentik-outpost
spec:
ports:
@ -54,7 +54,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
name: authentik-outpost
spec:
selector:
@ -62,14 +62,14 @@ spec:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
template:
metadata:
labels:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
spec:
containers:
- env:
@ -88,7 +88,7 @@ spec:
secretKeyRef:
key: authentik_host_insecure
name: authentik-outpost-api
image: ghcr.io/goauthentik/proxy:2021.6.2
image: ghcr.io/goauthentik/proxy:2021.6.3
name: proxy
ports:
- containerPort: 4180
@ -110,7 +110,7 @@ metadata:
app.kubernetes.io/instance: __OUTPOST_NAME__
app.kubernetes.io/managed-by: goauthentik.io
app.kubernetes.io/name: authentik-proxy
app.kubernetes.io/version: 2021.6.2
app.kubernetes.io/version: 2021.6.3
name: authentik-outpost
spec:
rules:

View file

@ -46,24 +46,46 @@ import TabItem from '@theme/TabItem';
<TabItem value="standalone-nginx">
```
location /akprox {
proxy_pass http://*ip of your outpost*:4180;
error_page 401 = @akprox_signin;
proxy_set_header X-Forwarded-Host $http_host;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
}
server {
# SSL and VHost configuration
listen 443 ssl http2;
server_name _;
location @akprox_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /akprox/start?rd=$request_uri;
}
ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
location / {
auth_request /akprox/auth?nginx;
# All your other options...
# Put your proxy_pass to your application here
# proxy_pass http://localhost:5000;
# authentik-specific config
auth_request /akprox/auth;
error_page 401 = @akprox_signin;
# translate headers from the outposts back to the actual upstream
auth_request_set $username $upstream_http_x_auth_username;
auth_request_set $email $upstream_http_X_Forwarded_Email;
proxy_set_header X-Auth-Username $username;
proxy_set_header X-Forwarded-Email $email;
}
# all requests to /akprox must be accessible without authentication
location /akprox {
proxy_pass http://*ip or hostname of the authentik OUTPOST*:4180;
# ensure the host of this vserver matches your external URL you've configured
# in authentik
proxy_set_header Host $host;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
}
# Special location for when the /auth endpoint returns a 401,
# redirect to the /start URL which initiates SSO
location @akprox_signin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /akprox/start?rd=$request_uri;
}
}
```
</TabItem>