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 (637)
Loading
@@ -7,20 +7,17 @@
Loading
@@ -7,20 +7,17 @@
.gitlab_shell_secret .gitlab_shell_secret
.idea .idea
/*.log* /*.log*
/bin/check /bin/*
/bin/gitlab-shell /gl-code-quality-report.json
/bin/gitlab-shell-authorized-keys-check
/bin/gitlab-shell-authorized-principals-check
/bin/gitlab-sshd
/go_build /go_build
/support/bin/golangci-*
/support/bin/gotestsum-*
authorized_keys.lock authorized_keys.lock
config.yml config.yml
cover.out cover.out
cover.xml cover.xml
custom_hooks custom_hooks
hooks/*.d hooks/*.d
/support/bin/golangci-*
/support/bin/gotestsum-*
tags tags
tmp/* tmp/*
vendor vendor
Loading
@@ -3,26 +3,29 @@ include:
Loading
@@ -3,26 +3,29 @@ include:
- template: Security/SAST.gitlab-ci.yml - template: Security/SAST.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml - template: Security/Secret-Detection.gitlab-ci.yml
- project: 'gitlab-org/quality/pipeline-common'
file:
- '/ci/danger-review.yml'
stages: stages:
- prepare - prepare
- lint
- test - test
- post-test
variables: variables:
FF_USE_FASTZIP: 'true' FF_USE_FASTZIP: 'true'
TRANSFER_METER_FREQUENCY: "1s" TRANSFER_METER_FREQUENCY: "1s"
DOCKER_VERSION: "20.10.15" DOCKER_VERSION: "20.10.15"
BUNDLE_FROZEN: "true" BUNDLE_FROZEN: "true"
GO_VERSION: "golang-1.20" GO_VERSION: "1.23"
GOPATH: $CI_PROJECT_DIR/.GOPATH GOPATH: $CI_PROJECT_DIR/.GOPATH
DEBIAN_VERSION: "bullseye" DEBIAN_VERSION: "bookworm"
RUBY_VERSION: "ruby-3.2" RUBY_VERSION: "3.2.5"
BUNDLE_PATH: vendor/ruby BUNDLE_PATH: vendor/ruby
POLICY: pull POLICY: pull
CI_DEBUG_SERVICES: 'true' CI_DEBUG_SERVICES: 'true'
RUST_VERSION: "1.73"
UBI_VERSION: "8.6"
IMAGE_TAG: "rubygems-3.5-git-2.45-exiftool-12.60"
GITLAB_ADVANCED_SAST_ENABLED: 'true'
workflow: workflow:
rules: &workflow_rules rules: &workflow_rules
Loading
@@ -33,8 +36,15 @@ workflow:
Loading
@@ -33,8 +36,15 @@ workflow:
# For tags, create a pipeline. # For tags, create a pipeline.
- if: '$CI_COMMIT_TAG' - if: '$CI_COMMIT_TAG'
.rules:go-changes:
rules:
- changes:
- 'go.mod'
- 'go.sum'
- '**/*.go'
default: default:
image: registry.gitlab.com/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-${RUBY_VERSION}-${GO_VERSION}-rust-1.65:rubygems-3.4-git-2.36-exiftool-12.60 image: registry.gitlab.com/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:${IMAGE_TAG}
tags: tags:
- gitlab-org - gitlab-org
Loading
@@ -48,7 +58,7 @@ default:
Loading
@@ -48,7 +58,7 @@ default:
.cached-go: &cached_go .cached-go: &cached_go
- key: - key:
prefix: $GO_VERSION-cache prefix: "golang-${GO_VERSION}-cache"
files: files:
- go.mod - go.mod
- go.sum - go.sum
Loading
@@ -58,7 +68,7 @@ default:
Loading
@@ -58,7 +68,7 @@ default:
.cached-ruby: &cached_ruby .cached-ruby: &cached_ruby
- key: - key:
prefix: $RUBY_VERSION-cache prefix: "ruby-${RUBY_VERSION}-cache"
files: files:
- Gemfile.lock - Gemfile.lock
policy: $POLICY policy: $POLICY
Loading
@@ -83,7 +93,7 @@ default:
Loading
@@ -83,7 +93,7 @@ default:
.go-matrix-job: .go-matrix-job:
parallel: parallel:
matrix: matrix:
- GO_VERSION: ["golang-1.19", "golang-1.20", "golang-1.21"] - GO_VERSION: ["1.22", "1.23"]
################################################################################ ################################################################################
# Prepare jobs # Prepare jobs
Loading
@@ -113,6 +123,7 @@ modules:download:
Loading
@@ -113,6 +123,7 @@ modules:download:
.test-job: .test-job:
needs: ['bundle:install', 'modules:download'] needs: ['bundle:install', 'modules:download']
rules: !reference [".rules:go-changes", rules]
variables: variables:
GITALY_CONNECTION_INFO: '{"address":"tcp://gitaly:8075", "storage":"default"}' GITALY_CONNECTION_INFO: '{"address":"tcp://gitaly:8075", "storage":"default"}'
before_script: before_script:
Loading
@@ -124,7 +135,7 @@ modules:download:
Loading
@@ -124,7 +135,7 @@ modules:download:
services: services:
- name: registry.gitlab.com/gitlab-org/build/cng/gitaly:master - name: registry.gitlab.com/gitlab-org/build/cng/gitaly:master
# Disable the hooks so we don't have to stub the GitLab API # Disable the hooks so we don't have to stub the GitLab API
command: ["bash", "-c", "mkdir -p /home/git/repositories && rm -rf /srv/gitlab-shell/hooks/* && touch /srv/gitlab-shell/.gitlab_shell_secret && cp /etc/gitaly/config.toml.erb /etc/gitaly/config.toml 2>/dev/null && exec /usr/bin/env GITALY_TESTING_NO_GIT_HOOKS=1 /scripts/process-wrapper"] command: ["bash", "-c", "mkdir -p /home/git/repositories && rm -rf /srv/gitlab-shell/hooks/* && touch /srv/gitlab-shell/.gitlab_shell_secret && exec /usr/bin/env GITALY_TESTING_NO_GIT_HOOKS=1 /scripts/process-wrapper"]
alias: gitaly alias: gitaly
tests: tests:
Loading
@@ -144,6 +155,26 @@ tests:
Loading
@@ -144,6 +155,26 @@ tests:
reports: reports:
junit: cover.xml junit: cover.xml
tests_without_cgo:
extends:
- .cached-job
- .go-matrix-job
- .test-job
variables:
CGO_ENABLED: 0
script:
- make verify test_fancy
tests:fips:
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
variables:
FIPS_MODE: 1
script:
- make test_fancy
race: race:
extends: extends:
- .cached-go-job - .cached-go-job
Loading
@@ -153,10 +184,12 @@ race:
Loading
@@ -153,10 +184,12 @@ race:
- make test_golang_race - make test_golang_race
code_quality: code_quality:
stage: lint
extends: .use-docker-in-docker extends: .use-docker-in-docker
rules: *workflow_rules rules: *workflow_rules
code_navigation: code_navigation:
stage: post-test
image: sourcegraph/lsif-go:v1.9 image: sourcegraph/lsif-go:v1.9
allow_failure: true allow_failure: true
script: script:
Loading
@@ -167,17 +200,25 @@ code_navigation:
Loading
@@ -167,17 +200,25 @@ code_navigation:
# SAST # SAST
semgrep-sast: semgrep-sast:
stage: lint
rules: *workflow_rules
gitlab-advanced-sast:
stage: lint
rules: *workflow_rules rules: *workflow_rules
# Dependency Scanning # Dependency Scanning
gemnasium-dependency_scanning: gemnasium-dependency_scanning:
stage: lint
rules: *workflow_rules rules: *workflow_rules
# Secret Detection # Secret Detection
secret_detection: secret_detection:
stage: lint
rules: *workflow_rules rules: *workflow_rules
build-package-and-qa: build-package-and-qa:
stage: post-test
trigger: trigger:
project: 'gitlab-org/build/omnibus-gitlab-mirror' project: 'gitlab-org/build/omnibus-gitlab-mirror'
branch: 'master' branch: 'master'
Loading
@@ -209,20 +250,34 @@ build-package-and-qa:
Loading
@@ -209,20 +250,34 @@ build-package-and-qa:
needs: [] needs: []
modules:tidy: modules:tidy:
stage: lint
needs: ['modules:download'] needs: ['modules:download']
script: script:
- go mod tidy - go mod tidy
- git diff --exit-code go.mod go.sum - git diff --exit-code go.mod go.sum
lint: lint:
stage: test stage: lint
script: script:
# Write the code coverage report to gl-code-quality-report.json # 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 # and print linting issues to stdout in the format: path/to/file:line description
# remove `--issues-exit-code 0` or set to non-zero to fail the job if linting issues are detected # remove `--issues-exit-code 0` or set to non-zero to fail the job if linting issues are detected
- make lint GOLANGCI_LINT_ARGS="--out-format code-climate:gl-code-quality-report.json,line-number" - apt update && apt install -y jq
- make lint GOLANGCI_LINT_ARGS="--out-format code-climate:gl-code-quality-report-temp.json,line-number"
- cat gl-code-quality-report-temp.json | jq '[ .[] | select(.severity == "warning").severity |= "minor" ]' > gl-code-quality-report.json
- rm -f gl-code-quality-report-temp.json
artifacts: artifacts:
reports: reports:
codequality: gl-code-quality-report.json codequality: gl-code-quality-report.json
paths: paths:
- gl-code-quality-report.json - gl-code-quality-report.json
nilaway:
stage: lint
rules: !reference [".rules:go-changes", rules]
before_script:
- go install go.uber.org/nilaway/cmd/nilaway@latest
script:
- ${GOPATH}/bin/nilaway ./... > /tmp/out.txt 2>&1 || true
- cat /tmp/out.txt
allow_failure: true
# https://gitlab.com/groups/gitlab-org/maintainers/gitlab-shell/-/group_members?with_inherited_permissions=exclude # https://gitlab.com/groups/gitlab-org/maintainers/gitlab-shell/-/group_members?with_inherited_permissions=exclude
* @gitlab-org/maintainers/gitlab-shell * @gitlab-org/maintainers/gitlab-shell
[Documentation] [Documentation] @gl-docsteam
*.md @aqualls *.md
/doc/
Loading
@@ -52,7 +52,8 @@ run:
Loading
@@ -52,7 +52,8 @@ run:
# output configuration options # output configuration options
output: output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: line-number formats:
- format: line-number
# print lines of code with issue, default is true # print lines of code with issue, default is true
print-issued-lines: true print-issued-lines: true
Loading
@@ -60,6 +61,8 @@ output:
Loading
@@ -60,6 +61,8 @@ output:
# print linter name in the end of issue text, default is true # print linter name in the end of issue text, default is true
print-linter-name: true print-linter-name: true
sort-results: true
# all available settings of specific linters # all available settings of specific linters
linters-settings: linters-settings:
errcheck: errcheck:
Loading
@@ -75,6 +78,7 @@ linters-settings:
Loading
@@ -75,6 +78,7 @@ linters-settings:
# the regex is used to ignore names within pkg. (default "fmt:.*"). # the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details # see https://github.com/kisielk/errcheck#the-deprecated-method for details
# ignore: fmt:.*,io/ioutil:^Read.* # ignore: fmt:.*,io/ioutil:^Read.*
ignore: ''
# path to a file containing a list of functions to exclude from checking # path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details # see https://github.com/kisielk/errcheck#excluding-functions for details
Loading
@@ -91,7 +95,8 @@ linters-settings:
Loading
@@ -91,7 +95,8 @@ linters-settings:
govet: govet:
# report about shadowed variables # report about shadowed variables
check-shadowing: true enable:
- shadow
# settings per analyzer # settings per analyzer
settings: settings:
Loading
@@ -109,9 +114,6 @@ linters-settings:
Loading
@@ -109,9 +114,6 @@ linters-settings:
# disable: # disable:
# - shadow # - shadow
# disable-all: false # disable-all: false
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.8
gofmt: gofmt:
# simplify code: gofmt with `-s` option, true by default # simplify code: gofmt with `-s` option, true by default
simplify: true simplify: true
Loading
@@ -136,7 +138,27 @@ linters-settings:
Loading
@@ -136,7 +138,27 @@ linters-settings:
min-len: 3 min-len: 3
# minimal occurrences count to trigger, 3 by default # minimal occurrences count to trigger, 3 by default
min-occurrences: 3 min-occurrences: 3
# depguard: depguard:
rules:
test:
files:
- $test
allow:
- $gostd
- github.com/stretchr/testify
- gitlab.com/gitlab-org/gitlab-shell
- gitlab.com/gitlab-org/labkit
- gitlab.com/gitlab-org/gitaly
- github.com/prometheus/client_golang/prometheus
- github.com/pires/go-proxyproto
- github.com/otiai10/copy
- github.com/hashicorp/go-retryablehttp
- github.com/golang-jwt/jwt
- github.com/mikesmitty/edkey
- github.com/sirupsen/logrus
- github.com/grpc-ecosystem/go-grpc-prometheus
- github.com/mattn/go-shellwords
# list-type: blacklist # list-type: blacklist
# include-go-root: false # include-go-root: false
# packages: # packages:
Loading
@@ -242,6 +264,7 @@ linters:
Loading
@@ -242,6 +264,7 @@ linters:
disable-all: true disable-all: true
enable: enable:
- bodyclose - bodyclose
- copyloopvar
- depguard - depguard
- dogsled - dogsled
- dupl - dupl
Loading
@@ -253,18 +276,16 @@ linters:
Loading
@@ -253,18 +276,16 @@ linters:
- godox - godox
- gofmt - gofmt
- goimports - goimports
- golint
- gosec - gosec
- gosimple - gosimple
- govet - govet
- ineffassign - ineffassign
- interfacer
- misspell - misspell
- nakedret - nakedret
- scopelint - revive
- staticcheck - staticcheck
- structcheck
- stylecheck - stylecheck
- testifylint
- typecheck - typecheck
- unconvert - unconvert
- unparam - unparam
Loading
Loading
3.2.2 3.3.4
ruby 3.2.2 ruby 3.3.5
golang 1.21.4 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
- Update github.com/charmbracelet/git-lfs-transfer digest to f0b226f !990
- Update module google.golang.org/grpc to v1.63.2 !993
- Update dependency golang to v1.22.2 !992
- Update golangci-lint to 1.57.2 !988
- Remove Gitlab-Shared-Secret reference that is no longer used !985
- git-lfs-transfer: Enable in shell and introduce batch download !942
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.10.0 !983
- Update golangci-lint to 1.57.1 !984
- Update github.com/charmbracelet/git-lfs-transfer digest to 6dbff1b !981
- Update dependency gitlab-dangerfiles to '~> 4.7.0' !982
- chore: Fix lint issues in cmd/gitlab-sshd/acceptance_test.go !979
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.9.2 !980
- Update module google.golang.org/protobuf to v1.33.0 !977
- Update module google.golang.org/grpc to v1.62.1 !976
- Update github.com/charmbracelet/git-lfs-transfer digest to 00bfe2e !974
- Update module github.com/golang-jwt/jwt/v5 to v5.2.1 !973
- Update module golang.org/x/crypto to v0.21.0 !972
- chore: Fixed lint issues in internal/testhelper/testhelper.go !978
- Update dependency golang to v1.22.1 !975
- Update module github.com/stretchr/testify to v1.9.0 !970
- Update github.com/charmbracelet/git-lfs-transfer digest to 3853b28 !968
- Update github.com/charmbracelet/git-lfs-transfer digest to df8ee50 !971
- Update module golang.org/x/crypto to v0.20.0 !966
- Update module github.com/prometheus/client_golang to v1.19.0 !967
- Update module google.golang.org/grpc to v1.62.0 !964
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.9.1 !963
v14.34.0
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.9.0 !960
- Update golangci-lint and gotestsum to latest stable !962
- Also test against go 1.22 !949
- Update dependency golang to v1.22.0 !952
- Update module google.golang.org/grpc to v1.61.1 !961
- Update github.com/charmbracelet/git-lfs-transfer digest to e8645ad !959
- Update github.com/charmbracelet/git-lfs-transfer digest to 8d8e152 !957
- Upgrade to using bookworm instead of bullseye !956
- Update GOLANGCI_LINT_VERSION to 1.56.1 !958
- Update golangci lint to v1.56.0 !954
- Set random correlation ID in uploadarchive test !955
- Update module golang.org/x/crypto to v0.19.0 !953
- Use GracefulStop() instead of Stop() !951
- Update dependency rspec to '~> 3.13.0' !947
- Fix scanner findings error !948
- Log error instead of warning when parsing keys !944
- Fix PureSSHProtocal name typo !945
- Update github.com/charmbracelet/git-lfs-transfer digest to 732ff5e !943
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.9.0-rc3 !941
- Run CI with FIPS_MODE enabled !940
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.8.1 !939
- Update module google.golang.org/grpc to v1.61.0 !937
- New lfs.pure_ssh_protocol setting !936
- Update local Ruby version !938
v14.33.0
- Load gssapi lib per server/connection !934
- Update module google.golang.org/grpc to v1.60.0 !912
- Expose error messages for failed Git operations !906
- Update module google.golang.org/protobuf to v1.32.0 !918
- Ensure build tags are used when testing !921
- Update module golang.org/x/sync to v0.6.0 !922
- Update module golang.org/x/crypto to v0.18.0 !923
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.8.0 !932
v14.32.0
- Geo: Add `done` pktline when git clone --depth option is given !905
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.6.1 !907
- Update module github.com/golang-jwt/jwt/v5 to v5.2.0 !908
- Update module golang.org/x/crypto to v0.16.0 !904
- Replace os.MkdirTemp() usages with t.TempDir() !909
- Update dependency golang to v1.21.5 !911
v14.31.0
- Update dependency gitlab-dangerfiles to '~> 4.6.0' !887
- Update module golang.org/x/crypto to v0.15.0 !884
- Revert workaround to start gitaly service in test !891
- Update module gitlab.com/gitlab-org/gitaly/v16 to v16.6.0 !890
- Remove the RPC call for Namespace removal !895
- Update module gitlab.com/gitlab-org/labkit to v1.21.0 !892
- Revert sending SSH certificate as a separate protocol !894
- Bump GO_VERSION to 1.21 !898
- Drop support for go 1.19 !899
- Move global tempDir into StartSocketHttpServer() !902
- New nilaway CI job !897
- Resolve "Remove NilAway detections for 'client' package" !896
- call git_autid_event during git pull/clone if in need !888
v14.30.1 v14.30.1
- Update dependency golang to v1.21.4 !881 - Update dependency golang to v1.21.4 !881
Loading
Loading
source 'https://rubygems.org' source 'https://rubygems.org'
group :development, :test do group :development, :test do
gem 'rspec', '~> 3.12.0' gem 'rspec', '~> 3.13.0'
gem 'webrick', '~> 1.8', '>= 1.8.1' gem 'webrick', '~> 1.8', '>= 1.8.2'
end end
group :development, :danger do group :development, :danger do
gem 'gitlab-dangerfiles', '~> 4.5.1' gem 'gitlab-dangerfiles', '~> 4.8.0'
end end
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
addressable (2.8.5) addressable (2.8.7)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 7.0)
base64 (0.1.1) bigdecimal (3.1.8)
claide (1.1.0) claide (1.1.0)
claide-plugins (0.9.2) claide-plugins (0.9.2)
cork cork
Loading
@@ -12,7 +12,8 @@ GEM
Loading
@@ -12,7 +12,8 @@ GEM
colored2 (3.1.2) colored2 (3.1.2)
cork (0.3.0) cork (0.3.0)
colored2 (~> 3.1) colored2 (~> 3.1)
danger (9.3.2) csv (3.3.0)
danger (9.4.3)
claide (~> 1.0) claide (~> 1.0)
claide-plugins (>= 0.9.2) claide-plugins (>= 0.9.2)
colored2 (~> 3.1) colored2 (~> 3.1)
Loading
@@ -23,30 +24,30 @@ GEM
Loading
@@ -23,30 +24,30 @@ GEM
kramdown (~> 2.3) kramdown (~> 2.3)
kramdown-parser-gfm (~> 1.0) kramdown-parser-gfm (~> 1.0)
no_proxy_fix no_proxy_fix
octokit (~> 6.0) octokit (>= 4.0)
terminal-table (>= 1, < 4) terminal-table (>= 1, < 4)
danger-gitlab (8.0.0) danger-gitlab (8.0.0)
danger danger
gitlab (~> 4.2, >= 4.2.0) gitlab (~> 4.2, >= 4.2.0)
diff-lcs (1.5.0) diff-lcs (1.5.1)
faraday (2.7.11) faraday (2.9.2)
base64 faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (>= 2.0, < 3.1) faraday-http-cache (2.5.1)
ruby2_keywords (>= 0.0.4)
faraday-http-cache (2.5.0)
faraday (>= 0.8) faraday (>= 0.8)
faraday-net_http (3.0.2) faraday-net_http (3.1.0)
git (1.18.0) net-http
git (1.19.1)
addressable (~> 2.8) addressable (~> 2.8)
rchardet (~> 1.8) rchardet (~> 1.8)
gitlab (4.19.0) gitlab (4.20.1)
httparty (~> 0.20) httparty (~> 0.20)
terminal-table (>= 1.5.1) terminal-table (>= 1.5.1)
gitlab-dangerfiles (4.5.1) gitlab-dangerfiles (4.8.0)
danger (>= 9.3.0) danger (>= 9.3.0)
danger-gitlab (>= 8.0.0) danger-gitlab (>= 8.0.0)
rake (~> 13.0) rake (~> 13.0)
httparty (0.21.0) httparty (0.22.0)
csv
mini_mime (>= 1.0.0) mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
kramdown (2.4.0) kramdown (2.4.0)
Loading
@@ -54,46 +55,51 @@ GEM
Loading
@@ -54,46 +55,51 @@ GEM
kramdown-parser-gfm (1.1.0) kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0) kramdown (~> 2.0)
mini_mime (1.1.5) mini_mime (1.1.5)
multi_xml (0.6.0) multi_xml (0.7.1)
bigdecimal (~> 3.1)
nap (1.1.0) nap (1.1.0)
net-http (0.4.1)
uri
no_proxy_fix (0.1.2) no_proxy_fix (0.1.2)
octokit (6.1.1) octokit (6.1.1)
faraday (>= 1, < 3) faraday (>= 1, < 3)
sawyer (~> 0.9) sawyer (~> 0.9)
open4 (1.3.4) open4 (1.3.4)
public_suffix (5.0.3) public_suffix (5.1.1)
rake (13.1.0) rake (13.2.1)
rchardet (1.8.0) rchardet (1.8.0)
rexml (3.2.6) rexml (3.3.1)
rspec (3.12.0) strscan
rspec-core (~> 3.12.0) rspec (3.13.0)
rspec-expectations (~> 3.12.0) rspec-core (~> 3.13.0)
rspec-mocks (~> 3.12.0) rspec-expectations (~> 3.13.0)
rspec-core (3.12.2) rspec-mocks (~> 3.13.0)
rspec-support (~> 3.12.0) rspec-core (3.13.0)
rspec-expectations (3.12.3) rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0) rspec-support (~> 3.13.0)
rspec-mocks (3.12.5) rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0) rspec-support (~> 3.13.0)
rspec-support (3.12.0) rspec-support (3.13.0)
ruby2_keywords (0.0.5)
sawyer (0.9.2) sawyer (0.9.2)
addressable (>= 2.3.5) addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3) faraday (>= 0.17.3, < 3)
strscan (3.1.0)
terminal-table (3.0.2) terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (>= 1.1.1, < 3)
unicode-display_width (2.5.0) unicode-display_width (2.5.0)
webrick (1.8.1) uri (0.13.0)
webrick (1.8.2)
PLATFORMS PLATFORMS
ruby ruby
DEPENDENCIES DEPENDENCIES
gitlab-dangerfiles (~> 4.5.1) gitlab-dangerfiles (~> 4.8.0)
rspec (~> 3.12.0) rspec (~> 3.13.0)
webrick (~> 1.8, >= 1.8.1) webrick (~> 1.8, >= 1.8.2)
BUNDLED WITH BUNDLED WITH
2.4.21 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 FIPS_MODE ?= 0
OS := $(shell uname | tr A-Z a-z) OS := $(shell uname | tr A-Z a-z)
GO_SOURCES := $(shell git ls-files \*.go) GO_SOURCES := $(shell git ls-files \*.go)
VERSION_STRING := $(shell git describe --match v* 2>/dev/null || awk '$$0="v"$$0' VERSION 2>/dev/null || echo unknown) VERSION_STRING := $(shell git describe --match v* 2>/dev/null || awk '$$0="v"$$0' VERSION 2>/dev/null || echo unknown)
BUILD_TIME := $(shell date -u +%Y%m%d.%H%M%S) BUILD_TIME := $(shell date -u +%Y%m%d.%H%M%S)
BUILD_TAGS := tracer_static tracer_static_jaeger continuous_profiler_stackdriver gssapi 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/') ARCH ?= $(shell uname -m | sed -e 's/x86_64/amd64/' | sed -e 's/aarch64/arm64/')
GOTESTSUM_VERSION := 1.10.0 GOTESTSUM_VERSION := 1.12.0
GOTESTSUM_VERSION_ARCH ?= ${ARCH}
GOTESTSUM_FILE := support/bin/gotestsum-${GOTESTSUM_VERSION} GOTESTSUM_FILE := support/bin/gotestsum-${GOTESTSUM_VERSION}
GOLANGCI_LINT_VERSION := 1.54.2 GOLANGCI_LINT_VERSION := 1.60.3
GOLANGCI_LINT_ARCH ?= ${ARCH}
GOLANGCI_LINT_FILE := support/bin/golangci-lint-${GOLANGCI_LINT_VERSION} GOLANGCI_LINT_FILE := support/bin/golangci-lint-${GOLANGCI_LINT_VERSION}
export GOFLAGS := -mod=readonly export GOFLAGS := -mod=readonly
ifeq (${FIPS_MODE}, 1) ifeq (${FIPS_MODE}, 1)
GO_TAGS += fips
# If the golang-fips compiler is built with CGO_ENABLED=0, this needs to be
# explicitly switched on.
export CGO_ENABLED=1
# Go 1.19 now requires GOEXPERIMENT=boringcrypto for FIPS compilation. # Go 1.19 now requires GOEXPERIMENT=boringcrypto for FIPS compilation.
# See https://github.com/golang/go/issues/51940 for more details. # See https://github.com/golang/go/issues/51940 for more details.
BORINGCRYPTO_SUPPORT := $(shell GOEXPERIMENT=boringcrypto go version > /dev/null 2>&1; echo $$?) BORINGCRYPTO_SUPPORT := $(shell GOEXPERIMENT=boringcrypto go version > /dev/null 2>&1; echo $$?)
ifeq ($(BORINGCRYPTO_SUPPORT), 0) ifeq ($(BORINGCRYPTO_SUPPORT), 0)
GOBUILD_ENV=GOEXPERIMENT=boringcrypto export GOEXPERIMENT=boringcrypto
endif endif
endif
BUILD_TAGS += fips ifneq (${CGO_ENABLED}, 0)
# If the golang-fips compiler is built with CGO_ENABLED=0, this needs to be GO_TAGS += gssapi
# explicitly switched on.
export CGO_ENABLED=1
endif endif
ifeq (${OS}, darwin) # Mac OS ifeq (${OS}, darwin) # Mac OS
Loading
@@ -40,7 +43,7 @@ ifeq (${OS}, darwin) # Mac OS
Loading
@@ -40,7 +43,7 @@ ifeq (${OS}, darwin) # Mac OS
export CGO_CFLAGS="-I$(BREW_PREFIX)/opt/heimdal/include" export CGO_CFLAGS="-I$(BREW_PREFIX)/opt/heimdal/include"
endif endif
GOBUILD_FLAGS := -ldflags "-X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)" -tags "$(BUILD_TAGS)" -mod=mod GOBUILD_FLAGS := -ldflags "-X main.Version=$(VERSION_STRING) -X main.BuildTime=$(BUILD_TIME)" -tags "$(GO_TAGS)" -mod=mod
PREFIX ?= /usr/local PREFIX ?= /usr/local
Loading
@@ -65,14 +68,15 @@ test_ruby:
Loading
@@ -65,14 +68,15 @@ test_ruby:
bundle exec rspec --color --format d spec bundle exec rspec --color --format d spec
test_golang: test_golang:
go test -cover -coverprofile=cover.out -count 1 ./... go test -cover -coverprofile=cover.out -count 1 -tags "$(GO_TAGS)" ./...
test_golang_fancy: ${GOTESTSUM_FILE} test_golang_fancy: ${GOTESTSUM_FILE}
@./${GOTESTSUM_FILE} --junitfile ./cover.xml --format pkgname -- -coverprofile=./cover.out -covermode=atomic -count 1 ./... @${GOTESTSUM_FILE} --version
@${GOTESTSUM_FILE} --junitfile ./cover.xml --format pkgname -- -coverprofile=./cover.out -covermode=atomic -count 1 -tags "$(GO_TAGS)" ./...
${GOTESTSUM_FILE}: ${GOTESTSUM_FILE}:
mkdir -p $(shell dirname ${GOTESTSUM_FILE}) mkdir -p $(shell dirname ${GOTESTSUM_FILE})
curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_${OS}_${GOTESTSUM_VERSION_ARCH}.tar.gz | tar -zOxf - gotestsum > ${GOTESTSUM_FILE} && chmod +x ${GOTESTSUM_FILE} curl -L https://github.com/gotestyourself/gotestsum/releases/download/v${GOTESTSUM_VERSION}/gotestsum_${GOTESTSUM_VERSION}_${OS}_${ARCH}.tar.gz | tar -zOxf - gotestsum > ${GOTESTSUM_FILE} && chmod +x ${GOTESTSUM_FILE}
test_golang_race: test_golang_race:
go test -race -count 1 ./... go test -race -count 1 ./...
Loading
@@ -82,35 +86,42 @@ coverage: coverage_golang
Loading
@@ -82,35 +86,42 @@ coverage: coverage_golang
coverage_golang: coverage_golang:
[ -f cover.out ] && go tool cover -func cover.out [ -f cover.out ] && go tool cover -func cover.out
lint: ${GOLANGCI_LINT_FILE} lint:
${GOLANGCI_LINT_FILE} run --issues-exit-code 0 --print-issued-lines=false ${GOLANGCI_LINT_ARGS} @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}: ${GOLANGCI_LINT_FILE}:
mkdir -p $(shell dirname ${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}-${GOLANGCI_LINT_ARCH}.tar.gz | tar --strip-components 1 -zOxf - golangci-lint-${GOLANGCI_LINT_VERSION}-${OS}-${GOLANGCI_LINT_ARCH}/golangci-lint > ${GOLANGCI_LINT_FILE} && chmod +x ${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: make_necessary_dirs:
bin/install support/make_necessary_dirs
compile: bin/gitlab-shell bin/gitlab-sshd compile: bin/gitlab-shell bin/gitlab-sshd
bin/gitlab-shell: $(GO_SOURCES)
GOBIN="$(CURDIR)/bin" $(GOBUILD_ENV) go install $(GOBUILD_FLAGS) ./cmd/...
bin/gitlab-sshd: $(GO_SOURCES) bin:
GOBIN="$(CURDIR)/bin" $(GOBUILD_ENV) go install $(GOBUILD_FLAGS) ./cmd/gitlab-sshd 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: check:
bin/check bin/gitlab-shell-check
clean: 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 install: compile
mkdir -p $(DESTDIR)$(PREFIX)/bin/ mkdir -p $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/check $(DESTDIR)$(PREFIX)/bin/check install -m755 bin/gitlab-shell-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell $(DESTDIR)$(PREFIX)/bin/gitlab-shell install -m755 bin/gitlab-shell $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell-authorized-keys-check $(DESTDIR)$(PREFIX)/bin/gitlab-shell-authorized-keys-check install -m755 bin/gitlab-shell-authorized-keys-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-shell-authorized-principals-check $(DESTDIR)$(PREFIX)/bin/gitlab-shell-authorized-principals-check install -m755 bin/gitlab-shell-authorized-principals-check $(DESTDIR)$(PREFIX)/bin/
install -m755 bin/gitlab-sshd $(DESTDIR)$(PREFIX)/bin/gitlab-sshd install -m755 bin/gitlab-sshd $(DESTDIR)$(PREFIX)/bin/
Loading
@@ -4,10 +4,48 @@ group: Source Code
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 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) [![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) [![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) [![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.30.1 14.39.0
Loading
@@ -13,6 +13,7 @@ import (
Loading
@@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver" "gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
Loading
@@ -25,7 +26,7 @@ var (
Loading
@@ -25,7 +26,7 @@ var (
) )
func TestClients(t *testing.T) { func TestClients(t *testing.T) {
testhelper.PrepareTestRootDir(t) testRoot := testhelper.PrepareTestRootDir(t)
testCases := []struct { testCases := []struct {
desc string desc string
Loading
@@ -36,45 +37,45 @@ func TestClients(t *testing.T) {
Loading
@@ -36,45 +37,45 @@ func TestClients(t *testing.T) {
}{ }{
{ {
desc: "Socket client", desc: "Socket client",
server: testserver.StartSocketHttpServer, server: testserver.StartSocketHTTPServer,
secret: secret, secret: secret,
}, },
{ {
desc: "Socket client with a relative URL at /", desc: "Socket client with a relative URL at /",
relativeURLRoot: "/", relativeURLRoot: "/",
server: testserver.StartSocketHttpServer, server: testserver.StartSocketHTTPServer,
secret: secret, secret: secret,
}, },
{ {
desc: "Socket client with relative URL at /gitlab", desc: "Socket client with relative URL at /gitlab",
relativeURLRoot: "/gitlab", relativeURLRoot: "/gitlab",
server: testserver.StartSocketHttpServer, server: testserver.StartSocketHTTPServer,
secret: secret, secret: secret,
}, },
{ {
desc: "Http client", desc: "Http client",
server: testserver.StartHttpServer, server: testserver.StartHTTPServer,
secret: secret, secret: secret,
}, },
{ {
desc: "Https client", desc: "Https client",
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
server: func(t *testing.T, handlers []testserver.TestRequestHandler) string { server: func(t *testing.T, handlers []testserver.TestRequestHandler) string {
return testserver.StartHttpsServer(t, handlers, "") return testserver.StartHTTPSServer(t, handlers, "")
}, },
secret: secret, secret: secret,
}, },
{ {
desc: "Secret with newlines", desc: "Secret with newlines",
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
server: func(t *testing.T, handlers []testserver.TestRequestHandler) string { server: func(t *testing.T, handlers []testserver.TestRequestHandler) string {
return testserver.StartHttpsServer(t, handlers, "") return testserver.StartHTTPSServer(t, handlers, "")
}, },
secret: "\n" + secret + "\n", secret: "\n" + secret + "\n",
}, },
{ {
desc: "Retry client", desc: "Retry client",
server: testserver.StartRetryHttpServer, server: testserver.StartRetryHTTPServer,
secret: secret, secret: secret,
}, },
} }
Loading
@@ -240,7 +241,7 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
Loading
@@ -240,7 +241,7 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
{ {
Path: "/api/v4/internal/hello", Path: "/api/v4/internal/hello",
Handler: func(w http.ResponseWriter, r *http.Request) { 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") fmt.Fprint(w, "Hello")
}, },
Loading
@@ -248,22 +249,16 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
Loading
@@ -248,22 +249,16 @@ func buildRequests(t *testing.T, relativeURLRoot string) []testserver.TestReques
{ {
Path: "/api/v4/internal/post_endpoint", Path: "/api/v4/internal/post_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) { 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) b, err := io.ReadAll(r.Body)
defer r.Body.Close() defer r.Body.Close()
require.NoError(t, err) assert.NoError(t, err)
fmt.Fprint(w, "Echo: "+string(b)) fmt.Fprint(w, "Echo: "+string(b))
}, },
}, },
{
Path: "/api/v4/internal/auth",
Handler: func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, r.Header.Get(secretHeaderName))
},
},
{ {
Path: "/api/v4/internal/jwt_auth", Path: "/api/v4/internal/jwt_auth",
Handler: func(w http.ResponseWriter, r *http.Request) { Handler: func(w http.ResponseWriter, r *http.Request) {
Loading
Loading
// Package client provides a client for interacting with GitLab API
package client package client
import ( import (
Loading
@@ -15,45 +16,48 @@ import (
Loading
@@ -15,45 +16,48 @@ import (
) )
const ( const (
internalApiPath = "/api/v4/internal" internalAPIPath = "/api/v4/internal"
secretHeaderName = "Gitlab-Shared-Secret" apiSecretHeaderName = "Gitlab-Shell-Api-Request" // #nosec G101
apiSecretHeaderName = "Gitlab-Shell-Api-Request"
defaultUserAgent = "GitLab-Shell" defaultUserAgent = "GitLab-Shell"
jwtTTL = time.Minute jwtTTL = time.Minute
jwtIssuer = "gitlab-shell" jwtIssuer = "gitlab-shell"
) )
// ErrorResponse represents an error response from the API
type ErrorResponse struct { type ErrorResponse struct {
Message string `json:"message"` Message string `json:"message"`
} }
// GitlabNetClient is a client for interacting with GitLab API
type GitlabNetClient struct { type GitlabNetClient struct {
httpClient *HttpClient httpClient *HTTPClient
user string user string
password string password string
secret string secret string
userAgent string userAgent string
} }
type ApiError struct { // APIError represents an API error
type APIError struct {
Msg string 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{} type OriginalRemoteIPContextKey struct{}
func (e *ApiError) Error() string { func (e *APIError) Error() string {
return e.Msg return e.Msg
} }
// NewGitlabNetClient creates a new GitlabNetClient instance
func NewGitlabNetClient( func NewGitlabNetClient(
user, user,
password, password,
secret string, secret string,
httpClient *HttpClient, httpClient *HTTPClient,
) (*GitlabNetClient, error) { ) (*GitlabNetClient, error) {
if httpClient == nil { if httpClient == nil {
return nil, fmt.Errorf("Unsupported protocol") return nil, fmt.Errorf("unsupported protocol")
} }
return &GitlabNetClient{ return &GitlabNetClient{
Loading
@@ -76,8 +80,8 @@ func normalizePath(path string) string {
Loading
@@ -76,8 +80,8 @@ func normalizePath(path string) string {
path = "/" + path path = "/" + path
} }
if !strings.HasPrefix(path, internalApiPath) { if !strings.HasPrefix(path, internalAPIPath) {
path = internalApiPath + path path = internalAPIPath + path
} }
return path return path
} }
Loading
@@ -106,40 +110,43 @@ func newRequest(ctx context.Context, method, host, path string, data interface{}
Loading
@@ -106,40 +110,43 @@ func newRequest(ctx context.Context, method, host, path string, data interface{}
} }
func parseError(resp *http.Response, respErr error) error { func parseError(resp *http.Response, respErr error) error {
if respErr != nil { if resp == nil || respErr != nil {
return &ApiError{"Internal API unreachable"} return &APIError{"Internal API unreachable"}
} }
if resp.StatusCode >= 200 && resp.StatusCode <= 399 { if resp.StatusCode >= 200 && resp.StatusCode <= 399 {
return nil return nil
} }
defer resp.Body.Close() defer func() { _ = resp.Body.Close() }()
parsedResponse := &ErrorResponse{} parsedResponse := &ErrorResponse{}
if err := json.NewDecoder(resp.Body).Decode(parsedResponse); err != nil { if err := json.NewDecoder(resp.Body).Decode(parsedResponse); err != nil {
return &ApiError{fmt.Sprintf("Internal API error (%v)", resp.StatusCode)} return &APIError{fmt.Sprintf("Internal API error (%v)", resp.StatusCode)}
} else {
return &ApiError{parsedResponse.Message}
} }
return &APIError{parsedResponse.Message}
} }
// Get makes a GET request
func (c *GitlabNetClient) Get(ctx context.Context, path string) (*http.Response, error) { func (c *GitlabNetClient) Get(ctx context.Context, path string) (*http.Response, error) {
return c.DoRequest(ctx, http.MethodGet, normalizePath(path), nil) 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) { func (c *GitlabNetClient) Post(ctx context.Context, path string, data interface{}) (*http.Response, error) {
return c.DoRequest(ctx, http.MethodPost, normalizePath(path), data) return c.DoRequest(ctx, http.MethodPost, normalizePath(path), data)
} }
// Do executes a request
func (c *GitlabNetClient) Do(request *http.Request) (*http.Response, error) { func (c *GitlabNetClient) Do(request *http.Request) (*http.Response, error) {
response, err := c.httpClient.RetryableHTTP.HTTPClient.Do(request) response, respErr := c.httpClient.RetryableHTTP.HTTPClient.Do(request)
if err := parseError(response, err); err != nil { if err := parseError(response, respErr); err != nil {
return nil, err return nil, err
} }
return response, nil 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) { 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) request, err := newRequest(ctx, method, c.httpClient.Host, path, data)
if err != nil { if err != nil {
Loading
@@ -166,8 +173,8 @@ func (c *GitlabNetClient) DoRequest(ctx context.Context, method, path string, da
Loading
@@ -166,8 +173,8 @@ func (c *GitlabNetClient) DoRequest(ctx context.Context, method, path string, da
request.Header.Add("Content-Type", "application/json") request.Header.Add("Content-Type", "application/json")
request.Header.Add("User-Agent", c.userAgent) request.Header.Add("User-Agent", c.userAgent)
response, err := c.httpClient.RetryableHTTP.Do(request) response, respErr := c.httpClient.RetryableHTTP.Do(request)
if err := parseError(response, err); err != nil { if err := parseError(response, respErr); err != nil {
return nil, err return nil, err
} }
Loading
Loading
// Package client provides functionality for interacting with HTTP clients
package client package client
import ( import (
Loading
@@ -17,19 +18,21 @@ import (
Loading
@@ -17,19 +18,21 @@ import (
) )
const ( const (
socketBaseUrl = "http://unix" socketBaseURL = "http://unix"
unixSocketProtocol = "http+unix://" unixSocketProtocol = "http+unix://"
httpProtocol = "http://" httpProtocol = "http://"
httpsProtocol = "https://" httpsProtocol = "https://"
defaultReadTimeoutSeconds = 300 defaultReadTimeoutSeconds = 300
defaultRetryWaitMin = time.Second defaultRetryWaitMinimum = time.Second
defaultRetryWaitMax = 15 * time.Second defaultRetryWaitMaximum = 15 * time.Second
defaultRetryMax = 2 defaultRetryMax = 2
) )
// ErrCafileNotFound indicates that the specified CA file was not found
var ErrCafileNotFound = errors.New("cafile 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 RetryableHTTP *retryablehttp.Client
Host string Host string
} }
Loading
@@ -55,6 +58,7 @@ func WithClientCert(certPath, keyPath string) HTTPClientOpt {
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 { func WithHTTPRetryOpts(waitMin, waitMax time.Duration, maxAttempts int) HTTPClientOpt {
return func(hcc *httpClientCfg) { return func(hcc *httpClientCfg) {
hcc.retryWaitMin = waitMin hcc.retryWaitMin = waitMin
Loading
@@ -80,12 +84,12 @@ func validateCaFile(filename string) error {
Loading
@@ -80,12 +84,12 @@ func validateCaFile(filename string) error {
} }
// NewHTTPClientWithOpts builds an HTTP client using the provided options // 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{ hcc := &httpClientCfg{
caFile: caFile, caFile: caFile,
caPath: caPath, caPath: caPath,
retryWaitMin: defaultRetryWaitMin, retryWaitMin: defaultRetryWaitMinimum,
retryWaitMax: defaultRetryWaitMax, retryWaitMax: defaultRetryWaitMaximum,
retryMax: defaultRetryMax, retryMax: defaultRetryMax,
} }
Loading
@@ -96,21 +100,21 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
Loading
@@ -96,21 +100,21 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
var transport *http.Transport var transport *http.Transport
var host string var host string
var err error var err error
if strings.HasPrefix(gitlabURL, unixSocketProtocol) { switch {
case strings.HasPrefix(gitlabURL, unixSocketProtocol):
transport, host = buildSocketTransport(gitlabURL, gitlabRelativeURLRoot) transport, host = buildSocketTransport(gitlabURL, gitlabRelativeURLRoot)
} else if strings.HasPrefix(gitlabURL, httpProtocol) { case strings.HasPrefix(gitlabURL, httpProtocol):
transport, host = buildHttpTransport(gitlabURL) transport, host = buildHTTPTransport(gitlabURL)
} else if strings.HasPrefix(gitlabURL, httpsProtocol) { case strings.HasPrefix(gitlabURL, httpsProtocol):
err = validateCaFile(caFile) err = validateCaFile(caFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
transport, host, err = buildHTTPSTransport(*hcc, gitlabURL)
transport, host, err = buildHttpsTransport(*hcc, gitlabURL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { default:
return nil, errors.New("unknown GitLab URL prefix") return nil, errors.New("unknown GitLab URL prefix")
} }
Loading
@@ -122,7 +126,7 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
Loading
@@ -122,7 +126,7 @@ func NewHTTPClientWithOpts(gitlabURL, gitlabRelativeURLRoot, caFile, caPath stri
c.HTTPClient.Transport = NewTransport(transport) c.HTTPClient.Transport = NewTransport(transport)
c.HTTPClient.Timeout = readTimeout(readTimeoutSeconds) c.HTTPClient.Timeout = readTimeout(readTimeoutSeconds)
client := &HttpClient{RetryableHTTP: c, Host: host} client := &HTTPClient{RetryableHTTP: c, Host: host}
return client, nil return client, nil
} }
Loading
@@ -137,7 +141,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
Loading
@@ -137,7 +141,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
}, },
} }
host := socketBaseUrl host := socketBaseURL
gitlabRelativeURLRoot = strings.Trim(gitlabRelativeURLRoot, "/") gitlabRelativeURLRoot = strings.Trim(gitlabRelativeURLRoot, "/")
if gitlabRelativeURLRoot != "" { if gitlabRelativeURLRoot != "" {
host = host + "/" + gitlabRelativeURLRoot host = host + "/" + gitlabRelativeURLRoot
Loading
@@ -146,7 +150,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
Loading
@@ -146,7 +150,7 @@ func buildSocketTransport(gitlabURL, gitlabRelativeURLRoot string) (*http.Transp
return transport, host 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() certPool, err := x509.SystemCertPool()
if err != nil { if err != nil {
certPool = x509.NewCertPool() certPool = x509.NewCertPool()
Loading
@@ -172,9 +176,9 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
Loading
@@ -172,9 +176,9 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
} }
if hcc.HaveCertAndKey() { if hcc.HaveCertAndKey() {
cert, err := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath) cert, loadErr := tls.LoadX509KeyPair(hcc.certPath, hcc.keyPath)
if err != nil { if loadErr != nil {
return nil, "", err return nil, "", loadErr
} }
tlsConfig.Certificates = []tls.Certificate{cert} tlsConfig.Certificates = []tls.Certificate{cert}
} }
Loading
@@ -187,13 +191,13 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
Loading
@@ -187,13 +191,13 @@ func buildHttpsTransport(hcc httpClientCfg, gitlabURL string) (*http.Transport,
} }
func addCertToPool(certPool *x509.CertPool, fileName string) { func addCertToPool(certPool *x509.CertPool, fileName string) {
cert, err := os.ReadFile(fileName) cert, err := os.ReadFile(filepath.Clean(fileName))
if err == nil { if err == nil {
certPool.AppendCertsFromPEM(cert) certPool.AppendCertsFromPEM(cert)
} }
} }
func buildHttpTransport(gitlabURL string) (*http.Transport, string) { func buildHTTPTransport(gitlabURL string) (*http.Transport, string) {
return &http.Transport{}, gitlabURL return &http.Transport{}, gitlabURL
} }
Loading
Loading
Loading
@@ -10,6 +10,7 @@ import (
Loading
@@ -10,6 +10,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver" "gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
) )
Loading
@@ -34,7 +35,7 @@ func TestBasicAuthSettings(t *testing.T) {
Loading
@@ -34,7 +35,7 @@ func TestBasicAuthSettings(t *testing.T) {
{ {
Path: "/api/v4/internal/get_endpoint", Path: "/api/v4/internal/get_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) { 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")) fmt.Fprint(w, r.Header.Get("Authorization"))
}, },
Loading
@@ -42,7 +43,7 @@ func TestBasicAuthSettings(t *testing.T) {
Loading
@@ -42,7 +43,7 @@ func TestBasicAuthSettings(t *testing.T) {
{ {
Path: "/api/v4/internal/post_endpoint", Path: "/api/v4/internal/post_endpoint",
Handler: func(w http.ResponseWriter, r *http.Request) { 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")) fmt.Fprint(w, r.Header.Get("Authorization"))
}, },
Loading
@@ -68,6 +69,7 @@ func testBasicAuthHeaders(t *testing.T, response *http.Response) {
Loading
@@ -68,6 +69,7 @@ func testBasicAuthHeaders(t *testing.T, response *http.Response) {
require.NoError(t, err) require.NoError(t, err)
headerParts := strings.Split(string(responseBody), " ") headerParts := strings.Split(string(responseBody), " ")
require.NotNil(t, headerParts)
require.Equal(t, "Basic", headerParts[0]) require.Equal(t, "Basic", headerParts[0])
credentials, err := base64.StdEncoding.DecodeString(headerParts[1]) credentials, err := base64.StdEncoding.DecodeString(headerParts[1])
Loading
@@ -80,16 +82,17 @@ func TestEmptyBasicAuthSettings(t *testing.T) {
Loading
@@ -80,16 +82,17 @@ func TestEmptyBasicAuthSettings(t *testing.T) {
requests := []testserver.TestRequestHandler{ requests := []testserver.TestRequestHandler{
{ {
Path: "/api/v4/internal/empty_basic_auth", Path: "/api/v4/internal/empty_basic_auth",
Handler: func(w http.ResponseWriter, r *http.Request) { Handler: func(_ http.ResponseWriter, r *http.Request) {
require.Equal(t, "", r.Header.Get("Authorization")) assert.Equal(t, "", r.Header.Get("Authorization"))
}, },
}, },
} }
client := setup(t, "", "", requests) 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) require.NoError(t, err)
resp.Body.Close()
} }
func TestRequestWithUserAgent(t *testing.T) { func TestRequestWithUserAgent(t *testing.T) {
Loading
@@ -97,30 +100,33 @@ func TestRequestWithUserAgent(t *testing.T) {
Loading
@@ -97,30 +100,33 @@ func TestRequestWithUserAgent(t *testing.T) {
requests := []testserver.TestRequestHandler{ requests := []testserver.TestRequestHandler{
{ {
Path: "/api/v4/internal/default_user_agent", Path: "/api/v4/internal/default_user_agent",
Handler: func(w http.ResponseWriter, r *http.Request) { Handler: func(_ http.ResponseWriter, r *http.Request) {
require.Equal(t, defaultUserAgent, r.UserAgent()) assert.Equal(t, defaultUserAgent, r.UserAgent())
}, },
}, },
{ {
Path: "/api/v4/internal/override_user_agent", Path: "/api/v4/internal/override_user_agent",
Handler: func(w http.ResponseWriter, r *http.Request) { Handler: func(_ http.ResponseWriter, r *http.Request) {
require.Equal(t, gitalyUserAgent, r.UserAgent()) assert.Equal(t, gitalyUserAgent, r.UserAgent())
}, },
}, },
} }
client := setup(t, "", "", requests) 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) require.NoError(t, err)
client.SetUserAgent(gitalyUserAgent) client.SetUserAgent(gitalyUserAgent)
_, err = client.Get(context.Background(), "/override_user_agent") overriddenUserAgentResp, err := client.Get(context.Background(), "/override_user_agent")
require.NoError(t, err) require.NoError(t, err)
defaultUserAgentResp.Body.Close()
overriddenUserAgentResp.Body.Close()
} }
func setup(t *testing.T, username, password string, requests []testserver.TestRequestHandler) *GitlabNetClient { 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) httpClient, err := NewHTTPClientWithOpts(url, "", "", "", 1, nil)
require.NoError(t, err) require.NoError(t, err)
Loading
Loading
Loading
@@ -8,6 +8,7 @@ import (
Loading
@@ -8,6 +8,7 @@ import (
"path" "path"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver" "gitlab.com/gitlab-org/gitlab-shell/v14/client/testserver"
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper" "gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper"
Loading
@@ -15,6 +16,8 @@ import (
Loading
@@ -15,6 +16,8 @@ import (
//go:generate openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -out ../internal/testhelper/testdata/testroot/certs/client/server.crt -keyout ../internal/testhelper/testdata/testroot/certs/client/key.pem -subj "/C=US/ST=California/L=San Francisco/O=GitLab/OU=GitLab-Shell/CN=localhost" //go:generate openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -out ../internal/testhelper/testdata/testroot/certs/client/server.crt -keyout ../internal/testhelper/testdata/testroot/certs/client/key.pem -subj "/C=US/ST=California/L=San Francisco/O=GitLab/OU=GitLab-Shell/CN=localhost"
func TestSuccessfulRequests(t *testing.T) { func TestSuccessfulRequests(t *testing.T) {
testRoot := testhelper.PrepareTestRootDir(t)
testCases := []struct { testCases := []struct {
desc string desc string
caFile, caPath string caFile, caPath string
Loading
@@ -22,25 +25,25 @@ func TestSuccessfulRequests(t *testing.T) {
Loading
@@ -22,25 +25,25 @@ func TestSuccessfulRequests(t *testing.T) {
}{ }{
{ {
desc: "Valid CaFile", desc: "Valid CaFile",
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
}, },
{ {
desc: "Valid CaPath", desc: "Valid CaPath",
caPath: path.Join(testhelper.TestRoot, "certs/valid"), caPath: path.Join(testRoot, "certs/valid"),
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
}, },
{ {
desc: "Invalid cert with self signed cert option enabled", desc: "Invalid cert with self signed cert option enabled",
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
}, },
{ {
desc: "Client certs with CA", desc: "Client certs with CA",
caFile: path.Join(testhelper.TestRoot, "certs/valid/server.crt"), caFile: path.Join(testRoot, "certs/valid/server.crt"),
// Run the command "go generate httpsclient_test.go" to // Run the command "go generate httpsclient_test.go" to
// regenerate the following test fixtures: // regenerate the following test fixtures:
clientCAPath: path.Join(testhelper.TestRoot, "certs/client/server.crt"), clientCAPath: path.Join(testRoot, "certs/client/server.crt"),
clientCertPath: path.Join(testhelper.TestRoot, "certs/client/server.crt"), clientCertPath: path.Join(testRoot, "certs/client/server.crt"),
clientKeyPath: path.Join(testhelper.TestRoot, "certs/client/key.pem"), clientKeyPath: path.Join(testRoot, "certs/client/key.pem"),
}, },
} }
Loading
@@ -63,6 +66,8 @@ func TestSuccessfulRequests(t *testing.T) {
Loading
@@ -63,6 +66,8 @@ func TestSuccessfulRequests(t *testing.T) {
} }
func TestFailedRequests(t *testing.T) { func TestFailedRequests(t *testing.T) {
testRoot := testhelper.PrepareTestRootDir(t)
testCases := []struct { testCases := []struct {
desc string desc string
caFile string caFile string
Loading
@@ -72,17 +77,17 @@ func TestFailedRequests(t *testing.T) {
Loading
@@ -72,17 +77,17 @@ func TestFailedRequests(t *testing.T) {
}{ }{
{ {
desc: "Invalid CaFile", desc: "Invalid CaFile",
caFile: path.Join(testhelper.TestRoot, "certs/invalid/server.crt"), caFile: path.Join(testRoot, "certs/invalid/server.crt"),
expectedError: "Internal API unreachable", expectedError: "Internal API unreachable",
}, },
{ {
desc: "Missing CaFile", desc: "Missing CaFile",
caFile: path.Join(testhelper.TestRoot, "certs/invalid/missing.crt"), caFile: path.Join(testRoot, "certs/invalid/missing.crt"),
expectedCaFileNotFound: true, expectedCaFileNotFound: true,
}, },
{ {
desc: "Invalid CaPath", desc: "Invalid CaPath",
caPath: path.Join(testhelper.TestRoot, "certs/invalid"), caPath: path.Join(testRoot, "certs/invalid"),
expectedError: "Internal API unreachable", expectedError: "Internal API unreachable",
}, },
{ {
Loading
@@ -108,20 +113,18 @@ func TestFailedRequests(t *testing.T) {
Loading
@@ -108,20 +113,18 @@ func TestFailedRequests(t *testing.T) {
} }
func setupWithRequests(t *testing.T, caFile, caPath, clientCAPath, clientCertPath, clientKeyPath string) (*GitlabNetClient, error) { func setupWithRequests(t *testing.T, caFile, caPath, clientCAPath, clientCertPath, clientKeyPath string) (*GitlabNetClient, error) {
testhelper.PrepareTestRootDir(t)
requests := []testserver.TestRequestHandler{ requests := []testserver.TestRequestHandler{
{ {
Path: "/api/v4/internal/hello", Path: "/api/v4/internal/hello",
Handler: func(w http.ResponseWriter, r *http.Request) { 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") fmt.Fprint(w, "Hello")
}, },
}, },
} }
url := testserver.StartHttpsServer(t, requests, clientCAPath) url := testserver.StartHTTPSServer(t, requests, clientCAPath)
opts := defaultHttpOpts opts := defaultHttpOpts
if clientCertPath != "" && clientKeyPath != "" { if clientCertPath != "" && clientKeyPath != "" {
Loading
Loading
Loading
@@ -84,11 +84,18 @@ func StartGitalyServer(t *testing.T, network string) (string, *TestGitalyServer)
Loading
@@ -84,11 +84,18 @@ func StartGitalyServer(t *testing.T, network string) (string, *TestGitalyServer)
switch network { switch network {
case "unix": case "unix":
tempDir, _ := os.MkdirTemp("", "gitlab-shell-test-api") // We can't use t.TempDir() here because it will create a directory that
gitalySocketPath := path.Join(tempDir, "gitaly.sock") // far exceeds the 108 character limit which results in the socket failing
// to be created.
//
// See https://gitlab.com/gitlab-org/gitlab-shell/-/issues/696#note_1664726924
// for more detail.
tempDir, err := os.MkdirTemp("", "gitaly")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, os.RemoveAll(tempDir)) }) t.Cleanup(func() { require.NoError(t, os.RemoveAll(tempDir)) })
err := os.MkdirAll(filepath.Dir(gitalySocketPath), 0700) gitalySocketPath := path.Join(tempDir, "gitaly.sock")
err = os.MkdirAll(filepath.Dir(gitalySocketPath), 0700)
require.NoError(t, err) require.NoError(t, err)
addr, testServer := doStartTestServer(t, "unix", gitalySocketPath) addr, testServer := doStartTestServer(t, "unix", gitalySocketPath)
Loading
@@ -123,7 +130,7 @@ func doStartTestServer(t *testing.T, network string, path string) (string, *Test
Loading
@@ -123,7 +130,7 @@ func doStartTestServer(t *testing.T, network string, path string) (string, *Test
go func() { go func() {
require.NoError(t, server.Serve(listener)) require.NoError(t, server.Serve(listener))
}() }()
t.Cleanup(func() { server.Stop() }) t.Cleanup(func() { server.GracefulStop() })
return listener.Addr().String(), &testServer return listener.Addr().String(), &testServer
} }
Loading
@@ -17,22 +17,28 @@ import (
Loading
@@ -17,22 +17,28 @@ import (
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper" "gitlab.com/gitlab-org/gitlab-shell/v14/internal/testhelper"
) )
var (
tempDir, _ = os.MkdirTemp("", "gitlab-shell-test-api")
testSocket = path.Join(tempDir, "internal.sock")
)
type TestRequestHandler struct { type TestRequestHandler struct {
Path string Path string
Handler func(w http.ResponseWriter, r *http.Request) 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() t.Helper()
err := os.MkdirAll(filepath.Dir(testSocket), 0700) // We can't use t.TempDir() here because it will create a directory that
// far exceeds the 108 character limit which results in the socket failing
// to be created.
//
// See https://gitlab.com/gitlab-org/gitlab-shell/-/issues/696#note_1664726924
// for more detail.
tempDir, err := os.MkdirTemp("", "http")
require.NoError(t, err)
t.Cleanup(func() { require.NoError(t, os.RemoveAll(tempDir)) })
testSocket := path.Join(tempDir, "internal.sock")
err = os.MkdirAll(filepath.Dir(testSocket), 0700)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() { os.RemoveAll(tempDir) })
socketListener, err := net.Listen("unix", testSocket) socketListener, err := net.Listen("unix", testSocket)
require.NoError(t, err) require.NoError(t, err)
Loading
@@ -50,7 +56,8 @@ func StartSocketHttpServer(t *testing.T, handlers []TestRequestHandler) string {
Loading
@@ -50,7 +56,8 @@ func StartSocketHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return url 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() t.Helper()
server := httptest.NewServer(buildHandler(handlers)) server := httptest.NewServer(buildHandler(handlers))
Loading
@@ -59,7 +66,8 @@ func StartHttpServer(t *testing.T, handlers []TestRequestHandler) string {
Loading
@@ -59,7 +66,8 @@ func StartHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return server.URL 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{} attempts := map[string]int{}
retryMiddileware := func(next func(w http.ResponseWriter, r *http.Request)) http.Handler { retryMiddileware := func(next func(w http.ResponseWriter, r *http.Request)) http.Handler {
Loading
@@ -87,11 +95,14 @@ func StartRetryHttpServer(t *testing.T, handlers []TestRequestHandler) string {
Loading
@@ -87,11 +95,14 @@ func StartRetryHttpServer(t *testing.T, handlers []TestRequestHandler) string {
return server.URL 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() t.Helper()
crt := path.Join(testhelper.TestRoot, "certs/valid/server.crt") testRoot := testhelper.PrepareTestRootDir(t)
key := path.Join(testhelper.TestRoot, "certs/valid/server.key")
crt := path.Join(testRoot, "certs/valid/server.crt")
key := path.Join(testRoot, "certs/valid/server.key")
server := httptest.NewUnstartedServer(buildHandler(handlers)) server := httptest.NewUnstartedServer(buildHandler(handlers))
cer, err := tls.LoadX509KeyPair(crt, key) cer, err := tls.LoadX509KeyPair(crt, key)
Loading
Loading
// Package client provides an HTTP client with enhanced logging, tracing, and correlation handling.
package client package client
import ( import (
Loading
@@ -13,6 +14,7 @@ type transport struct {
Loading
@@ -13,6 +14,7 @@ type transport struct {
next http.RoundTripper next http.RoundTripper
} }
// RoundTrip executes a single HTTP transaction, adding logging and tracing capabilities.
func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) { func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) {
ctx := request.Context() ctx := request.Context()
Loading
@@ -55,10 +57,12 @@ func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) {
Loading
@@ -55,10 +57,12 @@ func (rt *transport) RoundTrip(request *http.Request) (*http.Response, error) {
return response, nil return response, nil
} }
// DefaultTransport returns a clone of the default HTTP transport.
func DefaultTransport() http.RoundTripper { func DefaultTransport() http.RoundTripper {
return http.DefaultTransport.(*http.Transport).Clone() return http.DefaultTransport.(*http.Transport).Clone()
} }
// NewTransport creates a new transport with logging, tracing, and correlation handling.
func NewTransport(next http.RoundTripper) http.RoundTripper { func NewTransport(next http.RoundTripper) http.RoundTripper {
t := &transport{next: next} t := &transport{next: next}
return correlation.NewInstrumentedRoundTripper(tracing.NewRoundTripper(t)) return correlation.NewInstrumentedRoundTripper(tracing.NewRoundTripper(t))
Loading
Loading