outposts: include protocol in outpost deployment ports

This commit is contained in:
Jens Langhammer 2020-12-28 17:18:01 +01:00
parent 1a292feebb
commit 22ce142cb8
9 changed files with 55 additions and 25 deletions

View file

@ -1,5 +1,5 @@
"""Base Controller""" """Base Controller"""
from typing import Dict, List from dataclasses import dataclass
from structlog import get_logger from structlog import get_logger
from structlog.testing import capture_logs from structlog.testing import capture_logs
@ -7,15 +7,26 @@ from structlog.testing import capture_logs
from authentik.lib.sentry import SentryIgnoredException from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.models import Outpost, OutpostServiceConnection from authentik.outposts.models import Outpost, OutpostServiceConnection
FIELD_MANAGER = "goauthentik.io"
class ControllerException(SentryIgnoredException): class ControllerException(SentryIgnoredException):
"""Exception raised when anything fails during controller run""" """Exception raised when anything fails during controller run"""
@dataclass
class DeploymentPort:
"""Info about deployment's single port."""
port: int
name: str
protocol: str
class BaseController: class BaseController:
"""Base Outpost deployment controller""" """Base Outpost deployment controller"""
deployment_ports: Dict[str, int] deployment_ports: list[DeploymentPort]
outpost: Outpost outpost: Outpost
connection: OutpostServiceConnection connection: OutpostServiceConnection
@ -24,14 +35,14 @@ class BaseController:
self.outpost = outpost self.outpost = outpost
self.connection = connection self.connection = connection
self.logger = get_logger() self.logger = get_logger()
self.deployment_ports = {} self.deployment_ports = []
# pylint: disable=invalid-name # pylint: disable=invalid-name
def up(self): def up(self):
"""Called by scheduled task to reconcile deployment/service/etc""" """Called by scheduled task to reconcile deployment/service/etc"""
raise NotImplementedError raise NotImplementedError
def up_with_logs(self) -> List[str]: def up_with_logs(self) -> list[str]:
"""Call .up() but capture all log output and return it.""" """Call .up() but capture all log output and return it."""
with capture_logs() as logs: with capture_logs() as logs:
self.up() self.up()

View file

@ -68,7 +68,10 @@ class DockerController(BaseController):
"image": image_name, "image": image_name,
"name": f"authentik-proxy-{self.outpost.uuid.hex}", "name": f"authentik-proxy-{self.outpost.uuid.hex}",
"detach": True, "detach": True,
"ports": {x: x for _, x in self.deployment_ports.items()}, "ports": {
f"{port.port}/{port.protocol.lower()}": port.port
for port in self.deployment_ports
},
"environment": self._get_env(), "environment": self._get_env(),
"labels": self._get_labels(), "labels": self._get_labels(),
} }
@ -139,7 +142,10 @@ class DockerController(BaseController):
def get_static_deployment(self) -> str: def get_static_deployment(self) -> str:
"""Generate docker-compose yaml for proxy, version 3.5""" """Generate docker-compose yaml for proxy, version 3.5"""
ports = [f"{x}:{x}" for _, x in self.deployment_ports.items()] ports = [
f"{port.port}:{port.port}/{port.protocol.lower()}"
for port in self.deployment_ports
]
image_prefix = CONFIG.y("outposts.docker_image_base") image_prefix = CONFIG.y("outposts.docker_image_base")
compose = { compose = {
"version": "3.5", "version": "3.5",

View file

@ -18,11 +18,11 @@ from kubernetes.client import (
from authentik import __version__ from authentik import __version__
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import ( from authentik.outposts.controllers.k8s.base import (
KubernetesObjectReconciler, KubernetesObjectReconciler,
NeedsUpdate, NeedsUpdate,
) )
from authentik.outposts.controllers.kubernetes import FIELD_MANAGER
from authentik.outposts.models import Outpost from authentik.outposts.models import Outpost
if TYPE_CHECKING: if TYPE_CHECKING:
@ -65,8 +65,14 @@ class DeploymentReconciler(KubernetesObjectReconciler[V1Deployment]):
"""Get deployment object for outpost""" """Get deployment object for outpost"""
# Generate V1ContainerPort objects # Generate V1ContainerPort objects
container_ports = [] container_ports = []
for port_name, port in self.controller.deployment_ports.items(): for port in self.controller.deployment_ports:
container_ports.append(V1ContainerPort(container_port=port, name=port_name)) container_ports.append(
V1ContainerPort(
container_port=port.port,
name=port.name,
protocol=port.protocol.upper(),
)
)
meta = self.get_object_meta(name=self.name) meta = self.get_object_meta(name=self.name)
secret_name = f"authentik-outpost-{self.controller.outpost.uuid.hex}-api" secret_name = f"authentik-outpost-{self.controller.outpost.uuid.hex}-api"
image_prefix = CONFIG.y("outposts.docker_image_base") image_prefix = CONFIG.y("outposts.docker_image_base")

View file

@ -4,11 +4,11 @@ from typing import TYPE_CHECKING
from kubernetes.client import CoreV1Api, V1Secret from kubernetes.client import CoreV1Api, V1Secret
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import ( from authentik.outposts.controllers.k8s.base import (
KubernetesObjectReconciler, KubernetesObjectReconciler,
NeedsUpdate, NeedsUpdate,
) )
from authentik.outposts.controllers.kubernetes import FIELD_MANAGER
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.controllers.kubernetes import KubernetesController

View file

@ -3,12 +3,12 @@ from typing import TYPE_CHECKING
from kubernetes.client import CoreV1Api, V1Service, V1ServicePort, V1ServiceSpec from kubernetes.client import CoreV1Api, V1Service, V1ServicePort, V1ServiceSpec
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import ( from authentik.outposts.controllers.k8s.base import (
KubernetesObjectReconciler, KubernetesObjectReconciler,
NeedsUpdate, NeedsUpdate,
) )
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.kubernetes import FIELD_MANAGER
if TYPE_CHECKING: if TYPE_CHECKING:
from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.controllers.kubernetes import KubernetesController
@ -37,8 +37,15 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]):
"""Get deployment object for outpost""" """Get deployment object for outpost"""
meta = self.get_object_meta(name=self.name) meta = self.get_object_meta(name=self.name)
ports = [] ports = []
for port_name, port in self.controller.deployment_ports.items(): for port in self.controller.deployment_ports:
ports.append(V1ServicePort(name=port_name, port=port)) ports.append(
V1ServicePort(
name=port.name,
port=port.port,
protocol=port.protocol.upper(),
target_port=port.port,
)
)
selector_labels = DeploymentReconciler(self.controller).get_pod_meta() selector_labels = DeploymentReconciler(self.controller).get_pod_meta()
return V1Service( return V1Service(
metadata=meta, metadata=meta,

View file

@ -14,8 +14,6 @@ from authentik.outposts.controllers.k8s.secret import SecretReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler from authentik.outposts.controllers.k8s.service import ServiceReconciler
from authentik.outposts.models import KubernetesServiceConnection, Outpost from authentik.outposts.models import KubernetesServiceConnection, Outpost
FIELD_MANAGER = "goauthentik.io"
class KubernetesController(BaseController): class KubernetesController(BaseController):
"""Manage deployment of outpost in kubernetes""" """Manage deployment of outpost in kubernetes"""

View file

@ -2,6 +2,7 @@
from typing import Dict from typing import Dict
from urllib.parse import urlparse from urllib.parse import urlparse
from authentik.outposts.controllers.base import DeploymentPort
from authentik.outposts.controllers.docker import DockerController from authentik.outposts.controllers.docker import DockerController
from authentik.outposts.models import DockerServiceConnection, Outpost from authentik.outposts.models import DockerServiceConnection, Outpost
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
@ -12,10 +13,10 @@ class ProxyDockerController(DockerController):
def __init__(self, outpost: Outpost, connection: DockerServiceConnection): def __init__(self, outpost: Outpost, connection: DockerServiceConnection):
super().__init__(outpost, connection) super().__init__(outpost, connection)
self.deployment_ports = { self.deployment_ports = [
"http": 4180, DeploymentPort(4180, "http", "tcp"),
"https": 4443, DeploymentPort(4443, "https", "tcp"),
} ]
def _get_labels(self) -> Dict[str, str]: def _get_labels(self) -> Dict[str, str]:
hosts = [] hosts = []

View file

@ -15,11 +15,11 @@ from kubernetes.client.models.networking_v1beta1_ingress_rule import (
NetworkingV1beta1IngressRule, NetworkingV1beta1IngressRule,
) )
from authentik.outposts.controllers.base import FIELD_MANAGER
from authentik.outposts.controllers.k8s.base import ( from authentik.outposts.controllers.k8s.base import (
KubernetesObjectReconciler, KubernetesObjectReconciler,
NeedsUpdate, NeedsUpdate,
) )
from authentik.outposts.controllers.kubernetes import FIELD_MANAGER
from authentik.providers.proxy.models import ProxyProvider from authentik.providers.proxy.models import ProxyProvider
if TYPE_CHECKING: if TYPE_CHECKING:
@ -106,7 +106,7 @@ class IngressReconciler(KubernetesObjectReconciler[NetworkingV1beta1Ingress]):
NetworkingV1beta1HTTPIngressPath( NetworkingV1beta1HTTPIngressPath(
backend=NetworkingV1beta1IngressBackend( backend=NetworkingV1beta1IngressBackend(
service_name=self.name, service_name=self.name,
service_port=self.controller.deployment_ports["http"], service_port="http",
), ),
path="/", path="/",
) )

View file

@ -1,4 +1,5 @@
"""Proxy Provider Kubernetes Contoller""" """Proxy Provider Kubernetes Contoller"""
from authentik.outposts.controllers.base import DeploymentPort
from authentik.outposts.controllers.kubernetes import KubernetesController from authentik.outposts.controllers.kubernetes import KubernetesController
from authentik.outposts.models import KubernetesServiceConnection, Outpost from authentik.outposts.models import KubernetesServiceConnection, Outpost
from authentik.providers.proxy.controllers.k8s.ingress import IngressReconciler from authentik.providers.proxy.controllers.k8s.ingress import IngressReconciler
@ -9,9 +10,9 @@ class ProxyKubernetesController(KubernetesController):
def __init__(self, outpost: Outpost, connection: KubernetesServiceConnection): def __init__(self, outpost: Outpost, connection: KubernetesServiceConnection):
super().__init__(outpost, connection) super().__init__(outpost, connection)
self.deployment_ports = { self.deployment_ports = [
"http": 4180, DeploymentPort(4180, "http", "tcp"),
"https": 4443, DeploymentPort(4443, "https", "tcp"),
} ]
self.reconcilers["ingress"] = IngressReconciler self.reconcilers["ingress"] = IngressReconciler
self.reconcile_order.append("ingress") self.reconcile_order.append("ingress")