From 2ab3d88f1a399c170b7fb0b04c9f9555a9af841d Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Tue, 5 Apr 2022 14:50:01 +0200 Subject: [PATCH] Remove mounts for /etc/passwd and others by creating accounts within container --- Dockerfile | 3 +- main.go | 81 +++++++++++++++++++++++++++++++++++++++++++------- volume_flag.go | 16 ++++++++++ 3 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 volume_flag.go diff --git a/Dockerfile b/Dockerfile index f39bcd3..17bcca7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM ubuntu:21.10 +RUN yes | unminimize + RUN apt-get -y update && apt-get -y install locales RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ @@ -21,7 +23,6 @@ ENV LC_MEASUREMENT=en_US.UTF-8 ENV LC_IDENTIFICATION=en_US.UTF-8 ENV TZ=Europe/Amsterdam - RUN apt-get -y update && DEBIAN_FRONTEND=noninteractive apt-get -y install \ man-db jq curl git pwgen build-essential libjansson-dev \ libtiff-dev libgif-dev ffmpeg libffi-dev xutils-dev \ diff --git a/main.go b/main.go index 2e90784..e410369 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "bufio" _ "embed" + "errors" "flag" "fmt" "os" @@ -29,6 +30,51 @@ var customLisp string //go:embed bash/bash_aliases var bashAliases string +var ErrAddUserFailExit = errors.New("useradd command returned no-zero exit code") +var ErrAddGroupFailExit = errors.New("groupadd command returned no-zero exit code") + +func AddUser(username string, uid string) error { + cmd := exec.Command( + "useradd", + "--no-create-home", + "--uid", uid, + "--user-group", + username, + ) + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf( + "Error adding user: %w. Process error: %w. Process output: %s", + ErrAddUserFailExit, + err, + output, + ) + } + + return nil +} + +func AddGroup(name string, gid string) error { + cmd := exec.Command( + "groupadd", + "--gid", gid, + name, + ) + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf( + "Error adding group: %w. Process error: %w. Process output: %s", + ErrAddGroupFailExit, + err, + output, + ) + } + + return nil +} + func EntryPoint(command []string) error { if len(command) == 0 { command = []string{"/bin/bash", "-i"} @@ -44,7 +90,8 @@ func EntryPoint(command []string) error { ) } - dockerGid, err := strconv.Atoi(os.Getenv("WORKSPACE_DOCKER_GID")) + dockerGidString := os.Getenv("WORKSPACE_DOCKER_GID") + dockerGid, err := strconv.Atoi(dockerGidString) if err != nil { return fmt.Errorf( "Failed to parse GID from WORKSPACE_DOCKER_GID env var with contents \"%s\". Error: %w", @@ -53,17 +100,27 @@ func EntryPoint(command []string) error { ) } + err = AddUser(os.Getenv("WORKSPACE_USERNAME"), uidString) + if err != nil { + return err + } + + err = AddGroup("docker", dockerGidString) + if err != nil { + return err + } + err = syscall.Setgroups([]int{dockerGid}) if err != nil { return err } - err = syscall.Setgid(uid) + err = syscall.Setgid(int(uid)) if err != nil { return err } - err = syscall.Setuid(uid) + err = syscall.Setuid(int(uid)) if err != nil { return err } @@ -78,7 +135,7 @@ func EntryPoint(command []string) error { return syscall.Exec(path, command, os.Environ()) } -func Run(detach bool, command []string) error { +func Run(detach bool, mounts []string, command []string) error { workDir, err := os.Getwd() if err != nil { return err @@ -100,18 +157,13 @@ func Run(detach bool, command []string) error { "--workdir=" + workDir, "-e", "DISPLAY=" + os.Getenv("DISPLAY"), "-e", "WORKSPACE_USER=" + curUser.Uid, - "-e", "WORKSPACE_USERNAME=" + curUser.Name, + "-e", "WORKSPACE_USERNAME=" + curUser.Username, "-e", "WORKSPACE_DOCKER_GID=" + dockerGroup.Gid, "-e", "HOME=" + home, "-h", os.Getenv("HOSTNAME"), "-v", "/var/run/docker.sock:/var/run/docker.sock", - "-v", "/etc/subuid:/etc/subuid:ro", - "-v", "/etc/subgid:/etc/subgid:ro", "-v", "/etc/hosts:/etc/hosts:ro", - "-v", "/etc/passwd:/etc/passwd:ro", "-v", "/etc/resolv.conf:/etc/resolv.conf:ro", - "-v", "/etc/sudoers:/etc/sudoers:ro", - "-v", "/etc/group:/etc/group:ro", "-v", home + ":" + home, "-e", "SSH_AGENT_LAUNCHER=" + os.Getenv("SSH_AGENT_LAUNCHER"), "-e", "SSH_AUTH_SOCK=" + os.Getenv("SSH_AUTH_SOCK"), @@ -131,6 +183,10 @@ func Run(detach bool, command []string) error { dockerCommand = append(dockerCommand, "-ti") } + for _, mount := range mounts { + dockerCommand = append(dockerCommand, "-v", mount+":"+mount) + } + fileInfo, err := os.Lstat(home) if err != nil { return fmt.Errorf( @@ -216,6 +272,9 @@ func main() { "Whether or not to detach from the container after running the command", ) + var mounts arrayFlag + run.Var(&mounts, "mount", "Directory to mount inside the workspace container") + switch cmd { case "entrypoint": err := EntryPoint(os.Args[2:]) @@ -231,7 +290,7 @@ func main() { os.Exit(1) } - err = Run(detach, run.Args()) + err = Run(detach, mounts, run.Args()) if err != nil { fmt.Println("error running command in container", err) os.Exit(1) diff --git a/volume_flag.go b/volume_flag.go new file mode 100644 index 0000000..6c37480 --- /dev/null +++ b/volume_flag.go @@ -0,0 +1,16 @@ +package main + +import ( + "strings" +) + +type arrayFlag []string + +func (f *arrayFlag) String() string { + return strings.Join(*f, ",") +} + +func (f *arrayFlag) Set(value string) error { + *f = append(*f, value) + return nil +}