def test_09_add_user(self):
     """Test09 NixAuthentication().add_user()."""
     auth = NixAuthentication()
     with patch(BUILTINS + '.open', mock_open()):
         status = auth.add_user("root", "pw", 0, 0, "gecos", "/home",
                                "/bin/bash")
         self.assertTrue(status)
Example #2
0
 def _setup_container_user_noroot(self, user):
     """ Setup user for engines without root support.
     Equivalent to _setup_container_user() for engines without root support.
     """
     host_auth = NixAuthentication()
     (passwd, group) = self._select_auth_files()
     container_auth = NixAuthentication(passwd, group)
     if not user:
         user = HostInfo().username()
     (valid_user, user_id) = self._user_from_str(user,
                                                 host_auth, container_auth)
     if not valid_user:
         Msg().err("Error: invalid syntax for user", user)
         return False
     if self.opt["user"] == "root":
         self.opt["user"] = HostInfo().username()
         self.opt["uid"] = str(HostInfo.uid)
         self.opt["gid"] = str(HostInfo.gid)
     if (self._is_mountpoint("/etc/passwd") or
             self._is_mountpoint("/etc/group")):
         self.opt["hostauth"] = self.opt["containerauth"] = False
         return True
     if self.opt["user"]:
         self.opt["uid"] = str(HostInfo.uid)
         self.opt["gid"] = str(HostInfo.gid)
     else:
         if self.opt["hostauth"] or self.opt["containerauth"]:
             Msg().err("Error: user not found on host")
             return False
         self.opt["user"] = user_id["user"] if "user" in user_id else user
         self.opt["uid"] = user_id["uid"] if "uid" in user_id else ""
         self.opt["gid"] = user_id["gid"] if "gid" in user_id else ""
     self._create_user(container_auth, host_auth)
     return True
 def test_13_get_home(self, mock_user):
     """Test13 NixAuthentication().get_home()."""
     mock_user.return_value = ('root', '0', '0', 'root', '/root',
                               '/bin/bash')
     auth = NixAuthentication()
     status = auth.get_home()
     self.assertEqual(status, '/root')
    def test_01_init(self):
        """Test01 NixAuthentication() constructor."""
        auth = NixAuthentication()
        self.assertEqual(auth.passwd_file, None)
        self.assertEqual(auth.group_file, None)

        auth = NixAuthentication("passwd", "group")
        self.assertEqual(auth.passwd_file, "passwd")
        self.assertEqual(auth.group_file, "group")
    def test_04_user_in_subgid(self, mock_file, mock_host):
        """Test04 NixAuthentication().user_in_subgid."""
        mock_host.return_value = ("user", "1000", "1000", "usr", "/home/user",
                                  "/bin/bash")
        auth = NixAuthentication()
        auth.subuid_file = "/etc/subgid"
        subgid_line = StringIO('user:100000:65536')
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(subgid_line.readline, ''))
            listuser = auth.user_in_subgid("user")
            self.assertEqual(listuser, [("100000", "65536")])
            self.assertTrue(mock_host.called)

        mock_file.return_value = ("user", "1000", "1000", "usr", "/home/user",
                                  "/bin/bash")
        auth = NixAuthentication()
        auth.passwd_file = "/etc/passwd"
        auth.subgid_file = "/etc/subgid"
        subgid_line = StringIO('user:100000:65536')
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(subgid_line.readline, ''))
            listuser = auth.user_in_subgid("user")
            self.assertEqual(listuser, [("100000", "65536")])
            self.assertTrue(mock_file.called)
    def test_12_get_group(self, mock_file, mock_host):
        """Test12 NixAuthentication().get_group()."""
        auth = NixAuthentication()
        auth.group_file = ""
        auth.get_group("group")
        self.assertTrue(mock_host.called)
        self.assertFalse(mock_file.called)

        mock_host.reset_mock()
        mock_file.reset_mock()
        auth = NixAuthentication()
        auth.group_file = "group"
        auth.get_group("group")
        self.assertFalse(mock_host.called)
        self.assertTrue(mock_file.called)
    def test_11_get_user(self, mock_file, mock_host):
        """Test11 NixAuthentication().get_user()."""
        auth = NixAuthentication()
        auth.passwd_file = ""
        auth.get_user("user")
        self.assertTrue(mock_host.called)
        self.assertFalse(mock_file.called)

        mock_host.reset_mock()
        mock_file.reset_mock()
        auth = NixAuthentication()
        auth.passwd_file = "passwd"
        auth.get_user("user")
        self.assertFalse(mock_host.called)
        self.assertTrue(mock_file.called)
Example #8
0
 def _get_volume_bindings(self):
     """Get the volume bindings string for singularity exec"""
     vol_list = []
     home_dir = NixAuthentication().get_home()
     home_is_binded = False
     tmp_is_binded = False
     vartmp_is_binded = False
     for vol in self.opt["vol"]:
         (host_path, cont_path) = Uvolume(vol).split()
         if os.path.isdir(host_path):
             if host_path == home_dir and cont_path in ("", host_path):
                 home_is_binded = True
             elif host_path == "/tmp" and cont_path in ("", "/tmp"):
                 tmp_is_binded = True
             elif host_path == "/var/tmp" and cont_path in ("", "/var/tmp"):
                 vartmp_is_binded = True
         vol_list.extend(["-B", "%s:%s" % (host_path, cont_path), ])
     if not home_is_binded:
         vol_list.extend(["--home", "%s/root:%s" %
                          (self.container_root, "/root"), ])
     if not tmp_is_binded:
         vol_list.extend(["-B", "%s/tmp:/tmp" %
                          (self.container_root), ])
     if not vartmp_is_binded:
         vol_list.extend(["-B", "%s/var/tmp:/var/tmp" %
                          (self.container_root), ])
     return vol_list
    def test_07__get_user_from_file(self):
        """Test07 NixAuthentication()._get_user_from_file()."""
        auth = NixAuthentication()
        auth.passwd_file = "passwd"
        passwd_line = StringIO('root:x:0:0:root:/root:/bin/bash')
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(passwd_line.readline, ''))
            (name, uid, gid, gecos, _dir,
             shell) = auth._get_user_from_file("root")
            self.assertEqual(name, "root")
            self.assertEqual(uid, "0")
            self.assertEqual(gid, "0")
            self.assertEqual(gecos, "root")
            self.assertEqual(_dir, "/root")
            self.assertEqual(shell, "/bin/bash")

        passwd_line = StringIO('root:x:0:0:root:/root:/bin/bash')
        auth = NixAuthentication()
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(passwd_line.readline, ''))
            (name, uid, gid, gecos, _dir, shell) = auth._get_user_from_file(0)
            self.assertEqual(name, "root")
            self.assertEqual(uid, "0")
            self.assertEqual(gid, "0")
            self.assertEqual(gecos, "root")
            self.assertEqual(_dir, "/root")
            self.assertEqual(shell, "/bin/bash")
Example #10
0
 def _setup_container_user(self, user):
     """Once we know which username to use inside the container
     we need to check if it exists in the passwd file that will
     be used inside the container. Since we can override the
     usage of the container /etc/passwd and /etc/group with
     files passed from the host, then we must check if this
     username is in the appropriate file so:
     1. check if the passwd will be the one of the host system
        either because we passwd --hostauth or because we did
        --volume=/etc/passwd:/etc/passwd
     2. else we are using the container original /etc/passwd
     In either case the user specified may not exist, in which
     case we copy the passwd file to a new file and we create
     the intended user. The file is then passwd/mapped into
     the container.
     """
     host_auth = NixAuthentication()
     (passwd, group) = self._select_auth_files()
     container_auth = NixAuthentication(passwd, group)
     if not user:
         user = "******"
     (valid_user, user_id) = self._user_from_str(user,
                                                 host_auth, container_auth)
     if not valid_user:
         Msg().err("Error: invalid syntax for user", user)
         return False
     if (self._is_mountpoint("/etc/passwd") or
             self._is_mountpoint("/etc/group")):
         self.opt["hostauth"] = self.opt["containerauth"] = False
         return True
     if self.opt["user"]:
         if self.opt["user"] != "root":
             self.opt["uid"] = str(HostInfo.uid)
             self.opt["gid"] = str(HostInfo.gid)
     else:
         if self.opt["hostauth"] or self.opt["containerauth"]:
             Msg().err("Error: user not found")
             return False
         self.opt["user"] = user_id["user"] if "user" in user_id else user
         self.opt["uid"] = user_id["uid"] if "uid" in user_id else ""
         self.opt["gid"] = user_id["gid"] if "gid" in user_id else ""
     self._create_user(container_auth, host_auth)
     return True
Example #11
0
    def namespace_exec(self, method, flags=CLONE_NEWUSER):
        """Execute command in namespace"""
        (pread1, pwrite1) = os.pipe()
        (pread2, pwrite2) = os.pipe()
        cpid = os.fork()
        if cpid:
            os.close(pwrite1)
            os.read(pread1, 1)  # wait
            user = HostInfo().username()
            newidmap = ["newuidmap", str(cpid), "0", str(HostInfo.uid), "1"]
            for (subid, subcount) in NixAuthentication().user_in_subuid(user):
                newidmap.extend(["1", subid, subcount])

            subprocess.call(newidmap)
            newidmap = ["newgidmap", str(cpid), "0", str(HostInfo.uid), "1"]
            for (subid, subcount) in NixAuthentication().user_in_subgid(user):
                newidmap.extend(["1", subid, subcount])

            subprocess.call(newidmap)
            os.close(pwrite2)   # notify
            (dummy, status) = os.waitpid(cpid, 0)
            if status % 256:
                Msg().err("Error: namespace exec action failed")
                return False

            return True

        self.unshare(flags)
        os.close(pwrite2)
        os.close(pwrite1)   # notify
        os.read(pread2, 1)  # wait
        try:
            os.setgid(0)
            os.setuid(0)
            os.setgroups([0, 0, ])
        except OSError:
            Msg().err("Error: setting ids and groups")
            return False

        # pylint: disable=protected-access
        os._exit(int(method()))
        return True
Example #12
0
    def _run_as_root(self):
        """Set configure running as normal user or as root via --fakeroot
        """
        username = HostInfo().username()
        if "user" in self.opt:
            if self.opt["user"] == username:
                return False

            if self.opt["user"] != "root" and self.opt["uid"] != '0':
                Msg().out("Warning: running as another user not supported")
                return False

            if self._has_option("--fakeroot", "exec"):
                if (NixAuthentication().user_in_subuid(username) and
                        NixAuthentication().user_in_subgid(username)):
                    Config.conf['singularity_options'].extend(["--fakeroot", ])
                    return True

        self.opt["user"] = username
        return False
Example #13
0
 def _create_user(self, container_auth, host_auth):
     """If we need to create a new user then we first
     copy /etc/passwd and /etc/group to new files and them
     we add the user account into these copied files which
     later are binding/mapped/passed to the container. So
     setup this binding as well via hostauth.
     """
     if self.opt["containerauth"]:
         tmp_passwd = container_auth.passwd_file
         tmp_group = container_auth.group_file
         self.opt["hostauth"] = False
     else:
         FileUtil().umask(0o077)
         tmp_passwd = FileUtil("passwd").mktmp()
         tmp_group = FileUtil("group").mktmp()
         if self.opt["hostauth"]:
             FileUtil("/etc/passwd").copyto(tmp_passwd)
             FileUtil("/etc/group").copyto(tmp_group)
         else:
             FileUtil(container_auth.passwd_file).copyto(tmp_passwd)
             FileUtil(container_auth.group_file).copyto(tmp_group)
         FileUtil().umask()
     if not (self.opt["containerauth"] or self.opt["hostauth"]):
         Msg().out("Warning: non-existing user will be created",
                   l=Msg.DBG)
         self._fill_user()
         new_auth = NixAuthentication(tmp_passwd, tmp_group)
         new_auth.add_user(self.opt["user"], 'x',
                           self.opt["uid"], self.opt["gid"],
                           self.opt["gecos"], self.opt["home"],
                           self.opt["shell"])
         (group, dummy, dummy) = host_auth.get_group(self.opt["gid"])
         if not group:
             new_auth.add_group(self.opt["user"], self.opt["gid"])
         for sup_gid in os.getgroups():
             new_auth.add_group('G' + str(sup_gid), str(sup_gid),
                                [self.opt["user"], ])
     if not self.opt["containerauth"]:
         self.opt["hostauth"] = True
         self.hostauth_list = (tmp_passwd + ":/etc/passwd",
                               tmp_group + ":/etc/group")
     return True
Example #14
0
 def _fill_user(self):
     """Fill in values for user to be used in the account creation.
     Provide default values in case the required fields are empty.
     """
     if not self.opt["uid"]:
         self.opt["uid"] = str(HostInfo.uid)
     if not self.opt["gid"]:
         self.opt["gid"] = str(HostInfo.gid)
     if not self.opt["user"]:
         self.opt["user"] = "******" + self.opt["uid"][0:4]
     if self.opt["bindhome"]:
         self.opt["home"] = NixAuthentication().get_home()
     if not self.opt["home"]:
         self.opt["home"] = '/'
     if not self.opt["shell"]:
         self.opt["shell"] = "/bin/sh"
     if not self.opt["gecos"]:
         self.opt["gecos"] = "*UDOCKER*"
    def test_06__get_group_from_host(self, mock_grgid, mock_grname):
        """Test06 NixAuthentication()._get_group_from_host()."""
        hgr = grp.struct_group(["root", "*", "0", str([])])
        mock_grgid.return_value = hgr
        auth = NixAuthentication()
        (name, gid, mem) = auth._get_group_from_host(0)
        self.assertEqual(name, hgr.gr_name)
        self.assertEqual(gid, str(hgr.gr_gid))
        self.assertEqual(mem, hgr.gr_mem)

        mock_grname.return_value = hgr
        auth = NixAuthentication()
        (name, gid, mem) = auth._get_group_from_host("root")
        self.assertEqual(name, hgr.gr_name)
        self.assertEqual(gid, str(hgr.gr_gid))
        self.assertEqual(mem, hgr.gr_mem)
    def test_08__get_group_from_file(self):
        """Test08 NixAuthentication()._get_group_from_file()."""
        auth = NixAuthentication()
        auth.passwd_file = "passwd"
        group_line = StringIO('root:x:0:a,b,c')
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(group_line.readline, ''))
            (name, gid, mem) = auth._get_group_from_file("root")
            self.assertEqual(name, "root")
            self.assertEqual(gid, "0")
            self.assertEqual(mem, "a,b,c")

        group_line = StringIO('root:x:0:a,b,c')
        auth = NixAuthentication()
        with patch(BUILTINS + '.open') as mopen:
            mopen.return_value.__iter__ = (
                lambda self: iter(group_line.readline, ''))
            (name, gid, mem) = auth._get_group_from_file(0)
            self.assertEqual(name, "root")
            self.assertEqual(gid, "0")
            self.assertEqual(mem, "a,b,c")
    def test_05__get_user_from_host(self, mock_getpwuid, mock_getpwnam):
        """Test05 NixAuthentication()._get_user_from_host()."""
        usr = pwd.struct_passwd(
            ["root", "*", "0", "0", "root usr", "/root", "/bin/bash"])
        mock_getpwuid.return_value = usr
        auth = NixAuthentication()
        (name, uid, gid, gecos, _dir, shell) = auth._get_user_from_host(0)
        self.assertEqual(name, usr.pw_name)
        self.assertEqual(uid, usr.pw_uid)
        self.assertEqual(gid, str(usr.pw_gid))
        self.assertEqual(gecos, usr.pw_gecos)
        self.assertEqual(_dir, usr.pw_dir)
        self.assertEqual(shell, usr.pw_shell)

        mock_getpwnam.return_value = usr
        auth = NixAuthentication()
        (name, uid, gid, gecos, _dir, shell) = auth._get_user_from_host("root")
        self.assertEqual(name, usr.pw_name)
        self.assertEqual(uid, usr.pw_uid)
        self.assertEqual(gid, str(usr.pw_gid))
        self.assertEqual(gecos, usr.pw_gecos)
        self.assertEqual(_dir, usr.pw_dir)
Example #18
0
 def _get_bindhome(self):
     """Binding of the host $HOME in to the container $HOME"""
     if self.opt["bindhome"]:
         return NixAuthentication().get_home()
     return ""
 def test_10_add_group(self):
     """Test10 NixAuthentication().add_group()."""
     auth = NixAuthentication()
     with patch(BUILTINS + '.open', mock_open()):
         status = auth.add_group("root", 0)
         self.assertTrue(status)