summaryrefslogtreecommitdiff
path: root/doc/development/gitlab_shell
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/gitlab_shell')
-rw-r--r--doc/development/gitlab_shell/features.md89
-rw-r--r--doc/development/gitlab_shell/gitlab_sshd.md36
-rw-r--r--doc/development/gitlab_shell/index.md222
-rw-r--r--doc/development/gitlab_shell/process.md71
4 files changed, 418 insertions, 0 deletions
diff --git a/doc/development/gitlab_shell/features.md b/doc/development/gitlab_shell/features.md
new file mode 100644
index 00000000000..f7931c4b94d
--- /dev/null
+++ b/doc/development/gitlab_shell/features.md
@@ -0,0 +1,89 @@
+---
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# GitLab Shell feature list
+
+## Discover
+
+Allows users to identify themselves on an instance via SSH. The command helps to
+confirm quickly whether a user has SSH access to the instance:
+
+```shell
+ssh git@<hostname>
+
+PTY allocation request failed on channel 0
+Welcome to GitLab, @username!
+Connection to staging.gitlab.com closed.
+```
+
+When permission is denied, it returns:
+
+```shell
+ssh git@<hostname>
+git@<hostname>: Permission denied (publickey).
+```
+
+## Git operations
+
+GitLab Shell provides support for Git operations over SSH by processing
+`git-upload-pack`, `git-receive-pack` and `git-upload-archive` SSH commands.
+It limits the set of commands to predefined Git commands:
+
+- `git archive`
+- `git clone`
+- `git pull`
+- `git push`
+
+## Generate new 2FA recovery codes
+
+Enables users to
+[generate new 2FA recovery codes](../../user/profile/account/two_factor_authentication.md#generate-new-recovery-codes-using-ssh):
+
+```shell
+$ ssh git@<hostname> 2fa_recovery_codes
+
+Are you sure you want to generate new two-factor recovery codes?
+Any existing recovery codes you saved will be invalidated. (yes/no)
+yes
+
+Your two-factor authentication recovery codes are:
+...
+```
+
+## Verify 2FA OTP
+
+Allows users to verify their
+[2FA one-time password (OTP)](../../security/two_factor_authentication.md#2fa-for-git-over-ssh-operations):
+
+```shell
+$ ssh git@<hostname> 2fa_verify
+
+OTP: 347419
+
+OTP validation failed.
+```
+
+## LFS authentication
+
+Enables users to generate credentials for LFS authentication:
+
+```shell
+$ ssh git@<hostname> git-lfs-authenticate <project-path> <upload/download>
+
+{"header":{"Authorization":"Basic ..."},"href":"https://gitlab.com/user/project.git/info/lfs","expires_in":7200}
+```
+
+## Personal access token
+
+Enables users to use personal access tokens via SSH:
+
+```shell
+$ ssh git@<hostname> personal_access_token <name> <scope1[,scope2,...]> [ttl_days]
+
+Token: glpat-...
+Scopes: api
+Expires: 2022-02-05
+```
diff --git a/doc/development/gitlab_shell/gitlab_sshd.md b/doc/development/gitlab_shell/gitlab_sshd.md
new file mode 100644
index 00000000000..4c2cd6396c1
--- /dev/null
+++ b/doc/development/gitlab_shell/gitlab_sshd.md
@@ -0,0 +1,36 @@
+---
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# `gitlab-sshd` in GitLab Shell
+
+`gitlab-sshd` is a binary in [`gitlab-shell`](https://gitlab.com/gitlab-org/gitlab-shell)
+which runs as a persistent SSH daemon. It is intended to replace `OpenSSH` on GitLab SaaS,
+and eventually other cloud-native environments. Instead of running an `sshd` process,
+we run a `gitlab-sshd` process that does the same job, in a more focused manner:
+
+```mermaid
+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
+```
diff --git a/doc/development/gitlab_shell/index.md b/doc/development/gitlab_shell/index.md
new file mode 100644
index 00000000000..7f2c113fa0c
--- /dev/null
+++ b/doc/development/gitlab_shell/index.md
@@ -0,0 +1,222 @@
+---
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab Shell
+
+[![pipeline status](https://gitlab.com/gitlab-org/gitlab-shell/badges/main/pipeline.svg)](https://gitlab.com/gitlab-org/gitlab-shell/-/pipelines?ref=main) [![coverage report](https://gitlab.com/gitlab-org/gitlab-shell/badges/main/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-shell/-/pipelines?ref=main) [![Code Climate](https://codeclimate.com/github/gitlabhq/gitlab-shell.svg)](https://codeclimate.com/github/gitlabhq/gitlab-shell)
+
+GitLab Shell handles Git SSH sessions for GitLab and modifies the list of authorized keys.
+GitLab Shell is not a Unix shell nor a replacement for Bash or Zsh.
+
+GitLab supports Git LFS authentication through SSH.
+
+## Requirements
+
+GitLab Shell is written in Go, and needs a Go compiler to build. It still requires
+Ruby to build and test, but not to run.
+
+GitLab Shell runs on `port 22` on an Omnibus installation. To use a regular SSH
+service, configure it on an alternative port.
+
+Download and install the current version of Go from [golang.org](https://golang.org/dl/).
+We follow the [Golang Release Policy](https://golang.org/doc/devel/release.html#policy)
+and support:
+
+- The current stable version.
+- The previous two major versions.
+
+## How GitLab Shell works
+
+When you access the GitLab server over SSH, GitLab Shell then:
+
+1. Limits you to predefined Git commands (`git push`, `git pull`, `git fetch`).
+1. Calls the GitLab Rails API to check if you are authorized, and what Gitaly server your repository is on.
+1. Copies data back and forth between the SSH client and the Gitaly server.
+
+If you access a GitLab server over HTTP(S) you end up in [`gitlab-workhorse`](../workhorse/index.md).
+
+### `git pull` over SSH
+
+```mermaid
+graph LR
+ A[Git pull] --> |via SSH| B[gitlab-shell]
+ B -->|API call| C[gitlab-rails<br>authorization]
+ C -->|accept or decline| D[Gitaly session]
+```
+
+### `git push` over SSH
+
+The `git push` command is not performed until after `gitlab-rails` accepts the push:
+
+```mermaid
+graph LR
+subgraph User initiates
+ A[Git push] -->|via SSH| B[gitlab-shell]
+end
+subgraph Gitaly
+ B -->|establish Gitaly session| C[gitlab-shell pre-receive hook]
+ C -->|API auth call| D[Gitlab-rails]
+ D --> E[accept or decline push]
+end
+```
+
+[Full feature list](features.md)
+
+### Modifies `authorized_keys`
+
+GitLab Shell modifies the `authorized_keys` file on the client machine.
+
+## Contribute to GitLab Shell
+
+To contribute to GitLab Shell:
+
+1. Check if GitLab API access, and Redis via the internal API, can be reached: `make check`
+1. Compile the `gitlab-shell` binaries, placing them into `bin/`: `make compile`
+1. Run `make install` to build the `gitlab-shell` binaries and install. them onto the file system.
+ The default location is `/usr/local`. To change it, set the `PREFIX` and `DESTDIR` environment variables.
+1. To install GitLab from source on a single machine, run `make setup`.
+ It compiles the GitLab Shell binaries, and ensures that various paths on the file system
+ exist with the correct permissions. Do not run this command unless your installation method
+ documentation instructs you to.
+
+For more information, see
+[CONTRIBUTING.md](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/CONTRIBUTING.md).
+
+### Run tests
+
+When contributing, run tests:
+
+1. Run tests with `bundle install` and `make test`.
+1. Run Gofmt: `make verify`
+1. Run both test and verify (the default Makefile target):
+
+ ```shell
+ bundle install
+ make validate
+ ```
+
+1. If needed, configure Gitaly.
+
+### Configure Gitaly for local testing
+
+Some tests need a Gitaly server. The
+[`docker-compose.yml`](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/docker-compose.yml) file runs Gitaly on port 8075.
+To tell the tests where Gitaly is, set `GITALY_CONNECTION_INFO`:
+
+```plaintext
+export GITALY_CONNECTION_INFO='{"address": "tcp://localhost:8075", "storage": "default"}'
+make test
+```
+
+If no `GITALY_CONNECTION_INFO` is set, the test suite still runs, but any
+tests requiring Gitaly are skipped. The tests always run in the CI environment.
+
+## Rate limiting
+
+GitLab Shell performs rate-limiting by user account and project for Git operations.
+GitLab Shell accepts Git operation requests and then makes a call to the Rails
+rate-limiter, backed by Redis. If the `user + project` exceeds the rate limit,
+then GitLab Shell then drop further connection requests for that `user + project`.
+
+The rate-limiter is applied at the Git command (plumbing) level. Each command has
+a rate limit of 600 per minute. For example, `git push` has 600 per minute, and
+`git pull` has another 600 per minute.
+
+Because they are using the same plumbing command, `git-upload-pack`, `git pull`,
+and `git clone` are in effect the same command for the purposes of rate-limiting.
+
+Gitaly also has a rate-limiter in place, but calls are never made to Gitaly if
+the rate limit is exceeded in GitLab Shell (Rails).
+
+## Logs in GitLab Shell
+
+In general, you can determine the structure, but not content, of a GitLab Shell
+or `gitlab-sshd` session by inspecting the logs. Some guidelines:
+
+- We use [`gitlab.com/gitlab-org/labkit/log`](https://pkg.go.dev/gitlab.com/gitlab-org/labkit/log)
+ for logging.
+- Always include a correlation ID.
+- Log messages should be invariant and unique. Include accessory information in
+ fields, using `log.WithField`, `log.WithFields`, or `log.WithError`.
+- Log both success cases and error cases.
+- Logging too much is better than not logging enough. If a message seems too
+ verbose, consider reducing the log level before removing the message.
+
+## GitLab SaaS
+
+A diagram of the flow of `gitlab-shell` on GitLab.com:
+
+```mermaid
+graph LR
+ a2 --> b2
+ a2 --> b3
+ a2 --> b4
+ b2 --> c1
+ b3 --> c1
+ b4 --> c1
+ c2 --> d1
+ c2 --> d2
+ c2 --> d3
+ d1 --> e1
+ d2 --> e1
+ d3 --> e1
+ a1[Cloudflare] --> a2[TCP<br/> load balancer]
+ e1[Git]
+
+ subgraph HAProxy Fleet
+ b2[HAProxy]
+ b3[HAProxy]
+ b4[HAProxy]
+ end
+
+ subgraph GKE
+ c1[Internal TCP<br/> load balancer<br/>port 2222] --> c2[GitLab-shell<br/> pods]
+ end
+
+ subgraph Gitaly
+ d1[Gitaly]
+ d2[Gitaly]
+ d3[Gitaly]
+ end
+```
+
+## GitLab Shell architecture
+
+```mermaid
+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
+```
+
+## Related topics
+
+- [LICENSE](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/LICENSE).
+- [PROCESS.md](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/PROCESS.md)
+- [Using the GitLab Shell chart](https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/)
diff --git a/doc/development/gitlab_shell/process.md b/doc/development/gitlab_shell/process.md
new file mode 100644
index 00000000000..cc6f44b865c
--- /dev/null
+++ b/doc/development/gitlab_shell/process.md
@@ -0,0 +1,71 @@
+---
+stage: Create
+group: Source Code
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Processes for GitLab Shell
+
+## Releasing a new version
+
+GitLab Shell is versioned by Git tags, and the version used by the Rails
+application is stored in
+[`GITLAB_SHELL_VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_SHELL_VERSION).
+
+For each version, there is a raw version and a tag version:
+
+- The **raw version** is the version number. For instance, `15.2.8`.
+- The **tag version** is the raw version prefixed with `v`. For instance, `v15.2.8`.
+
+To release a new version of GitLab Shell and have that version available to the
+Rails application:
+
+1. Create a merge request to update the [`CHANGELOG`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/CHANGELOG.md) with the
+ **tag version** and the [`VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/VERSION) file with the **raw version**.
+1. Ask a maintainer to review and merge the merge request. If you're already a
+ maintainer, second maintainer review is not required.
+1. Add a new Git tag with the **tag version**.
+1. Update `GITLAB_SHELL_VERSION` in the Rails application to the **raw
+ version**.
+
+ NOTE:
+ This can be done as a separate merge request, or in a merge request
+ that uses the latest GitLab Shell changes.
+
+## Security releases
+
+GitLab Shell is included in the packages we create for GitLab. Each version of
+GitLab specifies the version of GitLab Shell it uses in the `GITLAB_SHELL_VERSION`
+file. Because of this specification, security fixes in GitLab Shell are tightly coupled to the
+[GitLab security release](https://about.gitlab.com/handbook/engineering/workflow/#security-issues) workflow.
+
+For a security fix in GitLab Shell, two sets of merge requests are required:
+
+1. The fix itself, in the `gitlab-org/security/gitlab-shell` repository and its
+ backports to the previous versions of GitLab Shell.
+1. Merge requests to change the versions of GitLab Shell included in the GitLab
+ security release, in the `gitlab-org/security/gitlab` repository.
+
+The first step could be to create a merge request with a fix targeting `main`
+in `gitlab-org/security/gitlab-shell`. When the merge request is approved by maintainers,
+backports targeting previous 3 versions of GitLab Shell must be created. The stable
+branches for those versions may not exist, so feel free to ask a maintainer to create
+them. The stable branches must be created out of the GitLab Shell tags or versions
+used by the 3 previous GitLab releases.
+
+To find out the GitLab Shell version used on a particular GitLab stable release,
+run this command, replacing `13-9-stable-ee` with the version you're interested in.
+These commands show the version used by the `13.9` version of GitLab:
+
+```shell
+git fetch security 13-9-stable-ee
+git show refs/remotes/security/13-9-stable-ee:GITLAB_SHELL_VERSION
+```
+
+Close to the GitLab security release, a maintainer should merge the fix and backports,
+and cut all the necessary GitLab Shell versions. This allows bumping the
+`GITLAB_SHELL_VERSION` for `gitlab-org/security/gitlab`. The GitLab merge request
+is handled by the general GitLab security release process.
+
+After the security release is done, a GitLab Shell maintainer is responsible for
+syncing tags and `main` to the `gitlab-org/gitlab-shell` repository.