diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2019-11-04 18:07:58 -0500 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2019-11-06 10:35:37 -0500 |
commit | a6108f1c19f4432eff4ee1e52eef9e60d13329e5 (patch) | |
tree | d1451bc83388799088ef0134b4cd27aa1458133b | |
parent | 581a7ec2984c2c125ff255c9aca62f2547c7d46f (diff) | |
download | podman-a6108f1c19f4432eff4ee1e52eef9e60d13329e5.tar.gz podman-a6108f1c19f4432eff4ee1e52eef9e60d13329e5.tar.bz2 podman-a6108f1c19f4432eff4ee1e52eef9e60d13329e5.zip |
Add support for RunAsUser and RunAsGroup
Currently podman generate kube does not generate the correct RunAsUser and RunAsGroup
options in the yaml file. This patch fixes this.
This patch also make `podman play kube` use the RunAdUser and RunAsGroup options if
they are specified in the yaml file.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
-rw-r--r-- | libpod/kube.go | 9 | ||||
-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 |
4 files changed, 95 insertions, 43 deletions
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/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 |