Compare commits
	
		
			10 Commits
		
	
	
		
			reduce-mem
			...
			outposts/f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4e9a466d64 | |||
| 9bd8cfbac0 | |||
| e18c2fe084 | |||
| 205f11532f | |||
| bc6d66cd88 | |||
| 609e9a00b4 | |||
| d5708d22e0 | |||
| 71ac1282f9 | |||
| cf9d8f64a2 | |||
| 1cda01511b | 
| @ -84,6 +84,8 @@ RUN apt-get update && \ | ||||
|     apt-get install -y --no-install-recommends libxmlsec1-openssl libmaxminddb0 && \ | ||||
|     # Required for bootstrap & healtcheck | ||||
|     apt-get install -y --no-install-recommends runit && \ | ||||
|     # Required for outposts | ||||
|     apt-get install -y --no-install-recommends openssh-client && \ | ||||
|     pip install --no-cache-dir -r /requirements.txt && \ | ||||
|     apt-get remove --purge -y build-essential pkg-config libxmlsec1-dev && \ | ||||
|     apt-get autoremove --purge -y && \ | ||||
| @ -91,8 +93,9 @@ RUN apt-get update && \ | ||||
|     rm -rf /tmp/* /var/lib/apt/lists/* /var/tmp/ && \ | ||||
|     adduser --system --no-create-home --uid 1000 --group --home /authentik authentik && \ | ||||
|     mkdir -p /certs /media /blueprints && \ | ||||
|     mkdir -p /authentik/.ssh && \ | ||||
|     chown authentik:authentik /certs /media /authentik/.ssh | ||||
|     chown authentik:authentik /certs /media && \ | ||||
|     chmod g+w /etc/ssh/ssh_config.d/ && \ | ||||
|     chgrp authentik /etc/ssh/ssh_config.d/ | ||||
|  | ||||
| COPY ./authentik/ /authentik | ||||
| COPY ./pyproject.toml / | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| """Docker controller""" | ||||
| from subprocess import SubprocessError  # nosec | ||||
| from time import sleep | ||||
| from typing import Optional | ||||
| from urllib.parse import urlparse | ||||
| @ -9,7 +10,6 @@ from docker import DockerClient as UpstreamDockerClient | ||||
| from docker.errors import DockerException, NotFound | ||||
| from docker.models.containers import Container | ||||
| from docker.utils.utils import kwargs_from_env | ||||
| from paramiko.ssh_exception import SSHException | ||||
| from structlog.stdlib import get_logger | ||||
| from yaml import safe_dump | ||||
|  | ||||
| @ -58,8 +58,9 @@ class DockerClient(UpstreamDockerClient, BaseClient): | ||||
|                 super().__init__( | ||||
|                     base_url=connection.url, | ||||
|                     tls=tls_config, | ||||
|                     use_ssh_client=True, | ||||
|                 ) | ||||
|             except SSHException as exc: | ||||
|             except SubprocessError as exc: | ||||
|                 if self.ssh: | ||||
|                     self.ssh.cleanup() | ||||
|                 raise ServiceConnectionInvalid(exc) from exc | ||||
|  | ||||
| @ -7,8 +7,7 @@ from docker.errors import DockerException | ||||
|  | ||||
| from authentik.crypto.models import CertificateKeyPair | ||||
|  | ||||
| HEADER = "### Managed by authentik" | ||||
| FOOTER = "### End Managed by authentik" | ||||
| SSH_CONFIG_DIR = Path("/etc/ssh/ssh_config.d/") | ||||
|  | ||||
|  | ||||
| def opener(path, flags): | ||||
| @ -28,70 +27,54 @@ class DockerInlineSSH: | ||||
|  | ||||
|     key_path: str | ||||
|     config_path: Path | ||||
|     header: str | ||||
|  | ||||
|     def __init__(self, host: str, keypair: CertificateKeyPair) -> None: | ||||
|         self.host = host | ||||
|         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" | ||||
|             ) | ||||
|         self.config_path = SSH_CONFIG_DIR / Path(self.host + ".conf") | ||||
|         with open(self.config_path, "w", encoding="utf-8") as _config: | ||||
|             if not _config.writable(): | ||||
|                 # 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: | ||||
|             raise DockerException("keypair must be set for SSH connections") | ||||
|         self.header = f"{HEADER} - {self.host}\n" | ||||
|  | ||||
|     def write_config(self, key_path: str) -> bool: | ||||
|     def write_config(self, key_path: str): | ||||
|         """Update the local user's ssh config file""" | ||||
|         with open(self.config_path, "a+", encoding="utf-8") as ssh_config: | ||||
|             if self.header in ssh_config.readlines(): | ||||
|                 return False | ||||
|         with open(self.config_path, "w", encoding="utf-8") as ssh_config: | ||||
|             ssh_config.writelines( | ||||
|                 [ | ||||
|                     self.header, | ||||
|                     f"Host {self.host}\n", | ||||
|                     f"    IdentityFile {key_path}\n", | ||||
|                     f"    IdentityFile {str(key_path)}\n", | ||||
|                     "    StrictHostKeyChecking No\n", | ||||
|                     "    UserKnownHostsFile /dev/null\n", | ||||
|                     f"{FOOTER}\n", | ||||
|                     "\n", | ||||
|                 ] | ||||
|             ) | ||||
|         return True | ||||
|  | ||||
|     def write_key(self): | ||||
|     def write_key(self) -> Path: | ||||
|         """Write keypair's private key to a temporary file""" | ||||
|         path = Path(gettempdir(), f"{self.keypair.pk}_private.pem") | ||||
|         with open(path, "w", encoding="utf8", opener=opener) as _file: | ||||
|             _file.write(self.keypair.key_data) | ||||
|         return str(path) | ||||
|         return path | ||||
|  | ||||
|     def write(self): | ||||
|         """Write keyfile and update ssh config""" | ||||
|         self.key_path = self.write_key() | ||||
|         was_written = self.write_config(self.key_path) | ||||
|         if not was_written: | ||||
|         try: | ||||
|             self.write_config(self.key_path) | ||||
|         except OSError: | ||||
|             self.cleanup() | ||||
|  | ||||
|     def cleanup(self): | ||||
|         """Cleanup when we're done""" | ||||
|         try: | ||||
|             os.unlink(self.key_path) | ||||
|             with open(self.config_path, "r", encoding="utf-8") as ssh_config: | ||||
|                 start = 0 | ||||
|                 end = 0 | ||||
|                 lines = ssh_config.readlines() | ||||
|                 for idx, line in enumerate(lines): | ||||
|                     if line == self.header: | ||||
|                         start = idx | ||||
|                     if start != 0 and line == f"{FOOTER}\n": | ||||
|                         end = idx | ||||
|             with open(self.config_path, "w+", encoding="utf-8") as ssh_config: | ||||
|                 lines = lines[:start] + lines[end + 2 :] | ||||
|                 ssh_config.writelines(lines) | ||||
|             os.unlink(self.config_path) | ||||
|         except OSError: | ||||
|             # If we fail deleting a file it doesn't matter that much | ||||
|             # since we're just in a container | ||||
|  | ||||
| @ -85,7 +85,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio | ||||
|             html`<ak-label color=${item.local ? PFColor.Grey : PFColor.Green}> | ||||
|                 ${item.local ? t`Yes` : t`No`} | ||||
|             </ak-label>`, | ||||
|             html`${itemState.healthy | ||||
|             html`${itemState?.healthy | ||||
|                 ? html`<ak-label color=${PFColor.Green}>${ifDefined(itemState.version)}</ak-label>` | ||||
|                 : html`<ak-label color=${PFColor.Red}>${t`Unhealthy`}</ak-label>`}`, | ||||
|             html` <ak-forms-modal> | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	