PodSecurityPolicy: avoid unnecessary mutation of container capabilities

This commit is contained in:
Jordan Liggitt 2017-10-09 17:30:13 -04:00
parent 59510caaf3
commit cfb490e3a1
No known key found for this signature in database
GPG Key ID: 39928704103C7229
2 changed files with 46 additions and 16 deletions

View File

@ -48,13 +48,17 @@ func NewDefaultCapabilities(defaultAddCapabilities, requiredDropCapabilities, al
// 1. a capabilities.Add set containing all the required adds (unless the // 1. a capabilities.Add set containing all the required adds (unless the
// container specifically is dropping the cap) and container requested adds // container specifically is dropping the cap) and container requested adds
// 2. a capabilities.Drop set containing all the required drops and container requested drops // 2. a capabilities.Drop set containing all the required drops and container requested drops
//
// Returns the original container capabilities if no changes are required.
func (s *defaultCapabilities) Generate(pod *api.Pod, container *api.Container) (*api.Capabilities, error) { func (s *defaultCapabilities) Generate(pod *api.Pod, container *api.Container) (*api.Capabilities, error) {
defaultAdd := makeCapSet(s.defaultAddCapabilities) defaultAdd := makeCapSet(s.defaultAddCapabilities)
requiredDrop := makeCapSet(s.requiredDropCapabilities) requiredDrop := makeCapSet(s.requiredDropCapabilities)
containerAdd := sets.NewString() containerAdd := sets.NewString()
containerDrop := sets.NewString() containerDrop := sets.NewString()
var containerCapabilities *api.Capabilities
if container.SecurityContext != nil && container.SecurityContext.Capabilities != nil { if container.SecurityContext != nil && container.SecurityContext.Capabilities != nil {
containerCapabilities = container.SecurityContext.Capabilities
containerAdd = makeCapSet(container.SecurityContext.Capabilities.Add) containerAdd = makeCapSet(container.SecurityContext.Capabilities.Add)
containerDrop = makeCapSet(container.SecurityContext.Capabilities.Drop) containerDrop = makeCapSet(container.SecurityContext.Capabilities.Drop)
} }
@ -62,17 +66,17 @@ func (s *defaultCapabilities) Generate(pod *api.Pod, container *api.Container) (
// remove any default adds that the container is specifically dropping // remove any default adds that the container is specifically dropping
defaultAdd = defaultAdd.Difference(containerDrop) defaultAdd = defaultAdd.Difference(containerDrop)
combinedAdd := defaultAdd.Union(containerAdd).List() combinedAdd := defaultAdd.Union(containerAdd)
combinedDrop := requiredDrop.Union(containerDrop).List() combinedDrop := requiredDrop.Union(containerDrop)
// nothing generated? return nil // no changes? return the original capabilities
if len(combinedAdd) == 0 && len(combinedDrop) == 0 { if (len(combinedAdd) == len(containerAdd)) && (len(combinedDrop) == len(containerDrop)) {
return nil, nil return containerCapabilities, nil
} }
return &api.Capabilities{ return &api.Capabilities{
Add: capabilityFromStringSlice(combinedAdd), Add: capabilityFromStringSlice(combinedAdd.List()),
Drop: capabilityFromStringSlice(combinedDrop), Drop: capabilityFromStringSlice(combinedDrop.List()),
}, nil }, nil
} }

View File

@ -31,6 +31,10 @@ func TestGenerateAdds(t *testing.T) {
expectedCaps *api.Capabilities expectedCaps *api.Capabilities
}{ }{
"no required, no container requests": {}, "no required, no container requests": {},
"no required, no container requests, non-nil": {
containerCaps: &api.Capabilities{},
expectedCaps: &api.Capabilities{},
},
"required, no container requests": { "required, no container requests": {
defaultAddCaps: []api.Capability{"foo"}, defaultAddCaps: []api.Capability{"foo"},
expectedCaps: &api.Capabilities{ expectedCaps: &api.Capabilities{
@ -64,13 +68,22 @@ func TestGenerateAdds(t *testing.T) {
Add: []api.Capability{"bar", "foo"}, Add: []api.Capability{"bar", "foo"},
}, },
}, },
"generation dedupes": { "generation does not mutate unnecessarily": {
defaultAddCaps: []api.Capability{"foo", "foo", "foo", "foo"}, defaultAddCaps: []api.Capability{"foo", "bar"},
containerCaps: &api.Capabilities{ containerCaps: &api.Capabilities{
Add: []api.Capability{"foo", "foo", "foo"}, Add: []api.Capability{"foo", "foo", "bar", "baz"},
}, },
expectedCaps: &api.Capabilities{ expectedCaps: &api.Capabilities{
Add: []api.Capability{"foo"}, Add: []api.Capability{"foo", "foo", "bar", "baz"},
},
},
"generation dedupes": {
defaultAddCaps: []api.Capability{"foo", "bar"},
containerCaps: &api.Capabilities{
Add: []api.Capability{"foo", "baz"},
},
expectedCaps: &api.Capabilities{
Add: []api.Capability{"bar", "baz", "foo"},
}, },
}, },
"generation is case sensitive - will not dedupe": { "generation is case sensitive - will not dedupe": {
@ -121,6 +134,10 @@ func TestGenerateDrops(t *testing.T) {
"no required, no container requests": { "no required, no container requests": {
expectedCaps: nil, expectedCaps: nil,
}, },
"no required, no container requests, non-nil": {
containerCaps: &api.Capabilities{},
expectedCaps: &api.Capabilities{},
},
"required drops are defaulted": { "required drops are defaulted": {
requiredDropCaps: []api.Capability{"foo"}, requiredDropCaps: []api.Capability{"foo"},
expectedCaps: &api.Capabilities{ expectedCaps: &api.Capabilities{
@ -128,12 +145,21 @@ func TestGenerateDrops(t *testing.T) {
}, },
}, },
"required drops are defaulted when making container requests": { "required drops are defaulted when making container requests": {
requiredDropCaps: []api.Capability{"foo"}, requiredDropCaps: []api.Capability{"baz"},
containerCaps: &api.Capabilities{ containerCaps: &api.Capabilities{
Drop: []api.Capability{"foo", "bar"}, Drop: []api.Capability{"foo", "bar"},
}, },
expectedCaps: &api.Capabilities{ expectedCaps: &api.Capabilities{
Drop: []api.Capability{"bar", "foo"}, Drop: []api.Capability{"bar", "baz", "foo"},
},
},
"required drops do not mutate unnecessarily": {
requiredDropCaps: []api.Capability{"baz"},
containerCaps: &api.Capabilities{
Drop: []api.Capability{"foo", "bar", "baz"},
},
expectedCaps: &api.Capabilities{
Drop: []api.Capability{"foo", "bar", "baz"},
}, },
}, },
"can drop a required add": { "can drop a required add": {
@ -167,12 +193,12 @@ func TestGenerateDrops(t *testing.T) {
}, },
}, },
"generation dedupes": { "generation dedupes": {
requiredDropCaps: []api.Capability{"bar", "bar", "bar", "bar"}, requiredDropCaps: []api.Capability{"baz", "foo"},
containerCaps: &api.Capabilities{ containerCaps: &api.Capabilities{
Drop: []api.Capability{"bar", "bar", "bar"}, Drop: []api.Capability{"bar", "foo"},
}, },
expectedCaps: &api.Capabilities{ expectedCaps: &api.Capabilities{
Drop: []api.Capability{"bar"}, Drop: []api.Capability{"bar", "baz", "foo"},
}, },
}, },
"generation is case sensitive - will not dedupe": { "generation is case sensitive - will not dedupe": {