summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2022-05-09 16:37:34 +0200
committerGiuseppe Scrivano <gscrivan@redhat.com>2022-05-10 09:09:14 +0200
commit9e1ee081f8849cbba89fb0f79218812164527251 (patch)
tree8d8c161ebce56588faee0f79a04b7da8a84e2f43
parent82a4b8f01c8061c022e7c9222746865a44f25d64 (diff)
downloadpodman-9e1ee081f8849cbba89fb0f79218812164527251.tar.gz
podman-9e1ee081f8849cbba89fb0f79218812164527251.tar.bz2
podman-9e1ee081f8849cbba89fb0f79218812164527251.zip
kube: honor pod security context IDs
If the RunAsUser, RunAsGroup, SupplementalGroups settings are not overriden in the container security context, then take the value from the pod security context. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r--pkg/domain/infra/abi/play.go64
-rw-r--r--pkg/specgen/generate/kube/kube.go38
-rw-r--r--test/e2e/play_kube_test.go100
3 files changed, 152 insertions, 50 deletions
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index b3ded7db6..f44b46a6d 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -412,22 +412,23 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
specgenOpts := kube.CtrSpecGenOptions{
- Annotations: annotations,
- Container: initCtr,
- Image: pulledImage,
- Volumes: volumes,
- PodID: pod.ID(),
- PodName: podName,
- PodInfraID: podInfraID,
- ConfigMaps: configMaps,
- SeccompPaths: seccompPaths,
- RestartPolicy: ctrRestartPolicy,
- NetNSIsHost: p.NetNS.IsHost(),
- SecretsManager: secretsManager,
- LogDriver: options.LogDriver,
- LogOptions: options.LogOptions,
- Labels: labels,
- InitContainerType: define.AlwaysInitContainer,
+ Annotations: annotations,
+ ConfigMaps: configMaps,
+ Container: initCtr,
+ Image: pulledImage,
+ InitContainerType: define.AlwaysInitContainer,
+ Labels: labels,
+ LogDriver: options.LogDriver,
+ LogOptions: options.LogOptions,
+ NetNSIsHost: p.NetNS.IsHost(),
+ PodID: pod.ID(),
+ PodInfraID: podInfraID,
+ PodName: podName,
+ PodSecurityContext: podYAML.Spec.SecurityContext,
+ RestartPolicy: ctrRestartPolicy,
+ SeccompPaths: seccompPaths,
+ SecretsManager: secretsManager,
+ Volumes: volumes,
}
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
@@ -460,21 +461,22 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
specgenOpts := kube.CtrSpecGenOptions{
- Annotations: annotations,
- Container: container,
- Image: pulledImage,
- Volumes: volumes,
- PodID: pod.ID(),
- PodName: podName,
- PodInfraID: podInfraID,
- ConfigMaps: configMaps,
- SeccompPaths: seccompPaths,
- RestartPolicy: ctrRestartPolicy,
- NetNSIsHost: p.NetNS.IsHost(),
- SecretsManager: secretsManager,
- LogDriver: options.LogDriver,
- LogOptions: options.LogOptions,
- Labels: labels,
+ Annotations: annotations,
+ ConfigMaps: configMaps,
+ Container: container,
+ Image: pulledImage,
+ Labels: labels,
+ LogDriver: options.LogDriver,
+ LogOptions: options.LogOptions,
+ NetNSIsHost: p.NetNS.IsHost(),
+ PodID: pod.ID(),
+ PodInfraID: podInfraID,
+ PodName: podName,
+ PodSecurityContext: podYAML.Spec.SecurityContext,
+ RestartPolicy: ctrRestartPolicy,
+ SeccompPaths: seccompPaths,
+ SecretsManager: secretsManager,
+ Volumes: volumes,
}
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index c04b94d4e..04195d15a 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -133,6 +133,8 @@ type CtrSpecGenOptions struct {
// InitContainerType sets what type the init container is
// Note: When playing a kube yaml, the inti container type will be set to "always" only
InitContainerType string
+ // PodSecurityContext is the security context specified for the pod
+ PodSecurityContext *v1.PodSecurityContext
}
func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) {
@@ -188,7 +190,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
s.InitContainerType = opts.InitContainerType
- setupSecurityContext(s, opts.Container.SecurityContext)
+ setupSecurityContext(s, opts.Container.SecurityContext, opts.PodSecurityContext)
err := setupLivenessProbe(s, opts.Container, opts.RestartPolicy)
if err != nil {
return nil, errors.Wrap(err, "Failed to configure livenessProbe")
@@ -531,10 +533,14 @@ func makeHealthCheck(inCmd string, interval int32, retries int32, timeout int32,
return &hc, nil
}
-func setupSecurityContext(s *specgen.SpecGenerator, securityContext *v1.SecurityContext) {
+func setupSecurityContext(s *specgen.SpecGenerator, securityContext *v1.SecurityContext, podSecurityContext *v1.PodSecurityContext) {
if securityContext == nil {
- return
+ securityContext = &v1.SecurityContext{}
}
+ if podSecurityContext == nil {
+ podSecurityContext = &v1.PodSecurityContext{}
+ }
+
if securityContext.ReadOnlyRootFilesystem != nil {
s.ReadOnlyFilesystem = *securityContext.ReadOnlyRootFilesystem
}
@@ -546,7 +552,11 @@ func setupSecurityContext(s *specgen.SpecGenerator, securityContext *v1.Security
s.NoNewPrivileges = !*securityContext.AllowPrivilegeEscalation
}
- if seopt := securityContext.SELinuxOptions; seopt != nil {
+ seopt := securityContext.SELinuxOptions
+ if seopt == nil {
+ seopt = podSecurityContext.SELinuxOptions
+ }
+ if seopt != nil {
if seopt.User != "" {
s.SelinuxOpts = append(s.SelinuxOpts, fmt.Sprintf("user:%s", seopt.User))
}
@@ -568,14 +578,26 @@ func setupSecurityContext(s *specgen.SpecGenerator, securityContext *v1.Security
s.CapDrop = append(s.CapDrop, string(capability))
}
}
- if securityContext.RunAsUser != nil {
- s.User = fmt.Sprintf("%d", *securityContext.RunAsUser)
+ runAsUser := securityContext.RunAsUser
+ if runAsUser == nil {
+ runAsUser = podSecurityContext.RunAsUser
+ }
+ if runAsUser != nil {
+ s.User = fmt.Sprintf("%d", *runAsUser)
}
- if securityContext.RunAsGroup != nil {
+
+ runAsGroup := securityContext.RunAsGroup
+ if runAsGroup == nil {
+ runAsGroup = podSecurityContext.RunAsGroup
+ }
+ if runAsGroup != nil {
if s.User == "" {
s.User = "0"
}
- s.User = fmt.Sprintf("%s:%d", s.User, *securityContext.RunAsGroup)
+ s.User = fmt.Sprintf("%s:%d", s.User, *runAsGroup)
+ }
+ for _, group := range podSecurityContext.SupplementalGroups {
+ s.Groups = append(s.Groups, fmt.Sprintf("%d", group))
}
}
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index fb01dc1e9..c627ada53 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -327,6 +327,11 @@ spec:
name: {{ .Name }}
{{ end }}
{{ end }}
+{{ if .SecurityContext }}
+ securityContext:
+ {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }}
+ {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }}
+{{ end }}
containers:
{{ with .Ctrs }}
{{ range . }}
@@ -393,6 +398,8 @@ spec:
{{- end }}
{{ if .SecurityContext }}
securityContext:
+ {{ if .RunAsUser }}runAsUser: {{ .RunAsUser }}{{- end }}
+ {{ if .RunAsGroup }}runAsGroup: {{ .RunAsGroup }}{{- end }}
allowPrivilegeEscalation: true
{{ if .Caps }}
capabilities:
@@ -758,16 +765,19 @@ func withPVCAnnotations(k, v string) pvcOption {
// Pod describes the options a kube yaml can be configured at pod level
type Pod struct {
- Name string
- RestartPolicy string
- Hostname string
- HostNetwork bool
- HostAliases []HostAlias
- Ctrs []*Ctr
- InitCtrs []*Ctr
- Volumes []*Volume
- Labels map[string]string
- Annotations map[string]string
+ Name string
+ RestartPolicy string
+ Hostname string
+ HostNetwork bool
+ HostAliases []HostAlias
+ Ctrs []*Ctr
+ InitCtrs []*Ctr
+ Volumes []*Volume
+ Labels map[string]string
+ Annotations map[string]string
+ SecurityContext bool
+ RunAsUser string
+ RunAsGroup string
}
type HostAlias struct {
@@ -802,6 +812,24 @@ func getPod(options ...podOption) *Pod {
type podOption func(*Pod)
+func withPodSecurityContext(sc bool) podOption {
+ return func(p *Pod) {
+ p.SecurityContext = sc
+ }
+}
+
+func withPodRunAsUser(runAsUser string) podOption {
+ return func(p *Pod) {
+ p.RunAsUser = runAsUser
+ }
+}
+
+func withPodRunAsGroup(runAsGroup string) podOption {
+ return func(p *Pod) {
+ p.RunAsGroup = runAsGroup
+ }
+}
+
func withPodName(name string) podOption {
return func(pod *Pod) {
pod.Name = name
@@ -949,6 +977,8 @@ type Ctr struct {
Env []Env
EnvFrom []EnvFrom
InitCtrType string
+ RunAsUser string
+ RunAsGroup string
}
// getCtr takes a list of ctrOptions and returns a Ctr with sane defaults
@@ -1042,6 +1072,18 @@ func withSecurityContext(sc bool) ctrOption {
}
}
+func withRunAsUser(runAsUser string) ctrOption {
+ return func(c *Ctr) {
+ c.RunAsUser = runAsUser
+ }
+}
+
+func withRunAsGroup(runAsGroup string) ctrOption {
+ return func(c *Ctr) {
+ c.RunAsGroup = runAsGroup
+ }
+}
+
func withCapAdd(caps []string) ctrOption {
return func(c *Ctr) {
c.CapAdd = caps
@@ -1105,8 +1147,12 @@ func withEnvFrom(name, from string, optional bool) ctrOption {
}
}
+func makeCtrNameInPod(pod *Pod, containerName string) string {
+ return fmt.Sprintf("%s-%s", pod.Name, containerName)
+}
+
func getCtrNameInPod(pod *Pod) string {
- return fmt.Sprintf("%s-%s", pod.Name, defaultCtrName)
+ return makeCtrNameInPod(pod, defaultCtrName)
}
type HostPath struct {
@@ -3222,6 +3268,38 @@ invalid kube kind
Expect(ls.OutputToStringArray()).To(HaveLen(1))
})
+ It("podman play kube RunAsUser", func() {
+ ctr1Name := "ctr1"
+ ctr2Name := "ctr2"
+ ctr1 := getCtr(withName(ctr1Name), withSecurityContext(true), withRunAsUser("101"), withRunAsGroup("102"))
+ ctr2 := getCtr(withName(ctr2Name), withSecurityContext(true))
+
+ pod := getPod(
+ withCtr(ctr1),
+ withCtr(ctr2),
+ withPodSecurityContext(true),
+ withPodRunAsUser("103"),
+ withPodRunAsGroup("104"),
+ )
+
+ err := generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ cmd := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ cmd.WaitWithDefaultTimeout()
+ Expect(cmd).Should(Exit(0))
+
+ // we expect the user:group as configured for the container
+ inspect := podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr1Name)})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal("'101:102'"))
+
+ // we expect the user:group as configured for the pod
+ inspect = podmanTest.Podman([]string{"container", "inspect", "--format", "'{{.Config.User}}'", makeCtrNameInPod(pod, ctr2Name)})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal("'103:104'"))
+ })
+
Describe("verify environment variables", func() {
var maxLength int
BeforeEach(func() {