Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-11-01 13:52:15 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-11-03 13:53:00 +0300
commit0e67646e4201dd6399cdc8a7232961f1aa318337 (patch)
treee795becd256713d9b1cc0866894698986d2198e6
parent04af331b09732d8a6d4af4e38e28f0a86d3e6a36 (diff)
tests: Make the VCS workaround for unprivileged builds global
The testcfg package has some helper functions that build Go binaries required by Gitaly at runtime. As Go 1.18 has started to run Git as part of the build process to embed VCS information into the resulting Git binaries we had two employ two workarounds: - We intercept Git commands and thus had to use a Git command factory to set up a proper environment. - Git refuses to run in repositories not owned by the current user, and because CI runs tests as an unprivileged user this safety mechanism kicked in. We thus had to inject the `safe.directory` Git configuration into the process. With the introduction of Go 1.19, we furthermore have to change how we set up the unprivileged user. As a consequence, we also need to start building binaries outside of our tests as an unprivileged user and thus the second issue also hits us during the build process. Now that we have dropped Go 1.17 though we can just bail and do the easy thing, which is to pass `-buildvcs=false` to Go and be done. This allows us to get rid of the nasty build hacks and prepares us for Go 1.19.
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--internal/testhelper/testcfg/build.go62
2 files changed, 10 insertions, 58 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 282a31d67..43983a524 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,6 +22,12 @@ variables:
PGBOUNCER_VERSION: "1.16.1"
BUNDLE_PATH: "${CI_PROJECT_DIR}/.ruby"
GOPATH: "${CI_PROJECT_DIR}/.go"
+ # We run the build as an untrusted user in a source directory owned by
+ # "root". Running Git commands in that repository will thus fail due to
+ # Git's `safe.directory` protections, and that in turns breaks the Go
+ # build. We work around this by telling Go to not embed VCS information in
+ # the binaries.
+ GOFLAGS: "-buildvcs=false"
# Run tests with an intercepted home directory so that we detect cases where
# Gitaly picks up the gitconfig even though it ought not to.
GITALY_TESTING_INTERCEPT_HOME: "YesPlease"
diff --git a/internal/testhelper/testcfg/build.go b/internal/testhelper/testcfg/build.go
index 3d527a041..0eb03031d 100644
--- a/internal/testhelper/testcfg/build.go
+++ b/internal/testhelper/testcfg/build.go
@@ -1,18 +1,15 @@
package testcfg
import (
- "context"
"fmt"
"os"
"os/exec"
"path/filepath"
- "runtime"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
)
@@ -93,67 +90,15 @@ func BuildBinary(tb testing.TB, targetDir, sourcePath string) string {
buildOnce.Do(func() {
require.NoFileExists(tb, sharedBinaryPath, "binary has already been built")
- cfg := Build(tb)
- gitCommandFactory := gittest.NewCommandFactory(tb, cfg)
- gitExecEnv := gitCommandFactory.GetExecutionEnvironment(context.TODO())
-
- // Unfortunately, Go has started to execute Git as parts of its build process in
- // order to embed VCS information into the resulting binary. In Gitaly we're doing a
- // bunch of things to verify that we don't ever use Git information from outside of
- // our defined parameters: we intercept Git executed via PATH, and we also override
- // Git configuration locations. So executing Git without special logic simply does
- // not work.
- //
- // While we could in theory just ask it not to do that via `-buildvcs=false`, this
- // option is only understood with Go 1.18+. So we have the option between either
- // using logic that is conditional on the Go version here, or alternatively we fix
- // the environment to allow for the execution of Git. We opt for the latter here and
- // set up a Git command factory.
- gitEnvironment := make([]string, 0, len(os.Environ()))
-
// We need to filter out some environments we set globally in our tests which would
// cause Git to not operate correctly.
+ filteredEnvironment := make([]string, 0, len(os.Environ()))
for _, env := range os.Environ() {
if !strings.HasPrefix(env, "GIT_DIR=") {
- gitEnvironment = append(gitEnvironment, env)
+ filteredEnvironment = append(filteredEnvironment, env)
}
}
- // Furthermore, as we're using the Git command factory which may or may not use
- // bundled Git we need to append some environment variables that make Git find its
- // auxiliary helper binaries.
- gitEnvironment = append(gitEnvironment, gitExecEnv.EnvironmentVariables...)
-
- // And last but not least we need to override PATH so that our Git binary from the
- // command factory is up front.
- gitEnvironment = append(gitEnvironment, fmt.Sprintf(
- "PATH=%s:%s", filepath.Dir(gitExecEnv.BinaryPath), os.Getenv("PATH"),
- ))
-
- // Go 1.18 has started to extract VCS information so that it can be embedded into
- // the resulting binary and will thus execute Git in the Gitaly repository. In CI,
- // the Gitaly repository is owned by a different user than the one that is executing
- // tests though, which means that Git will refuse to open the repository because of
- // CVE-2022-24765.
- //
- // Let's override this mechanism by labelling the Git repository as safe. While this
- // does in theory make us vulnerable to this exploit, it is clear that any adversary
- // would already have arbitrary code execution because we are executing code right
- // now that would be controlled by the very same adversary.
- //
- // Note that we cannot pass `safe.directory` via command line arguments by design.
- // Instead, we just override the system-level gitconfig to point to a temporary file
- // that contains this setting.
- _, currentFile, _, ok := runtime.Caller(0)
- require.True(tb, ok)
- gitconfigPath := filepath.Join(testhelper.TempDir(tb), "gitconfig")
- require.NoError(tb, os.WriteFile(gitconfigPath, []byte(
- "[safe]\ndirectory = "+filepath.Join(filepath.Dir(currentFile), "..", "..", "..")+"\n"), 0o400),
- )
- gitEnvironment = append(gitEnvironment,
- "GIT_CONFIG_SYSTEM="+gitconfigPath,
- )
-
buildTags := []string{
"static", "system_libgit2", "gitaly_test",
}
@@ -164,11 +109,12 @@ func BuildBinary(tb testing.TB, targetDir, sourcePath string) string {
cmd := exec.Command(
"go",
"build",
+ "-buildvcs=false",
"-tags", strings.Join(buildTags, ","),
"-o", sharedBinaryPath,
sourcePath,
)
- cmd.Env = gitEnvironment
+ cmd.Env = filteredEnvironment
output, err := cmd.CombinedOutput()
require.NoError(tb, err, "building Go executable: %v, output: %q", err, output)