Compare commits

1 Commits

Author SHA1 Message Date
15ea503d2e fix build
All checks were successful
Build and push image / build-containers (push) Successful in 1m51s
2025-07-23 09:40:29 +02:00
3 changed files with 1 additions and 109 deletions

View File

@ -16,7 +16,7 @@ FROM node:lts-alpine AS frontend-build
WORKDIR /app WORKDIR /app
COPY packages/sshecret-frontend/ . COPY packages/sshecret-frontend/ .
RUN npm install RUN npm install
RUN npm build RUN npm run build
FROM python:3.13-slim-bookworm FROM python:3.13-slim-bookworm

View File

@ -1,106 +0,0 @@
"""SFTP Server."""
from collections.abc import AsyncIterator
from typing import cast, override
from pathlib import Path
import asyncssh
from sshecret.backend.api import SshecretBackend
from sshecret.backend.models import Client
READ_ONLY = asyncssh.FXF_READ
def get_connection(channel: asyncssh.SSHServerChannel[bytes]) -> asyncssh.SSHServerConnection:
"""Get the connection."""
conn = channel.get_extra_info("connection")
assert conn is not None
return cast(asyncssh.SSHServerConnection, conn)
def get_backend(connection: asyncssh.SSHServerConnection) -> SshecretBackend:
"""Get backend from connection."""
backend = connection.get_extra_info("backend")
assert backend is not None
return cast(SshecretBackend, backend)
def get_client(connection: asyncssh.SSHServerConnection) -> Client:
"""Get client."""
client = connection.get_extra_info("client")
assert client is not None
return cast(Client, client)
class SshecretFileServer(asyncssh.SFTPServer):
"""File server."""
@override
def __init__(self, chan: asyncssh.SSHServerChannel[bytes], chroot: bytes | None = None):
"""Initialize sftp server."""
super().__init__(chan, "/".encode())
self._conn: asyncssh.SSHServerConnection = get_connection(chan)
self.backend: SshecretBackend = get_backend(self._conn)
self.logger.info("Connected")
@property
def client(self) -> Client:
"""Get client."""
return get_client(self._conn)
@override
async def scandir(self, path: bytes) -> AsyncIterator[asyncssh.SFTPName]:
"""List secrets as files."""
for secret in self.client.secrets:
sftp_name = asyncssh.SFTPName(secret.encode(), READ_ONLY)
self.format_longname(sftp_name)
yield sftp_name
@override
def format_longname(self, name: asyncssh.SFTPName) -> None:
mode = "-r--------"
user = self.client.name
group = "sshecret_clients"
size = ''
modtime = ''
nlink = ''
detail = (
f'{mode:10s} {nlink:>4s} {user:8s} {group:8s} '
f'{size:>8s} {modtime:12s} '
)
name.longname = detail.encode('utf-8') + cast(bytes, name.filename)
@override
def format_user(self, uid: int | None) -> str:
return self.client.name
@override
def format_group(self, gid: int | None) -> str:
return "clients"
@override
async def open(self, path: bytes, pflags: int, attrs: asyncssh.SFTPAttrs) -> object:
"""Open file.
This is the tricky bit. We need to disallow writes, and we need to serve
an encrypted secret as a file.
"""
if pflags != READ_ONLY:
raise asyncssh.SFTPError(asyncssh.FX_WRITE_PROTECT, "Read write not supported")
filepath = path.decode()
secret_name = Path(filepath).name
if secret_name not in self.client.secrets:
raise asyncssh.SFTPError(asyncssh.FX_NO_SUCH_FILE, "No such secret")
secret = await self.backend.get_client_secret(("id", str(self.client.id)), secret_name)
if not secret:
raise asyncssh.SFTPError(asyncssh.FX_NO_SUCH_FILE, "No such secret")
# io.BytesIO
@override
async def close(self, file_obj: object) -> None:
"""Close the file object."""

View File

@ -16,7 +16,6 @@ from sshecret_sshd.commands import dispatch_command
from sshecret.backend import SshecretBackend, Client, Operation, SubSystem from sshecret.backend import SshecretBackend, Client, Operation, SubSystem
from .settings import ServerSettings, ClientRegistrationSettings from .settings import ServerSettings, ClientRegistrationSettings
from .sftp_server import SshecretFileServer
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -223,7 +222,6 @@ async def run_ssh_server(
port, port,
server_host_keys=keys, server_host_keys=keys,
process_factory=dispatch_command, process_factory=dispatch_command,
sftp_factory=SshecretFileServer,
) )
return server return server