diff options
-rw-r--r-- | cmd/podman/attach.go | 3 | ||||
-rw-r--r-- | cmd/podman/common.go | 2 | ||||
-rw-r--r-- | cmd/podman/exec.go | 3 | ||||
-rw-r--r-- | cmd/podman/start.go | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-attach.1.md | 4 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 4 | ||||
-rw-r--r-- | docs/source/markdown/podman-exec.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 4 | ||||
-rw-r--r-- | docs/source/markdown/podman-start.1.md | 4 | ||||
-rw-r--r-- | libpod.conf | 23 | ||||
-rw-r--r-- | libpod/kube.go | 9 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 2 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 11 | ||||
-rw-r--r-- | pkg/adapter/pods.go | 93 | ||||
-rw-r--r-- | test/e2e/generate_kube_test.go | 33 | ||||
-rw-r--r-- | test/e2e/test.yaml | 3 |
16 files changed, 131 insertions, 71 deletions
diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go index b78633ed6..b03673f29 100644 --- a/cmd/podman/attach.go +++ b/cmd/podman/attach.go @@ -2,6 +2,7 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -31,7 +32,7 @@ func init() { attachCommand.SetHelpTemplate(HelpTemplate()) attachCommand.SetUsageTemplate(UsageTemplate()) flags := attachCommand.Flags() - flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") + flags.StringVar(&attachCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process") flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 37511641b..8afbe2e0b 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -188,7 +188,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "Run container in background and print container ID", ) createFlags.String( - "detach-keys", "", + "detach-keys", define.DefaultDetachKeys, "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`", ) createFlags.StringSlice( diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 649a7b0db..afa701897 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -2,6 +2,7 @@ package main import ( "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -34,7 +35,7 @@ func init() { execCommand.SetUsageTemplate(UsageTemplate()) flags := execCommand.Flags() flags.SetInterspersed(false) - flags.StringVar(&execCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") + flags.StringVar(&execCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _") flags.StringArrayVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables") flags.BoolVarP(&execCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&execCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") diff --git a/cmd/podman/start.go b/cmd/podman/start.go index 2d2cf74d2..d4b4534bb 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -35,7 +35,7 @@ func init() { startCommand.SetUsageTemplate(UsageTemplate()) flags := startCommand.Flags() flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") - flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") + flags.StringVar(&startCommand.DetachKeys, "detach-keys", define.DefaultDetachKeys, "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&startCommand.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") diff --git a/docs/source/markdown/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md index cef01f0f6..1ac2e49a9 100644 --- a/docs/source/markdown/podman-attach.1.md +++ b/docs/source/markdown/podman-attach.1.md @@ -20,9 +20,7 @@ it in the **libpod.conf** file: see **libpod.conf(5)** for more information. ## OPTIONS **--detach-keys**=*sequence* -Override the key sequence for detaching a container. Format is a single character `[a-Z]` or -a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: -`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. **--latest**, **-l** diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 2e0dd934c..c10cf2cfa 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -198,9 +198,7 @@ it in the **libpod.conf** file: see **libpod.conf(5)** for more information. **--detach-keys**=*sequence* -Override the key sequence for detaching a container. Format is a single character `[a-Z]` or -a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: -`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. **--device**=*device* diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md index 4c17c056a..9624425dc 100644 --- a/docs/source/markdown/podman-exec.1.md +++ b/docs/source/markdown/podman-exec.1.md @@ -15,7 +15,7 @@ podman\-exec - Execute a command in a running container **--detach-keys**=*sequence* -Override the key sequence for detaching a container. Format is a single character `[a-Z]` or `ctrl-<value>` where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. **--env**, **-e** diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 8baa39570..75f1f94ce 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -204,9 +204,7 @@ it in the **libpod.conf** file: see **libpod.conf(5)** for more information. **--detach-keys**=*sequence* -Override the key sequence for detaching a container. Format is a single character `[a-Z]` or -a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: -`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. **--device**=*device* diff --git a/docs/source/markdown/podman-start.1.md b/docs/source/markdown/podman-start.1.md index 4c81d17bd..84af9d800 100644 --- a/docs/source/markdown/podman-start.1.md +++ b/docs/source/markdown/podman-start.1.md @@ -23,9 +23,7 @@ starting multiple containers. **--detach-keys**=*sequence* -Override the key sequence for detaching a container. Format is a single character `[a-Z]` or -a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: -`a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`. +Specify the key sequence for detaching a container. Format is a single character `[a-Z]` or one or more `ctrl-<value>` characters where `<value>` is one of: `a-z`, `@`, `^`, `[`, `,` or `_`. Specifying "" will disable this feature. The default is *ctrl-p,ctrl-q*. **--interactive**, **-i** diff --git a/libpod.conf b/libpod.conf index ef7c101a6..7e0228c19 100644 --- a/libpod.conf +++ b/libpod.conf @@ -151,6 +151,29 @@ crun = [ "/run/current-system/sw/bin/crun", ] +# Kata Containers is an OCI runtime, where containers are run inside lightweight +# Virtual Machines (VMs). Kata provides additional isolation towards the host, +# minimizing the host attack surface and mitigating the consequences of +# containers breakout. +# Please notes that Kata does not support rootless podman yet, but we can leave +# the paths below blank to let them be discovered by the $PATH environment +# variable. + +# Kata Containers with the default configured VMM +kata-runtime = [ + "/usr/bin/kata-runtime", +] + +# Kata Containers with the QEMU VMM +kata-qemu = [ + "/usr/bin/kata-qemu", +] + +# Kata Containers with the Firecracker VMM +kata-fc = [ + "/usr/bin/kata-fc", +] + # The [runtimes] table MUST be the last thing in this file. # (Unless another table is added) # TOML does not provide a way to end a table other than a further table being diff --git a/libpod/kube.go b/libpod/kube.go index d0e7baf95..47a77991e 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -487,13 +487,16 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) { if err := c.syncContainer(); err != nil { return nil, errors.Wrapf(err, "unable to sync container during YAML generation") } + logrus.Debugf("Looking in container for user: %s", c.User()) - u, err := lookup.GetUser(c.state.Mountpoint, c.User()) + execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.User(), nil) if err != nil { return nil, err } - user := int64(u.Uid) - sc.RunAsUser = &user + uid := int64(execUser.Uid) + gid := int64(execUser.Gid) + sc.RunAsUser = &uid + sc.RunAsGroup = &gid } return &sc, nil } diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index eeaee6d43..46c70e7eb 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -152,7 +152,7 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c func processDetachKeys(keys string) ([]byte, error) { // Check the validity of the provided keys first if len(keys) == 0 { - keys = define.DefaultDetachKeys + return []byte{}, nil } detachKeys, err := term.ToBytes(keys) if err != nil { diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 64550f545..a09466243 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -400,17 +400,8 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode } } - config, err := r.Runtime.GetConfig() - if err != nil { - return exitCode, err - } - detachKeys := c.String("detach-keys") - if detachKeys == "" { - detachKeys = config.DetachKeys - } - // if the container was created as part of a pod, also start its dependencies, if any. - if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, detachKeys, c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil { + if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil { // We've manually detached from the container // Do not perform cleanup, or wait for container exit code // Just exit immediately diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index f6795970b..6648edc82 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -666,6 +666,58 @@ func getPodPorts(containers []v1.Container) []ocicni.PortMapping { return infraPorts } +func setupSecurityContext(containerConfig *createconfig.CreateConfig, containerYAML v1.Container) { + if containerYAML.SecurityContext == nil { + return + } + if containerYAML.SecurityContext.ReadOnlyRootFilesystem != nil { + containerConfig.ReadOnlyRootfs = *containerYAML.SecurityContext.ReadOnlyRootFilesystem + } + if containerYAML.SecurityContext.Privileged != nil { + containerConfig.Privileged = *containerYAML.SecurityContext.Privileged + } + + if containerYAML.SecurityContext.AllowPrivilegeEscalation != nil { + containerConfig.NoNewPrivs = !*containerYAML.SecurityContext.AllowPrivilegeEscalation + } + + if seopt := containerYAML.SecurityContext.SELinuxOptions; seopt != nil { + if seopt.User != "" { + containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=user:%s", seopt.User)) + containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("user:%s", seopt.User)) + } + if seopt.Role != "" { + containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=role:%s", seopt.Role)) + containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("role:%s", seopt.Role)) + } + if seopt.Type != "" { + containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=type:%s", seopt.Type)) + containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("type:%s", seopt.Type)) + } + if seopt.Level != "" { + containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=level:%s", seopt.Level)) + containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("level:%s", seopt.Level)) + } + } + if caps := containerYAML.SecurityContext.Capabilities; caps != nil { + for _, capability := range caps.Add { + containerConfig.CapAdd = append(containerConfig.CapAdd, string(capability)) + } + for _, capability := range caps.Drop { + containerConfig.CapDrop = append(containerConfig.CapDrop, string(capability)) + } + } + if containerYAML.SecurityContext.RunAsUser != nil { + containerConfig.User = fmt.Sprintf("%d", *containerYAML.SecurityContext.RunAsUser) + } + if containerYAML.SecurityContext.RunAsGroup != nil { + if containerConfig.User == "" { + containerConfig.User = "0" + } + containerConfig.User = fmt.Sprintf("%s:%d", containerConfig.User, *containerYAML.SecurityContext.RunAsGroup) + } +} + // kubeContainerToCreateConfig takes a v1.Container and returns a createconfig describing a container func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container, runtime *libpod.Runtime, newImage *image.Image, namespaces map[string]string, volumes map[string]string, podID string) (*createconfig.CreateConfig, error) { var ( @@ -690,47 +742,8 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container containerConfig.User = imageData.Config.User } - if containerYAML.SecurityContext != nil { - if containerConfig.SecurityOpts != nil { - if containerYAML.SecurityContext.ReadOnlyRootFilesystem != nil { - containerConfig.ReadOnlyRootfs = *containerYAML.SecurityContext.ReadOnlyRootFilesystem - } - if containerYAML.SecurityContext.Privileged != nil { - containerConfig.Privileged = *containerYAML.SecurityContext.Privileged - } - - if containerYAML.SecurityContext.AllowPrivilegeEscalation != nil { - containerConfig.NoNewPrivs = !*containerYAML.SecurityContext.AllowPrivilegeEscalation - } + setupSecurityContext(&containerConfig, containerYAML) - } - if seopt := containerYAML.SecurityContext.SELinuxOptions; seopt != nil { - if seopt.User != "" { - containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=user:%s", seopt.User)) - containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("user:%s", seopt.User)) - } - if seopt.Role != "" { - containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=role:%s", seopt.Role)) - containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("role:%s", seopt.Role)) - } - if seopt.Type != "" { - containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=type:%s", seopt.Type)) - containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("type:%s", seopt.Type)) - } - if seopt.Level != "" { - containerConfig.SecurityOpts = append(containerConfig.SecurityOpts, fmt.Sprintf("label=level:%s", seopt.Level)) - containerConfig.LabelOpts = append(containerConfig.LabelOpts, fmt.Sprintf("level:%s", seopt.Level)) - } - } - if caps := containerYAML.SecurityContext.Capabilities; caps != nil { - for _, capability := range caps.Add { - containerConfig.CapAdd = append(containerConfig.CapAdd, string(capability)) - } - for _, capability := range caps.Drop { - containerConfig.CapDrop = append(containerConfig.CapDrop, string(capability)) - } - } - } var err error containerConfig.SeccompProfilePath, err = libpod.DefaultSeccompPath() if err != nil { diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 5d3b1238a..603edbe6b 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -208,6 +208,39 @@ var _ = Describe("Podman generate kube", func() { Expect(psOut).To(ContainSubstring("test2")) }) + It("podman generate with user and reimport kube on pod", func() { + podName := "toppod" + _, rc, _ := podmanTest.CreatePod(podName) + Expect(rc).To(Equal(0)) + + session := podmanTest.Podman([]string{"create", "--pod", podName, "--name", "test1", "--user", "100:200", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.Config.User}}", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(ContainSubstring("100:200")) + + outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml") + kube := podmanTest.Podman([]string{"generate", "kube", "-f", outputFile, podName}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"pod", "rm", "-af"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"play", "kube", outputFile}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + inspect1 := podmanTest.Podman([]string{"inspect", "--format", "{{.Config.User}}", "test1"}) + inspect1.WaitWithDefaultTimeout() + Expect(inspect1.ExitCode()).To(Equal(0)) + Expect(inspect1.OutputToString()).To(ContainSubstring(inspect.OutputToString())) + }) + It("podman generate kube with volume", func() { vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") err := os.MkdirAll(vol1, 0755) diff --git a/test/e2e/test.yaml b/test/e2e/test.yaml index 319d6a4a0..98d2c91df 100644 --- a/test/e2e/test.yaml +++ b/test/e2e/test.yaml @@ -24,6 +24,9 @@ spec: name: test resources: {} securityContext: + runAsUser: 1000 + runAsGroup: 3000 + fsGroup: 2000 allowPrivilegeEscalation: true capabilities: {} privileged: false |