|
4 | 4 | "fmt" |
5 | 5 | "os" |
6 | 6 | "path/filepath" |
| 7 | + "regexp" |
7 | 8 | "runtime" |
8 | 9 | "strconv" |
9 | 10 | "strings" |
@@ -124,6 +125,55 @@ var _ = Describe("podman machine init", func() { |
124 | 125 | Expect(repeatSession.errorToString()).To(ContainSubstring(fmt.Sprintf("Error: machine %q already exists", mb.names[0]))) |
125 | 126 | }) |
126 | 127 |
|
| 128 | + It("init subid range check for rootless PinP", func() { |
| 129 | + /* By default, a new user is assigned the following sub-ID ranges (see manual useradd): |
| 130 | + * SUB_UID_MIN=100000, SUB_GID_MIN=100000, SUB_UID_COUNT=65536, SUB_GID_COUNT=65536 |
| 131 | + * This means the default sub-UID and sub-GID ranges are 100000–165535. |
| 132 | + * |
| 133 | + * When the container is run rootless by the user in WSL, ID mappings occur as follows: |
| 134 | + * Container ID 0 (root) maps to user ID on the host. |
| 135 | + * Container IDs 1–65536 map to IDs 100000–165535 on host (range previously mentioned). |
| 136 | + * |
| 137 | + * If a new user is created inside the container and used to build containers with |
| 138 | + * (rootless PinP), it will attempt to use the default sub-ID range (100000–165535). Given |
| 139 | + * the mapping, this means that the host must at least have a SUB_UID_COUNT and |
| 140 | + * SUB_GID_COUNT of 165536. Since 165536 would only allow rootless PinP for the first |
| 141 | + * user (with ID 1000), the check is run against a count of 166536 (=165536+1000) as to |
| 142 | + * provide additional margin. |
| 143 | + */ |
| 144 | + |
| 145 | + count_min := 166536 |
| 146 | + i := new(initMachine) |
| 147 | + name := randomString() |
| 148 | + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath)).run() |
| 149 | + Expect(err).ToNot(HaveOccurred()) |
| 150 | + Expect(session).To(Exit(0)) |
| 151 | + |
| 152 | + // obtain the users subid range from the machine |
| 153 | + ssh := new(sshMachine) |
| 154 | + sshSession, err := mb.setName(name).setCmd(ssh.withSSHCommand([]string{"cat", "/etc/subuid", "/etc/subgid"})).run() |
| 155 | + Expect(err).ToNot(HaveOccurred()) |
| 156 | + Expect(sshSession).To(Exit(0)) |
| 157 | + output := strings.TrimSpace(sshSession.outputToString()) |
| 158 | + |
| 159 | + // subuid and subgid have the format 'USER:SUB_ID_MIN:SUB_ID_COUNT', for example |
| 160 | + // 'user:100000:65536', only count is of interest. |
| 161 | + re := regexp.MustCompile(`(?m):(\d+)$`) |
| 162 | + counts := re.FindAllStringSubmatch(output, -1) |
| 163 | + |
| 164 | + // A user must exist in order to run podman rootless, a line in both subuid and subgid |
| 165 | + // should exist for it, so 2 lines in total. |
| 166 | + Expect(len(counts)).To(BeNumerically(">=", 2), "expected at least 1 user/line in /etc/subuid and /etc/subgid each, got %d", len(counts)) |
| 167 | + |
| 168 | + // Verify the count. At the moment only 1 user is created in the machine. If multiple users |
| 169 | + // are ever created, this will check that all users have a sufficient subid range. |
| 170 | + for _, count := range counts { |
| 171 | + n, err := strconv.Atoi(count[1]) |
| 172 | + Expect(err).ToNot(HaveOccurred()) |
| 173 | + Expect(n).To(BeNumerically(">=", count_min), "expected last number %d to be >= %d", n, count_min) |
| 174 | + } |
| 175 | + }) |
| 176 | + |
127 | 177 | It("run playbook", func() { |
128 | 178 | str := randomString() |
129 | 179 |
|
|
0 commit comments