From 1f467a3cb67b02c88511c678dde9b4f8087546e2 Mon Sep 17 00:00:00 2001 From: Christian Weichel Date: Fri, 29 Oct 2021 07:29:13 +0000 Subject: [PATCH] [supervisor] Provide child proc env to SSH session --- components/supervisor/openssh/BUILD.yaml | 2 + .../supervisor/openssh/leeway.Dockerfile | 2 + .../supervisor/openssh/supervisorenv.patch | 14 +++++++ components/supervisor/pkg/supervisor/ssh.go | 40 +++++++++++++++++-- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 components/supervisor/openssh/supervisorenv.patch diff --git a/components/supervisor/openssh/BUILD.yaml b/components/supervisor/openssh/BUILD.yaml index 1e0b07d79f8026..013fba3cb562a0 100644 --- a/components/supervisor/openssh/BUILD.yaml +++ b/components/supervisor/openssh/BUILD.yaml @@ -9,5 +9,7 @@ packages: - ["rm", "-rf", "components-supervisor-openssh--docker-build"] - name: docker-build type: docker + srcs: + - "*.patch" config: dockerfile: leeway.Dockerfile diff --git a/components/supervisor/openssh/leeway.Dockerfile b/components/supervisor/openssh/leeway.Dockerfile index 3ede280e52dbfd..53ca37a114fa51 100644 --- a/components/supervisor/openssh/leeway.Dockerfile +++ b/components/supervisor/openssh/leeway.Dockerfile @@ -54,10 +54,12 @@ RUN ./configure \ --with-privsep-user=nobody \ --with-ssl-engine +COPY supervisorenv.patch . ENV aports=https://raw.githubusercontent.com/alpinelinux/aports/master/main/openssh RUN curl -fsSL \ "${aports}/{fix-utmp,fix-verify-dns-segfault,sftp-interactive}.patch" \ | patch -p1 +RUN cat supervisorenv.patch | patch -p1 RUN make install-nosysconf exec_prefix=/openssh RUN TEST_SSH_UNSAFE_PERMISSIONS=1 \ diff --git a/components/supervisor/openssh/supervisorenv.patch b/components/supervisor/openssh/supervisorenv.patch new file mode 100644 index 00000000000000..dad1babcd94cca --- /dev/null +++ b/components/supervisor/openssh/supervisorenv.patch @@ -0,0 +1,14 @@ +--- a/session.c 2021-10-29 07:07:35.794323753 +0000 ++++ b/session.c 2021-10-29 07:23:07.420640891 +0000 +@@ -1126,6 +1126,11 @@ + options.permit_user_env_allowlist); + } + ++ snprintf(buf, sizeof buf, "%.200s/%s/supervisor_env", ++ pw->pw_dir, _PATH_SSH_USER_DIR); ++ read_environment_file(&env, &envsize, buf, ++ options.permit_user_env_allowlist); ++ + #ifdef USE_PAM + /* + * Pull in any environment variables that may have diff --git a/components/supervisor/pkg/supervisor/ssh.go b/components/supervisor/pkg/supervisor/ssh.go index 7bf398f4d88f45..0040492d238309 100644 --- a/components/supervisor/pkg/supervisor/ssh.go +++ b/components/supervisor/pkg/supervisor/ssh.go @@ -27,11 +27,15 @@ func newSSHServer(ctx context.Context, cfg *Config) (*sshServer, error) { sshkey := filepath.Join(filepath.Dir(bin), "ssh", "sshkey") if _, err := os.Stat(sshkey); err != nil { - err := prepareSSHServer(ctx, sshkey) + err := prepareSSHKey(ctx, sshkey) if err != nil { return nil, xerrors.Errorf("unexpected error creating SSH key: %w", err) } } + err = writeSSHEnv(cfg) + if err != nil { + return nil, xerrors.Errorf("unexpected error creating SSH env: %w", err) + } return &sshServer{ ctx: ctx, @@ -126,6 +130,8 @@ func (s *sshServer) handleConn(ctx context.Context, conn net.Conn) { done <- cmd.Wait() }() + log.Debug("sshd started") + select { case <-ctx.Done(): if cmd.Process != nil { @@ -139,7 +145,7 @@ func (s *sshServer) handleConn(ctx context.Context, conn net.Conn) { } } -func prepareSSHServer(ctx context.Context, sshkey string) error { +func prepareSSHKey(ctx context.Context, sshkey string) error { bin, err := os.Executable() if err != nil { return xerrors.Errorf("cannot find executable path: %w", err) @@ -175,6 +181,34 @@ func prepareSSHServer(ctx context.Context, sshkey string) error { return xerrors.Errorf("cannot create SSH hostkey file: %w", err) } - return os.Chown(sshkey, gitpodUID, gitpodGID) + err = os.Chown(sshkey, gitpodUID, gitpodGID) + if err != nil { + return xerrors.Errorf("cannot chown SSH hostkey file: %w", err) + } + + return nil +} + +func writeSSHEnv(cfg *Config) error { + home, err := os.UserHomeDir() + if err != nil { + return err + } + + d := filepath.Join(home, ".ssh") + err = os.MkdirAll(d, 0755) + if err != nil { + return xerrors.Errorf("cannot create $HOME/.ssh: %w", err) + } + + fn := filepath.Join(d, "supervisor_env") + env := strings.Join(buildChildProcEnv(cfg, nil), "\n") + err = os.WriteFile(fn, []byte(env), 0644) + if err != nil { + return xerrors.Errorf("cannot write %s: %w", fn, err) + } + + _ = exec.Command("chown", "-R", fmt.Sprintf("%d:%d", gitpodUID, gitpodGID), d).Run() + return nil }