|
1 | 1 | package specconv |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "os" |
4 | 5 | "runtime" |
| 6 | + "strings" |
5 | 7 |
|
6 | 8 | "github.com/opencontainers/runtime-spec/specs-go" |
7 | 9 | ) |
8 | 10 |
|
9 | 11 | func sPtr(s string) *string { return &s } |
10 | 12 |
|
11 | | -// ExampleSpec returns an example spec file, with many options set so a user |
12 | | -// can see what a standard spec file looks like. |
13 | | -func ExampleSpec() *specs.Spec { |
| 13 | +// Example returns an example spec file, with many options set so a user can |
| 14 | +// see what a standard spec file looks like. |
| 15 | +func Example() *specs.Spec { |
14 | 16 | return &specs.Spec{ |
15 | 17 | Version: specs.Version, |
16 | 18 | Platform: specs.Platform{ |
@@ -158,3 +160,68 @@ func ExampleSpec() *specs.Spec { |
158 | 160 | }, |
159 | 161 | } |
160 | 162 | } |
| 163 | + |
| 164 | +// ExampleRootless returns an example spec file that works with rootless |
| 165 | +// containers. It's essentially a modified version of the specfile from |
| 166 | +// Example(). |
| 167 | +func ToRootless(spec *specs.Spec) { |
| 168 | + var namespaces []specs.LinuxNamespace |
| 169 | + |
| 170 | + // Remove networkns from the spec. |
| 171 | + for _, ns := range spec.Linux.Namespaces { |
| 172 | + switch ns.Type { |
| 173 | + case specs.NetworkNamespace, specs.UserNamespace: |
| 174 | + // Do nothing. |
| 175 | + default: |
| 176 | + namespaces = append(namespaces, ns) |
| 177 | + } |
| 178 | + } |
| 179 | + // Add userns to the spec. |
| 180 | + namespaces = append(namespaces, specs.LinuxNamespace{ |
| 181 | + Type: specs.UserNamespace, |
| 182 | + }) |
| 183 | + spec.Linux.Namespaces = namespaces |
| 184 | + |
| 185 | + // Add mappings for the current user. |
| 186 | + spec.Linux.UIDMappings = []specs.LinuxIDMapping{{ |
| 187 | + HostID: uint32(os.Geteuid()), |
| 188 | + ContainerID: 0, |
| 189 | + Size: 1, |
| 190 | + }} |
| 191 | + spec.Linux.GIDMappings = []specs.LinuxIDMapping{{ |
| 192 | + HostID: uint32(os.Getegid()), |
| 193 | + ContainerID: 0, |
| 194 | + Size: 1, |
| 195 | + }} |
| 196 | + |
| 197 | + // Fix up mounts. |
| 198 | + var mounts []specs.Mount |
| 199 | + for _, mount := range spec.Mounts { |
| 200 | + // Ignore all mounts that are under /sys. |
| 201 | + if strings.HasPrefix(mount.Destination, "/sys") { |
| 202 | + continue |
| 203 | + } |
| 204 | + |
| 205 | + // Remove all gid= and uid= mappings. |
| 206 | + var options []string |
| 207 | + for _, option := range mount.Options { |
| 208 | + if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") { |
| 209 | + options = append(options, option) |
| 210 | + } |
| 211 | + } |
| 212 | + |
| 213 | + mount.Options = options |
| 214 | + mounts = append(mounts, mount) |
| 215 | + } |
| 216 | + // Add the sysfs mount as an rbind. |
| 217 | + mounts = append(mounts, specs.Mount{ |
| 218 | + Source: "/sys", |
| 219 | + Destination: "/sys", |
| 220 | + Type: "none", |
| 221 | + Options: []string{"rbind", "nosuid", "noexec", "nodev", "ro"}, |
| 222 | + }) |
| 223 | + spec.Mounts = mounts |
| 224 | + |
| 225 | + // Remove cgroup settings. |
| 226 | + spec.Linux.Resources = nil |
| 227 | +} |
0 commit comments