diff --git a/.bumpversion.cfg b/.bumpversion.cfg index c00de9016..83d806ef6 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2021.4.5 +current_version = 2021.5.1-rc7 tag = True commit = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)\-?(?P.*) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e6cffffd1..966bbd646 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,5 +1,13 @@ version: 2 updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 10 + assignees: + - BeryJu - package-ecosystem: gomod directory: "/outpost" schedule: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bb922e2dd..61af7f927 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,36 +3,49 @@ name: authentik-on-release on: release: types: [published, created] + push: + branches: + - version-* jobs: # Build build-server: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v1.1.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Docker Login Registry uses: docker/login-action@v1 with: - username: ${{ secrets.DOCKER_PASSWORD }} - password: ${{ secrets.DOCKER_USERNAME }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: prepare ts api client + run: | + docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/api --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0 - name: Building Docker Image uses: docker/build-push-action@v2 with: - push: true + push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik:2021.4.5, + beryju/authentik:2021.5.1-rc7, beryju/authentik:latest, - ghcr.io/goauthentik/server:2021.4.5, + ghcr.io/goauthentik/server:2021.5.1-rc7, ghcr.io/goauthentik/server:latest - platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8 + platforms: linux/amd64,linux/arm64 + context: . build-proxy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: go-version: "^1.15" @@ -41,32 +54,38 @@ jobs: cd outpost go get -u github.com/go-swagger/go-swagger/cmd/swagger swagger generate client -f ../swagger.yaml -A authentik -t pkg/ - go build -v . + go build -v ./cmd/proxy/server.go - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v1.1.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Docker Login Registry uses: docker/login-action@v1 with: - username: ${{ secrets.DOCKER_PASSWORD }} - password: ${{ secrets.DOCKER_USERNAME }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Building Docker Image uses: docker/build-push-action@v2 with: - push: true + push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik-proxy:2021.4.5, + beryju/authentik-proxy:2021.5.1-rc7, beryju/authentik-proxy:latest, - ghcr.io/goauthentik/proxy:2021.4.5, + ghcr.io/goauthentik/proxy:2021.5.1-rc7, ghcr.io/goauthentik/proxy:latest context: outpost/ file: outpost/proxy.Dockerfile - platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8 + platforms: linux/amd64,linux/arm64 build-ldap: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - uses: actions/setup-go@v2 with: go-version: "^1.15" @@ -75,36 +94,43 @@ jobs: cd outpost go get -u github.com/go-swagger/go-swagger/cmd/swagger swagger generate client -f ../swagger.yaml -A authentik -t pkg/ - go build -v . + go build -v ./cmd/ldap/server.go - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v1.1.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Docker Login Registry uses: docker/login-action@v1 with: - username: ${{ secrets.DOCKER_PASSWORD }} - password: ${{ secrets.DOCKER_USERNAME }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Building Docker Image uses: docker/build-push-action@v2 with: - push: true + push: ${{ github.event_name == 'release' }} tags: | - beryju/authentik-ldap:2021.4.5, + beryju/authentik-ldap:2021.5.1-rc7, beryju/authentik-ldap:latest, - ghcr.io/goauthentik/ldap:2021.4.5, + ghcr.io/goauthentik/ldap:2021.5.1-rc7, ghcr.io/goauthentik/ldap:latest context: outpost/ file: outpost/ldap.Dockerfile - platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8 + platforms: linux/amd64,linux/arm64 test-release: + if: ${{ github.event_name == 'release' }} needs: - build-server - build-proxy - build-ldap runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Run test suite in final docker images run: | sudo apt-get install -y pwgen @@ -115,11 +141,12 @@ jobs: 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" sentry-release: + if: ${{ github.event_name == 'release' }} needs: - test-release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Create a Sentry.io release uses: getsentry/action-release@v1 env: @@ -128,5 +155,5 @@ jobs: SENTRY_PROJECT: authentik SENTRY_URL: https://sentry.beryju.org with: - version: authentik@2021.4.5 + version: authentik@2021.5.1-rc7 environment: beryjuorg-prod diff --git a/.github/workflows/tag.yml b/.github/workflows/tag.yml index 293289567..97e7e9c8c 100644 --- a/.github/workflows/tag.yml +++ b/.github/workflows/tag.yml @@ -10,7 +10,10 @@ jobs: name: Create Release from Tag runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v2 + - name: prepare ts api client + run: | + docker run --rm -v $(pwd):/local openapitools/openapi-generator-cli generate -i /local/swagger.yaml -g typescript-fetch -o /local/web/api --additional-properties=typescriptThreePlus=true,supportsES6=true,npmName=authentik-api,npmVersion=1.0.0 - name: Pre-release test run: | sudo apt-get install -y pwgen diff --git a/Dockerfile b/Dockerfile index 80dc60778..b49089827 100644 --- a/Dockerfile +++ b/Dockerfile @@ -52,11 +52,12 @@ RUN apt-get update && \ 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 && \ apt-get update && \ - apt-get install -y --no-install-recommends postgresql-client-12 postgresql-client-11 build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \ - apt-get clean && \ + apt-get install -y --no-install-recommends libpq-dev postgresql-client build-essential libxmlsec1-dev pkg-config libmaxminddb0 && \ pip install -r /requirements.txt --no-cache-dir && \ apt-get remove --purge -y build-essential && \ apt-get autoremove --purge -y && \ + apt-get clean && \ + 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 diff --git a/Pipfile.lock b/Pipfile.lock index e8ea1d669..9847b9879 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -88,10 +88,10 @@ }, "attrs": { "hashes": [ - "sha256:3901be1cb7c2a780f14668691474d9252c070a756be0a9ead98cfeabfa11aeb8", - "sha256:8ee1e5f5a1afc5b19bdfae4fdf0c35ed324074bdce3500c939842c8f818645d9" + "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", + "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" ], - "version": "==21.1.0" + "version": "==21.2.0" }, "autobahn": { "hashes": [ @@ -116,18 +116,18 @@ }, "boto3": { "hashes": [ - "sha256:56f1766f1271b6b4e979c7b56225377f8912050e5935adc5c1c9e3a0338b949e", - "sha256:c61c809d288e88b9a0d926f56f803d0128b498aa9b45a42a6e03cd9a83e5c124" + "sha256:6c8c9c173a8d6c5127a9812ec4b9369280caec4f574e297900dc8e735a92f71f", + "sha256:8bdbe29bc9308124e7e96ef912dfa1d656400499edcf398b677db739939e9ba6" ], "index": "pypi", - "version": "==1.17.68" + "version": "==1.17.70" }, "botocore": { "hashes": [ - "sha256:0f693f5ad6348ec1a62b3a66fee2840d3b722d66b44896022d644275ff8b143d", - "sha256:eb3544911cb0316a33b328a27d137130af278a9c0006be0c95e5e402b01d9865" + "sha256:3dea2656b5555a1bcb299a83fdefe6f0ef331ffae55cc8f8edf06557342738c0", + "sha256:9bc8bd5f601d35658b2aaa78ebeef154fd092e64b37059e8eeef51648a3936c8" ], - "version": "==1.20.68" + "version": "==1.20.70" }, "cachetools": { "hashes": [ @@ -351,11 +351,11 @@ }, "django-otp": { "hashes": [ - "sha256:04852c5301befb02d1d8ba4a31d375eb08d7c2cb6fe86b5f840867435ab1309c", - "sha256:3916fc7652c2f934b1cf3807dd8ed257ce7605c10dfefa27fadda5628d9a9c9e" + "sha256:75a815747a0542cc5442e3a6396dfd272c49a0866bee2149ac57ecc36ddd3961", + "sha256:cc657a0e7266cda6ab42f861bdc3840ed24f7e441bc7f249916174dd1a6375a0" ], "index": "pypi", - "version": "==1.0.4" + "version": "==1.0.5" }, "django-prometheus": { "hashes": [ @@ -1101,11 +1101,11 @@ }, "service-identity": { "hashes": [ - "sha256:001c0707759cb3de7e49c078a7c0c9cd12594161d3bf06b9c254fdcb1a60dc36", - "sha256:0858a54aabc5b459d1aafa8a518ed2081a285087f349fe3e55197989232e2e2d" + "sha256:6e6c6086ca271dc11b033d17c3a8bea9f24ebff920c587da090afc9519419d34", + "sha256:f0b0caac3d40627c3c04d7a51b6e06721857a0e10a8775f2d1d7e72901b3a7db" ], "index": "pypi", - "version": "==18.1.0" + "version": "==21.1.0" }, "six": { "hashes": [ @@ -1424,10 +1424,10 @@ }, "attrs": { "hashes": [ - "sha256:3901be1cb7c2a780f14668691474d9252c070a756be0a9ead98cfeabfa11aeb8", - "sha256:8ee1e5f5a1afc5b19bdfae4fdf0c35ed324074bdce3500c939842c8f818645d9" + "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1", + "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb" ], - "version": "==21.1.0" + "version": "==21.2.0" }, "bandit": { "hashes": [ diff --git a/authentik/__init__.py b/authentik/__init__.py index e89c3acb0..4e6c83da2 100644 --- a/authentik/__init__.py +++ b/authentik/__init__.py @@ -1,3 +1,3 @@ """authentik""" -__version__ = "2021.4.5" +__version__ = "2021.5.1-rc7" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" diff --git a/authentik/admin/tests/test_api.py b/authentik/admin/tests/test_api.py index 1c2ff2266..92fbd9b83 100644 --- a/authentik/admin/tests/test_api.py +++ b/authentik/admin/tests/test_api.py @@ -7,6 +7,7 @@ from django.urls import reverse from authentik import __version__ from authentik.core.models import Group, User from authentik.core.tasks import clean_expired_models +from authentik.events.monitored_tasks import TaskResultStatus class TestAdminAPI(TestCase): @@ -30,6 +31,26 @@ class TestAdminAPI(TestCase): any(task["task_name"] == "clean_expired_models" for task in body) ) + def test_tasks_single(self): + """Test Task API (read single)""" + clean_expired_models.delay() + response = self.client.get( + reverse( + "authentik_api:admin_system_tasks-detail", + kwargs={"pk": "clean_expired_models"}, + ) + ) + self.assertEqual(response.status_code, 200) + body = loads(response.content) + self.assertEqual(body["status"], TaskResultStatus.SUCCESSFUL.name) + self.assertEqual(body["task_name"], "clean_expired_models") + response = self.client.get( + reverse( + "authentik_api:admin_system_tasks-detail", kwargs={"pk": "qwerqwer"} + ) + ) + self.assertEqual(response.status_code, 404) + def test_tasks_retry(self): """Test Task API (retry)""" clean_expired_models.delay() diff --git a/authentik/api/auth.py b/authentik/api/auth.py index 1992061f8..97f821b56 100644 --- a/authentik/api/auth.py +++ b/authentik/api/auth.py @@ -54,4 +54,4 @@ class AuthentikTokenAuthentication(BaseAuthentication): if not token: return None - return (token.user, None) + return (token.user, None) # pragma: no cover diff --git a/authentik/api/tests/test_swagger.py b/authentik/api/tests/test_swagger.py index b8095a388..7857248ce 100644 --- a/authentik/api/tests/test_swagger.py +++ b/authentik/api/tests/test_swagger.py @@ -22,3 +22,10 @@ class TestSwaggerGeneration(APITestCase): reverse("authentik_api:schema-json", kwargs={"format": ".json"}), ) self.assertTrue(loads(response.content.decode())) + + def test_browser(self): + """Test API Browser""" + response = self.client.get( + reverse("authentik_api:swagger"), + ) + self.assertEqual(response.status_code, 200) diff --git a/authentik/core/sources/flow_manager.py b/authentik/core/sources/flow_manager.py index b3b8bb3aa..c02cef90f 100644 --- a/authentik/core/sources/flow_manager.py +++ b/authentik/core/sources/flow_manager.py @@ -3,6 +3,7 @@ from enum import Enum from typing import Any, Optional, Type from django.contrib import messages +from django.db import IntegrityError from django.db.models.query_utils import Q from django.http import HttpRequest, HttpResponse, HttpResponseBadRequest from django.shortcuts import redirect @@ -116,9 +117,11 @@ class SourceFlowManager: ) return Action.DENY, None query = Q(username__exact=self.enroll_info.get("username", None)) + self._logger.debug("trying to link with existing user", query=query) matching_users = User.objects.filter(query) # No matching users, always enroll if not matching_users.exists(): + self._logger.debug("no matching users found, enrolling") return Action.ENROLL, self.update_connection(new_connection, **kwargs) user = matching_users.first() @@ -147,7 +150,11 @@ class SourceFlowManager: def get_flow(self, **kwargs) -> HttpResponse: """Get the flow response based on user_matching_mode""" - action, connection = self.get_action(**kwargs) + try: + action, connection = self.get_action(**kwargs) + except IntegrityError as exc: + self._logger.warning("failed to get action", exc=exc) + return redirect("/") self._logger.debug("get_action() says", action=action, connection=connection) if connection: if action == Action.LINK: diff --git a/authentik/events/api/notification.py b/authentik/events/api/notification.py index df012cf67..546754104 100644 --- a/authentik/events/api/notification.py +++ b/authentik/events/api/notification.py @@ -1,7 +1,9 @@ """Notification API Views""" +from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user from rest_framework import mixins from rest_framework.fields import ReadOnlyField +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet @@ -47,6 +49,11 @@ class NotificationViewSet( "event", "seen", ] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/lib/connector.py b/authentik/lib/connector.py new file mode 100644 index 000000000..3ba0e25ca --- /dev/null +++ b/authentik/lib/connector.py @@ -0,0 +1,13 @@ +"""Fix dbbackup quoting the password""" +from dbbackup.db.postgresql import PgDumpConnector + + +class PgCustom(PgDumpConnector): + """Fix dbbackup quoting the password""" + + def run_command(self, *args, **kwargs): + if self.settings.get("PASSWORD"): + env = kwargs.get("env", {}) + env["PGPASSWORD"] = self.settings["PASSWORD"] + kwargs["env"] = env + return super(PgDumpConnector, self).run_command(*args, **kwargs) diff --git a/authentik/lib/default.yml b/authentik/lib/default.yml index d0729a1f4..6f4aa46e8 100644 --- a/authentik/lib/default.yml +++ b/authentik/lib/default.yml @@ -3,6 +3,7 @@ postgresql: host: localhost name: authentik user: authentik + port: 5432 password: 'env://POSTGRES_PASSWORD' web: diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index af0941eda..7268cfdf6 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -1,23 +1,35 @@ """Outpost API Views""" +from dacite.core import from_dict +from dacite.exceptions import DaciteError from drf_yasg.utils import swagger_auto_schema from rest_framework.decorators import action from rest_framework.fields import BooleanField, CharField, DateTimeField from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.serializers import JSONField, ModelSerializer +from rest_framework.serializers import JSONField, ModelSerializer, ValidationError from rest_framework.viewsets import ModelViewSet from authentik.core.api.providers import ProviderSerializer from authentik.core.api.utils import PassiveSerializer, is_dict -from authentik.outposts.models import Outpost, default_outpost_config +from authentik.outposts.models import Outpost, OutpostConfig, default_outpost_config class OutpostSerializer(ModelSerializer): """Outpost Serializer""" - _config = JSONField(validators=[is_dict]) + 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) + def validate_config(self, config) -> dict: + """Check that the config has all required fields""" + try: + from_dict(OutpostConfig, config) + except DaciteError as exc: + raise ValidationError(f"Failed to validate config: {str(exc)}") from exc + return config + class Meta: model = Outpost @@ -29,6 +41,7 @@ class OutpostSerializer(ModelSerializer): "providers_obj", "service_connection", "token_identifier", + "config", "_config", ] diff --git a/authentik/outposts/controllers/base.py b/authentik/outposts/controllers/base.py index 4777a61d0..ef22b79d5 100644 --- a/authentik/outposts/controllers/base.py +++ b/authentik/outposts/controllers/base.py @@ -56,6 +56,12 @@ class BaseController: """Handler to delete everything we've created""" raise NotImplementedError + def down_with_logs(self) -> list[str]: + """Call .down() but capture all log output and return it.""" + with capture_logs() as logs: + self.down() + return [x["event"] for x in logs] + def get_static_deployment(self) -> str: """Return a static deployment configuration""" raise NotImplementedError diff --git a/authentik/outposts/controllers/k8s/base.py b/authentik/outposts/controllers/k8s/base.py index 7b75654e2..96c2f9464 100644 --- a/authentik/outposts/controllers/k8s/base.py +++ b/authentik/outposts/controllers/k8s/base.py @@ -30,11 +30,6 @@ class NeedsUpdate(ReconcileTrigger): """Exception to trigger an update to the Kubernetes Object""" -class Disabled(SentryIgnoredException): - """Exception which can be thrown in a reconciler to signal than an - object should not be created.""" - - class KubernetesObjectReconciler(Generic[T]): """Base Kubernetes Reconciler, handles the basic logic.""" @@ -45,22 +40,29 @@ class KubernetesObjectReconciler(Generic[T]): self.namespace = controller.outpost.config.kubernetes_namespace self.logger = get_logger().bind(type=self.__class__.__name__) + @property + def noop(self) -> bool: + """Return true if this object should not be created/updated/deleted in this cluster""" + return False + @property def name(self) -> str: """Get the name of the object this reconciler manages""" - return self.controller.outpost.config.object_naming_template % { - "name": slugify(self.controller.outpost.name), - "uuid": self.controller.outpost.uuid.hex, - } + return ( + self.controller.outpost.config.object_naming_template + % { + "name": slugify(self.controller.outpost.name), + "uuid": self.controller.outpost.uuid.hex, + } + ).lower() def up(self): """Create object if it doesn't exist, update if needed or recreate if needed.""" current = None - try: - reference = self.get_reference_object() - except Disabled: - self.logger.debug("Object not required") + if self.noop: + self.logger.debug("Object is noop") return + reference = self.get_reference_object() try: try: current = self.retrieve() @@ -89,11 +91,8 @@ class KubernetesObjectReconciler(Generic[T]): def down(self): """Delete object if found""" - # Call self.get_reference_object to check if we even need to do anything - try: - self.get_reference_object() - except Disabled: - self.logger.debug("Object not required") + if self.noop: + self.logger.debug("Object is noop") return try: current = self.retrieve() diff --git a/authentik/outposts/controllers/k8s/utils.py b/authentik/outposts/controllers/k8s/utils.py new file mode 100644 index 000000000..c4e446a25 --- /dev/null +++ b/authentik/outposts/controllers/k8s/utils.py @@ -0,0 +1,11 @@ +"""k8s utils""" +from pathlib import Path + + +def get_namespace() -> str: + """Get the namespace if we're running in a pod, otherwise default to default""" + path = Path("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + if path.exists(): + with open(path, "r") as _namespace_file: + return _namespace_file.read() + return "default" diff --git a/authentik/outposts/controllers/kubernetes.py b/authentik/outposts/controllers/kubernetes.py index 736d044c8..68363fabb 100644 --- a/authentik/outposts/controllers/kubernetes.py +++ b/authentik/outposts/controllers/kubernetes.py @@ -8,7 +8,7 @@ from structlog.testing import capture_logs from yaml import dump_all from authentik.outposts.controllers.base import BaseController, ControllerException -from authentik.outposts.controllers.k8s.base import Disabled, KubernetesObjectReconciler +from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler from authentik.outposts.controllers.k8s.secret import SecretReconciler from authentik.outposts.controllers.k8s.service import ServiceReconciler @@ -49,6 +49,9 @@ class KubernetesController(BaseController): try: all_logs = [] for reconcile_key in self.reconcile_order: + if reconcile_key in self.outpost.config.kubernetes_disabled_components: + all_logs += [f"{reconcile_key.title()}: Disabled"] + continue with capture_logs() as logs: reconciler = self.reconcilers[reconcile_key](self) reconciler.up() @@ -61,19 +64,34 @@ class KubernetesController(BaseController): try: for reconcile_key in self.reconcile_order: reconciler = self.reconcilers[reconcile_key](self) + self.logger.debug("Tearing down object", name=reconcile_key) reconciler.down() except ApiException as exc: raise ControllerException(str(exc)) from exc + def down_with_logs(self) -> list[str]: + try: + all_logs = [] + for reconcile_key in self.reconcile_order: + if reconcile_key in self.outpost.config.kubernetes_disabled_components: + all_logs += [f"{reconcile_key.title()}: Disabled"] + continue + with capture_logs() as logs: + reconciler = self.reconcilers[reconcile_key](self) + reconciler.down() + all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs] + return all_logs + except ApiException as exc: + raise ControllerException(str(exc)) from exc + def get_static_deployment(self) -> str: documents = [] for reconcile_key in self.reconcile_order: reconciler = self.reconcilers[reconcile_key](self) - try: - documents.append(reconciler.get_reference_object().to_dict()) - except Disabled: + if reconciler.noop: continue + documents.append(reconciler.get_reference_object().to_dict()) with StringIO() as _str: dump_all( diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index 9cc3e087b..d7bbdf300 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -33,6 +33,7 @@ from authentik.lib.config import CONFIG from authentik.lib.models import InheritanceForeignKey from authentik.lib.sentry import SentryIgnoredException from authentik.lib.utils.http import USER_ATTRIBUTE_CAN_OVERRIDE_IP +from authentik.outposts.controllers.k8s.utils import get_namespace from authentik.outposts.docker_tls import DockerInlineTLS OUR_VERSION = parse(__version__) @@ -59,10 +60,11 @@ class OutpostConfig: object_naming_template: str = field(default="ak-outpost-%(name)s") kubernetes_replicas: int = field(default=1) - kubernetes_namespace: str = field(default="default") + kubernetes_namespace: str = field(default_factory=get_namespace) kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict) kubernetes_ingress_secret_name: str = field(default="authentik-outpost-tls") kubernetes_service_type: str = field(default="ClusterIP") + kubernetes_disabled_components: list[str] = field(default_factory=list) class OutpostModel(Model): diff --git a/authentik/outposts/signals.py b/authentik/outposts/signals.py index edf85dc0a..85667cf37 100644 --- a/authentik/outposts/signals.py +++ b/authentik/outposts/signals.py @@ -1,5 +1,5 @@ """authentik outpost signals""" -from django.conf import settings +from django.core.cache import cache from django.db.models import Model from django.db.models.signals import post_save, pre_delete, pre_save from django.dispatch import receiver @@ -8,9 +8,12 @@ from structlog.stdlib import get_logger from authentik.core.models import Provider from authentik.crypto.models import CertificateKeyPair from authentik.lib.utils.reflection import class_to_path -from authentik.outposts.controllers.base import ControllerException from authentik.outposts.models import Outpost, OutpostServiceConnection -from authentik.outposts.tasks import outpost_controller_down, outpost_post_save +from authentik.outposts.tasks import ( + CACHE_KEY_OUTPOST_DOWN, + outpost_controller, + outpost_post_save, +) LOGGER = get_logger() UPDATE_TRIGGERING_MODELS = ( @@ -39,7 +42,8 @@ def pre_save_outpost(sender, instance: Outpost, **_): ) if bool(dirty): LOGGER.info("Outpost needs re-deployment due to changes", instance=instance) - outpost_controller_down_wrapper(old_instance) + cache.set(CACHE_KEY_OUTPOST_DOWN % instance.pk.hex, old_instance) + outpost_controller.delay(instance.pk.hex, action="down", from_cache=True) @receiver(post_save) @@ -63,23 +67,5 @@ def post_save_update(sender, instance: Model, **_): def pre_delete_cleanup(sender, instance: Outpost, **_): """Ensure that Outpost's user is deleted (which will delete the token through cascade)""" instance.user.delete() - outpost_controller_down_wrapper(instance) - - -def outpost_controller_down_wrapper(instance: Outpost): - """To ensure that deployment is cleaned up *consistently* we call the controller, and wait - for it to finish. We don't want to call it in this thread, as we don't have the Outpost - Service connection here""" - try: - outpost_controller_down.delay(instance.pk.hex).get() - except RuntimeError: # pragma: no cover - # In e2e/integration tests, this might run inside a thread/process and - # trigger the celery `Never call result.get() within a task` detection - if settings.TEST: - pass - else: - raise - except ControllerException as exc: - LOGGER.warning( - "failed to cleanup outpost deployment", exc=exc, instance=instance - ) + cache.set(CACHE_KEY_OUTPOST_DOWN % instance.pk.hex, instance) + outpost_controller.delay(instance.pk.hex, action="down", from_cache=True) diff --git a/authentik/outposts/tasks.py b/authentik/outposts/tasks.py index 2c247fc83..982acfbee 100644 --- a/authentik/outposts/tasks.py +++ b/authentik/outposts/tasks.py @@ -36,6 +36,7 @@ from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesCont from authentik.root.celery import CELERY_APP LOGGER = get_logger() +CACHE_KEY_OUTPOST_DOWN = "outpost_teardown_%s" def controller_for_outpost(outpost: Outpost) -> Optional[BaseController]: @@ -56,13 +57,6 @@ def controller_for_outpost(outpost: Outpost) -> Optional[BaseController]: return None -@CELERY_APP.task() -def outpost_controller_all(): - """Launch Controller for all Outposts which support it""" - for outpost in Outpost.objects.exclude(service_connection=None): - outpost_controller.delay(outpost.pk.hex) - - @CELERY_APP.task() def outpost_service_connection_state(connection_pk: Any): """Update cached state of a service connection""" @@ -89,17 +83,29 @@ def outpost_service_connection_monitor(self: MonitoredTask): ) +@CELERY_APP.task() +def outpost_controller_all(): + """Launch Controller for all Outposts which support it""" + for outpost in Outpost.objects.exclude(service_connection=None): + outpost_controller.delay(outpost.pk.hex, "up", from_cache=False) + + @CELERY_APP.task(bind=True, base=MonitoredTask) -def outpost_controller(self: MonitoredTask, outpost_pk: str): - """Create/update/monitor the deployment of an Outpost""" +def outpost_controller( + self: MonitoredTask, outpost_pk: str, action: str = "up", from_cache: bool = False +): + """Create/update/monitor/delete the deployment of an Outpost""" logs = [] - outpost: Outpost = Outpost.objects.get(pk=outpost_pk) + if from_cache: + outpost: Outpost = cache.get(CACHE_KEY_OUTPOST_DOWN % outpost_pk) + else: + outpost: Outpost = Outpost.objects.get(pk=outpost_pk) self.set_uid(slugify(outpost.name)) try: controller = controller_for_outpost(outpost) if not controller: return - logs = controller.up_with_logs() + logs = getattr(controller, f"{action}_with_logs")() LOGGER.debug("---------------Outpost Controller logs starting----------------") for log in logs: LOGGER.debug(log) @@ -110,16 +116,6 @@ def outpost_controller(self: MonitoredTask, outpost_pk: str): self.set_status(TaskResult(TaskResultStatus.SUCCESSFUL, logs)) -@CELERY_APP.task() -def outpost_controller_down(outpost_pk: str): - """Delete outpost objects before deleting the DB Object""" - outpost = Outpost.objects.get(pk=outpost_pk) - controller = controller_for_outpost(outpost) - if not controller: - return - controller.down() - - @CELERY_APP.task(bind=True, base=MonitoredTask) def outpost_token_ensurer(self: MonitoredTask): """Periodically ensure that all Outposts have valid Service Accounts diff --git a/authentik/outposts/tests/test_api.py b/authentik/outposts/tests/test_api.py index 841f52a15..61a09ce0f 100644 --- a/authentik/outposts/tests/test_api.py +++ b/authentik/outposts/tests/test_api.py @@ -3,6 +3,10 @@ from django.urls import reverse from rest_framework.test import APITestCase from authentik.core.models import PropertyMapping, User +from authentik.flows.models import Flow +from authentik.outposts.api.outposts import OutpostSerializer +from authentik.outposts.models import default_outpost_config +from authentik.providers.proxy.models import ProxyProvider class TestOutpostServiceConnectionsAPI(APITestCase): @@ -22,3 +26,22 @@ class TestOutpostServiceConnectionsAPI(APITestCase): reverse("authentik_api:outpostserviceconnection-types"), ) self.assertEqual(response.status_code, 200) + + def test_outpost_config(self): + """Test Outpost's config field""" + provider = ProxyProvider.objects.create( + name="test", authorization_flow=Flow.objects.first() + ) + invalid = OutpostSerializer( + data={"name": "foo", "providers": [provider.pk], "config": {}} + ) + self.assertFalse(invalid.is_valid()) + self.assertIn("config", invalid.errors) + valid = OutpostSerializer( + data={ + "name": "foo", + "providers": [provider.pk], + "config": default_outpost_config("foo"), + } + ) + self.assertTrue(valid.is_valid()) diff --git a/authentik/providers/oauth2/api/tokens.py b/authentik/providers/oauth2/api/tokens.py index fb00a044b..e509b0ce8 100644 --- a/authentik/providers/oauth2/api/tokens.py +++ b/authentik/providers/oauth2/api/tokens.py @@ -1,7 +1,9 @@ """OAuth2Provider API Views""" +from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user from rest_framework import mixins from rest_framework.fields import CharField, ListField +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet @@ -37,6 +39,11 @@ class AuthorizationCodeViewSet( serializer_class = ExpiringBaseGrantModelSerializer filterset_fields = ["user", "provider"] ordering = ["provider", "expires"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() @@ -57,6 +64,11 @@ class RefreshTokenViewSet( serializer_class = ExpiringBaseGrantModelSerializer filterset_fields = ["user", "provider"] ordering = ["provider", "expires"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/providers/proxy/controllers/k8s/ingress.py b/authentik/providers/proxy/controllers/k8s/ingress.py index e6356a244..bf0c588ab 100644 --- a/authentik/providers/proxy/controllers/k8s/ingress.py +++ b/authentik/providers/proxy/controllers/k8s/ingress.py @@ -17,7 +17,6 @@ from kubernetes.client.models.networking_v1beta1_ingress_rule import ( from authentik.outposts.controllers.base import FIELD_MANAGER from authentik.outposts.controllers.k8s.base import ( - Disabled, KubernetesObjectReconciler, NeedsUpdate, ) @@ -137,9 +136,6 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]): ), ) rules.append(rule) - if not rules: - self.logger.debug("No providers use proxying, no ingress needed") - raise Disabled() tls_config = None if tls_hosts: tls_config = NetworkingV1beta1IngressTLS( diff --git a/authentik/providers/proxy/controllers/k8s/traefik.py b/authentik/providers/proxy/controllers/k8s/traefik.py index 1b3e15949..3e3c98827 100644 --- a/authentik/providers/proxy/controllers/k8s/traefik.py +++ b/authentik/providers/proxy/controllers/k8s/traefik.py @@ -7,7 +7,6 @@ from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi from authentik.outposts.controllers.base import FIELD_MANAGER from authentik.outposts.controllers.k8s.base import ( - Disabled, KubernetesObjectReconciler, NeedsUpdate, ) @@ -70,6 +69,19 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware]) self.api_ex = ApiextensionsV1Api(controller.client) self.api = CustomObjectsApi(controller.client) + @property + def noop(self) -> bool: + if not ProxyProvider.objects.filter( + outpost__in=[self.controller.outpost], + forward_auth_mode=True, + ).exists(): + self.logger.debug("No providers with forward auth enabled.") + return True + if not self._crd_exists(): + self.logger.debug("CRD doesn't exist") + return True + return False + def _crd_exists(self) -> bool: """Check if the traefik middleware exists""" return bool( @@ -87,15 +99,6 @@ class TraefikMiddlewareReconciler(KubernetesObjectReconciler[TraefikMiddleware]) def get_reference_object(self) -> TraefikMiddleware: """Get deployment object for outpost""" - if not ProxyProvider.objects.filter( - outpost__in=[self.controller.outpost], - forward_auth_mode=True, - ).exists(): - self.logger.debug("No providers with forward auth enabled.") - raise Disabled() - if not self._crd_exists(): - self.logger.debug("CRD doesn't exist") - raise Disabled() return TraefikMiddleware( apiVersion=f"{CRD_GROUP}/{CRD_VERSION}", kind="Middleware", diff --git a/authentik/root/settings.py b/authentik/root/settings.py index 344ce3e86..bfa946b24 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -248,6 +248,7 @@ DATABASES = { "NAME": CONFIG.y("postgresql.name"), "USER": CONFIG.y("postgresql.user"), "PASSWORD": CONFIG.y("postgresql.password"), + "PORT": int(CONFIG.y("postgresql.port")), } } @@ -320,7 +321,8 @@ CELERY_RESULT_BACKEND = ( DBBACKUP_STORAGE = "django.core.files.storage.FileSystemStorage" DBBACKUP_STORAGE_OPTIONS = {"location": "./backups" if DEBUG else "/backups"} DBBACKUP_CONNECTOR_MAPPING = { - "django_prometheus.db.backends.postgresql": "dbbackup.db.postgresql.PgDumpConnector" + "django_prometheus.db.backends.postgresql": "authentik.lib.connector.PgCustom", + "django.db.backends.postgresql": "authentik.lib.connector.PgCustom", } if CONFIG.y("postgresql.s3_backup"): DBBACKUP_STORAGE = "storages.backends.s3boto3.S3Boto3Storage" @@ -331,9 +333,10 @@ if CONFIG.y("postgresql.s3_backup"): "region_name": CONFIG.y("postgresql.s3_backup.region", "eu-central-1"), "default_acl": "private", "endpoint_url": CONFIG.y("postgresql.s3_backup.host"), + "location": CONFIG.y("postgresql.s3_backup.location", ""), } j_print( - "Database backup to S3 is configured.", + "Database backup to S3 is configured", host=CONFIG.y("postgresql.s3_backup.host"), ) @@ -355,7 +358,7 @@ if _ERROR_REPORTING: send_default_pii=CONFIG.y_bool("error_reporting.send_pii", False), ) j_print( - "Error reporting is enabled.", + "Error reporting is enabled", env=CONFIG.y("error_reporting.environment", "customer"), ) diff --git a/authentik/sources/oauth/api/source.py b/authentik/sources/oauth/api/source.py index 13db82c1e..b2813af1f 100644 --- a/authentik/sources/oauth/api/source.py +++ b/authentik/sources/oauth/api/source.py @@ -75,6 +75,7 @@ class OAuthSourceSerializer(SourceSerializer): "callback_url", "type", ] + extra_kwargs = {"consumer_secret": {"write_only": True}} class OAuthSourceViewSet(ModelViewSet): diff --git a/authentik/sources/oauth/api/source_connection.py b/authentik/sources/oauth/api/source_connection.py index e602ca96e..fb140fcc8 100644 --- a/authentik/sources/oauth/api/source_connection.py +++ b/authentik/sources/oauth/api/source_connection.py @@ -1,5 +1,7 @@ """OAuth Source Serializer""" +from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import ModelViewSet from authentik.core.api.sources import SourceSerializer @@ -25,6 +27,11 @@ class UserOAuthSourceConnectionViewSet(ModelViewSet): queryset = UserOAuthSourceConnection.objects.all() serializer_class = UserOAuthSourceConnectionSerializer filterset_fields = ["source__slug"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/sources/oauth/tests/test_type_google.py b/authentik/sources/oauth/tests/test_type_google.py index 6f79f8a2d..8c7b8fe05 100644 --- a/authentik/sources/oauth/tests/test_type_google.py +++ b/authentik/sources/oauth/tests/test_type_google.py @@ -33,6 +33,5 @@ class TestTypeGoogle(TestCase): def test_enroll_context(self): """Test Google Enrollment context""" ak_context = GoogleOAuth2Callback().get_user_enroll_context(GOOGLE_USER) - self.assertEqual(ak_context["username"], GOOGLE_USER["email"]) self.assertEqual(ak_context["email"], GOOGLE_USER["email"]) self.assertEqual(ak_context["name"], GOOGLE_USER["name"]) diff --git a/authentik/sources/oauth/types/google.py b/authentik/sources/oauth/types/google.py index ee6bdf63f..28735b635 100644 --- a/authentik/sources/oauth/types/google.py +++ b/authentik/sources/oauth/types/google.py @@ -23,7 +23,6 @@ class GoogleOAuth2Callback(OAuthCallback): info: dict[str, Any], ) -> dict[str, Any]: return { - "username": info.get("email"), "email": info.get("email"), "name": info.get("name"), } diff --git a/authentik/stages/authenticator_static/api.py b/authentik/stages/authenticator_static/api.py index 4b59964fa..297c43b39 100644 --- a/authentik/stages/authenticator_static/api.py +++ b/authentik/stages/authenticator_static/api.py @@ -1,6 +1,9 @@ """AuthenticatorStaticStage API Views""" +from django_filters import OrderingFilter +from django_filters.rest_framework import DjangoFilterBackend from django_otp.plugins.otp_static.models import StaticDevice from guardian.utils import get_anonymous_user +from rest_framework.filters import SearchFilter from rest_framework.permissions import IsAdminUser from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet @@ -43,6 +46,11 @@ class StaticDeviceViewSet(ModelViewSet): search_fields = ["name"] filterset_fields = ["name"] ordering = ["name"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/stages/authenticator_totp/api.py b/authentik/stages/authenticator_totp/api.py index 3b2cbde03..4329d4a4a 100644 --- a/authentik/stages/authenticator_totp/api.py +++ b/authentik/stages/authenticator_totp/api.py @@ -1,6 +1,8 @@ """AuthenticatorTOTPStage API Views""" +from django_filters.rest_framework import DjangoFilterBackend from django_otp.plugins.otp_totp.models import TOTPDevice from guardian.utils import get_anonymous_user +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet @@ -46,6 +48,11 @@ class TOTPDeviceViewSet(ModelViewSet): search_fields = ["name"] filterset_fields = ["name"] ordering = ["name"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/stages/authenticator_webauthn/api.py b/authentik/stages/authenticator_webauthn/api.py index 0ecb08b28..3afd59a80 100644 --- a/authentik/stages/authenticator_webauthn/api.py +++ b/authentik/stages/authenticator_webauthn/api.py @@ -1,5 +1,7 @@ """AuthenticateWebAuthnStage API Views""" +from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.permissions import IsAdminUser from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet @@ -45,6 +47,11 @@ class WebAuthnDeviceViewSet(ModelViewSet): search_fields = ["name"] filterset_fields = ["name"] ordering = ["name"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/authentik/stages/consent/api.py b/authentik/stages/consent/api.py index 501b4f008..edd067921 100644 --- a/authentik/stages/consent/api.py +++ b/authentik/stages/consent/api.py @@ -1,6 +1,8 @@ """ConsentStage API Views""" +from django_filters.rest_framework import DjangoFilterBackend from guardian.utils import get_anonymous_user from rest_framework import mixins +from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.core.api.applications import ApplicationSerializer @@ -49,6 +51,11 @@ class UserConsentViewSet( serializer_class = UserConsentSerializer filterset_fields = ["user", "application"] ordering = ["application", "expires"] + filter_backends = [ + DjangoFilterBackend, + OrderingFilter, + SearchFilter, + ] def get_queryset(self): user = self.request.user if self.request else get_anonymous_user() diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 41f985a00..971ef6db2 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -19,7 +19,7 @@ variables: branchName: ${{ replace(variables['Build.SourceBranchName'], 'refs/heads/', '') }} stages: - - stage: Lint + - stage: Lint_and_test jobs: - job: pylint pool: @@ -118,8 +118,6 @@ stages: - task: CmdLine@2 inputs: script: pipenv run pyright e2e lifecycle - - stage: Test - jobs: - job: migrations pool: vmImage: 'ubuntu-latest' diff --git a/docker-compose.yml b/docker-compose.yml index dcabafb97..f67df4411 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,7 +21,7 @@ services: networks: - internal server: - image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.5} + image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc7} restart: unless-stopped command: server environment: @@ -52,7 +52,7 @@ services: - "0.0.0.0:9000:9000" - "0.0.0.0:9443:9443" worker: - image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.4.5} + image: ${AUTHENTIK_IMAGE:-beryju/authentik}:${AUTHENTIK_TAG:-2021.5.1-rc7} restart: unless-stopped command: worker networks: diff --git a/internal/constants/constants.go b/internal/constants/constants.go index cae501e05..1599a76a8 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -1,3 +1,3 @@ package constants -const VERSION = "2021.4.5" +const VERSION = "2021.5.1-rc7" diff --git a/lifecycle/wait_for_db.py b/lifecycle/wait_for_db.py index 64a6fd926..462041cfb 100755 --- a/lifecycle/wait_for_db.py +++ b/lifecycle/wait_for_db.py @@ -41,11 +41,9 @@ while True: while True: try: - redis = Redis( - host=CONFIG.y("redis.host"), - port=6379, - db=CONFIG.y("redis.message_queue_db"), - password=CONFIG.y("redis.password"), + redis = Redis.from_url( + f"redis://:{CONFIG.y('redis.password')}@{CONFIG.y('redis.host')}:6379" + f"/{CONFIG.y('redis.ws_db')}" ) redis.ping() break diff --git a/outpost/pkg/ak/api.go b/outpost/pkg/ak/api.go index c4ead9265..62571163b 100644 --- a/outpost/pkg/ak/api.go +++ b/outpost/pkg/ak/api.go @@ -90,6 +90,10 @@ func (a *APIController) Start() error { a.logger.Debug("Starting WS Health notifier...") a.startWSHealth() }() + go func() { + a.logger.Debug("Starting Interval updater...") + a.startIntervalUpdater() + }() go func() { err := a.Server.Start() if err != nil { diff --git a/outpost/pkg/ak/api_ws.go b/outpost/pkg/ak/api_ws.go index 235247ec1..cdf891ed0 100644 --- a/outpost/pkg/ak/api_ws.go +++ b/outpost/pkg/ak/api_ws.go @@ -111,3 +111,14 @@ func (ac *APIController) startWSHealth() { } } } + +func (ac *APIController) startIntervalUpdater() { + logger := ac.logger.WithField("loop", "interval-updater") + ticker := time.NewTicker(time.Second * 150) + for ; true; <-ticker.C { + err := ac.Server.Refresh() + if err != nil { + logger.WithError(err).Debug("Failed to update") + } + } +} diff --git a/outpost/pkg/ak/global.go b/outpost/pkg/ak/global.go index b9512fc90..108803ec3 100644 --- a/outpost/pkg/ak/global.go +++ b/outpost/pkg/ak/global.go @@ -20,6 +20,8 @@ func doGlobalSetup(config map[string]interface{}) { }, }) switch config[ConfigLogLevel].(string) { + case "trace": + log.SetLevel(log.TraceLevel) case "debug": log.SetLevel(log.DebugLevel) case "info": diff --git a/outpost/pkg/proxy/proxy.go b/outpost/pkg/proxy/proxy.go index a380f486c..897e97a30 100644 --- a/outpost/pkg/proxy/proxy.go +++ b/outpost/pkg/proxy/proxy.go @@ -344,7 +344,11 @@ func (p *OAuthProxy) AuthenticateOnly(rw http.ResponseWriter, req *http.Request) } if _, ok := req.URL.Query()["traefik"]; ok { host := getHost(req) - http.Redirect(rw, req, fmt.Sprintf("//%s%s", host, p.OAuthStartPath), http.StatusTemporaryRedirect) + proto := req.Header.Get("X-Forwarded-Proto") + if proto != "" { + proto = proto + ":" + } + http.Redirect(rw, req, fmt.Sprintf("%s//%s%s", proto, host, p.OAuthStartPath), http.StatusTemporaryRedirect) return } } diff --git a/outpost/pkg/version.go b/outpost/pkg/version.go index 3745556ef..b68db357a 100644 --- a/outpost/pkg/version.go +++ b/outpost/pkg/version.go @@ -1,3 +1,3 @@ package pkg -const VERSION = "2021.4.5" +const VERSION = "2021.5.1-rc7" diff --git a/swagger.yaml b/swagger.yaml index aa676bfa8..2b8da5f83 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -531,11 +531,6 @@ paths: description: '' required: false type: string - - name: ordering - in: query - description: Which field to use when ordering the results. - required: false - type: string - name: search in: query description: A search term. @@ -16203,7 +16198,7 @@ definitions: required: - name - providers - - _config + - config type: object properties: pk: @@ -16242,8 +16237,8 @@ definitions: title: Token identifier type: string readOnly: true - _config: - title: config + config: + title: Config type: object OutpostDefaultConfig: type: object diff --git a/web/nginx.conf b/web/nginx.conf index 13085576e..19ec6644c 100644 --- a/web/nginx.conf +++ b/web/nginx.conf @@ -81,7 +81,7 @@ http { location /static/ { expires 31d; add_header Cache-Control "public, no-transform"; - add_header X-authentik-version "2021.4.5"; + add_header X-authentik-version "2021.5.1-rc7"; add_header Vary X-authentik-version; } diff --git a/web/package-lock.json b/web/package-lock.json index b314b2f64..17e58af0b 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -24,13 +24,13 @@ "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-replace": "^2.4.2", "@rollup/plugin-typescript": "^8.2.1", - "@sentry/browser": "^6.3.5", - "@sentry/tracing": "^6.3.5", + "@sentry/browser": "^6.3.6", + "@sentry/tracing": "^6.3.6", "@types/chart.js": "^2.9.32", "@types/codemirror": "5.60.0", "@types/grecaptcha": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^4.22.1", - "@typescript-eslint/parser": "^4.22.1", + "@typescript-eslint/eslint-plugin": "^4.23.0", + "@typescript-eslint/parser": "^4.23.0", "@webcomponents/webcomponentsjs": "^2.5.0", "authentik-api": "file:api", "babel-plugin-macros": "^3.1.0", @@ -39,10 +39,10 @@ "chartjs-adapter-moment": "^1.0.0", "codemirror": "^5.61.0", "construct-style-sheets-polyfill": "^2.4.16", - "eslint": "^7.25.0", + "eslint": "^7.26.0", "eslint-config-google": "^0.14.0", "eslint-plugin-custom-elements": "0.0.2", - "eslint-plugin-lit": "^1.3.0", + "eslint-plugin-lit": "^1.4.0", "flowchart.js": "^1.15.0", "lit-element": "^2.5.1", "lit-html": "^1.4.1", @@ -61,13 +61,12 @@ "typescript": "^4.2.4", "webcomponent-qr-code": "^1.0.5", "yaml": "^1.10.2" - }, - "devDependencies": {} + } }, "api": { "name": "authentik-api", - "version": "1.0.0", - "devDependencies": { + "version": "0.0.1", + "dependencies": { "typescript": "^3.6" } }, @@ -75,7 +74,6 @@ "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -1725,9 +1723,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -1752,6 +1750,9 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@eslint/eslintrc/node_modules/ignore": { @@ -2337,33 +2338,13 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" }, "node_modules/@sentry/browser": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.5.tgz", - "integrity": "sha512-fjkhPR5gLCGVWhbWjEoN64hnmTvfTLRCgWmYTc9SiGchWFoFEmLqZyF2uJFyt27+qamLQ9fN58nnv4Ly2yyxqg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.6.tgz", + "integrity": "sha512-l4323jxuBOArki6Wf+EHes39IEyJ2Zj/CIUaTY7GWh7CntpfHQAfFmZWQw3Ozq+ka1u8lVp25RPhb4Wng3azNA==", "dependencies": { - "@sentry/core": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/browser/node_modules/@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/browser/node_modules/@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", - "dependencies": { - "@sentry/types": "6.3.5", + "@sentry/core": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2376,60 +2357,14 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/core": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.5.tgz", - "integrity": "sha512-VR2ibDy33mryD0mT6d9fGhKjdNzS2FSwwZPe9GvmNOjkyjly/oV91BKVoYJneCqOeq8fyj2lvkJGKuupdJNDqg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.6.tgz", + "integrity": "sha512-w6BRizAqh7BaiM9oeKzO6aACXwRijUPacYaVLX/OfhqCSueF9uDxpMRT7+4D/eCeDVqgJYhBJ4Vsu2NSstkk4A==", "dependencies": { - "@sentry/hub": "6.3.5", - "@sentry/minimal": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/core/node_modules/@sentry/hub": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz", - "integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==", - "dependencies": { - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/core/node_modules/@sentry/minimal": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz", - "integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==", - "dependencies": { - "@sentry/hub": "6.3.5", - "@sentry/types": "6.3.5", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/core/node_modules/@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/core/node_modules/@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", - "dependencies": { - "@sentry/types": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/minimal": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2442,12 +2377,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/hub": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz", - "integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.6.tgz", + "integrity": "sha512-foBZ3ilMnm9Gf9OolrAxYHK8jrA6IF72faDdJ3Al+1H27qcpnBaMdrdEp2/jzwu/dgmwuLmbBaMjEPXaGH/0JQ==", "dependencies": { - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2460,12 +2395,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/minimal": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz", - "integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.6.tgz", + "integrity": "sha512-uM2/dH0a6zfvI5f+vg+/mST+uTBdN6Jgpm585ipH84ckCYQwIIDRg6daqsen4S1sy/xgg1P1YyC3zdEC4G6b1Q==", "dependencies": { - "@sentry/hub": "6.3.5", - "@sentry/types": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/types": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2478,14 +2413,14 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/tracing": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.5.tgz", - "integrity": "sha512-TNKAST1ge2g24BlTfVxNp4gP5t3drbi0OVCh8h8ah+J7UjHSfdiqhd9W2h5qv1GO61gGlpWeN/TyioyQmOxu0Q==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.6.tgz", + "integrity": "sha512-dfyYY2eESJGt5Qbigmfmb2U9ntqbwPhLNAOcjKaVg9WQRV5q2RkHCVctPoYk7TEAvfNeNRXCD8SnuFOZhttt8g==", "dependencies": { - "@sentry/hub": "6.3.5", - "@sentry/minimal": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/minimal": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2498,19 +2433,19 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.6.tgz", + "integrity": "sha512-93cFJdJkWyCfyZeWFARSU11qnoHVOS/R2h5WIsEf+jbQmkqG2C+TXVz/19s6nHVsfDrwpvYpwALPv4/nrxfU7g==", "engines": { "node": ">=6" } }, "node_modules/@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.6.tgz", + "integrity": "sha512-HnYlDBf8Dq8MEv7AulH7B6R1D/2LAooVclGdjg48tSrr9g+31kmtj+SAj2WWVHP9+bp29BWaC7i5nkfKrOibWw==", "dependencies": { - "@sentry/types": "6.3.5", + "@sentry/types": "6.3.6", "tslib": "^1.9.3" }, "engines": { @@ -2668,12 +2603,12 @@ "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz", - "integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.23.0.tgz", + "integrity": "sha512-tGK1y3KIvdsQEEgq6xNn1DjiFJtl+wn8JJQiETtCbdQxw1vzjXyAaIkEmO2l6Nq24iy3uZBMFQjZ6ECf1QdgGw==", "dependencies": { - "@typescript-eslint/experimental-utils": "4.22.1", - "@typescript-eslint/scope-manager": "4.22.1", + "@typescript-eslint/experimental-utils": "4.23.0", + "@typescript-eslint/scope-manager": "4.23.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -2699,14 +2634,14 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz", - "integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz", + "integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==", "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.22.1", - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/typescript-estree": "4.22.1", + "@typescript-eslint/scope-manager": "4.23.0", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/typescript-estree": "4.23.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, @@ -2722,13 +2657,13 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz", - "integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.23.0.tgz", + "integrity": "sha512-wsvjksHBMOqySy/Pi2Q6UuIuHYbgAMwLczRl4YanEPKW5KVxI9ZzDYh3B5DtcZPQTGRWFJrfcbJ6L01Leybwug==", "dependencies": { - "@typescript-eslint/scope-manager": "4.22.1", - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/typescript-estree": "4.22.1", + "@typescript-eslint/scope-manager": "4.23.0", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/typescript-estree": "4.23.0", "debug": "^4.1.1" }, "engines": { @@ -2748,12 +2683,12 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz", - "integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz", + "integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==", "dependencies": { - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/visitor-keys": "4.22.1" + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -2764,9 +2699,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz", - "integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz", + "integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw==", "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" }, @@ -2776,12 +2711,12 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz", - "integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz", + "integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==", "dependencies": { - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/visitor-keys": "4.22.1", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -2821,11 +2756,11 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz", - "integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz", + "integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==", "dependencies": { - "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/types": "4.23.0", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -2860,7 +2795,10 @@ "node_modules/acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, "node_modules/ajv": { "version": "6.12.6", @@ -2871,6 +2809,10 @@ "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-colors": { @@ -3906,12 +3848,12 @@ } }, "node_modules/eslint": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", - "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", + "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", "dependencies": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3953,6 +3895,9 @@ }, "engines": { "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-google": { @@ -3972,13 +3917,16 @@ } }, "node_modules/eslint-plugin-lit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.3.0.tgz", - "integrity": "sha512-fy6Lr5vYI3kvCYaDXA20lwyKAp1keS9UjR5ntj8U2TeV+1yUta3S7xxXe+rABKRPbcNzi1ZvQLE1LmNKc9yr4Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.4.0.tgz", + "integrity": "sha512-3PJCC1p4pvDBKtFmg1g2cGzAgJF4IDqhb9NJUh95nYc+QXExa/O/0fILF4WB6X7qdNQKm+gW6nYtSKTyYPHtXw==", "dependencies": { "parse5": "^6.0.1", "parse5-htmlparser2-tree-adapter": "^6.0.1", "requireindex": "^1.2.0" + }, + "peerDependencies": { + "eslint": ">= 5" } }, "node_modules/eslint-rule-documentation": { @@ -7355,6 +7303,9 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { @@ -9632,9 +9583,9 @@ } }, "@eslint/eslintrc": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", - "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -10146,30 +10097,16 @@ } }, "@sentry/browser": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.5.tgz", - "integrity": "sha512-fjkhPR5gLCGVWhbWjEoN64hnmTvfTLRCgWmYTc9SiGchWFoFEmLqZyF2uJFyt27+qamLQ9fN58nnv4Ly2yyxqg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.3.6.tgz", + "integrity": "sha512-l4323jxuBOArki6Wf+EHes39IEyJ2Zj/CIUaTY7GWh7CntpfHQAfFmZWQw3Ozq+ka1u8lVp25RPhb4Wng3azNA==", "requires": { - "@sentry/core": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/core": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { - "@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==" - }, - "@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", - "requires": { - "@sentry/types": "6.3.5", - "tslib": "^1.9.3" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -10178,51 +10115,17 @@ } }, "@sentry/core": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.5.tgz", - "integrity": "sha512-VR2ibDy33mryD0mT6d9fGhKjdNzS2FSwwZPe9GvmNOjkyjly/oV91BKVoYJneCqOeq8fyj2lvkJGKuupdJNDqg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.3.6.tgz", + "integrity": "sha512-w6BRizAqh7BaiM9oeKzO6aACXwRijUPacYaVLX/OfhqCSueF9uDxpMRT7+4D/eCeDVqgJYhBJ4Vsu2NSstkk4A==", "requires": { - "@sentry/hub": "6.3.5", - "@sentry/minimal": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/minimal": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { - "@sentry/hub": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz", - "integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==", - "requires": { - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", - "tslib": "^1.9.3" - } - }, - "@sentry/minimal": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz", - "integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==", - "requires": { - "@sentry/hub": "6.3.5", - "@sentry/types": "6.3.5", - "tslib": "^1.9.3" - } - }, - "@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==" - }, - "@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", - "requires": { - "@sentry/types": "6.3.5", - "tslib": "^1.9.3" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -10231,12 +10134,12 @@ } }, "@sentry/hub": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.5.tgz", - "integrity": "sha512-ZYFo7VYKwdPVjuV9BDFiYn+MpANn6eZMz5QDBfZ2dugIvIVbuOyOOLx8PSa3ZXJoVTZZ7s2wD2fi/ZxKjNjZOQ==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.3.6.tgz", + "integrity": "sha512-foBZ3ilMnm9Gf9OolrAxYHK8jrA6IF72faDdJ3Al+1H27qcpnBaMdrdEp2/jzwu/dgmwuLmbBaMjEPXaGH/0JQ==", "requires": { - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { @@ -10248,12 +10151,12 @@ } }, "@sentry/minimal": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.5.tgz", - "integrity": "sha512-4RqIGAU0+8iI/1sw0GYPTr4SUA88/i2+JPjFJ+qloh5ANVaNwhFPRChw+Ys9xpre8LV9JZrEsEf8AvQr4fkNbA==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.3.6.tgz", + "integrity": "sha512-uM2/dH0a6zfvI5f+vg+/mST+uTBdN6Jgpm585ipH84ckCYQwIIDRg6daqsen4S1sy/xgg1P1YyC3zdEC4G6b1Q==", "requires": { - "@sentry/hub": "6.3.5", - "@sentry/types": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/types": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { @@ -10265,14 +10168,14 @@ } }, "@sentry/tracing": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.5.tgz", - "integrity": "sha512-TNKAST1ge2g24BlTfVxNp4gP5t3drbi0OVCh8h8ah+J7UjHSfdiqhd9W2h5qv1GO61gGlpWeN/TyioyQmOxu0Q==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.3.6.tgz", + "integrity": "sha512-dfyYY2eESJGt5Qbigmfmb2U9ntqbwPhLNAOcjKaVg9WQRV5q2RkHCVctPoYk7TEAvfNeNRXCD8SnuFOZhttt8g==", "requires": { - "@sentry/hub": "6.3.5", - "@sentry/minimal": "6.3.5", - "@sentry/types": "6.3.5", - "@sentry/utils": "6.3.5", + "@sentry/hub": "6.3.6", + "@sentry/minimal": "6.3.6", + "@sentry/types": "6.3.6", + "@sentry/utils": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { @@ -10284,16 +10187,16 @@ } }, "@sentry/types": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.5.tgz", - "integrity": "sha512-tY/3pkAmGYJ3F0BtwInsdt/uclNvF8aNG7XHsTPQNzk7BkNVWjCXx0sjxi6CILirl5nwNxYxVeTr2ZYAEZ/dSQ==" + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.3.6.tgz", + "integrity": "sha512-93cFJdJkWyCfyZeWFARSU11qnoHVOS/R2h5WIsEf+jbQmkqG2C+TXVz/19s6nHVsfDrwpvYpwALPv4/nrxfU7g==" }, "@sentry/utils": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.5.tgz", - "integrity": "sha512-kHUcZ37QYlNzz7c9LVdApITXHaNmQK7+sw/If3M/qpff1fd5XoecA8laLfcYuz+Cw5mRhVmdhPcCRM3Xi1IGXg==", + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.3.6.tgz", + "integrity": "sha512-HnYlDBf8Dq8MEv7AulH7B6R1D/2LAooVclGdjg48tSrr9g+31kmtj+SAj2WWVHP9+bp29BWaC7i5nkfKrOibWw==", "requires": { - "@sentry/types": "6.3.5", + "@sentry/types": "6.3.6", "tslib": "^1.9.3" }, "dependencies": { @@ -10450,12 +10353,12 @@ "integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==" }, "@typescript-eslint/eslint-plugin": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.1.tgz", - "integrity": "sha512-kVTAghWDDhsvQ602tHBc6WmQkdaYbkcTwZu+7l24jtJiYvm9l+/y/b2BZANEezxPDiX5MK2ZecE+9BFi/YJryw==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.23.0.tgz", + "integrity": "sha512-tGK1y3KIvdsQEEgq6xNn1DjiFJtl+wn8JJQiETtCbdQxw1vzjXyAaIkEmO2l6Nq24iy3uZBMFQjZ6ECf1QdgGw==", "requires": { - "@typescript-eslint/experimental-utils": "4.22.1", - "@typescript-eslint/scope-manager": "4.22.1", + "@typescript-eslint/experimental-utils": "4.23.0", + "@typescript-eslint/scope-manager": "4.23.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "lodash": "^4.17.15", @@ -10465,50 +10368,50 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.22.1.tgz", - "integrity": "sha512-svYlHecSMCQGDO2qN1v477ax/IDQwWhc7PRBiwAdAMJE7GXk5stF4Z9R/8wbRkuX/5e9dHqbIWxjeOjckK3wLQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.23.0.tgz", + "integrity": "sha512-WAFNiTDnQfrF3Z2fQ05nmCgPsO5o790vOhmWKXbbYQTO9erE1/YsFot5/LnOUizLzU2eeuz6+U/81KV5/hFTGA==", "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.22.1", - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/typescript-estree": "4.22.1", + "@typescript-eslint/scope-manager": "4.23.0", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/typescript-estree": "4.23.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.22.1.tgz", - "integrity": "sha512-l+sUJFInWhuMxA6rtirzjooh8cM/AATAe3amvIkqKFeMzkn85V+eLzb1RyuXkHak4dLfYzOmF6DXPyflJvjQnw==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.23.0.tgz", + "integrity": "sha512-wsvjksHBMOqySy/Pi2Q6UuIuHYbgAMwLczRl4YanEPKW5KVxI9ZzDYh3B5DtcZPQTGRWFJrfcbJ6L01Leybwug==", "requires": { - "@typescript-eslint/scope-manager": "4.22.1", - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/typescript-estree": "4.22.1", + "@typescript-eslint/scope-manager": "4.23.0", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/typescript-estree": "4.23.0", "debug": "^4.1.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.1.tgz", - "integrity": "sha512-d5bAiPBiessSmNi8Amq/RuLslvcumxLmyhf1/Xa9IuaoFJ0YtshlJKxhlbY7l2JdEk3wS0EnmnfeJWSvADOe0g==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.23.0.tgz", + "integrity": "sha512-ZZ21PCFxPhI3n0wuqEJK9omkw51wi2bmeKJvlRZPH5YFkcawKOuRMQMnI8mH6Vo0/DoHSeZJnHiIx84LmVQY+w==", "requires": { - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/visitor-keys": "4.22.1" + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0" } }, "@typescript-eslint/types": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.1.tgz", - "integrity": "sha512-2HTkbkdAeI3OOcWbqA8hWf/7z9c6gkmnWNGz0dKSLYLWywUlkOAQ2XcjhlKLj5xBFDf8FgAOF5aQbnLRvgNbCw==" + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.23.0.tgz", + "integrity": "sha512-oqkNWyG2SLS7uTWLZf6Sr7Dm02gA5yxiz1RP87tvsmDsguVATdpVguHr4HoGOcFOpCvx9vtCSCyQUGfzq28YCw==" }, "@typescript-eslint/typescript-estree": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.22.1.tgz", - "integrity": "sha512-p3We0pAPacT+onSGM+sPR+M9CblVqdA9F1JEdIqRVlxK5Qth4ochXQgIyb9daBomyQKAXbygxp1aXQRV0GC79A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.23.0.tgz", + "integrity": "sha512-5Sty6zPEVZF5fbvrZczfmLCOcby3sfrSPu30qKoY1U3mca5/jvU5cwsPb/CO6Q3ByRjixTMIVsDkqwIxCf/dMw==", "requires": { - "@typescript-eslint/types": "4.22.1", - "@typescript-eslint/visitor-keys": "4.22.1", + "@typescript-eslint/types": "4.23.0", + "@typescript-eslint/visitor-keys": "4.23.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -10532,11 +10435,11 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.22.1.tgz", - "integrity": "sha512-WPkOrIRm+WCLZxXQHCi+WG8T2MMTUFR70rWjdWYddLT7cEfb2P4a3O/J2U1FBVsSFTocXLCoXWY6MZGejeStvQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.23.0.tgz", + "integrity": "sha512-5PNe5cmX9pSifit0H+nPoQBXdbNzi5tOEec+3riK+ku4e3er37pKxMKDH5Ct5Y4fhWxcD4spnlYjxi9vXbSpwg==", "requires": { - "@typescript-eslint/types": "4.22.1", + "@typescript-eslint/types": "4.23.0", "eslint-visitor-keys": "^2.0.0" } }, @@ -10558,7 +10461,8 @@ "acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "requires": {} }, "ajv": { "version": "6.12.6", @@ -10685,8 +10589,7 @@ "typescript": { "version": "3.9.9", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.9.tgz", - "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==", - "dev": true + "integrity": "sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==" } } }, @@ -11415,12 +11318,12 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.25.0.tgz", - "integrity": "sha512-TVpSovpvCNpLURIScDRB6g5CYu/ZFq9GfX2hLNIV4dSBKxIWojeDODvYl3t0k0VtMxYeR8OXPCFE5+oHMlGfhw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", + "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -11535,9 +11438,9 @@ } }, "eslint-plugin-lit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.3.0.tgz", - "integrity": "sha512-fy6Lr5vYI3kvCYaDXA20lwyKAp1keS9UjR5ntj8U2TeV+1yUta3S7xxXe+rABKRPbcNzi1ZvQLE1LmNKc9yr4Q==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.4.0.tgz", + "integrity": "sha512-3PJCC1p4pvDBKtFmg1g2cGzAgJF4IDqhb9NJUh95nYc+QXExa/O/0fILF4WB6X7qdNQKm+gW6nYtSKTyYPHtXw==", "requires": { "parse5": "^6.0.1", "parse5-htmlparser2-tree-adapter": "^6.0.1", diff --git a/web/package.json b/web/package.json index 6266a12c8..aff47a2b5 100644 --- a/web/package.json +++ b/web/package.json @@ -50,13 +50,13 @@ "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-replace": "^2.4.2", "@rollup/plugin-typescript": "^8.2.1", - "@sentry/browser": "^6.3.5", - "@sentry/tracing": "^6.3.5", + "@sentry/browser": "^6.3.6", + "@sentry/tracing": "^6.3.6", "@types/chart.js": "^2.9.32", "@types/codemirror": "5.60.0", "@types/grecaptcha": "^3.0.2", - "@typescript-eslint/eslint-plugin": "^4.22.1", - "@typescript-eslint/parser": "^4.22.1", + "@typescript-eslint/eslint-plugin": "^4.23.0", + "@typescript-eslint/parser": "^4.23.0", "@webcomponents/webcomponentsjs": "^2.5.0", "authentik-api": "file:api", "babel-plugin-macros": "^3.1.0", @@ -65,10 +65,10 @@ "chartjs-adapter-moment": "^1.0.0", "codemirror": "^5.61.0", "construct-style-sheets-polyfill": "^2.4.16", - "eslint": "^7.25.0", + "eslint": "^7.26.0", "eslint-config-google": "^0.14.0", "eslint-plugin-custom-elements": "0.0.2", - "eslint-plugin-lit": "^1.3.0", + "eslint-plugin-lit": "^1.4.0", "flowchart.js": "^1.15.0", "lit-element": "^2.5.1", "lit-html": "^1.4.1", diff --git a/web/src/constants.ts b/web/src/constants.ts index 601bd2231..912fd288a 100644 --- a/web/src/constants.ts +++ b/web/src/constants.ts @@ -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.4.5"; +export const VERSION = "2021.5.1-rc7"; export const PAGE_SIZE = 20; export const EVENT_REFRESH = "ak-refresh"; export const EVENT_NOTIFICATION_TOGGLE = "ak-notification-toggle"; diff --git a/web/src/elements/charts/Chart.ts b/web/src/elements/charts/Chart.ts index ab42a0f0f..946f5ddba 100644 --- a/web/src/elements/charts/Chart.ts +++ b/web/src/elements/charts/Chart.ts @@ -6,6 +6,7 @@ import { ArcElement, BarElement } from "chart.js"; import { TimeScale, LinearScale } from "chart.js"; import "chartjs-adapter-moment"; import { FONT_COLOUR_DARK_MODE, FONT_COLOUR_LIGHT_MODE } from "../../pages/flows/FlowDiagram"; +import {EVENT_REFRESH} from "../../constants"; Chart.register(Legend, Tooltip); Chart.register(LineController, BarController, DoughnutController); @@ -43,6 +44,13 @@ export abstract class AKChart extends LitElement { this.chart.resize(); } }); + window.addEventListener(EVENT_REFRESH, () => { + this.apiRequest().then((r: T) => { + if (!this.chart) return; + this.chart.data = this.getChartData(r); + this.chart.update(); + }); + }); const matcher = window.matchMedia("(prefers-color-scheme: light)"); const handler = (ev?: MediaQueryListEvent) => { if (ev?.matches || matcher.matches) { @@ -56,6 +64,22 @@ export abstract class AKChart extends LitElement { handler(); } + firstUpdated(): void { + this.apiRequest().then((r) => { + const canvas = this.shadowRoot?.querySelector("canvas"); + if (!canvas) { + console.warn("Failed to get canvas element"); + return false; + } + const ctx = canvas.getContext("2d"); + if (!ctx) { + console.warn("failed to get 2d context"); + return false; + } + this.chart = this.configureChart(r, ctx); + }); + } + getChartType(): string { return "bar"; } @@ -129,23 +153,6 @@ export abstract class AKChart extends LitElement { return new Chart(ctx, config as ChartConfiguration); } - - firstUpdated(): void { - this.apiRequest().then((r) => { - const canvas = this.shadowRoot?.querySelector("canvas"); - if (!canvas) { - console.warn("Failed to get canvas element"); - return false; - } - const ctx = canvas.getContext("2d"); - if (!ctx) { - console.warn("failed to get 2d context"); - return false; - } - this.chart = this.configureChart(r, ctx); - }); - } - render(): TemplateResult { return html`
diff --git a/web/src/pages/outposts/OutpostForm.ts b/web/src/pages/outposts/OutpostForm.ts index 24d531a40..1e65dd045 100644 --- a/web/src/pages/outposts/OutpostForm.ts +++ b/web/src/pages/outposts/OutpostForm.ts @@ -102,18 +102,18 @@ export class OutpostForm extends Form {

${t`Hold control/command to select multiple items.`}

- ${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => { - let fc = config.config; - if (this.outpost) { - fc = this.outpost.config; - } - return html` - -

${t`Set custom attributes using YAML or JSON.`}

-
`; - }))} + + +

${t`Set custom attributes using YAML or JSON.`}

+
`; } diff --git a/website/docs/installation/beta.mdx b/website/docs/installation/beta.mdx index d93a62c30..ec64ba8e0 100644 --- a/website/docs/installation/beta.mdx +++ b/website/docs/installation/beta.mdx @@ -17,10 +17,9 @@ import TabItem from '@theme/TabItem'; Add the following block to your `.env` file: ```shell -AUTHENTIK_IMAGE=docker.beryju.org/authentik/server -AUTHENTIK_IMAGE_STATIC=docker.beryju.org/authentik/static +AUTHENTIK_IMAGE=beryju.org/authentik/server AUTHENTIK_TAG=gh-next -AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE=docker.beryju.org/authentik/outpost-%(type)s:gh-next +AUTHENTIK_OUTPOSTS__DOCKER_IMAGE_BASE=beryju.org/authentik/outpost-%(type)s:gh-next ``` Afterwards, run the upgrade commands from the latest releasae notes. @@ -30,9 +29,8 @@ Add the following block to your `values.yml` file: ```yaml image: - name: docker.beryju.org/authentik/server - name_static: docker.beryju.org/authentik/static - name_outposts: docker.beryju.org/authentik/outpost-%(type)s:gh-next + name: beryju.org/authentik/server + name_outposts: beryju.org/authentik/outpost-%(type)s:gh-next tag: gh-next # pullPolicy: Always to ensure you always get the latest version pullPolicy: Always diff --git a/website/docs/installation/docker-compose.md b/website/docs/installation/docker-compose.md index b08d66766..6488ced03 100644 --- a/website/docs/installation/docker-compose.md +++ b/website/docs/installation/docker-compose.md @@ -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 deploy a different version run `echo AUTHENTIK_TAG=2021.4.5 >> .env` +To optionally deploy a different version run `echo AUTHENTIK_TAG=2021.5.1-rc7 >> .env` If this is a fresh authentik install run the following commands to generate a password: diff --git a/website/docs/installation/kubernetes.md b/website/docs/installation/kubernetes.md index a5a06cd75..d2448796e 100644 --- a/website/docs/installation/kubernetes.md +++ b/website/docs/installation/kubernetes.md @@ -22,9 +22,9 @@ See all configurable values on [artifacthub](https://artifacthub.io/packages/hel Afterwards, run these commands to install authentik: ``` -helm repo add authentik https://helm.goauthentik.io +helm repo add authentik https://charts.goauthentik.io helm repo update -helm install authentik/authentik -f values.yaml +helm install authentik authentik/authentik -f values.yaml ``` This installation automatically applies database migrations on startup. After the installation is done, navigate to the `https:///if/flow/initial-setup/`, to set a password for the akadmin user. diff --git a/website/docs/outposts/manual-deploy-docker-compose.md b/website/docs/outposts/manual-deploy-docker-compose.md index e46401882..cba7385ca 100644 --- a/website/docs/outposts/manual-deploy-docker-compose.md +++ b/website/docs/outposts/manual-deploy-docker-compose.md @@ -11,7 +11,7 @@ version: "3.5" services: authentik_proxy: - image: beryju/authentik-proxy:2021.4.5 + image: beryju/authentik-proxy:2021.5.1-rc7 ports: - 4180:4180 - 4443:4443 diff --git a/website/docs/outposts/manual-deploy-kubernetes.md b/website/docs/outposts/manual-deploy-kubernetes.md index f265db3b3..d77e43bae 100644 --- a/website/docs/outposts/manual-deploy-kubernetes.md +++ b/website/docs/outposts/manual-deploy-kubernetes.md @@ -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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 spec: containers: - env: @@ -88,7 +88,7 @@ spec: secretKeyRef: key: authentik_host_insecure name: authentik-outpost-api - image: beryju/authentik-proxy:2021.4.5 + image: beryju/authentik-proxy:2021.5.1-rc7 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.4.5 + app.kubernetes.io/version: 2021.5.1-rc7 name: authentik-outpost spec: rules: diff --git a/website/docs/releases/v2021.5.md b/website/docs/releases/v2021.5.md index 2f6910e64..fc2895838 100644 --- a/website/docs/releases/v2021.5.md +++ b/website/docs/releases/v2021.5.md @@ -72,7 +72,7 @@ The public port of the compose stack has been changed from 443 to 9000 and 9443 ### Kubernetes -The helm chart has been rewritten by [@dirtycajunrice](https://github.com/dirtycajunrice) and now lives on `https://helm.goauthentik.io`. +The helm chart has been rewritten by [@dirtycajunrice](https://github.com/dirtycajunrice) and now lives on `https://charts.goauthentik.io`. Please upgrade to the new chart using values from [ArtifactHub](https://artifacthub.io/packages/helm/goauthentik/authentik). diff --git a/website/package-lock.json b/website/package-lock.json index 82babea96..7cc371e26 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -11,7 +11,7 @@ "@docusaurus/preset-classic": "2.0.0-alpha.75", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", - "postcss": "^8.2.14", + "postcss": "^8.2.15", "rapidoc": "^9.0.0", "react": "^17.0.2", "react-before-after-slider": "^1.0.4", @@ -20,7 +20,7 @@ "react-toggle": "^4.1.2" }, "devDependencies": { - "prettier": "2.2.1" + "prettier": "2.3.0" } }, "node_modules/@algolia/autocomplete-core": { @@ -8004,9 +8004,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", - "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -8823,12 +8823,12 @@ } }, "node_modules/postcss": { - "version": "8.2.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz", - "integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==", + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", "dependencies": { "colorette": "^1.2.2", - "nanoid": "^3.1.22", + "nanoid": "^3.1.23", "source-map": "^0.6.1" }, "engines": { @@ -9306,9 +9306,9 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -20240,9 +20240,9 @@ "optional": true }, "nanoid": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz", - "integrity": "sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ==" + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==" }, "nanomatch": { "version": "1.2.13", @@ -20895,12 +20895,12 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "8.2.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.14.tgz", - "integrity": "sha512-+jD0ZijcvyCqPQo/m/CW0UcARpdFylq04of+Q7RKX6f/Tu+dvpUI/9Sp81+i6/vJThnOBX09Quw0ZLOVwpzX3w==", + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", "requires": { "colorette": "^1.2.2", - "nanoid": "^3.1.22", + "nanoid": "^3.1.23", "source-map": "^0.6.1" }, "dependencies": { @@ -21255,9 +21255,9 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true }, "pretty-error": { diff --git a/website/package.json b/website/package.json index 934e2017b..b8b9f8298 100644 --- a/website/package.json +++ b/website/package.json @@ -14,7 +14,7 @@ "@docusaurus/preset-classic": "2.0.0-alpha.75", "@mdx-js/react": "^1.6.22", "clsx": "^1.1.1", - "postcss": "^8.2.14", + "postcss": "^8.2.15", "rapidoc": "^9.0.0", "react": "^17.0.2", "react-before-after-slider": "^1.0.4", @@ -35,6 +35,6 @@ ] }, "devDependencies": { - "prettier": "2.2.1" + "prettier": "2.3.0" } } diff --git a/website/static/service-account.yaml b/website/static/service-account.yaml new file mode 100644 index 000000000..722d0970f --- /dev/null +++ b/website/static/service-account.yaml @@ -0,0 +1,102 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: authentik + namespace: ##NAMESPACE## +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: authentik + namespace: ##NAMESPACE## +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: authentik +subjects: + - kind: ServiceAccount + name: authentik + namespace: ##NAMESPACE## +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: authentik + namespace: ##NAMESPACE## +rules: + - apiGroups: + - "" + resources: + - secrets + - services + - configmaps + verbs: + - get + - create + - delete + - list + - patch + - apiGroups: + - extensions + - apps + resources: + - deployments + verbs: + - get + - create + - delete + - list + - patch + - apiGroups: + - extensions + - networking.k8s.io + resources: + - ingresses + verbs: + - get + - create + - delete + - list + - patch + - apiGroups: + - traefik.containo.us + resources: + - middlewares + verbs: + - get + - create + - delete + - list + - patch + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: authentik +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: authentik +subjects: + - kind: ServiceAccount + name: authentik + namespace: ingress +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: authentik +rules: + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list