outposts: Enhance config options for k8s outposts (#7363)

* Allow specifying the service's ipFamilyPolicy and ipFamilies

* Add documentation

* Only create k8s TLS Ingress config if secretName is set

* Fix linter issues.

* Fix wrong attributes

* Remove IP family configuration option

This shall rather be configured using `kubernetes_json_patch` introduced with https://github.com/goauthentik/authentik/pull/6319

* Add test for k8s service reconciler

* Fix linter issues
This commit is contained in:
Philipp Kolberg
2024-03-15 18:23:12 +01:00
committed by GitHub
parent 09e6b80fd6
commit 61b61ce960
5 changed files with 49 additions and 9 deletions

View File

@ -33,6 +33,8 @@ class ServiceReconciler(KubernetesObjectReconciler[V1Service]):
# priority than being updated. # priority than being updated.
if current.spec.selector != reference.spec.selector: if current.spec.selector != reference.spec.selector:
raise NeedsUpdate() raise NeedsUpdate()
if current.spec.type != reference.spec.type:
raise NeedsUpdate()
super().reconcile(current, reference) super().reconcile(current, reference)
def get_reference_object(self) -> V1Service: def get_reference_object(self) -> V1Service:

View File

@ -56,7 +56,10 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
proxy_provider: ProxyProvider proxy_provider: ProxyProvider
external_host_name = urlparse(proxy_provider.external_host) external_host_name = urlparse(proxy_provider.external_host)
expected_hosts.append(external_host_name.hostname) expected_hosts.append(external_host_name.hostname)
if external_host_name.scheme == "https": if (
external_host_name.scheme == "https"
and self.controller.outpost.config.kubernetes_ingress_secret_name
):
expected_hosts_tls.append(external_host_name.hostname) expected_hosts_tls.append(external_host_name.hostname)
expected_hosts.sort() expected_hosts.sort()
expected_hosts_tls.sort() expected_hosts_tls.sort()
@ -116,7 +119,10 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
): ):
proxy_provider: ProxyProvider proxy_provider: ProxyProvider
external_host_name = urlparse(proxy_provider.external_host) external_host_name = urlparse(proxy_provider.external_host)
if external_host_name.scheme == "https": if (
external_host_name.scheme == "https"
and self.controller.outpost.config.kubernetes_ingress_secret_name
):
tls_hosts.append(external_host_name.hostname) tls_hosts.append(external_host_name.hostname)
if proxy_provider.mode in [ if proxy_provider.mode in [
ProxyMode.FORWARD_SINGLE, ProxyMode.FORWARD_SINGLE,
@ -160,13 +166,15 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
rules.append(rule) rules.append(rule)
tls_config = None tls_config = None
if tls_hosts: if tls_hosts:
tls_config = V1IngressTLS( tls_config = [
hosts=tls_hosts, V1IngressTLS(
secret_name=self.controller.outpost.config.kubernetes_ingress_secret_name, hosts=tls_hosts,
) secret_name=self.controller.outpost.config.kubernetes_ingress_secret_name,
)
]
spec = V1IngressSpec( spec = V1IngressSpec(
rules=rules, rules=rules,
tls=[tls_config], tls=tls_config,
) )
if self.controller.outpost.config.kubernetes_ingress_class_name: if self.controller.outpost.config.kubernetes_ingress_class_name:
spec.ingress_class_name = self.controller.outpost.config.kubernetes_ingress_class_name spec.ingress_class_name = self.controller.outpost.config.kubernetes_ingress_class_name

View File

@ -10,6 +10,7 @@ from kubernetes.client.exceptions import OpenApiException
from authentik.core.tests.utils import create_test_flow from authentik.core.tests.utils import create_test_flow
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
from authentik.outposts.controllers.k8s.service import ServiceReconciler
from authentik.outposts.controllers.k8s.triggers import NeedsUpdate from authentik.outposts.controllers.k8s.triggers import NeedsUpdate
from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType
from authentik.outposts.tasks import outpost_connection_discovery from authentik.outposts.tasks import outpost_connection_discovery
@ -91,6 +92,35 @@ class OutpostKubernetesTests(TestCase):
deployment_reconciler.delete(deployment_reconciler.get_reference_object()) deployment_reconciler.delete(deployment_reconciler.get_reference_object())
@pytest.mark.timeout(120)
def test_service_reconciler(self):
"""test that service requires update"""
controller = ProxyKubernetesController(self.outpost, self.service_connection)
service_reconciler = ServiceReconciler(controller)
self.assertIsNotNone(service_reconciler.retrieve())
config = self.outpost.config
config.kubernetes_service_type = "NodePort"
config.kubernetes_json_patches = {
"service": [
{
"op": "add",
"path": "/spec/ipFamilyPolicy",
"value": "PreferDualStack",
}
]
}
self.outpost.config = config
with self.assertRaises(NeedsUpdate):
service_reconciler.reconcile(
service_reconciler.retrieve(),
service_reconciler.get_reference_object(),
)
service_reconciler.delete(service_reconciler.get_reference_object())
@pytest.mark.timeout(120) @pytest.mark.timeout(120)
def test_controller_rename(self): def test_controller_rename(self):
"""test that objects get deleted and re-created with new names""" """test that objects get deleted and re-created with new names"""

View File

@ -43,7 +43,7 @@ kubernetes_replicas: 1
kubernetes_namespace: authentik kubernetes_namespace: authentik
# Any additional annotations to add to the ingress object, for example cert-manager # Any additional annotations to add to the ingress object, for example cert-manager
kubernetes_ingress_annotations: {} kubernetes_ingress_annotations: {}
# Name of the secret that is used for TLS connections # Name of the secret that is used for TLS connections, leave empty to disable TLS
kubernetes_ingress_secret_name: authentik-outpost-tls kubernetes_ingress_secret_name: authentik-outpost-tls
# Service kind created, can be set to LoadBalancer for LDAP outposts for example # Service kind created, can be set to LoadBalancer for LDAP outposts for example
kubernetes_service_type: ClusterIP kubernetes_service_type: ClusterIP

View File

@ -22,7 +22,7 @@ The following outpost settings are used:
- `kubernetes_replicas`: Replica count for the deployment of the outpost - `kubernetes_replicas`: Replica count for the deployment of the outpost
- `kubernetes_namespace`: Namespace to deploy in, defaults to the same namespace authentik is deployed in (if available) - `kubernetes_namespace`: Namespace to deploy in, defaults to the same namespace authentik is deployed in (if available)
- `kubernetes_ingress_annotations`: Any additional annotations to add to the ingress object, for example cert-manager - `kubernetes_ingress_annotations`: Any additional annotations to add to the ingress object, for example cert-manager
- `kubernetes_ingress_secret_name`: Name of the secret that is used for TLS connections - `kubernetes_ingress_secret_name`: Name of the secret that is used for TLS connections, can be empty to disable TLS config
- `kubernetes_ingress_class_name`: Optionally set the ingress class used for the generated ingress, requires authentik 2022.11.0 - `kubernetes_ingress_class_name`: Optionally set the ingress class used for the generated ingress, requires authentik 2022.11.0
- `kubernetes_service_type`: Service kind created, can be set to LoadBalancer for LDAP outposts for example - `kubernetes_service_type`: Service kind created, can be set to LoadBalancer for LDAP outposts for example
- `kubernetes_disabled_components`: Disable any components of the kubernetes integration, can be any of - `kubernetes_disabled_components`: Disable any components of the kubernetes integration, can be any of