outposts: move local connection check to task, run every 60 minutes
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
aa0e8edb8b
commit
b8a566f4a0
|
@ -1,17 +1,8 @@
|
|||
"""authentik outposts app config"""
|
||||
from importlib import import_module
|
||||
from os import R_OK, access
|
||||
from os.path import expanduser
|
||||
from pathlib import Path
|
||||
from socket import gethostname
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import yaml
|
||||
from django.apps import AppConfig
|
||||
from django.db import ProgrammingError
|
||||
from docker.constants import DEFAULT_UNIX_SOCKET
|
||||
from kubernetes.config.incluster_config import SERVICE_TOKEN_FILENAME
|
||||
from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
@ -27,49 +18,8 @@ class AuthentikOutpostConfig(AppConfig):
|
|||
def ready(self):
|
||||
import_module("authentik.outposts.signals")
|
||||
try:
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
|
||||
outpost_local_connection.delay()
|
||||
except ProgrammingError:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def init_local_connection():
|
||||
"""Check if local kubernetes or docker connections should be created"""
|
||||
from authentik.outposts.models import (
|
||||
DockerServiceConnection,
|
||||
KubernetesServiceConnection,
|
||||
)
|
||||
|
||||
# Explicitly check against token filename, as thats
|
||||
# only present when the integration is enabled
|
||||
if Path(SERVICE_TOKEN_FILENAME).exists():
|
||||
LOGGER.debug("Detected in-cluster Kubernetes Config")
|
||||
if not KubernetesServiceConnection.objects.filter(local=True).exists():
|
||||
LOGGER.debug("Created Service Connection for in-cluster")
|
||||
KubernetesServiceConnection.objects.create(
|
||||
name="Local Kubernetes Cluster", local=True, kubeconfig={}
|
||||
)
|
||||
# For development, check for the existence of a kubeconfig file
|
||||
kubeconfig_path = expanduser(KUBE_CONFIG_DEFAULT_LOCATION)
|
||||
if Path(kubeconfig_path).exists():
|
||||
LOGGER.debug("Detected kubeconfig")
|
||||
kubeconfig_local_name = f"k8s-{gethostname()}"
|
||||
if not KubernetesServiceConnection.objects.filter(
|
||||
name=kubeconfig_local_name
|
||||
).exists():
|
||||
LOGGER.debug("Creating kubeconfig Service Connection")
|
||||
with open(kubeconfig_path, "r") as _kubeconfig:
|
||||
KubernetesServiceConnection.objects.create(
|
||||
name=kubeconfig_local_name,
|
||||
kubeconfig=yaml.safe_load(_kubeconfig),
|
||||
)
|
||||
unix_socket_path = urlparse(DEFAULT_UNIX_SOCKET).path
|
||||
socket = Path(unix_socket_path)
|
||||
if socket.exists() and access(socket, R_OK):
|
||||
LOGGER.debug("Detected local docker socket")
|
||||
if len(DockerServiceConnection.objects.filter(local=True)) == 0:
|
||||
LOGGER.debug("Created Service Connection for docker")
|
||||
DockerServiceConnection.objects.create(
|
||||
name="Local Docker connection",
|
||||
local=True,
|
||||
url=unix_socket_path,
|
||||
)
|
||||
|
|
|
@ -17,4 +17,9 @@ CELERY_BEAT_SCHEDULE = {
|
|||
"schedule": crontab(minute="*/5"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
},
|
||||
"outpost_local_connection": {
|
||||
"task": "authentik.outposts.tasks.outpost_local_connection",
|
||||
"schedule": crontab(minute="*/60"),
|
||||
"options": {"queue": "authentik_scheduled"},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
"""outpost tasks"""
|
||||
from os import R_OK, access
|
||||
from os.path import expanduser
|
||||
from pathlib import Path
|
||||
from socket import gethostname
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import yaml
|
||||
from asgiref.sync import async_to_sync
|
||||
from channels.layers import get_channel_layer
|
||||
from django.core.cache import cache
|
||||
from django.db.models.base import Model
|
||||
from django.utils.text import slugify
|
||||
from docker.constants import DEFAULT_UNIX_SOCKET
|
||||
from kubernetes.config.incluster_config import SERVICE_TOKEN_FILENAME
|
||||
from kubernetes.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.events.monitored_tasks import MonitoredTask, TaskResult, TaskResultStatus
|
||||
|
@ -185,3 +194,42 @@ def _outpost_single_update(outpost: Outpost, layer=None):
|
|||
for state in OutpostState.for_outpost(outpost):
|
||||
LOGGER.debug("sending update", channel=state.uid, outpost=outpost)
|
||||
async_to_sync(layer.send)(state.uid, {"type": "event.update"})
|
||||
|
||||
|
||||
@CELERY_APP.task()
|
||||
def outpost_local_connection():
|
||||
"""Checks the local environment and create Service connections."""
|
||||
# Explicitly check against token filename, as thats
|
||||
# only present when the integration is enabled
|
||||
if Path(SERVICE_TOKEN_FILENAME).exists():
|
||||
LOGGER.debug("Detected in-cluster Kubernetes Config")
|
||||
if not KubernetesServiceConnection.objects.filter(local=True).exists():
|
||||
LOGGER.debug("Created Service Connection for in-cluster")
|
||||
KubernetesServiceConnection.objects.create(
|
||||
name="Local Kubernetes Cluster", local=True, kubeconfig={}
|
||||
)
|
||||
# For development, check for the existence of a kubeconfig file
|
||||
kubeconfig_path = expanduser(KUBE_CONFIG_DEFAULT_LOCATION)
|
||||
if Path(kubeconfig_path).exists():
|
||||
LOGGER.debug("Detected kubeconfig")
|
||||
kubeconfig_local_name = f"k8s-{gethostname()}"
|
||||
if not KubernetesServiceConnection.objects.filter(
|
||||
name=kubeconfig_local_name
|
||||
).exists():
|
||||
LOGGER.debug("Creating kubeconfig Service Connection")
|
||||
with open(kubeconfig_path, "r") as _kubeconfig:
|
||||
KubernetesServiceConnection.objects.create(
|
||||
name=kubeconfig_local_name,
|
||||
kubeconfig=yaml.safe_load(_kubeconfig),
|
||||
)
|
||||
unix_socket_path = urlparse(DEFAULT_UNIX_SOCKET).path
|
||||
socket = Path(unix_socket_path)
|
||||
if socket.exists() and access(socket, R_OK):
|
||||
LOGGER.debug("Detected local docker socket")
|
||||
if len(DockerServiceConnection.objects.filter(local=True)) == 0:
|
||||
LOGGER.debug("Created Service Connection for docker")
|
||||
DockerServiceConnection.objects.create(
|
||||
name="Local Docker connection",
|
||||
local=True,
|
||||
url=unix_socket_path,
|
||||
)
|
||||
|
|
|
@ -13,13 +13,13 @@ from selenium.webdriver.common.by import By
|
|||
from authentik import __version__
|
||||
from authentik.core.models import Application
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||
from authentik.outposts.models import (
|
||||
DockerServiceConnection,
|
||||
Outpost,
|
||||
OutpostConfig,
|
||||
OutpostType,
|
||||
)
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
from tests.e2e.utils import SeleniumTestCase, apply_migration, object_manager, retry
|
||||
|
||||
|
@ -117,7 +117,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase):
|
|||
@object_manager
|
||||
def test_proxy_connectivity(self):
|
||||
"""Test proxy connectivity over websocket"""
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
outpost_local_connection()
|
||||
proxy: ProxyProvider = ProxyProvider.objects.create(
|
||||
name="proxy_provider",
|
||||
authorization_flow=Flow.objects.get(
|
||||
|
|
|
@ -12,9 +12,9 @@ from docker.types.healthcheck import Healthcheck
|
|||
from authentik import __version__
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||
from authentik.outposts.controllers.docker import DockerController
|
||||
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostType
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ class OutpostDockerTests(TestCase):
|
|||
self.ssl_folder = mkdtemp()
|
||||
self.container = self._start_container(self.ssl_folder)
|
||||
# Ensure that local connection have been created
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
outpost_local_connection()
|
||||
self.provider: ProxyProvider = ProxyProvider.objects.create(
|
||||
name="test",
|
||||
internal_host="http://localhost",
|
||||
|
|
|
@ -3,11 +3,11 @@ from django.test import TestCase
|
|||
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||
from authentik.outposts.controllers.k8s.base import NeedsUpdate
|
||||
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
|
||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
||||
from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
|
||||
|
||||
|
@ -17,7 +17,7 @@ class OutpostKubernetesTests(TestCase):
|
|||
def setUp(self):
|
||||
super().setUp()
|
||||
# Ensure that local connection have been created
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
outpost_local_connection()
|
||||
self.provider: ProxyProvider = ProxyProvider.objects.create(
|
||||
name="test",
|
||||
internal_host="http://localhost",
|
||||
|
|
|
@ -12,8 +12,8 @@ from docker.types.healthcheck import Healthcheck
|
|||
from authentik import __version__
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostType
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.controllers.docker import DockerController
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
|
||||
|
@ -53,7 +53,7 @@ class TestProxyDocker(TestCase):
|
|||
self.ssl_folder = mkdtemp()
|
||||
self.container = self._start_container(self.ssl_folder)
|
||||
# Ensure that local connection have been created
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
outpost_local_connection()
|
||||
self.provider: ProxyProvider = ProxyProvider.objects.create(
|
||||
name="test",
|
||||
internal_host="http://localhost",
|
||||
|
|
|
@ -3,8 +3,8 @@ import yaml
|
|||
from django.test import TestCase
|
||||
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.outposts.apps import AuthentikOutpostConfig
|
||||
from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType
|
||||
from authentik.outposts.tasks import outpost_local_connection
|
||||
from authentik.providers.proxy.controllers.kubernetes import ProxyKubernetesController
|
||||
from authentik.providers.proxy.models import ProxyProvider
|
||||
|
||||
|
@ -14,7 +14,7 @@ class TestProxyKubernetes(TestCase):
|
|||
|
||||
def setUp(self):
|
||||
# Ensure that local connection have been created
|
||||
AuthentikOutpostConfig.init_local_connection()
|
||||
outpost_local_connection()
|
||||
|
||||
def test_kubernetes_controller_static(self):
|
||||
"""Test Kubernetes Controller"""
|
||||
|
|
Reference in New Issue