Skip to content

RFC: Simple built-in SSH server

Lorenz Brun requested to merge lorenz/gitlab-shell:master into main

This implements a minimalist built-in SSH server, entirely dropping calling external binaries and similar things. It tries to touch the least amount of code outside of the very small server (~200 LOC) to make it work. As such it runs perfectly fine in a simple distroless/static base container containing nothing but CA certificates and stuff like tzdata making it very easy to maintain and secure.

It's intended for use in containers, takes all configuration from environment variables and logs to stdout/stderr (and doesn't need/touch any other files besides mounted-in secrets).

AFAIK it supports all operations GitLab needs including SSH certificate support. This has been running here for some time without any obvious problems.

This is marked RFC as it's currently very K8s-centric with host key / SSH authority paths hardcoded and environment-only configuration.

Before

sequenceDiagram
    participant Git on client
    participant SSH server
    participant AuthorizedKeysCommand
    participant GitLab Shell
    participant Rails
    participant Gitaly
    participant Git on server

    Note left of Git on client: git fetch
    Git on client->>+SSH server: ssh git fetch-pack request
    SSH server->>+AuthorizedKeysCommand: gitlab-shell-authorized-keys-check git AAAA...
    AuthorizedKeysCommand->>+Rails: GET /internal/api/authorized_keys?key=AAAA...
    Note right of Rails: Lookup key ID
    Rails-->>-AuthorizedKeysCommand: 200 OK, command="gitlab-shell upload-pack key_id=1"
    AuthorizedKeysCommand-->>-SSH server: command="gitlab-shell upload-pack key_id=1"
    SSH server->>+GitLab Shell: gitlab-shell upload-pack key_id=1
    GitLab Shell->>+Rails: GET /internal/api/allowed?action=upload_pack&key_id=1
    Note right of Rails: Auth check
    Rails-->>-GitLab Shell: 200 OK, { gitaly: ... }
    GitLab Shell->>+Gitaly: SSHService.SSHUploadPack request
    Gitaly->>+Git on server: git upload-pack request
    Note over Git on client,Git on server: Bidirectional communication between Git client and server
    Git on server-->>-Gitaly: git upload-pack response
    Gitaly -->>-GitLab Shell: SSHService.SSHUploadPack response
    GitLab Shell-->>-SSH server: gitlab-shell upload-pack response
    SSH server-->>-Git on client: ssh git fetch-pack response

After

sequenceDiagram
    participant Git on client
    participant GitLab SSHD
    participant Rails
    participant Gitaly
    participant Git on server

    Note left of Git on client: git fetch
    Git on client->>+GitLab SSHD: ssh git fetch-pack request
    GitLab SSHD->>+Rails: GET /internal/api/authorized_keys?key=AAAA...
    Note right of Rails: Lookup key ID
    Rails-->>-GitLab SSHD: 200 OK, command="gitlab-shell upload-pack key_id=1"
    GitLab SSHD->>+Rails: GET /internal/api/allowed?action=upload_pack&key_id=1
    Note right of Rails: Auth check
    Rails-->>-GitLab SSHD: 200 OK, { gitaly: ... }
    GitLab SSHD->>+Gitaly: SSHService.SSHUploadPack request
    Gitaly->>+Git on server: git upload-pack request
    Note over Git on client,Git on server: Bidirectional communication between Git client and server
    Git on server-->>-Gitaly: git upload-pack response
    Gitaly -->>-GitLab SSHD: SSHService.SSHUploadPack response
    GitLab SSHD-->>-Git on client: ssh git fetch-pack response

Closes #165 (closed)

Edited by Nick Thomas

Merge request reports