From 24163497711b4712bd55cd60da780f00efe4bfca Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Tue, 14 Mar 2023 12:35:31 -0500 Subject: [PATCH] landlock: git needs more files for private repositories This PR fixes artifact downloading so that git may work when cloning from private repositories. It needs - file read on /etc/passwd - dir read on /root/.ssh - file write on /root/.ssh/known_hosts Add these rules to the landlock rules for the artifact sandbox. --- .changelog/16495.txt | 3 ++ .../taskrunner/getter/util_linux.go | 48 +++++++++++++++++-- .../taskrunner/getter/util_linux_test.go | 36 +++++++++++--- 3 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 .changelog/16495.txt diff --git a/.changelog/16495.txt b/.changelog/16495.txt new file mode 100644 index 00000000000..79aac2ce259 --- /dev/null +++ b/.changelog/16495.txt @@ -0,0 +1,3 @@ +```release-note:bug +artifact: Fixed a bug where artifact downloading failed when using git-ssh +``` diff --git a/client/allocrunner/taskrunner/getter/util_linux.go b/client/allocrunner/taskrunner/getter/util_linux.go index 092b8b59dfb..5ecf551ef77 100644 --- a/client/allocrunner/taskrunner/getter/util_linux.go +++ b/client/allocrunner/taskrunner/getter/util_linux.go @@ -71,26 +71,64 @@ func lockdown(allocDir, taskDir string) error { landlock.Dir(allocDir, "rwc"), landlock.Dir(taskDir, "rwc"), } - paths = append(paths, systemVersionControlGlobalConfigs()...) + + paths = append(paths, additionalFilesForVCS()...) locker := landlock.New(paths...) return locker.Lock(landlock.Mandatory) } -func systemVersionControlGlobalConfigs() []*landlock.Path { +func additionalFilesForVCS() []*landlock.Path { const ( + sshDir = ".ssh" // git ssh + knownHosts = ".ssh/known_hosts" // git ssh + etcPasswd = "/etc/passwd" // git ssh gitGlobalFile = "/etc/gitconfig" // https://git-scm.com/docs/git-config#SCOPES hgGlobalFile = "/etc/mercurial/hgrc" // https://www.mercurial-scm.org/doc/hgrc.5.html#files hgGlobalDir = "/etc/mercurial/hgrc.d" // https://www.mercurial-scm.org/doc/hgrc.5.html#files ) - return loadVersionControlGlobalConfigs(gitGlobalFile, hgGlobalFile, hgGlobalDir) + return filesForVCS( + sshDir, + knownHosts, + etcPasswd, + gitGlobalFile, + hgGlobalFile, + hgGlobalDir, + ) } -func loadVersionControlGlobalConfigs(gitGlobalFile, hgGlobalFile, hgGlobalDir string) []*landlock.Path { +func filesForVCS( + sshDir, + knownHosts, + etcPasswd, + gitGlobalFile, + hgGlobalFile, + hgGlobalDir string) []*landlock.Path { + + var includeSSH bool + + // omit ssh if there is no home directory + if home, err := os.UserHomeDir(); err == nil { + includeSSH = true + sshDir = filepath.Join(home, sshDir) + knownHosts = filepath.Join(home, knownHosts) + } + + // only add if a path exists exists := func(p string) bool { _, err := os.Stat(p) return err == nil } - result := make([]*landlock.Path, 0, 3) + + result := make([]*landlock.Path, 0, 6) + if includeSSH && exists(sshDir) { + result = append(result, landlock.Dir(sshDir, "r")) + } + if includeSSH && exists(knownHosts) { + result = append(result, landlock.File(knownHosts, "rw")) + } + if exists(etcPasswd) { + result = append(result, landlock.File(etcPasswd, "r")) + } if exists(gitGlobalFile) { result = append(result, landlock.File(gitGlobalFile, "r")) } diff --git a/client/allocrunner/taskrunner/getter/util_linux_test.go b/client/allocrunner/taskrunner/getter/util_linux_test.go index 28cb857d8b6..f1d63a406e3 100644 --- a/client/allocrunner/taskrunner/getter/util_linux_test.go +++ b/client/allocrunner/taskrunner/getter/util_linux_test.go @@ -14,15 +14,27 @@ import ( func TestUtil_loadVersionControlGlobalConfigs(t *testing.T) { const filePerm = 0o644 const dirPerm = 0o755 + fakeEtc := t.TempDir() + fakeHome := t.TempDir() + + t.Setenv("HOME", fakeHome) + + const ( + ssh = ".ssh" + knownHosts = ".ssh/known_hosts" + ) var ( - gitFile = filepath.Join(fakeEtc, "gitconfig") - hgFile = filepath.Join(fakeEtc, "hgrc") - hgDir = filepath.Join(fakeEtc, "hgrc.d") + gitConfig = filepath.Join(fakeEtc, "gitconfig") + hgFile = filepath.Join(fakeEtc, "hgrc") + hgDir = filepath.Join(fakeEtc, "hgrc.d") + etcPasswd = filepath.Join(fakeEtc, "passwd") + sshDir = filepath.Join(fakeHome, ssh) + knownHostsFile = filepath.Join(fakeHome, knownHosts) ) - err := os.WriteFile(gitFile, []byte("git"), filePerm) + err := os.WriteFile(gitConfig, []byte("git"), filePerm) must.NoError(t, err) err = os.WriteFile(hgFile, []byte("hg"), filePerm) @@ -31,9 +43,21 @@ func TestUtil_loadVersionControlGlobalConfigs(t *testing.T) { err = os.Mkdir(hgDir, dirPerm) must.NoError(t, err) - paths := loadVersionControlGlobalConfigs(gitFile, hgFile, hgDir) + err = os.WriteFile(etcPasswd, []byte("x:y:z"), filePerm) + must.NoError(t, err) + + err = os.Mkdir(sshDir, dirPerm) + must.NoError(t, err) + + err = os.WriteFile(knownHostsFile, []byte("abc123"), filePerm) + must.NoError(t, err) + + paths := filesForVCS(ssh, knownHosts, etcPasswd, gitConfig, hgFile, hgDir) must.SliceEqual(t, []*landlock.Path{ - landlock.File(gitFile, "r"), + landlock.Dir(sshDir, "r"), + landlock.File(knownHostsFile, "rw"), + landlock.File(etcPasswd, "r"), + landlock.File(gitConfig, "r"), landlock.File(hgFile, "r"), landlock.Dir(hgDir, "r"), }, paths)