-
Notifications
You must be signed in to change notification settings - Fork 159
cmd: generate: add --linux-namespace-* family of flags #288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,7 +24,6 @@ var generateFlags = []cli.Flag{ | |
| cli.StringSliceFlag{Name: "bind", Usage: "bind mount directories src:dest[:options...]"}, | ||
| cli.StringSliceFlag{Name: "cap-add", Usage: "add Linux capabilities"}, | ||
| cli.StringSliceFlag{Name: "cap-drop", Usage: "drop Linux capabilities"}, | ||
| cli.StringFlag{Name: "cgroup", Usage: "cgroup namespace"}, | ||
| cli.StringFlag{Name: "cgroups-path", Usage: "specify the path to the cgroups"}, | ||
| cli.StringFlag{Name: "cwd", Value: "/", Usage: "current working directory for the process"}, | ||
| cli.BoolFlag{Name: "disable-oom-kill", Usage: "disable OOM Killer"}, | ||
|
|
@@ -34,7 +33,6 @@ var generateFlags = []cli.Flag{ | |
| cli.StringSliceFlag{Name: "gidmappings", Usage: "add GIDMappings e.g HostID:ContainerID:Size"}, | ||
| cli.StringSliceFlag{Name: "groups", Usage: "supplementary groups for the process"}, | ||
| cli.StringFlag{Name: "hostname", Usage: "hostname value for the container"}, | ||
| cli.StringFlag{Name: "ipc", Usage: "ipc namespace"}, | ||
| cli.StringSliceFlag{Name: "label", Usage: "add annotations to the configuration e.g. key=value"}, | ||
| cli.Uint64Flag{Name: "linux-cpu-shares", Usage: "the relative share of CPU time available to the tasks in a cgroup"}, | ||
| cli.Uint64Flag{Name: "linux-cpu-period", Usage: "the CPU period to be used for hardcapping (in usecs)"}, | ||
|
|
@@ -47,21 +45,21 @@ var generateFlags = []cli.Flag{ | |
| cli.Uint64Flag{Name: "linux-mem-swap", Usage: "total memory limit (memory + swap) (in bytes)"}, | ||
| cli.Uint64Flag{Name: "linux-mem-swappiness", Usage: "how aggressive the kernel will swap memory pages (Range from 0 to 100)"}, | ||
| cli.StringFlag{Name: "linux-mems", Usage: "list of memory nodes in the cpuset (default is to use any available memory node)"}, | ||
| cli.StringSliceFlag{Name: "linux-namespace-add", Usage: "adds a namespace to the set of namespaces to create or join of the form 'ns[:path]'"}, | ||
| cli.StringSliceFlag{Name: "linux-namespace-remove", Usage: "removes a namespace from the set of namespaces to create or join of the form 'ns'"}, | ||
| cli.BoolFlag{Name: "linux-namespace-remove-all", Usage: "removes all namespaces from the set of namespaces created or joined"}, | ||
| cli.IntFlag{Name: "linux-network-classid", Usage: "specifies class identifier tagged by container's network packets"}, | ||
| cli.StringSliceFlag{Name: "linux-network-priorities", Usage: "specifies priorities of network traffic"}, | ||
| cli.Int64Flag{Name: "linux-pids-limit", Usage: "maximum number of PIDs"}, | ||
| cli.Uint64Flag{Name: "linux-realtime-period", Usage: "CPU period to be used for realtime scheduling (in usecs)"}, | ||
| cli.Uint64Flag{Name: "linux-realtime-runtime", Usage: "the time realtime scheduling may use (in usecs)"}, | ||
| cli.StringSliceFlag{Name: "masked-paths", Usage: "specifies paths can not be read inside container"}, | ||
| cli.StringFlag{Name: "mount", Usage: "mount namespace"}, | ||
| cli.StringFlag{Name: "mount-cgroups", Value: "no", Usage: "mount cgroups (rw,ro,no)"}, | ||
| cli.StringFlag{Name: "mount-label", Usage: "selinux mount context label"}, | ||
| cli.StringFlag{Name: "network", Usage: "network namespace"}, | ||
| cli.BoolFlag{Name: "no-new-privileges", Usage: "set no new privileges bit for the container process"}, | ||
| cli.IntFlag{Name: "oom-score-adj", Usage: "oom_score_adj for the container"}, | ||
| cli.StringFlag{Name: "os", Value: runtime.GOOS, Usage: "operating system the container is created for"}, | ||
| cli.StringFlag{Name: "output", Usage: "output file (defaults to stdout)"}, | ||
| cli.StringFlag{Name: "pid", Usage: "pid namespace"}, | ||
| cli.StringSliceFlag{Name: "poststart", Usage: "set command to run in poststart hooks"}, | ||
| cli.StringSliceFlag{Name: "poststop", Usage: "set command to run in poststop hooks"}, | ||
| cli.StringSliceFlag{Name: "prestart", Usage: "set command to run in prestart hooks"}, | ||
|
|
@@ -91,8 +89,6 @@ var generateFlags = []cli.Flag{ | |
| cli.BoolFlag{Name: "tty", Usage: "allocate a new tty for the container process"}, | ||
| cli.IntFlag{Name: "uid", Usage: "uid for the process"}, | ||
| cli.StringSliceFlag{Name: "uidmappings", Usage: "add UIDMappings e.g HostID:ContainerID:Size"}, | ||
| cli.StringFlag{Name: "user", Usage: "user namespace"}, | ||
| cli.StringFlag{Name: "uts", Usage: "uts namespace"}, | ||
| } | ||
|
|
||
| var generateCommand = cli.Command{ | ||
|
|
@@ -284,8 +280,6 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { | |
| } | ||
| } | ||
|
|
||
| needsNewUser := false | ||
|
|
||
| var uidMaps, gidMaps []string | ||
|
|
||
| if context.IsSet("uidmappings") { | ||
|
|
@@ -296,12 +290,11 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { | |
| gidMaps = context.StringSlice("gidmappings") | ||
| } | ||
|
|
||
| // Add default user namespace. | ||
| if len(uidMaps) > 0 || len(gidMaps) > 0 { | ||
| needsNewUser = true | ||
| g.AddOrReplaceLinuxNamespace("user", "") | ||
| } | ||
|
|
||
| setupLinuxNamespaces(context, g, needsNewUser) | ||
|
|
||
| if context.IsSet("tmpfs") { | ||
| tmpfsSlice := context.StringSlice("tmpfs") | ||
| for _, s := range tmpfsSlice { | ||
|
|
@@ -461,6 +454,32 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { | |
| } | ||
| } | ||
|
|
||
| if context.IsSet("linux-namespace-add") { | ||
| namespaces := context.StringSlice("linux-namespace-add") | ||
| for _, ns := range namespaces { | ||
| name, path, err := parseNamespace(ns) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| if err := g.AddOrReplaceLinuxNamespace(name, path); err != nil { | ||
| return err | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if context.IsSet("linux-namespace-remove") { | ||
| namespaces := context.StringSlice("linux-namespace-remove") | ||
| for _, name := range namespaces { | ||
| if err := g.RemoveLinuxNamespace(name); err != nil { | ||
| return err | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if context.Bool("linux-namespace-remove-all") { | ||
| g.ClearLinuxNamespaces() | ||
| } | ||
|
|
||
| if context.IsSet("rlimits-add") { | ||
| rlimits := context.StringSlice("rlimits-add") | ||
| for _, rlimit := range rlimits { | ||
|
|
@@ -490,20 +509,6 @@ func setupSpec(g *generate.Generator, context *cli.Context) error { | |
| return err | ||
| } | ||
|
|
||
| func setupLinuxNamespaces(context *cli.Context, g *generate.Generator, needsNewUser bool) { | ||
| for _, nsName := range generate.Namespaces { | ||
| if !context.IsSet(nsName) && !(needsNewUser && nsName == "user") { | ||
| continue | ||
| } | ||
| nsPath := context.String(nsName) | ||
| if nsPath == "host" { | ||
| g.RemoveLinuxNamespace(nsName) | ||
| continue | ||
| } | ||
| g.AddOrReplaceLinuxNamespace(nsName, nsPath) | ||
| } | ||
| } | ||
|
|
||
| func parseIDMapping(idms string) (uint32, uint32, uint32, error) { | ||
| idm := strings.Split(idms, ":") | ||
| if len(idm) != 3 { | ||
|
|
@@ -608,6 +613,22 @@ func parseRlimit(rlimit string) (string, uint64, uint64, error) { | |
| return parts[0], uint64(hard), uint64(soft), nil | ||
| } | ||
|
|
||
| func parseNamespace(ns string) (string, string, error) { | ||
| parts := strings.SplitN(ns, ":", 2) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't check parts[0], then
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can validate it against the spec's whitelist. But I'm fine punting validation to a post-generate call (for callers who care). Maybe they intend to fix the values in post-processing.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've fixed it to check There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what kind of tests?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There aren't any unit tests or integration tests for
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More importantly, as far as I can tell there's no tests of the validation -- which is quite worrying. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we should add unit tests. unit tests for validation already in #273
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd floated some sharness stubs for testing in #180. Happy to rebase if there is renewed interest. |
||
| if len(parts) == 0 || parts[0] == "" { | ||
| return "", "", fmt.Errorf("invalid namespace value: %s", ns) | ||
| } | ||
|
|
||
| nsType := parts[0] | ||
| nsPath := "" | ||
|
|
||
| if len(parts) == 2 { | ||
| nsPath = parts[1] | ||
| } | ||
|
|
||
| return nsType, nsPath, nil | ||
| } | ||
|
|
||
| func addSeccomp(context *cli.Context, g *generate.Generator) error { | ||
|
|
||
| // Set the DefaultAction of seccomp | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will silently create an invalid config with
--uidmappings=… --linux-namespace-add=user:foo, because the resulting config with call for tweaking a joined namespace. I'm pro-tweaking though, and we're already doing something silent about this case, so I'm ok with that ;). Folks who want to ensure validity can pass their final config through tovalidateas a separate step.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it'll generate an invalid config, because the
--linux-namespace-addhandling is done afterwards and so theuserentry will be replaced.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, sorry, it will generate an invalid config, but the user asked us to generate it...