Merge pull request #215 from Random-Liu/add-capability-all

Add "ALL" capabilities support.
This commit is contained in:
Lantao Liu
2017-09-05 18:14:36 -07:00
committed by GitHub
4 changed files with 203 additions and 19 deletions

View File

@@ -28,7 +28,9 @@ import (
"github.com/opencontainers/runc/libcontainer/devices"
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/runtime-tools/validate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/syndtr/gocapability/capability"
"golang.org/x/net/context"
"golang.org/x/sys/unix"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
@@ -526,21 +528,58 @@ func setOCILinuxResource(g *generate.Generator, resources *runtime.LinuxContaine
g.SetProcessOOMScoreAdj(int(resources.GetOomScoreAdj()))
}
// getOCICapabilitiesList returns a list of all available capabilities.
func getOCICapabilitiesList() []string {
var caps []string
for _, cap := range capability.List() {
if cap > validate.LastCap() {
continue
}
caps = append(caps, "CAP_"+strings.ToUpper(cap.String()))
}
return caps
}
// setOCICapabilities adds/drops process capabilities.
func setOCICapabilities(g *generate.Generator, capabilities *runtime.Capability) error {
if capabilities == nil {
return nil
}
// Capabilities in CRI doesn't have `CAP_` prefix, so add it.
// Add/drop all capabilities if "all" is specified, so that
// following individual add/drop could still work. E.g.
// AddCapabilities: []string{"ALL"}, DropCapabilities: []string{"CHOWN"}
// will be all capabilities without `CAP_CHOWN`.
if util.InStringSlice(capabilities.GetAddCapabilities(), "ALL") {
for _, c := range getOCICapabilitiesList() {
if err := g.AddProcessCapability(c); err != nil {
return err
}
}
}
if util.InStringSlice(capabilities.GetDropCapabilities(), "ALL") {
for _, c := range getOCICapabilitiesList() {
if err := g.DropProcessCapability(c); err != nil {
return err
}
}
}
for _, c := range capabilities.GetAddCapabilities() {
if err := g.AddProcessCapability("CAP_" + c); err != nil {
if strings.ToUpper(c) == "ALL" {
continue
}
// Capabilities in CRI doesn't have `CAP_` prefix, so add it.
if err := g.AddProcessCapability("CAP_" + strings.ToUpper(c)); err != nil {
return err
}
}
for _, c := range capabilities.GetDropCapabilities() {
if err := g.DropProcessCapability("CAP_" + c); err != nil {
if strings.ToUpper(c) == "ALL" {
continue
}
if err := g.DropProcessCapability("CAP_" + strings.ToUpper(c)); err != nil {
return err
}
}

View File

@@ -25,6 +25,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
"github.com/kubernetes-incubator/cri-containerd/pkg/util"
)
func checkMount(t *testing.T, mounts []runtimespec.Mount, src, dest, typ string,
@@ -87,10 +89,6 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
OomScoreAdj: 500,
},
SecurityContext: &runtime.LinuxContainerSecurityContext{
Capabilities: &runtime.Capability{
AddCapabilities: []string{"SYS_ADMIN"},
DropCapabilities: []string{"CHOWN"},
},
SupplementalGroups: []int64{1111, 2222},
NoNewPrivs: true,
},
@@ -134,18 +132,6 @@ func getCreateContainerTestData() (*runtime.ContainerConfig, *runtime.PodSandbox
assert.EqualValues(t, *spec.Linux.Resources.Memory.Limit, 400)
assert.EqualValues(t, *spec.Process.OOMScoreAdj, 500)
t.Logf("Check capabilities")
assert.Contains(t, spec.Process.Capabilities.Bounding, "CAP_SYS_ADMIN")
assert.Contains(t, spec.Process.Capabilities.Effective, "CAP_SYS_ADMIN")
assert.Contains(t, spec.Process.Capabilities.Inheritable, "CAP_SYS_ADMIN")
assert.Contains(t, spec.Process.Capabilities.Permitted, "CAP_SYS_ADMIN")
assert.Contains(t, spec.Process.Capabilities.Ambient, "CAP_SYS_ADMIN")
assert.NotContains(t, spec.Process.Capabilities.Bounding, "CAP_CHOWN")
assert.NotContains(t, spec.Process.Capabilities.Effective, "CAP_CHOWN")
assert.NotContains(t, spec.Process.Capabilities.Inheritable, "CAP_CHOWN")
assert.NotContains(t, spec.Process.Capabilities.Permitted, "CAP_CHOWN")
assert.NotContains(t, spec.Process.Capabilities.Ambient, "CAP_CHOWN")
t.Logf("Check supplemental groups")
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(1111))
assert.Contains(t, spec.Process.User.AdditionalGids, uint32(2222))
@@ -183,6 +169,74 @@ func TestGeneralContainerSpec(t *testing.T) {
specCheck(t, testID, testPid, spec)
}
func TestContainerCapabilities(t *testing.T) {
testID := "test-id"
testPid := uint32(1234)
config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData()
c := newTestCRIContainerdService()
for desc, test := range map[string]struct {
capability *runtime.Capability
includes []string
excludes []string
}{
"should be able to add/drop capabilities": {
capability: &runtime.Capability{
AddCapabilities: []string{"SYS_ADMIN"},
DropCapabilities: []string{"CHOWN"},
},
includes: []string{"CAP_SYS_ADMIN"},
excludes: []string{"CAP_CHOWN"},
},
"should be able to add all capabilities": {
capability: &runtime.Capability{
AddCapabilities: []string{"ALL"},
},
includes: getOCICapabilitiesList(),
},
"should be able to drop all capabilities": {
capability: &runtime.Capability{
DropCapabilities: []string{"ALL"},
},
excludes: getOCICapabilitiesList(),
},
"should be able to drop capabilities with add all": {
capability: &runtime.Capability{
AddCapabilities: []string{"ALL"},
DropCapabilities: []string{"CHOWN"},
},
includes: util.SubstractStringSlice(getOCICapabilitiesList(), "CAP_CHOWN"),
excludes: []string{"CAP_CHOWN"},
},
"should be able to add capabilities with drop all": {
capability: &runtime.Capability{
AddCapabilities: []string{"SYS_ADMIN"},
DropCapabilities: []string{"ALL"},
},
includes: []string{"CAP_SYS_ADMIN"},
excludes: util.SubstractStringSlice(getOCICapabilitiesList(), "CAP_SYS_ADMIN"),
},
} {
t.Logf("TestCase %q", desc)
config.Linux.SecurityContext.Capabilities = test.capability
spec, err := c.generateContainerSpec(testID, testPid, config, sandboxConfig, imageConfig, nil)
assert.NoError(t, err)
specCheck(t, testID, testPid, spec)
t.Log(spec.Process.Capabilities.Bounding)
for _, include := range test.includes {
assert.Contains(t, spec.Process.Capabilities.Bounding, include)
assert.Contains(t, spec.Process.Capabilities.Effective, include)
assert.Contains(t, spec.Process.Capabilities.Inheritable, include)
assert.Contains(t, spec.Process.Capabilities.Permitted, include)
}
for _, exclude := range test.excludes {
assert.NotContains(t, spec.Process.Capabilities.Bounding, exclude)
assert.NotContains(t, spec.Process.Capabilities.Effective, exclude)
assert.NotContains(t, spec.Process.Capabilities.Inheritable, exclude)
assert.NotContains(t, spec.Process.Capabilities.Permitted, exclude)
}
}
}
func TestContainerSpecTty(t *testing.T) {
testID := "test-id"
testPid := uint32(1234)