Skip to content

Commit

Permalink
Generate Kube should not print default structs
Browse files Browse the repository at this point in the history
If podman uses Workdir="/" or the workdir specified in the image, it
should not add it to the yaml.
If Podman find environment variables in the image, they should not
get added to the yaml.

If the container or pod do not have changes to SELinux we should not
print seLinuxOpt{}

If the container or pod do not change any dns options the yaml should
not have a dnsOption={}

If the container is not privileged it should not have privileged=false
in the yaml.

Fixes: containers#11995

Signed-off-by: Daniel J Walsh <[email protected]>
  • Loading branch information
rhatdan authored and mheon committed Nov 12, 2021
1 parent d489abf commit b3eaa08
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 74 deletions.
56 changes: 5 additions & 51 deletions docs/source/markdown/podman-generate-kube.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,7 @@ spec:
- docker-entrypoint.sh
- mysqld
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: HOSTNAME
- name: container
value: podman
- name: GOSU_VERSION
value: "1.10"
- name: GPG_KEYS
Expand All @@ -77,14 +71,14 @@ spec:
ports:
- containerPort: 3306
hostPort: 36533
protocol: TCP
resources: {}
securityContext:
allowPrivilegeEscalation: true
privileged: false
readOnlyRootFilesystem: false
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
tty: true
workingDir: /
status: {}
```

Expand All @@ -106,31 +100,18 @@ spec:
containers:
- command:
- /bin/sh
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: container
value: podman
image: docker.io/library/alpine:latest
name: test-bind-mount
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
privileged: false
readOnlyRootFilesystem: false
seLinuxOptions: {}
volumeMounts:
- mountPath: /volume
name: home-user-my-data-host
workingDir: /
dnsConfig: {}
restartPolicy: Never
volumes:
- hostPath:
Expand Down Expand Up @@ -158,31 +139,18 @@ spec:
containers:
- command:
- /bin/sh
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: container
value: podman
image: docker.io/library/alpine:latest
name: test-bind-mount
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- CAP_MKNOD
- CAP_NET_RAW
- CAP_AUDIT_WRITE
privileged: false
readOnlyRootFilesystem: false
seLinuxOptions: {}
volumeMounts:
- mountPath: /volume
name: priceless-data-pvc
workingDir: /
dnsConfig: {}
restartPolicy: Never
volumes:
- name: priceless-data-pvc
Expand Down Expand Up @@ -210,22 +178,9 @@ spec:
- command:
- python3
- /root/code/graph.py
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: TERM
value: xterm
- name: HOSTNAME
- name: container
value: podman
image: quay.io/baude/demoweb:latest
name: practicalarchimedes
resources: {}
securityContext:
allowPrivilegeEscalation: true
capabilities: {}
privileged: false
readOnlyRootFilesystem: false
tty: true
workingDir: /root/code
status: {}
Expand All @@ -242,7 +197,6 @@ spec:
- name: "8050"
nodePort: 31269
port: 8050
protocol: TCP
targetPort: 0
selector:
app: demoweb
Expand Down
64 changes: 42 additions & 22 deletions libpod/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func newPodObject(podName string, annotations map[string]string, initCtrs, conta
InitContainers: initCtrs,
Volumes: volumes,
}
if dnsOptions != nil {
if dnsOptions != nil && (len(dnsOptions.Nameservers)+len(dnsOptions.Searches)+len(dnsOptions.Options) > 0) {
ps.DNSConfig = dnsOptions
}
p := v1.Pod{
Expand Down Expand Up @@ -447,11 +447,6 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
kubeVolumes = append(kubeVolumes, volumes...)
}

envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env)
if err != nil {
return kubeContainer, kubeVolumes, nil, annotations, err
}

portmappings, err := c.PortMappings()
if err != nil {
return kubeContainer, kubeVolumes, nil, annotations, err
Expand Down Expand Up @@ -489,15 +484,23 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
kubeContainer.Command = nil
}

if c.WorkingDir() != "/" && imgData.Config.WorkingDir != c.WorkingDir() {
kubeContainer.WorkingDir = c.WorkingDir()
}

if imgData.User == c.User() {
kubeSec.RunAsGroup, kubeSec.RunAsUser = nil, nil
}

kubeContainer.WorkingDir = c.WorkingDir()
envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env, imgData.Config.Env)
if err != nil {
return kubeContainer, kubeVolumes, nil, annotations, err
}
kubeContainer.Env = envVariables

kubeContainer.Ports = ports
// This should not be applicable
//container.EnvFromSource =
kubeContainer.Env = envVariables
kubeContainer.SecurityContext = kubeSec
kubeContainer.StdinOnce = false
kubeContainer.TTY = c.config.Spec.Process.Terminal
Expand Down Expand Up @@ -600,9 +603,14 @@ func ocicniPortMappingToContainerPort(portMappings []ocicni.PortMapping) ([]v1.C
}

// libpodEnvVarsToKubeEnvVars converts a key=value string slice to []v1.EnvVar
func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
func libpodEnvVarsToKubeEnvVars(envs []string, imageEnvs []string) ([]v1.EnvVar, error) {
defaultEnv := env.DefaultEnvVariables()
envVars := make([]v1.EnvVar, 0, len(envs))
imageMap := make(map[string]string, len(imageEnvs))
for _, ie := range envs {
split := strings.SplitN(ie, "=", 2)
imageMap[split[0]] = split[1]
}
for _, e := range envs {
split := strings.SplitN(e, "=", 2)
if len(split) != 2 {
Expand All @@ -611,6 +619,9 @@ func libpodEnvVarsToKubeEnvVars(envs []string) ([]v1.EnvVar, error) {
if defaultEnv[split[0]] == split[1] {
continue
}
if imageMap[split[0]] == split[1] {
continue
}
ev := v1.EnvVar{
Name: split[0],
Value: split[1],
Expand Down Expand Up @@ -808,33 +819,42 @@ func generateKubeSecurityContext(c *Container) (*v1.SecurityContext, error) {
capabilities = newCaps
}

sc := v1.SecurityContext{
// RunAsNonRoot is an optional parameter; our first implementations should be root only; however
// I'm leaving this as a bread-crumb for later
//RunAsNonRoot: &nonRoot,
}
if capabilities != nil {
sc.Capabilities = capabilities
}
var selinuxOpts v1.SELinuxOptions
opts := strings.SplitN(c.config.Spec.Annotations[define.InspectAnnotationLabel], ":", 2)
if len(opts) == 2 {
switch len(opts) {
case 2:
switch opts[0] {
case "type":
selinuxOpts.Type = opts[1]
sc.SELinuxOptions = &selinuxOpts
case "level":
selinuxOpts.Level = opts[1]
sc.SELinuxOptions = &selinuxOpts
}
}
if len(opts) == 1 {
case 1:
if opts[0] == "disable" {
selinuxOpts.Type = "spc_t"
sc.SELinuxOptions = &selinuxOpts
}
}

sc := v1.SecurityContext{
Capabilities: capabilities,
Privileged: &privileged,
SELinuxOptions: &selinuxOpts,
// RunAsNonRoot is an optional parameter; our first implementations should be root only; however
// I'm leaving this as a bread-crumb for later
//RunAsNonRoot: &nonRoot,
ReadOnlyRootFilesystem: &ro,
AllowPrivilegeEscalation: &allowPrivEscalation,
if !allowPrivEscalation {
sc.AllowPrivilegeEscalation = &allowPrivEscalation
}
if privileged {
sc.Privileged = &privileged
}
if ro {
sc.ReadOnlyRootFilesystem = &ro
}

if c.User() != "" {
if !c.batched {
c.lock.Lock()
Expand Down
9 changes: 8 additions & 1 deletion test/e2e/generate_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ var _ = Describe("Podman generate kube", func() {
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(pod.Spec.HostNetwork).To(Equal(false))
Expect(pod.Spec.SecurityContext).To(BeNil())
Expect(pod.Spec.DNSConfig).To(BeNil())
Expect(pod.Spec.Containers[0].WorkingDir).To(Equal(""))
Expect(pod.Spec.Containers[0].Env).To(BeNil())

numContainers := 0
for range pod.Spec.Containers {
Expand Down Expand Up @@ -103,6 +107,7 @@ var _ = Describe("Podman generate kube", func() {
err = yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(kube.OutputToString()).To(ContainSubstring("type: spc_t"))

})

It("podman generate service kube on container with --security-opt type", func() {
Expand Down Expand Up @@ -1079,7 +1084,7 @@ USER test1`
top1.WaitWithDefaultTimeout()
Expect(top1).Should(Exit(0))

top2 := podmanTest.Podman([]string{"run", "-dt", "--name", "top2", "--pod", "pod1", "--label", "io.containers.autoupdate=registry", "--label", "io.containers.autoupdate.authfile=/some/authfile.json", ALPINE, "top"})
top2 := podmanTest.Podman([]string{"run", "-dt", "--name", "top2", "--workdir", "/root", "--pod", "pod1", "--label", "io.containers.autoupdate=registry", "--label", "io.containers.autoupdate.authfile=/some/authfile.json", ALPINE, "top"})
top2.WaitWithDefaultTimeout()
Expect(top2).Should(Exit(0))

Expand All @@ -1090,6 +1095,8 @@ USER test1`
pod := new(v1.Pod)
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(pod.Spec.Containers[0].WorkingDir).To(Equal(""))
Expect(pod.Spec.Containers[1].WorkingDir).To(Equal("/root"))

for _, ctr := range []string{"top1", "top2"} {
v, ok := pod.GetAnnotations()["io.containers.autoupdate/"+ctr]
Expand Down

0 comments on commit b3eaa08

Please sign in to comment.