From a5aa141ed64ce2bc87c8c79b2bfc79a07ada05c4 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Wed, 27 Sep 2017 20:46:31 +0200 Subject: [PATCH] sandbox, ctrs: fixup seccomp for 1.8 Signed-off-by: Antonio Murdaca --- libkpod/container_server.go | 5 + libkpod/sandbox/sandbox.go | 13 +- oci/container.go | 23 +- pkg/annotations/annotations.go | 3 + server/container_create.go | 29 +- server/sandbox_run.go | 9 + test/ctr_seccomp.bats | 221 ++++++++++++ test/seccomp.bats | 368 -------------------- test/testdata/container_config_seccomp.json | 9 +- test/testdata/sandbox_config_seccomp.json | 2 +- 10 files changed, 289 insertions(+), 393 deletions(-) create mode 100644 test/ctr_seccomp.bats delete mode 100644 test/seccomp.bats diff --git a/libkpod/container_server.go b/libkpod/container_server.go index 1bc94871..a1b595d8 100644 --- a/libkpod/container_server.go +++ b/libkpod/container_server.go @@ -323,6 +323,8 @@ func (c *ContainerServer) LoadSandbox(id string) error { return err } + spp := m.Annotations[annotations.SeccompProfilePath] + kubeAnnotations := make(map[string]string) if err = json.Unmarshal([]byte(m.Annotations[annotations.Annotations]), &kubeAnnotations); err != nil { return err @@ -337,6 +339,7 @@ func (c *ContainerServer) LoadSandbox(id string) error { } sb.AddHostnamePath(m.Annotations[annotations.HostnamePath]) sb.AddIP(ip) + sb.SetSeccompProfilePath(spp) // We add a netNS only if we can load a permanent one. // Otherwise, the sandbox will live in the host namespace. @@ -512,6 +515,8 @@ func (c *ContainerServer) LoadContainer(id string) error { return err } ctr.SetMountPoint(m.Annotations[annotations.MountPoint]) + spp := m.Annotations[annotations.SeccompProfilePath] + ctr.SetSeccompProfilePath(spp) c.ContainerStateFromDisk(ctr) diff --git a/libkpod/sandbox/sandbox.go b/libkpod/sandbox/sandbox.go index d7d6569d..7293747b 100644 --- a/libkpod/sandbox/sandbox.go +++ b/libkpod/sandbox/sandbox.go @@ -156,7 +156,8 @@ type Sandbox struct { portMappings []*hostport.PortMapping stopped bool // ipv4 or ipv6 cache - ip string + ip string + seccompProfilePath string } const ( @@ -205,6 +206,16 @@ func New(id, namespace, name, kubeName, logDir string, labels, annotations map[s return sb, nil } +// SetSeccompProfilePath sets the seccomp profile path +func (s *Sandbox) SetSeccompProfilePath(pp string) { + s.seccompProfilePath = pp +} + +// SeccompProfilePath returns the seccomp profile path +func (s *Sandbox) SeccompProfilePath() string { + return s.seccompProfilePath +} + // AddIP stores the ip in the sandbox func (s *Sandbox) AddIP(ip string) { s.ip = ip diff --git a/oci/container.go b/oci/container.go index 197c3d85..e4f6c605 100644 --- a/oci/container.go +++ b/oci/container.go @@ -42,12 +42,13 @@ type Container struct { // this is the /var/run/storage/... directory, erased on reboot bundlePath string // this is the /var/lib/storage/... directory - dir string - stopSignal string - imageName string - imageRef string - volumes []ContainerVolume - mountPoint string + dir string + stopSignal string + imageName string + imageRef string + volumes []ContainerVolume + mountPoint string + seccompProfilePath string } // ContainerVolume is a bind mount for the container. @@ -145,6 +146,16 @@ func (c *Container) ID() string { return c.id } +// SetSeccompProfilePath sets the seccomp profile path +func (c *Container) SetSeccompProfilePath(pp string) { + c.seccompProfilePath = pp +} + +// SeccompProfilePath returns the seccomp profile path +func (c *Container) SeccompProfilePath() string { + return c.seccompProfilePath +} + // BundlePath returns the bundlePath of the container. func (c *Container) BundlePath() string { return c.bundlePath diff --git a/pkg/annotations/annotations.go b/pkg/annotations/annotations.go index 151d9390..9b5b1352 100644 --- a/pkg/annotations/annotations.go +++ b/pkg/annotations/annotations.go @@ -22,6 +22,9 @@ const ( // IP is the container ipv4 or ipv6 address IP = "io.kubernetes.cri-o.IP" + // SeccompProfilePath is the node seccomp profile path + SeccompProfilePath = "io.kubernetes.cri-o.SeccompProfilePath" + // Image is the container image ID annotation Image = "io.kubernetes.cri-o.Image" diff --git a/server/container_create.go b/server/container_create.go index bb7fafd1..4f41d211 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "os" "path/filepath" "regexp" @@ -1004,13 +1005,16 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, } specgen.AddAnnotation(annotations.Annotations, string(kubeAnnotationsJSON)) - metaname := metadata.Name + spp := containerConfig.GetLinux().GetSecurityContext().GetSeccompProfilePath() if !privileged { - if err = s.setupSeccomp(&specgen, metaname, sb.Annotations()); err != nil { + if err = s.setupSeccomp(&specgen, spp); err != nil { return nil, err } } + specgen.AddAnnotation(annotations.SeccompProfilePath, spp) + // TODO(runcom): add spp to container... + metaname := metadata.Name attempt := metadata.Attempt containerInfo, err := s.StorageRuntimeServer().CreateContainer(s.ImageContext(), sb.Name(), sb.ID(), @@ -1141,14 +1145,11 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string, return container, nil } -func (s *Server) setupSeccomp(specgen *generate.Generator, cname string, sbAnnotations map[string]string) error { - profile, ok := sbAnnotations["container.seccomp.security.alpha.kubernetes.io/"+cname] - if !ok { - profile, ok = sbAnnotations["seccomp.security.alpha.kubernetes.io/pod"] - if !ok { - // running w/o seccomp, aka unconfined - profile = seccompUnconfined - } +func (s *Server) setupSeccomp(specgen *generate.Generator, profile string) error { + if profile == "" { + // running w/o seccomp, aka unconfined + specgen.Spec().Linux.Seccomp = nil + return nil } if !s.seccompEnabled { if profile != seccompUnconfined { @@ -1167,8 +1168,12 @@ func (s *Server) setupSeccomp(specgen *generate.Generator, cname string, sbAnnot if !strings.HasPrefix(profile, seccompLocalhostPrefix) { return fmt.Errorf("unknown seccomp profile option: %q", profile) } - // FIXME: https://github.com/kubernetes/kubernetes/issues/39128 - return nil + fname := strings.TrimPrefix(profile, "localhost/") + file, err := ioutil.ReadFile(filepath.FromSlash(fname)) + if err != nil { + return fmt.Errorf("cannot load seccomp profile %q: %v", fname, err) + } + return seccomp.LoadProfileFromBytes(file, specgen) } // getAppArmorProfileName gets the profile name for the given container. diff --git a/server/sandbox_run.go b/server/sandbox_run.go index daa3a44a..eaf9ccc1 100644 --- a/server/sandbox_run.go +++ b/server/sandbox_run.go @@ -505,6 +505,15 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest g.AddAnnotation(annotations.IP, ip) sb.AddIP(ip) + spp := req.GetConfig().GetLinux().GetSecurityContext().GetSeccompProfilePath() + g.AddAnnotation(annotations.SeccompProfilePath, spp) + sb.SetSeccompProfilePath(spp) + if !privileged { + if err = s.setupSeccomp(&g, spp); err != nil { + return nil, err + } + } + err = g.SaveToFile(filepath.Join(podContainer.Dir, "config.json"), saveOptions) if err != nil { return nil, fmt.Errorf("failed to save template configuration for pod sandbox %s(%s): %v", sb.Name(), id, err) diff --git a/test/ctr_seccomp.bats b/test/ctr_seccomp.bats new file mode 100644 index 00000000..da7f9fad --- /dev/null +++ b/test/ctr_seccomp.bats @@ -0,0 +1,221 @@ +#!/usr/bin/env bats + +load helpers + +function teardown() { + cleanup_test +} + +# 1. test running with ctr unconfined +# test that we can run with a syscall which would be otherwise blocked +@test "ctr seccomp profiles unconfined" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + start_crio "$TESTDIR"/seccomp_profile1.json + + sed -e 's/%VALUE%/unconfined/g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp1.json + run crioctl pod run --name seccomp1 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname --config "$TESTDIR"/seccomp1.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + run crioctl ctr execsync --id "$ctr_id" chmod 777 . + echo "$output" + [ "$status" -eq 0 ] + + cleanup_ctrs + cleanup_pods + stop_crio +} + +# 2. test running with ctr runtime/default +# test that we cannot run with a syscall blocked by the default seccomp profile +@test "ctr seccomp profiles runtime/default" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + start_crio "$TESTDIR"/seccomp_profile1.json + + sed -e 's/%VALUE%/runtime\/default/g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp2.json + run crioctl pod run --name seccomp2 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname2 --config "$TESTDIR"/seccomp2.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + run crioctl ctr execsync --id "$ctr_id" chmod 777 . + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "Exit code: 1" ]] + [[ "$output" =~ "Operation not permitted" ]] + + cleanup_ctrs + cleanup_pods + stop_crio +} + +# 3. test running with ctr unconfined and profile empty +# test that we can run with a syscall which would be otherwise blocked +@test "ctr seccomp profiles unconfined by empty field" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + start_crio "$TESTDIR"/seccomp_profile1.json + + sed -e 's/%VALUE%//g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp1.json + run crioctl pod run --name seccomp1 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname --config "$TESTDIR"/seccomp1.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + run crioctl ctr execsync --id "$ctr_id" chmod 777 . + echo "$output" + [ "$status" -eq 0 ] + + cleanup_ctrs + cleanup_pods + stop_crio +} + +# 4. test running with ctr wrong profile name +@test "ctr seccomp profiles wrong profile name" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + start_crio "$TESTDIR"/seccomp_profile1.json + + sed -e 's/%VALUE%/wontwork/g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp1.json + run crioctl pod run --name seccomp1 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname --config "$TESTDIR"/seccomp1.json --pod "$pod_id" + echo "$output" + [[ "$status" -ne 0 ]] + [[ "$output" =~ "unknown seccomp profile option:" ]] + [[ "$output" =~ "wontwork" ]] + + cleanup_ctrs + cleanup_pods + stop_crio +} + +# 5. test running with ctr localhost/profile_name +@test "ctr seccomp profiles localhost/profile_name" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + start_crio + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + sed -e 's@%VALUE%@localhost/'"$TESTDIR"'/seccomp_profile1.json@g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp1.json + run crioctl pod run --name seccomp1 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname --config "$TESTDIR"/seccomp1.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + run crioctl ctr execsync --id "$ctr_id" chmod 777 . + [ "$status" -eq 0 ] + [[ "$output" =~ "Exit code: 1" ]] + [[ "$output" =~ "Operation not permitted" ]] + + cleanup_ctrs + cleanup_pods + stop_crio +} + +# 6. test running with ctr docker/default +# test that we cannot run with a syscall blocked by the default seccomp profile +@test "ctr seccomp profiles runtime/default" { + # this test requires seccomp, so skip this test if seccomp is not enabled. + enabled=$(is_seccomp_enabled) + if [[ "$enabled" -eq 0 ]]; then + skip "skip this test since seccomp is not enabled." + fi + + sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json + sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json + + start_crio "$TESTDIR"/seccomp_profile1.json + + sed -e 's/%VALUE%/docker\/default/g' "$TESTDATA"/container_config_seccomp.json > "$TESTDIR"/seccomp2.json + run crioctl pod run --name seccomp2 --config "$TESTDATA"/sandbox_config.json + echo "$output" + [ "$status" -eq 0 ] + pod_id="$output" + run crioctl ctr create --name testname2 --config "$TESTDIR"/seccomp2.json --pod "$pod_id" + echo "$output" + [ "$status" -eq 0 ] + ctr_id="$output" + run crioctl ctr start --id "$ctr_id" + echo "$output" + [ "$status" -eq 0 ] + run crioctl ctr execsync --id "$ctr_id" chmod 777 . + echo "$output" + [ "$status" -eq 0 ] + [[ "$output" =~ "Exit code: 1" ]] + [[ "$output" =~ "Operation not permitted" ]] + + cleanup_ctrs + cleanup_pods + stop_crio +} diff --git a/test/seccomp.bats b/test/seccomp.bats deleted file mode 100644 index b77a7f8c..00000000 --- a/test/seccomp.bats +++ /dev/null @@ -1,368 +0,0 @@ -#!/usr/bin/env bats - -load helpers - -function teardown() { - cleanup_test -} - -# 1. test running with ctr unconfined -# test that we can run with a syscall which would be otherwise blocked -@test "ctr seccomp profiles unconfined" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/testname": "unconfined"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp1.json - run crioctl pod run --name seccomp1 --config "$TESTDIR"/seccomp1.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --name testname --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 2. test running with ctr runtime/default -# test that we cannot run with a syscall blocked by the default seccomp profile -@test "ctr seccomp profiles runtime/default" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/testname2": "runtime\/default"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp2.json - run crioctl pod run --name seccomp2 --config "$TESTDIR"/seccomp2.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --name testname2 --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - [[ "$output" =~ "Exit code: 1" ]] - [[ "$output" =~ "Operation not permitted" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 3. test running with ctr wrong profile name -@test "ctr seccomp profiles wrong profile name" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/testname3": "notgood"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp3.json - run crioctl pod run --name seccomp3 --config "$TESTDIR"/seccomp3.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --name testname3 --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -ne 0 ] - [[ "$output" =~ "unknown seccomp profile option:" ]] - [[ "$output" =~ "notgood" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# TODO(runcom): need https://issues.k8s.io/36997 -# 4. test running with ctr localhost/profile_name -@test "ctr seccomp profiles localhost/profile_name" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - #sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - #sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - #sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - #start_crio "$TESTDIR"/seccomp_profile1.json - - skip "need https://issues.k8s.io/36997" -} - -# 5. test running with unkwown ctr profile falls back to pod profile -# unknown ctr -> unconfined -# pod -> runtime/default -# result: fail chmod -@test "ctr seccomp profiles falls back to pod profile" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/redhat\.test\.crio-seccomp2-1-testname2-0-not-exists": "unconfined", "seccomp\.security\.alpha\.kubernetes\.io\/pod": "runtime\/default"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp5.json - run crioctl pod run --name seccomp5 --config "$TESTDIR"/seccomp5.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - [[ "$output" =~ "Exit code: 1" ]] - [[ "$output" =~ "Operation not permitted" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 6. test running with unkwown ctr profile and no pod, falls back to unconfined -# unknown ctr -> runtime/default -# pod -> NO -# result: success, running unconfined -@test "ctr seccomp profiles falls back to unconfined" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/redhat\.test\.crio-seccomp6-1-testname6-0-not-exists": "runtime-default"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp6.json - run crioctl pod run --name seccomp6 --config "$TESTDIR"/seccomp6.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --name testname6 --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 1. test running with pod unconfined -# test that we can run with a syscall which would be otherwise blocked -@test "pod seccomp profiles unconfined" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"seccomp\.security\.alpha\.kubernetes\.io\/pod": "unconfined"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp1.json - run crioctl pod run --name seccomp1 --config "$TESTDIR"/seccomp1.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 2. test running with pod runtime/default -# test that we cannot run with a syscall blocked by the default seccomp profile -@test "pod seccomp profiles runtime/default" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"seccomp\.security\.alpha\.kubernetes\.io\/pod": "runtime\/default"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp2.json - run crioctl pod run --name seccomp2 --config "$TESTDIR"/seccomp2.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - [[ "$output" =~ "Exit code: 1" ]] - [[ "$output" =~ "Operation not permitted" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# 3. test running with pod wrong profile name -@test "pod seccomp profiles wrong profile name" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - # 3. test running with pod wrong profile name - sed -e 's/%VALUE%/,"seccomp\.security\.alpha\.kubernetes\.io\/pod": "notgood"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp3.json - run crioctl pod run --name seccomp3 --config "$TESTDIR"/seccomp3.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" - echo "$output" - [ "$status" -ne 0 ] - [[ "$output" =~ "unknown seccomp profile option:" ]] - [[ "$output" =~ "notgood" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} - -# TODO(runcom): need https://issues.k8s.io/36997 -# 4. test running with pod localhost/profile_name -@test "pod seccomp profiles localhost/profile_name" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - #sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - #sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - #sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - #start_crio "$TESTDIR"/seccomp_profile1.json - - skip "need https://issues.k8s.io/36997" -} - -# test running with ctr docker/default -# test that we cannot run with a syscall blocked by the default seccomp profile -@test "ctr seccomp profiles docker/default" { - # this test requires seccomp, so skip this test if seccomp is not enabled. - enabled=$(is_seccomp_enabled) - if [[ "$enabled" -eq 0 ]]; then - skip "skip this test since seccomp is not enabled." - fi - - sed -e 's/"chmod",//' "$CRIO_ROOT"/cri-o/seccomp.json > "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmod",//' "$TESTDIR"/seccomp_profile1.json - sed -i 's/"fchmodat",//g' "$TESTDIR"/seccomp_profile1.json - - start_crio "$TESTDIR"/seccomp_profile1.json - - sed -e 's/%VALUE%/,"container\.seccomp\.security\.alpha\.kubernetes\.io\/testname2": "docker\/default"/g' "$TESTDATA"/sandbox_config_seccomp.json > "$TESTDIR"/seccomp2.json - run crioctl pod run --name seccomp2 --config "$TESTDIR"/seccomp2.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run crioctl ctr create --name testname2 --config "$TESTDATA"/container_redis.json --pod "$pod_id" - echo "$output" - [ "$status" -eq 0 ] - ctr_id="$output" - run crioctl ctr start --id "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run crioctl ctr execsync --id "$ctr_id" chmod 777 . - echo "$output" - [ "$status" -eq 0 ] - [[ "$output" =~ "Exit code: 1" ]] - [[ "$output" =~ "Operation not permitted" ]] - - cleanup_ctrs - cleanup_pods - stop_crio -} diff --git a/test/testdata/container_config_seccomp.json b/test/testdata/container_config_seccomp.json index 582132b0..6097050a 100644 --- a/test/testdata/container_config_seccomp.json +++ b/test/testdata/container_config_seccomp.json @@ -6,13 +6,11 @@ "image": { "image": "redis:alpine" }, - "command": [ - "/bin/bash" - ], "args": [ - "/bin/chmod", "777", "." + "docker-entrypoint.sh", + "redis-server" ], - "working_dir": "/", + "working_dir": "/data", "envs": [ { "key": "PATH", @@ -53,6 +51,7 @@ "oom_score_adj": 30 }, "security_context": { + "seccomp_profile_path": "%VALUE%", "capabilities": { "add_capabilities": [ "setuid", diff --git a/test/testdata/sandbox_config_seccomp.json b/test/testdata/sandbox_config_seccomp.json index 8e440b16..30084a9f 100644 --- a/test/testdata/sandbox_config_seccomp.json +++ b/test/testdata/sandbox_config_seccomp.json @@ -32,11 +32,11 @@ }, "annotations": { "owner": "hmeng" - %VALUE% }, "linux": { "cgroup_parent": "/Burstable/pod_123-456", "security_context": { + "seccomp_profile_path": "%VALUE%", "namespace_options": { "host_network": false, "host_pid": false,