outposts: allow externally managed SSH Config for outposts (#2917)
This commit is contained in:
parent
d9d42020cc
commit
2dee8034d3
|
@ -15,7 +15,7 @@ from yaml import safe_dump
|
||||||
|
|
||||||
from authentik import __version__
|
from authentik import __version__
|
||||||
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
|
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
|
||||||
from authentik.outposts.docker_ssh import DockerInlineSSH
|
from authentik.outposts.docker_ssh import DockerInlineSSH, SSHManagedExternallyException
|
||||||
from authentik.outposts.docker_tls import DockerInlineTLS
|
from authentik.outposts.docker_tls import DockerInlineTLS
|
||||||
from authentik.outposts.managed import MANAGED_OUTPOST
|
from authentik.outposts.managed import MANAGED_OUTPOST
|
||||||
from authentik.outposts.models import (
|
from authentik.outposts.models import (
|
||||||
|
@ -35,6 +35,7 @@ class DockerClient(UpstreamDockerClient, BaseClient):
|
||||||
def __init__(self, connection: DockerServiceConnection):
|
def __init__(self, connection: DockerServiceConnection):
|
||||||
self.tls = None
|
self.tls = None
|
||||||
self.ssh = None
|
self.ssh = None
|
||||||
|
self.logger = get_logger()
|
||||||
if connection.local:
|
if connection.local:
|
||||||
# Same result as DockerClient.from_env
|
# Same result as DockerClient.from_env
|
||||||
super().__init__(**kwargs_from_env())
|
super().__init__(**kwargs_from_env())
|
||||||
|
@ -42,8 +43,12 @@ class DockerClient(UpstreamDockerClient, BaseClient):
|
||||||
parsed_url = urlparse(connection.url)
|
parsed_url = urlparse(connection.url)
|
||||||
tls_config = False
|
tls_config = False
|
||||||
if parsed_url.scheme == "ssh":
|
if parsed_url.scheme == "ssh":
|
||||||
self.ssh = DockerInlineSSH(parsed_url.hostname, connection.tls_authentication)
|
try:
|
||||||
self.ssh.write()
|
self.ssh = DockerInlineSSH(parsed_url.hostname, connection.tls_authentication)
|
||||||
|
self.ssh.write()
|
||||||
|
except SSHManagedExternallyException as exc:
|
||||||
|
# SSH config is managed externally
|
||||||
|
self.logger.info(f"SSH Managed externally: {exc}")
|
||||||
else:
|
else:
|
||||||
self.tls = DockerInlineTLS(
|
self.tls = DockerInlineTLS(
|
||||||
verification_kp=connection.tls_verification,
|
verification_kp=connection.tls_verification,
|
||||||
|
@ -57,7 +62,6 @@ class DockerClient(UpstreamDockerClient, BaseClient):
|
||||||
)
|
)
|
||||||
except SSHException as exc:
|
except SSHException as exc:
|
||||||
raise ServiceConnectionInvalid from exc
|
raise ServiceConnectionInvalid from exc
|
||||||
self.logger = get_logger()
|
|
||||||
# Ensure the client actually works
|
# Ensure the client actually works
|
||||||
self.containers.list()
|
self.containers.list()
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@ def opener(path, flags):
|
||||||
return os.open(path, flags, 0o700)
|
return os.open(path, flags, 0o700)
|
||||||
|
|
||||||
|
|
||||||
|
class SSHManagedExternallyException(DockerException):
|
||||||
|
"""Raised when the ssh config file is managed externally."""
|
||||||
|
|
||||||
|
|
||||||
class DockerInlineSSH:
|
class DockerInlineSSH:
|
||||||
"""Create paramiko ssh config from CertificateKeyPair"""
|
"""Create paramiko ssh config from CertificateKeyPair"""
|
||||||
|
|
||||||
|
@ -29,9 +33,15 @@ class DockerInlineSSH:
|
||||||
def __init__(self, host: str, keypair: CertificateKeyPair) -> None:
|
def __init__(self, host: str, keypair: CertificateKeyPair) -> None:
|
||||||
self.host = host
|
self.host = host
|
||||||
self.keypair = keypair
|
self.keypair = keypair
|
||||||
|
self.config_path = Path("~/.ssh/config").expanduser()
|
||||||
|
if self.config_path.exists() and HEADER not in self.config_path.read_text(encoding="utf-8"):
|
||||||
|
# SSH Config file already exists and there's no header from us, meaning that it's
|
||||||
|
# been externally mapped into the container for more complex configs
|
||||||
|
raise SSHManagedExternallyException(
|
||||||
|
"SSH Config exists and does not contain authentik header"
|
||||||
|
)
|
||||||
if not self.keypair:
|
if not self.keypair:
|
||||||
raise DockerException("keypair must be set for SSH connections")
|
raise DockerException("keypair must be set for SSH connections")
|
||||||
self.config_path = Path("~/.ssh/config").expanduser()
|
|
||||||
self.header = f"{HEADER} - {self.host}\n"
|
self.header = f"{HEADER} - {self.host}\n"
|
||||||
|
|
||||||
def write_config(self, key_path: str) -> bool:
|
def write_config(self, key_path: str) -> bool:
|
||||||
|
|
Reference in New Issue