19099: Use --fakeroot to test network isolation without being root.
authorTom Clegg <tom@curii.com>
Fri, 13 May 2022 14:23:21 +0000 (10:23 -0400)
committerTom Clegg <tom@curii.com>
Fri, 13 May 2022 14:23:21 +0000 (10:23 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@curii.com>

lib/crunchrun/singularity.go
lib/crunchrun/singularity_test.go

index 921f58ff0a3d7fd8a4ed1992aef0fc3bfcc1bbb7..f154728c70630ac31dbc8daf04d87377c4441b32 100644 (file)
@@ -12,6 +12,7 @@ import (
        "net"
        "os"
        "os/exec"
+       "os/user"
        "regexp"
        "sort"
        "strconv"
@@ -24,6 +25,7 @@ import (
 
 type singularityExecutor struct {
        logf          func(string, ...interface{})
+       fakeroot      bool // use --fakeroot flag, allow --network=bridge when non-root (currently only used by tests)
        spec          containerSpec
        tmpdir        string
        child         *exec.Cmd
@@ -247,9 +249,21 @@ func (e *singularityExecutor) Create(spec containerSpec) error {
 }
 
 func (e *singularityExecutor) execCmd(path string) *exec.Cmd {
-       args := []string{path, "exec", "--containall", "--cleanenv", "--pwd", e.spec.WorkingDir, "--net"}
+       args := []string{path, "exec", "--containall", "--cleanenv", "--pwd=" + e.spec.WorkingDir}
+       if e.fakeroot {
+               args = append(args, "--fakeroot")
+       }
        if !e.spec.EnableNetwork {
-               args = append(args, "--network=none")
+               args = append(args, "--net", "--network=none")
+       } else if u, err := user.Current(); err == nil && u.Uid == "0" || e.fakeroot {
+               // Specifying --network=bridge fails unless (a) we are
+               // root, (b) we are using --fakeroot, or (c)
+               // singularity has been configured to allow our
+               // uid/gid to use it like so:
+               //
+               // singularity config global --set 'allow net networks' bridge
+               // singularity config global --set 'allow net groups' mygroup
+               args = append(args, "--net", "--network=bridge")
        }
        if e.spec.CUDADeviceCount != 0 {
                args = append(args, "--nv")
index 8a2e62d7e77c232618a9525873983ac3f321d594..2bad082baa414d77be64937e0e8ba242a6439a0b 100644 (file)
@@ -28,6 +28,21 @@ func (s *singularitySuite) SetUpSuite(c *C) {
        }
 }
 
+func (s *singularitySuite) TearDownSuite(c *C) {
+       if s.executor != nil {
+               s.executor.Close()
+       }
+}
+
+func (s *singularitySuite) TestIPAddress(c *C) {
+       // In production, executor will choose --network=bridge
+       // because uid=0 under arvados-dispatch-cloud. But in test
+       // cases, uid!=0, which means --network=bridge is conditional
+       // on --fakeroot.
+       s.executor.(*singularityExecutor).fakeroot = true
+       s.executorSuite.TestIPAddress(c)
+}
+
 func (s *singularitySuite) TestInject(c *C) {
        path, err := exec.LookPath("nsenter")
        if err != nil || path != "/var/lib/arvados/bin/nsenter" {
@@ -55,6 +70,6 @@ func (s *singularityStubSuite) TestSingularityExecArgs(c *C) {
        c.Check(err, IsNil)
        e.imageFilename = "/fake/image.sif"
        cmd := e.execCmd("./singularity")
-       c.Check(cmd.Args, DeepEquals, []string{"./singularity", "exec", "--containall", "--cleanenv", "--pwd", "/WorkingDir", "--net", "--network=none", "--nv", "--bind", "/hostpath:/mnt:ro", "/fake/image.sif"})
+       c.Check(cmd.Args, DeepEquals, []string{"./singularity", "exec", "--containall", "--cleanenv", "--pwd=/WorkingDir", "--net", "--network=none", "--nv", "--bind", "/hostpath:/mnt:ro", "/fake/image.sif"})
        c.Check(cmd.Env, DeepEquals, []string{"SINGULARITYENV_FOO=bar"})
 }