Skip to content
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

play kube: make seccomp handling better conform to k8s #4781

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions cmd/podman/cliconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,12 +308,13 @@ type HealthCheckValues struct {

type KubePlayValues struct {
PodmanCommand
Authfile string
CertDir string
Creds string
Quiet bool
SignaturePolicy string
TlsVerify bool
Authfile string
CertDir string
Creds string
Quiet bool
SignaturePolicy string
TlsVerify bool
SeccompProfileRoot string
}

type PodCreateValues struct {
Expand Down
3 changes: 3 additions & 0 deletions cmd/podman/play_kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ var (
},
Example: `podman play kube demo.yml`,
}
// https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/
defaultSeccompRoot = "/var/lib/kubelet/seccomp"
)

func init() {
Expand All @@ -46,6 +48,7 @@ func init() {
flags.StringVar(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&playKubeCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&playKubeCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries")
flags.StringVar(&playKubeCommand.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles")
markFlagHidden(flags, "signature-policy")
}
}
Expand Down
1 change: 1 addition & 0 deletions completions/bash/podman
Original file line number Diff line number Diff line change
Expand Up @@ -2672,6 +2672,7 @@ _podman_play_kube() {
--quiet
-q
--tls-verify
--seccomp-profile-root
"

case "$cur" in
Expand Down
4 changes: 4 additions & 0 deletions docs/source/markdown/podman-play-kube.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ value can be entered. The password is entered without echo.

Suppress output information when pulling images

**--seccomp-profile-root**=*path*

Directory path for seccomp profiles (default: "/var/lib/kubelet/seccomp"). (Not available for remote commands)

**--tls-verify**=*true|false*

Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
Expand Down
20 changes: 9 additions & 11 deletions pkg/adapter/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/containers/buildah/pkg/parse"
Expand Down Expand Up @@ -597,7 +598,7 @@ func (r *LocalRuntime) PlayKubeYAML(ctx context.Context, c *cliconfig.KubePlayVa
volumes[volume.Name] = hostPath.Path
}

seccompPaths, err := initializeSeccompPaths(podYAML.ObjectMeta.Annotations)
seccompPaths, err := initializeSeccompPaths(podYAML.ObjectMeta.Annotations, c.SeccompProfileRoot)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -847,7 +848,8 @@ func (k *kubeSeccompPaths) findForContainer(ctrName string) string {

// initializeSeccompPaths takes annotations from the pod object metadata and finds annotations pertaining to seccomp
// it parses both pod and container level
func initializeSeccompPaths(annotations map[string]string) (*kubeSeccompPaths, error) {
// if the annotation is of the form "localhost/%s", the seccomp profile will be set to profileRoot/%s
func initializeSeccompPaths(annotations map[string]string, profileRoot string) (*kubeSeccompPaths, error) {
seccompPaths := &kubeSeccompPaths{containerPaths: make(map[string]string)}
var err error
if annotations != nil {
Expand All @@ -863,7 +865,7 @@ func initializeSeccompPaths(annotations map[string]string) (*kubeSeccompPaths, e
return nil, errors.Errorf("Invalid seccomp path: %s", prefixAndCtr[0])
}

path, err := verifySeccompPath(seccomp)
path, err := verifySeccompPath(seccomp, profileRoot)
if err != nil {
return nil, err
}
Expand All @@ -872,7 +874,7 @@ func initializeSeccompPaths(annotations map[string]string) (*kubeSeccompPaths, e

podSeccomp, ok := annotations[v1.SeccompPodAnnotationKey]
if ok {
seccompPaths.podPath, err = verifySeccompPath(podSeccomp)
seccompPaths.podPath, err = verifySeccompPath(podSeccomp, profileRoot)
} else {
seccompPaths.podPath, err = libpod.DefaultSeccompPath()
}
Expand All @@ -885,7 +887,7 @@ func initializeSeccompPaths(annotations map[string]string) (*kubeSeccompPaths, e

// verifySeccompPath takes a path and checks whether it is a default, unconfined, or a path
// the available options are parsed as defined in https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp
func verifySeccompPath(path string) (string, error) {
func verifySeccompPath(path string, profileRoot string) (string, error) {
switch path {
case v1.DeprecatedSeccompProfileDockerDefault:
fallthrough
Expand All @@ -894,13 +896,9 @@ func verifySeccompPath(path string) (string, error) {
case "unconfined":
return path, nil
default:
// TODO we have an inconsistency here
// k8s parses `localhost/<path>` which is found at `<seccomp_root>`
// we currently parse `localhost:<seccomp_root>/<path>
// to fully conform, we need to find a good location for the seccomp root
parts := strings.Split(path, ":")
parts := strings.Split(path, "/")
if parts[0] == "localhost" {
return parts[1], nil
return filepath.Join(profileRoot, parts[1]), nil
}
return "", errors.Errorf("invalid seccomp path: %s", path)
}
Expand Down
11 changes: 7 additions & 4 deletions test/e2e/play_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,11 @@ var _ = Describe("Podman generate kube", func() {
ctrAnnotation := "container.seccomp.security.alpha.kubernetes.io/" + defaultCtrName
ctr := getCtr(withCmd([]string{"pwd"}))

err = generateKubeYaml(getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost:"+jsonFile)), kubeYaml)
err = generateKubeYaml(getPod(withCtr(ctr), withAnnotation(ctrAnnotation, "localhost/"+filepath.Base(jsonFile))), kubeYaml)
Expect(err).To(BeNil())

kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
haircommander marked this conversation as resolved.
Show resolved Hide resolved
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))

Expand All @@ -378,13 +379,15 @@ var _ = Describe("Podman generate kube", func() {
fmt.Println(err)
Skip("Failed to prepare seccomp.json for test.")
}
defer os.Remove(jsonFile)

ctr := getCtr(withCmd([]string{"pwd"}))

err = generateKubeYaml(getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost:"+jsonFile)), kubeYaml)
err = generateKubeYaml(getPod(withCtr(ctr), withAnnotation("seccomp.security.alpha.kubernetes.io/pod", "localhost/"+filepath.Base(jsonFile))), kubeYaml)
Expect(err).To(BeNil())

kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
// CreateSeccompJson will put the profile into podmanTest.TempDir. Use --seccomp-profile-root to tell play kube where to look
kube := podmanTest.Podman([]string{"play", "kube", "--seccomp-profile-root", podmanTest.TempDir, kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))

Expand Down