As we reevaluate how to best support and maintain Staging Ref in the future, we encourage development teams using this environment to highlight their use cases in the following issue: https://gitlab.com/gitlab-com/gl-infra/software-delivery/framework/software-delivery-framework-issue-tracker/-/issues/36.

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • idrozdov/gitlab-shell
  • mmj/gitlab-shell
2 results
Show changes
Commits on Source (353)
Loading
Loading
@@ -7,11 +7,7 @@
.gitlab_shell_secret
.idea
/*.log*
/bin/check
/bin/gitlab-shell
/bin/gitlab-shell-authorized-keys-check
/bin/gitlab-shell-authorized-principals-check
/bin/gitlab-sshd
/bin/*
/gl-code-quality-report.json
/go_build
/support/bin/golangci-*
Loading
Loading
Loading
Loading
@@ -3,29 +3,29 @@ include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
- project: 'gitlab-org/quality/pipeline-common'
file:
- '/ci/danger-review.yml'
stages:
- prepare
- lint
- test
- post-test
variables:
FF_USE_FASTZIP: 'true'
TRANSFER_METER_FREQUENCY: "1s"
DOCKER_VERSION: "20.10.15"
BUNDLE_FROZEN: "true"
GO_VERSION: "golang-1.21"
GO_VERSION: "1.23"
GOPATH: $CI_PROJECT_DIR/.GOPATH
DEBIAN_VERSION: "bookworm"
RUBY_VERSION: "ruby-3.2"
RUBY_VERSION: "3.2.5"
BUNDLE_PATH: vendor/ruby
POLICY: pull
CI_DEBUG_SERVICES: 'true'
RUST_VERSION: "rust-1.73"
RUST_VERSION: "1.73"
UBI_VERSION: "8.6"
IMAGE_TAG: "rubygems-3.4-git-2.36-exiftool-12.60"
IMAGE_TAG: "rubygems-3.5-git-2.45-exiftool-12.60"
GITLAB_ADVANCED_SAST_ENABLED: 'true'
workflow:
rules: &workflow_rules
Loading
Loading
@@ -36,8 +36,15 @@ workflow:
# For tags, create a pipeline.
- if: '$CI_COMMIT_TAG'
.rules:go-changes:
rules:
- changes:
- 'go.mod'
- 'go.sum'
- '**/*.go'
default:
image: registry.gitlab.com/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-${RUBY_VERSION}-${GO_VERSION}-${RUST_VERSION}:${IMAGE_TAG}
image: registry.gitlab.com/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:${IMAGE_TAG}
tags:
- gitlab-org
Loading
Loading
@@ -51,7 +58,7 @@ default:
.cached-go: &cached_go
- key:
prefix: $GO_VERSION-cache
prefix: "golang-${GO_VERSION}-cache"
files:
- go.mod
- go.sum
Loading
Loading
@@ -61,7 +68,7 @@ default:
.cached-ruby: &cached_ruby
- key:
prefix: $RUBY_VERSION-cache
prefix: "ruby-${RUBY_VERSION}-cache"
files:
- Gemfile.lock
policy: $POLICY
Loading
Loading
@@ -86,7 +93,7 @@ default:
.go-matrix-job:
parallel:
matrix:
- GO_VERSION: ["golang-1.21", "golang-1.22"]
- GO_VERSION: ["1.22", "1.23"]
################################################################################
# Prepare jobs
Loading
Loading
@@ -116,6 +123,7 @@ modules:download:
.test-job:
needs: ['bundle:install', 'modules:download']
rules: !reference [".rules:go-changes", rules]
variables:
GITALY_CONNECTION_INFO: '{"address":"tcp://gitaly:8075", "storage":"default"}'
before_script:
Loading
Loading
@@ -158,7 +166,7 @@ tests_without_cgo:
- make verify test_fancy
tests:fips:
image: registry.gitlab.com/gitlab-org/gitlab-build-images/ubi-${UBI_VERSION}-${RUBY_VERSION}-${GO_VERSION}-${RUST_VERSION}:${IMAGE_TAG}
image: registry.gitlab.com/gitlab-org/gitlab-build-images/ubi-${UBI_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:${IMAGE_TAG}
extends:
- .cached-job
- .test-job
Loading
Loading
@@ -176,10 +184,12 @@ race:
- make test_golang_race
code_quality:
stage: lint
extends: .use-docker-in-docker
rules: *workflow_rules
code_navigation:
stage: post-test
image: sourcegraph/lsif-go:v1.9
allow_failure: true
script:
Loading
Loading
@@ -190,17 +200,25 @@ code_navigation:
# SAST
semgrep-sast:
stage: lint
rules: *workflow_rules
gitlab-advanced-sast:
stage: lint
rules: *workflow_rules
# Dependency Scanning
gemnasium-dependency_scanning:
stage: lint
rules: *workflow_rules
# Secret Detection
secret_detection:
stage: lint
rules: *workflow_rules
build-package-and-qa:
stage: post-test
trigger:
project: 'gitlab-org/build/omnibus-gitlab-mirror'
branch: 'master'
Loading
Loading
@@ -232,13 +250,14 @@ build-package-and-qa:
needs: []
modules:tidy:
stage: lint
needs: ['modules:download']
script:
- go mod tidy
- git diff --exit-code go.mod go.sum
lint:
stage: test
stage: lint
script:
# Write the code coverage report to gl-code-quality-report.json
# and print linting issues to stdout in the format: path/to/file:line description
Loading
Loading
@@ -254,7 +273,8 @@ lint:
- gl-code-quality-report.json
nilaway:
stage: test
stage: lint
rules: !reference [".rules:go-changes", rules]
before_script:
- go install go.uber.org/nilaway/cmd/nilaway@latest
script:
Loading
Loading
# https://gitlab.com/groups/gitlab-org/maintainers/gitlab-shell/-/group_members?with_inherited_permissions=exclude
* @gitlab-org/maintainers/gitlab-shell
[Documentation]
*.md @aqualls
[Documentation] @gl-docsteam
*.md
/doc/
Loading
Loading
@@ -61,6 +61,8 @@ output:
# print linter name in the end of issue text, default is true
print-linter-name: true
sort-results: true
# all available settings of specific linters
linters-settings:
errcheck:
Loading
Loading
@@ -76,6 +78,7 @@ linters-settings:
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
# ignore: fmt:.*,io/ioutil:^Read.*
ignore: ''
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
Loading
Loading
@@ -261,11 +264,11 @@ linters:
disable-all: true
enable:
- bodyclose
- copyloopvar
- depguard
- dogsled
- dupl
- errcheck
- exportloopref
- funlen
- gocognit
- goconst
Loading
Loading
3.2.3
3.3.4
ruby 3.2.3
golang 1.22.2
ruby 3.3.5
golang 1.23.2
v14.39.0
- Revise CODEOWNERS to use entire TW team !1125
- Rename bin/check to bin/gitlab-shell-check to to avoid name clash !801
- Update golangci to 1.60.1 !1122
- Move bin/install to support/make_necessary_dirs !799
- Update dependency golang to v1.23.0 !1121
- Use go build so we can use -o !1117
- Add 'make make_necessary_dirs' alias !1119
- Add GitLab Advanced SAST to CI/CD config !1120
- Update github.com/charmbracelet/git-lfs-transfer digest to 2cab0ea !1118
- Update module golang.org/x/crypto to v0.26.0 !1115
- Update dependency golang to v1.22.6 !1116
- Update github.com/charmbracelet/git-lfs-transfer digest to c3aa24b !1113
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.8 !1114
- Update module golang.org/x/sync to v0.8.0 !1112
v14.38.0
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.7 !1110
- Add basic LFS connections metric for SSH !1107
- Update module google.golang.org/grpc to v1.65.0 !1098
- Add basic LFS connections metric for HTTP !1108
- Remove migration section as no longer supported !1106
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.6 !1104
- Update dependency ruby to v3.3.4 !1102
- Update Ruby to 3.3.4 !1105
- Update module golang.org/x/crypto to v0.25.0 !1100
- Update github.com/charmbracelet/git-lfs-transfer digest to bacbfdb !1101
- Restructure CI jobs !1097
- Update dependency golang to v1.22.5 !1099
v14.37.0
- Update dependency danger-review to v1.4.1 !1095
- Allow pure_ssh_protocol to be set !1093
- Update dependency gitlab-dangerfiles to '~> 4.8.0' !1094
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.5 !1091
- Update dependency danger-review to v1.4.0 !1090
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.4 !1085
- Update golangci to 1.59.1 !1089
v14.36.0
- Use the danger-review component !1086
- Update module google.golang.org/protobuf to v1.34.2 !1083
- Geo: Replace Git over HTTP calls with Workhorse HTTP endpoint for SSH pull !1081
- Update github.com/charmbracelet/git-lfs-transfer digest to 0ffd62e !1080
- Update dependency golang to v1.22.4 !1079
- Update module golang.org/x/crypto to v0.24.0 !1078
- Update golang default to 1.22 !1077
- Geo: Replace Git over HTTP calls with Workhorse HTTP endpoint for SSH push !1076
- Update module github.com/hashicorp/go-retryablehttp to v0.7.7 !1074
- Update CI image to latest one !1073
- Update module golang.org/x/sync to v0.7.0 !1072
- git-lfs-transfer: Add support for lock and unlocking of files !1071
- Update golangci to 1.58.2 !1069
- Update github.com/charmbracelet/git-lfs-transfer digest to 4ef8f58 !1067
- Continue work on Git LFS over SSH !1066
- Update module google.golang.org/grpc to v1.64.0 !1065
- Update module github.com/prometheus/client_golang to v1.19.1 !1063
- Update module github.com/hashicorp/go-retryablehttp to v0.7.6 !1061
- Update dependency golang to v1.22.3 !1060
- Update golangci to 1.58.1 !1057
- Update module google.golang.org/protobuf to v1.34.1 !1056
- Update module golang.org/x/crypto to v0.23.0 !1055
- Update github.com/charmbracelet/git-lfs-transfer digest to cc13460 !1054
- Add configuration objects to PAT token !1053
- Update module google.golang.org/protobuf to v1.34.0 !1052
- Fix lint issues for sshd server_config !1043
- Resolve `make lint` (golangci-lint) issues for `internal/sshd/sshd.go` and `internal/sshd/sshd_test.go` !1040
- Update github.com/charmbracelet/git-lfs-transfer digest to 9e9a21d !1038
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.3 !1037
- Resolve `make lint` (golangci-lint) issues for `internal/command/uploadarchive/uploadarchive.go` and `internal/command/uploadarchive/uploadarchive_test.go` !1034
- Resolve `make lint` (golangci-lint) issues for `internal/command/uploadpack/uploadpack.go` and `internal/command/uploadpack/uploadpack_test.go` !1033
- Resolve `make lint` (golangci-lint) issues for `internal/sshd/session.go` and `internal/sshd/session_test.go` !1032
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/authorizedkeys/client.go` and `internal/gitlabnet/authorizedkeys/client_test.go` !1031
- Resolve `make lint` (golangci-lint) issues for `internal/command/receivepack/receivepack.go` and `internal/command/receivepack/receivepack_test.go` !1030
- Resolve `make lint` (golangci-lint) issues for `internal/command/lfsauthenticate/lfsauthenticate.go` and `internal/command/lfsauthenticate/lfsauthenticate_test.go !1029
- Update HttpClient method name !1028
- Resolves `make lint` (golangci-lint) issues for `cmd/gitlab-shell-authorized-keys-check/main.go` !1027
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/git/client.go` and `internal/gitlabnet/git/client_test.go` !1026
- Resolve `make lint` (golangci-lint) issues or `internal/command/uploadpack/gitalycall.go` and `internal/command/uploadpack/gitalycall_test.go` !1025
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/twofactorverify/client.go` and `internal/gitlabnet/twofactorverify/client_test.go` !1024
- Resolve `make lint` (golangci-lint) issues for `internal/command/twofactorverify/twofactorverify.go` and `internal/command/twofactorverify/twofactorverify_test.go` !1023
- Resolve `make lint` (golangci-lint) issues for `internal/command/shared/customaction/customaction.go` and `internal/command/shared/customaction/customaction_test.go` !1022
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/accessverifier/client.go` and `internal/gitlabnet/accessverifier/client_test.go` !1021
- Resolve `make lint` (golangci-lint) issues for `cmd/gitlab-shell/command/command.go` and `cmd/gitlab-shell/command/command_test.go` !1020
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/discover/client.go` and `internal/gitlabnet/discover/client_test.go` !1019
- Resolve `make lint` (golangci-lint) issues for `cmd/check/command/command.go` and `cmd/check/command/command_test.go` !1018
- Resolve `make lint` (golangci-lint) issues for `internal/keyline/key_line.go` and `internal/keyline/key_line_test.go` !1017
- Resolve `make lint` (golangci-lint) issues for `internal/gitlabnet/lfsauthenticate/client.go` and `internal/gitlabnet/lfsauthenticate/client_test.go` !1016
- Resolve `make lint` (golangci-lint) issues for `internal/sshenv/sshenv.go` and `internal/sshenv/sshenv_test.go` !1015
- Resolve `make lint` (golangci-lint) issues for `cmd/gitlab-shell-authorized-keys-check/command/command.go` and `cmd/gitlab-shell-authorized-keys-check/command/command_test.go` !1014
- Fix `make lint` (golangci-lint) issues for `client/httpclient.go` and `client/httpsclient_test.go` !1013
- Fix `make lint` (golangci-lint) issues for `internal/handler/exec.go` and `internal/handler/exec_test.go` !1012
- Fix `make lint` (golangci-lint) issues for `internal/gitlabnet/personalaccesstoken/client.go` and `internal/gitlabnet/personalaccesstoken/client_test.go` !1011
- Fix `make lint` (golangci-lint) issues for `client/gitlabnet.go` !1010
- Fixes `make lint` (golangci-lint) issues for `internal/gitlabnet/twofactorrecover/client.go` and `internal/gitlabnet/twofactorrecover/client_test.go` !1009
- Fix `make lint` (golangci-lint) issues for `internal/sshd/connection.go` and `internal/sshd/connection_test.go` !1008
- Fix `make lint` (golangci-lint) issues for `internal/console/console.go` and `internal/console/console_test.go` !1007
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.11.0 !1006
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.10.3 !1005
- Fix golanci shadow warning !1004
- Fix lint issues in requesthandlers.go !1003
- Resolve Use golang-1.21 for GO_VERSION in CI !1001
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.10.2 !997
- Update github.com/charmbracelet/git-lfs-transfer digest to 3263d2f !996
- Update module golang.org/x/crypto to v0.22.0 !995
- Extend shell logs with additional metadata !991
- git-lfs-transfer: Add support for batch upload and get object !989
v14.35.0
- sshd: limit server_host_key_algorithms in server config !986
Loading
Loading
Loading
Loading
@@ -2,9 +2,9 @@ source 'https://rubygems.org'
group :development, :test do
gem 'rspec', '~> 3.13.0'
gem 'webrick', '~> 1.8', '>= 1.8.1'
gem 'webrick', '~> 1.8', '>= 1.8.2'
end
group :development, :danger do
gem 'gitlab-dangerfiles', '~> 4.7.0'
gem 'gitlab-dangerfiles', '~> 4.8.0'
end
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
bigdecimal (3.1.8)
claide (1.1.0)
claide-plugins (0.9.2)
cork
Loading
Loading
@@ -11,6 +12,7 @@ GEM
colored2 (3.1.2)
cork (0.3.0)
colored2 (~> 3.1)
csv (3.3.0)
danger (9.4.3)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
Loading
Loading
@@ -28,7 +30,7 @@ GEM
danger
gitlab (~> 4.2, >= 4.2.0)
diff-lcs (1.5.1)
faraday (2.9.0)
faraday (2.9.2)
faraday-net_http (>= 2.0, < 3.2)
faraday-http-cache (2.5.1)
faraday (>= 0.8)
Loading
Loading
@@ -37,14 +39,15 @@ GEM
git (1.19.1)
addressable (~> 2.8)
rchardet (~> 1.8)
gitlab (4.19.0)
gitlab (4.20.1)
httparty (~> 0.20)
terminal-table (>= 1.5.1)
gitlab-dangerfiles (4.7.0)
gitlab-dangerfiles (4.8.0)
danger (>= 9.3.0)
danger-gitlab (>= 8.0.0)
rake (~> 13.0)
httparty (0.21.0)
httparty (0.22.0)
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
kramdown (2.4.0)
Loading
Loading
@@ -52,7 +55,8 @@ GEM
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
mini_mime (1.1.5)
multi_xml (0.6.0)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
nap (1.1.0)
net-http (0.4.1)
uri
Loading
Loading
@@ -61,10 +65,11 @@ GEM
faraday (>= 1, < 3)
sawyer (~> 0.9)
open4 (1.3.4)
public_suffix (5.0.4)
rake (13.1.0)
public_suffix (5.1.1)
rake (13.2.1)
rchardet (1.8.0)
rexml (3.2.6)
rexml (3.3.1)
strscan
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
Loading
Loading
@@ -81,19 +86,20 @@ GEM
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
strscan (3.1.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.5.0)
uri (0.13.0)
webrick (1.8.1)
webrick (1.8.2)
PLATFORMS
ruby
DEPENDENCIES
gitlab-dangerfiles (~> 4.7.0)
gitlab-dangerfiles (~> 4.8.0)
rspec (~> 3.13.0)
webrick (~> 1.8, >= 1.8.1)
webrick (~> 1.8, >= 1.8.2)
BUNDLED WITH
2.5.6
2.5.11
.PHONY: validate verify verify_ruby verify_golang test test_ruby test_golang test_fancy test_golang_fancy coverage coverage_golang setup _script_install build compile check clean install lint
.PHONY: validate verify verify_ruby verify_golang test test_ruby test_golang test_fancy test_golang_fancy coverage coverage_golang setup _script_install make_necessary_dirs build compile check clean install lint
FIPS_MODE ?= 0
OS := $(shell uname | tr A-Z a-z)
Loading
Loading
@@ -9,10 +9,10 @@ GO_TAGS := tracer_static tracer_static_jaeger continuous_profiler_stackdriver
ARCH ?= $(shell uname -m | sed -e 's/x86_64/amd64/' | sed -e 's/aarch64/arm64/')
GOTESTSUM_VERSION := 1.11.0
GOTESTSUM_VERSION := 1.12.0
GOTESTSUM_FILE := support/bin/gotestsum-${GOTESTSUM_VERSION}
GOLANGCI_LINT_VERSION := 1.57.2
GOLANGCI_LINT_VERSION := 1.60.3
GOLANGCI_LINT_FILE := support/bin/golangci-lint-${GOLANGCI_LINT_VERSION}
export GOFLAGS := -mod=readonly
Loading
Loading
@@ -86,36 +86,42 @@ coverage: coverage_golang
coverage_golang:
[ -f cover.out ] && go tool cover -func cover.out
lint: ${GOLANGCI_LINT_FILE}
${GOLANGCI_LINT_FILE} --version
${GOLANGCI_LINT_FILE} run --issues-exit-code 0 --print-issued-lines=false ${GOLANGCI_LINT_ARGS}
lint:
@support/lint.sh ./...
golangci: ${GOLANGCI_LINT_FILE}
@${GOLANGCI_LINT_FILE} run --issues-exit-code 0 --print-issued-lines=false ${GOLANGCI_LINT_ARGS}
${GOLANGCI_LINT_FILE}:
mkdir -p $(shell dirname ${GOLANGCI_LINT_FILE})
curl -L https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-${OS}-${ARCH}.tar.gz | tar --strip-components 1 -zOxf - golangci-lint-${GOLANGCI_LINT_VERSION}-${OS}-${ARCH}/golangci-lint > ${GOLANGCI_LINT_FILE} && chmod +x ${GOLANGCI_LINT_FILE}
@mkdir -p $(shell dirname ${GOLANGCI_LINT_FILE})
@curl -L https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-${OS}-${ARCH}.tar.gz | tar --strip-components 1 -zOxf - golangci-lint-${GOLANGCI_LINT_VERSION}-${OS}-${ARCH}/golangci-lint > ${GOLANGCI_LINT_FILE} && chmod +x ${GOLANGCI_LINT_FILE}
setup: _script_install bin/gitlab-shell
setup: make_necessary_dirs bin/gitlab-shell
_script_install:
bin/install
make_necessary_dirs:
support/make_necessary_dirs
compile: bin/gitlab-shell bin/gitlab-sshd
bin/gitlab-shell: $(GO_SOURCES)
GOBIN="$(CURDIR)/bin" go install $(GOBUILD_FLAGS) ./cmd/...
bin/gitlab-sshd: $(GO_SOURCES)
GOBIN="$(CURDIR)/bin" go install $(GOBUILD_FLAGS) ./cmd/gitlab-sshd
bin:
mkdir -p bin
bin/gitlab-shell: bin $(GO_SOURCES)
go build $(GOBUILD_FLAGS) -o $(CURDIR)/bin ./cmd/...
bin/gitlab-sshd: bin $(GO_SOURCES)
go build $(GOBUILD_FLAGS) -o $(CURDIR)/bin/gitlab-sshd ./cmd/gitlab-sshd
check:
bin/check
bin/gitlab-shell-check
clean:
rm -f bin/check bin/gitlab-shell bin/gitlab-shell-authorized-keys-check bin/gitlab-shell-authorized-principals-check bin/gitlab-sshd
rm -f bin/*
install: compile
mkdir -p $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/check $(DESTDIR)$(PREFIX)/bin/check
install -m755 bin/gitlab-shell $(DESTDIR)$(PREFIX)/bin/gitlab-shell
install -m755 bin/gitlab-shell-authorized-keys-check $(DESTDIR)$(PREFIX)/bin/gitlab-shell-authorized-keys-check
install -m755 bin/gitlab-shell-authorized-principals-check $(DESTDIR)$(PREFIX)/bin/gitlab-shell-authorized-principals-check
install -m755 bin/gitlab-sshd $(DESTDIR)$(PREFIX)/bin/gitlab-sshd
install -m755 bin/gitlab-shell-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell-authorized-keys-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell-authorized-principals-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-sshd $(DESTDIR)$(PREFIX)/bin/
Loading
Loading
@@ -4,10 +4,48 @@ 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 documentation has moved
[![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)
The documentation for GitLab Shell [has moved into the `gitlab` repository](https://docs.gitlab.com/ee/development/gitlab_shell/).
# 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.
## Development Documentation
Development documentation for GitLab Shell [has moved into the `gitlab` repository](https://docs.gitlab.com/ee/development/gitlab_shell/).
## Project structure
| Directory | Description |
|-----------|-------------|
| `cmd/` | 'Commands' that will ultimately be compiled into binaries. |
| `internal/` | Internal Go source code that is not intended to be used outside of the project/module. |
| `client/` | HTTP and GitLab client logic that is used internally and by other modules, e.g. Gitaly. |
| `bin/` | Compiled binaries are created here. |
| `support/` | Scripts and tools that assist in development and/or testing. |
| `spec/` | Ruby based integration tests. |
## Building
Run `make` or `make build`.
## Testing
Run `make test`.
## Release Process
1. Create a `gitlab-org/gitlab-shell` MR to update [`VERSION`](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/VERSION) and [`CHANGELOG`](https://gitlab.com/gitlab-org/gitlab-shell/-/blob/main/CHANGELOG) files, e.g. [Release v14.39.0](https://gitlab.com/gitlab-org/gitlab-shell/-/merge_requests/1123).
2. Once `gitlab-org/gitlab-shell` MR is merged, create the corresponding git tag, e.g. https://gitlab.com/gitlab-org/gitlab-shell/-/tags/v14.39.0.
3. Create a `gitlab-org/gitlab` MR to update [`GITLAB_SHELL_VERSION`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/GITLAB_SHELL_VERSION) to the proposed tag, e.g. [Bump GitLab Shell to 14.39.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162661).
4. Announce in `#gitlab-shell` a new version has been created.
## Licensing
See the `LICENSE` file for licensing information as it pertains to files in
this repository.
14.35.0
14.39.0
Loading
Loading
@@ -13,6 +13,7 @@ import (
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
Loading
Loading
@@ -36,31 +37,31 @@ func TestClients(t *testing.T) {
}{
{
desc: "Socket client",
server: testserver.StartSocketHttpServer,
server: testserver.StartSocketHTTPServer,
secret: secret,
},
{
desc: "Socket client with a relative URL at /",
relativeURLRoot: "/",
server: testserver.StartSocketHttpServer,
server: testserver.StartSocketHTTPServer,
secret: secret,
},
{
desc: "Socket client with relative URL at /gitlab",
relativeURLRoot: "/gitlab",
server: testserver.StartSocketHttpServer,
server: testserver.StartSocketHTTPServer,
secret: secret,
},
{
desc: "Http client",
server: testserver.StartHttpServer,
server: testserver.StartHTTPServer,
secret: secret,
},
{
desc: "Https client",
caFile: path.Join(testRoot, "certs/valid/server.crt"),
server: func(t *testing.T, handlers []testserver.TestRequestHandler) string {
return testserver.StartHttpsServer(t, handlers, "")
return testserver.StartHTTPSServer(t, handlers, "")
},
secret: secret,
},
Loading
Loading
@@ -68,13 +69,13 @@ func TestClients(t *testing.T) {
desc: "Secret with newlines",
caFile: path.Join(testRoot, "certs/valid/server.crt"),
server: func(t *testing.T, handlers []testserver.TestRequestHandler) string {
return testserver.StartHttpsServer(t, handlers, "")
return testserver.StartHTTPSServer(t, handlers, "")
},
secret: "\n" + secret + "\n",
},
{
desc: "Retry client",
server: testserver.StartRetryHttpServer,
server: testserver.StartRetryHTTPServer,
secret: secret,
},
}
Loading
Loading
@@ -240,7 +241,7 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
{
Path: "/api/v4/internal/hello",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, "Hello")
},
Loading
Loading
@@ -248,12 +249,12 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
{
Path: "/api/v4/internal/post_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, http.MethodPost, r.Method)
b, err := io.ReadAll(r.Body)
defer r.Body.Close()
require.NoError(t, err)
assert.NoError(t, err)
fmt.Fprint(w, "Echo: "+string(b))
},
Loading
Loading
// Package client provides a client for interacting with GitLab API
package client
import (
Loading
Loading
@@ -15,44 +16,48 @@ import (
)
const (
internalApiPath = "/api/v4/internal"
apiSecretHeaderName = "Gitlab-Shell-Api-Request"
internalAPIPath = "/api/v4/internal"
apiSecretHeaderName = "Gitlab-Shell-Api-Request" // #nosec G101
defaultUserAgent = "GitLab-Shell"
jwtTTL = time.Minute
jwtIssuer = "gitlab-shell"
)
// ErrorResponse represents an error response from the API
type ErrorResponse struct {
Message string `json:"message"`
}
// GitlabNetClient is a client for interacting with GitLab API
type GitlabNetClient struct {
httpClient *HttpClient
httpClient *HTTPClient
user string
password string
secret string
userAgent string
}
type ApiError struct {
// APIError represents an API error
type APIError struct {
Msg string
}
// To use as the key in a Context to set an X-Forwarded-For header in a request
// OriginalRemoteIPContextKey is used as the key in a Context to set an X-Forwarded-For header in a request
type OriginalRemoteIPContextKey struct{}
func (e *ApiError) Error() string {
func (e *APIError) Error() string {
return e.Msg
}
// NewGitlabNetClient creates a new GitlabNetClient instance
func NewGitlabNetClient(
user,
password,
secret string,
httpClient *HttpClient,
httpClient *HTTPClient,
) (*GitlabNetClient, error) {
if httpClient == nil {
return nil, fmt.Errorf("Unsupported protocol")
return nil, fmt.Errorf("unsupported protocol")
}
return &GitlabNetClient{
Loading
Loading
@@ -75,8 +80,8 @@ func normalizePath(path string) string {
path = "/" + path
}
if !strings.HasPrefix(path, internalApiPath) {
path = internalApiPath + path
if !strings.HasPrefix(path, internalAPIPath) {
path = internalAPIPath + path
}
return path
}
Loading
Loading
@@ -106,39 +111,42 @@ func newRequest(ctx context.Context, method, host, path string, data interface{}
func parseError(resp *http.Response, respErr error) error {
if resp == nil || respErr != nil {
return &ApiError{"Internal API unreachable"}
return &APIError{"Internal API unreachable"}
}
if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
return nil
}
defer resp.Body.Close()
defer func() { _ = resp.Body.Close() }()
parsedResponse := &ErrorResponse{}
if err := json.NewDecoder(resp.Body).Decode(parsedResponse); err != nil {
return &ApiError{fmt.Sprintf("Internal API error (%v)", resp.StatusCode)}
} else {
return &ApiError{parsedResponse.Message}
return &APIError{fmt.Sprintf("Internal API error (%v)", resp.StatusCode)}
}
return &APIError{parsedResponse.Message}
}
// Get makes a GET request
func (c *GitlabNetClient) Get(ctx context.Context, path string) (*http.Response, error) {
return c.DoRequest(ctx, http.MethodGet, normalizePath(path), nil)
}
// Post makes a POST request
func (c *GitlabNetClient) Post(ctx context.Context, path string, data interface{}) (*http.Response, error) {
return c.DoRequest(ctx, http.MethodPost, normalizePath(path), data)
}
// Do executes a request
func (c *GitlabNetClient) Do(request *http.Request) (*http.Response, error) {
response, err := c.httpClient.RetryableHTTP.HTTPClient.Do(request)
if err := parseError(response, err); err != nil {
response, respErr := c.httpClient.RetryableHTTP.HTTPClient.Do(request)
if err := parseError(response, respErr); err != nil {
return nil, err
}
return response, nil
}
// DoRequest executes a request with the given method, path, and data
func (c *GitlabNetClient) DoRequest(ctx context.Context, method, path string, data interface{}) (*http.Response, error) {
request, err := newRequest(ctx, method, c.httpClient.Host, path, data)
if err != nil {
Loading
Loading
@@ -165,8 +173,8 @@ func (c *GitlabNetClient) DoRequest(ctx context.Context, method, path string, da
request.Header.Add("Content-Type", "application/json")
request.Header.Add("User-Agent", c.userAgent)
response, err := c.httpClient.RetryableHTTP.Do(request)
if err := parseError(response, err); err != nil {
response, respErr := c.httpClient.RetryableHTTP.Do(request)
if err := parseError(response, respErr); err != nil {
return nil, err
}
Loading
Loading
// Package client provides functionality for interacting with HTTP clients
package client
import (
Loading
Loading
@@ -17,19 +18,21 @@ import (
)
const (
socketBaseUrl = "http://unix"
socketBaseURL = "http://unix"
unixSocketProtocol = "http+unix://"
httpProtocol = "http://"
httpsProtocol = "https://"
defaultReadTimeoutSeconds = 300
defaultRetryWaitMin = time.Second
defaultRetryWaitMax = 15 * time.Second
defaultRetryWaitMinimum = time.Second
defaultRetryWaitMaximum = 15 * time.Second
defaultRetryMax = 2
)
// ErrCafileNotFound indicates that the specified CA file was not found
var ErrCafileNotFound = errors.New("cafile not found")
type HttpClient struct {
// HTTPClient provides an HTTP client with retry capabilities
type HTTPClient struct {
RetryableHTTP *retryablehttp.Client
Host string
}
Loading
Loading
@@ -55,6 +58,7 @@ func WithClientCert(certPath, keyPath string) HTTPClientOpt {
}
}
// WithHTTPRetryOpts configures HTTP retry options for the HttpClient
func WithHTTPRetryOpts(waitMin, waitMax time.Duration, maxAttempts int) HTTPClientOpt {
return func(hcc *httpClientCfg) {
hcc.retryWaitMin = waitMin
Loading
Loading
@@ -80,12 +84,12 @@ func validateCaFile(filename string) error {
}
// NewHTTPClientWithOpts builds an HTTP client using the provided options
func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath string, readTimeoutSeconds uint64, opts []HTTPClientOpt) (*HttpClient, error) {
func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath string, readTimeoutSeconds uint64, opts []HTTPClientOpt) (*HTTPClient, error) {
hcc := &httpClientCfg{
caFile: caFile,
caPath: caPath,
retryWaitMin: defaultRetryWaitMin,
retryWaitMax: defaultRetryWaitMax,
retryWaitMin: defaultRetryWaitMinimum,
retryWaitMax: defaultRetryWaitMaximum,
retryMax: defaultRetryMax,
}
Loading
Loading
@@ -96,21 +100,21 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
var transport *http.Transport
var host string
var err error
if strings.HasPrefix(gitlabURL, unixSocketProtocol) {
switch {
case strings.HasPrefix(gitlabURL, unixSocketProtocol):
transport, host = buildSocketTransport(gitlabURL, gitlabRelativeURLRoot)
} else if strings.HasPrefix(gitlabURL, httpProtocol) {
transport, host = buildHttpTransport(gitlabURL)
} else if strings.HasPrefix(gitlabURL, httpsProtocol) {
case strings.HasPrefix(gitlabURL, httpProtocol):
transport, host = buildHTTPTransport(gitlabURL)
case strings.HasPrefix(gitlabURL, httpsProtocol):
err = validateCaFile(caFile)
if err != nil {
return nil, err
}
transport, host, err = buildHttpsTransport(*hcc, gitlabURL)
transport, host, err = buildHTTPSTransport(*hcc, gitlabURL)
if err != nil {
return nil, err
}
} else {
default:
return nil, errors.New("unknown GitLab URL prefix")
}
Loading
Loading
@@ -122,7 +126,7 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
c.HTTPClient.Transport = NewTransport(transport)
c.HTTPClient.Timeout = readTimeout(readTimeoutSeconds)
client := &HttpClient{RetryableHTTP: c, Host: host}
client := &HTTPClient{RetryableHTTP: c, Host: host}
return client, nil
}
Loading
Loading
@@ -137,7 +141,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
},
}
host := socketBaseUrl
host := socketBaseURL
gitlabRelativeURLRoot = strings.Trim(gitlabRelativeURLRoot, "/")
if gitlabRelativeURLRoot != "" {
host = host + "/" + gitlabRelativeURLRoot
Loading
Loading
@@ -146,7 +150,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
return transport, host
}
func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport, string, error) {
func buildHTTPSTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport, string, error) {
certPool, err := x509.SystemCertPool()
if err != nil {
certPool = x509.NewCertPool()
Loading
Loading
@@ -172,9 +176,9 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
}
if hcc.HaveCertAndKey() {
cert, err := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath)
if err != nil {
return nil, "", err
cert, loadErr := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath)
if loadErr != nil {
return nil, "", loadErr
}
tlsConfig.Certificates = []tls.Certificate{cert}
}
Loading
Loading
@@ -187,13 +191,13 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
}
func addCertToPool(certPool *x509.CertPool, fileName string) {
cert, err := os.ReadFile(fileName)
cert, err := os.ReadFile(filepath.Clean(fileName))
if err == nil {
certPool.AppendCertsFromPEM(cert)
}
}
func buildHttpTransport(gitlabURL string) (*http.Transport, string) {
func buildHTTPTransport(gitlabURL string) (*http.Transport, string) {
return &http.Transport{}, gitlabURL
}
Loading
Loading
Loading
Loading
@@ -10,6 +10,7 @@ import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
)
Loading
Loading
@@ -34,7 +35,7 @@ func TestBasicAuthSettings(t *testing.T) {
{
Path: "/api/v4/internal/get_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, r.Header.Get("Authorization"))
},
Loading
Loading
@@ -42,7 +43,7 @@ func TestBasicAuthSettings(t *testing.T) {
{
Path: "/api/v4/internal/post_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodPost, r.Method)
assert.Equal(t, http.MethodPost, r.Method)
fmt.Fprint(w, r.Header.Get("Authorization"))
},
Loading
Loading
@@ -81,16 +82,17 @@ func TestEmptyBasicAuthSettings(t *testing.T) {
requests := []testserver.TestRequestHandler{
{
Path: "/api/v4/internal/empty_basic_auth",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "", r.Header.Get("Authorization"))
Handler: func(_ http.ResponseWriter, r *http.Request) {
assert.Equal(t, "", r.Header.Get("Authorization"))
},
},
}
client := setup(t, "", "", requests)
_, err := client.Get(context.Background(), "/empty_basic_auth")
resp, err := client.Get(context.Background(), "/empty_basic_auth")
require.NoError(t, err)
resp.Body.Close()
}
func TestRequestWithUserAgent(t *testing.T) {
Loading
Loading
@@ -98,30 +100,33 @@ func TestRequestWithUserAgent(t *testing.T) {
requests := []testserver.TestRequestHandler{
{
Path: "/api/v4/internal/default_user_agent",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, defaultUserAgent, r.UserAgent())
Handler: func(_ http.ResponseWriter, r *http.Request) {
assert.Equal(t, defaultUserAgent, r.UserAgent())
},
},
{
Path: "/api/v4/internal/override_user_agent",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, gitalyUserAgent, r.UserAgent())
Handler: func(_ http.ResponseWriter, r *http.Request) {
assert.Equal(t, gitalyUserAgent, r.UserAgent())
},
},
}
client := setup(t, "", "", requests)
_, err := client.Get(context.Background(), "/default_user_agent")
defaultUserAgentResp, err := client.Get(context.Background(), "/default_user_agent")
require.NoError(t, err)
client.SetUserAgent(gitalyUserAgent)
_, err = client.Get(context.Background(), "/override_user_agent")
overriddenUserAgentResp, err := client.Get(context.Background(), "/override_user_agent")
require.NoError(t, err)
defaultUserAgentResp.Body.Close()
overriddenUserAgentResp.Body.Close()
}
func setup(t *testing.T, username, password string, requests []testserver.TestRequestHandler) *GitlabNetClient {
url := testserver.StartHttpServer(t, requests)
url := testserver.StartHTTPServer(t, requests)
httpClient, err := NewHTTPClientWithOpts(url, "", "", "", 1, nil)
require.NoError(t, err)
Loading
Loading
Loading
Loading
@@ -8,6 +8,7 @@ import (
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper"
Loading
Loading
@@ -116,14 +117,14 @@ func setupWithRequests(t *testing.T, caFile, caPath, clientCAPath, clientCertPat
{
Path: "/api/v4/internal/hello",
Handler: func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
assert.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, "Hello")
},
},
}
url := testserver.StartHttpsServer(t, requests, clientCAPath)
url := testserver.StartHTTPSServer(t, requests, clientCAPath)
opts := defaultHttpOpts
if clientCertPath != "" && clientKeyPath != "" {
Loading
Loading
Loading
Loading
@@ -22,7 +22,8 @@ type TestRequestHandler struct {
Handler func(w http.ResponseWriter, r *http.Request)
}
func StartSocketHttpServer(t *testing.T, handlers []TestRequestHandler) string {
// StartSocketHTTPServer starts a socket based HTTP server
func StartSocketHTTPServer(t *testing.T, handlers []TestRequestHandler) string {
t.Helper()
// We can't use t.TempDir() here because it will create a directory that
Loading
Loading
@@ -55,7 +56,8 @@ func StartSocketHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return url
}
func StartHttpServer(t *testing.T, handlers []TestRequestHandler) string {
// StartHTTPServer starts a TCP based HTTP server
func StartHTTPServer(t *testing.T, handlers []TestRequestHandler) string {
t.Helper()
server := httptest.NewServer(buildHandler(handlers))
Loading
Loading
@@ -64,7 +66,8 @@ func StartHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return server.URL
}
func StartRetryHttpServer(t *testing.T, handlers []TestRequestHandler) string {
// StartRetryHTTPServer starts a TCP based HTTP server with retry capabilities
func StartRetryHTTPServer(t *testing.T, handlers []TestRequestHandler) string {
attempts := map[string]int{}
retryMiddileware := func(next func(w http.ResponseWriter, r *http.Request)) http.Handler {
Loading
Loading
@@ -92,7 +95,8 @@ func StartRetryHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return server.URL
}
func StartHttpsServer(t *testing.T, handlers []TestRequestHandler, clientCAPath string) string {
// StartHTTPSServer starts a TCP based HTTPS capable server
func StartHTTPSServer(t *testing.T, handlers []TestRequestHandler, clientCAPath string) string {
t.Helper()
testRoot := testhelper.PrepareTestRootDir(t)
Loading
Loading
// Package client provides an HTTP client with enhanced logging, tracing, and correlation handling.
package client
import (
Loading
Loading
@@ -13,6 +14,7 @@ type transport struct {
next http.RoundTripper
}
// RoundTrip executes a single HTTP transaction, adding logging and tracing capabilities.
func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) {
ctx := request.Context()
Loading
Loading
@@ -55,10 +57,12 @@ func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) {
return response, nil
}
// DefaultTransport returns a clone of the default HTTP transport.
func DefaultTransport() http.RoundTripper {
return http.DefaultTransport.(*http.Transport).Clone()
}
// NewTransport creates a new transport with logging, tracing, and correlation handling.
func NewTransport(next http.RoundTripper) http.RoundTripper {
t := &transport{next: next}
return correlation.NewInstrumentedRoundTripper(tracing.NewRoundTripper(t))
Loading
Loading
// Package command provides functionality for handling gitlab-shell authorized keys commands
package command
import (
Loading
Loading
@@ -9,6 +10,7 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/config"
)
// New creates a new command based on the provided arguments, configuration, and readwriter
func New(arguments []string, config *config.Config, readWriter *readwriter.ReadWriter) (command.Command, error) {
args, err := Parse(arguments)
if err != nil {
Loading
Loading
@@ -22,6 +24,7 @@ func New(arguments []string, config *config.Config, readWriter *readwriter.ReadW
return nil, disallowedcommand.Error
}
// Parse parses the provided arguments and returns an AuthorizedKeys command
func Parse(arguments []string) (*commandargs.AuthorizedKeys, error) {
args := &commandargs.AuthorizedKeys{Arguments: arguments}
Loading
Loading