From 1160686e9b0e9d63bd3596786724dd541bb868e2 Mon Sep 17 00:00:00 2001 From: Scott Date: Tue, 6 Oct 2020 15:18:51 -0400 Subject: [PATCH] Avoid dangling symlinks in git-init When the following conditions are met: 1. the feature flag disable-home-env-overwrite is "true" 2. the container user is root 3. no git / ssh secret is attached to a taskrun service account 4. user is running new-ish version of catalog git-clone task with git-init v0.15.2+ git-init will error out in the git-clone task because we create a circular symlink from /root/.ssh to itself and then try to look up /root/.ssh/known_hosts. This commit adds a check to avoid this from happening: If the user's $HOME/.ssh directory doesn't exist or if they aren't able to access it for any reason, then we don't try to create a symlink to it at all since we can trust that the user is incapable of utilizing the credential. This commit also expands an existing check to see if the $HOME/.ssh directory is the same as the user's home directory + '.ssh'. This was originally only checked if the user was nonroot, but now this is also checked if the user is root too. --- pkg/git/git.go | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/pkg/git/git.go b/pkg/git/git.go index 9d7dca7419d..0a2ec3a13ba 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -206,9 +206,11 @@ func SubmoduleFetch(logger *zap.SugaredLogger, spec FetchSpec) error { return nil } +// ensureHomeEnv works around an issue where ssh doesn't respect the HOME env variable. If HOME is set and +// different from the user's detected home directory then symlink .ssh from the home directory to the HOME env +// var. This way ssh will see the .ssh directory in the user's home directory even though it ignores +// the HOME env var. func ensureHomeEnv(logger *zap.SugaredLogger) error { - // HACK: This is to get git+ssh to work since ssh doesn't respect the HOME - // env variable. homepath, err := homedir.Dir() if err != nil { logger.Errorf("Unexpected error: getting the user home directory: %v", err) @@ -216,23 +218,32 @@ func ensureHomeEnv(logger *zap.SugaredLogger) error { } homeenv := os.Getenv("HOME") euid := os.Geteuid() - // Special case the root user/directory + if _, err := os.Stat(filepath.Join(homeenv, ".ssh")); err != nil { + // There's no $HOME/.ssh directory to access or the user doesn't have permissions + // to read it, or something else; in any event there's no need to try creating a + // symlink to it. + return nil + } if euid == 0 { - if err := os.Symlink(homeenv+"/.ssh", "/root/.ssh"); err != nil { - // Only do a warning, in case we don't have a real home - // directory writable in our image - logger.Warnf("Unexpected error: creating symlink: %v", err) - } - } else if homeenv != "" && homeenv != homepath { - if _, err := os.Stat(homepath + "/.ssh"); os.IsNotExist(err) { - if err := os.Symlink(homeenv+"/.ssh", homepath+"/.ssh"); err != nil { + ensureHomeEnvSSHLinkedFromPath(logger, homeenv, "/root") + } else if homeenv != "" { + ensureHomeEnvSSHLinkedFromPath(logger, homeenv, homepath) + } + return nil +} + +func ensureHomeEnvSSHLinkedFromPath(logger *zap.SugaredLogger, homeenv string, homepath string) { + if filepath.Clean(homeenv) != filepath.Clean(homepath) { + homeEnvSSH := filepath.Join(homeenv, ".ssh") + homePathSSH := filepath.Join(homepath, ".ssh") + if _, err := os.Stat(homePathSSH); os.IsNotExist(err) { + if err := os.Symlink(homeEnvSSH, homePathSSH); err != nil { // Only do a warning, in case we don't have a real home // directory writable in our image logger.Warnf("Unexpected error: creating symlink: %v", err) } } } - return nil } func userHasKnownHostsFile(logger *zap.SugaredLogger) (bool, error) {