securitycontext: move docker-specific logic into kubelet/dockertools

This change moves the code specific to docker to kubelet/dockertools,
while leaving the common utility functions at its current package
(pkg/securitycontext).

When we deprecate dockertools in the future, the code will be moved to
pkg/kubelet/dockershim instead.
This commit is contained in:
Yu-Ju Hong
2017-01-26 18:22:13 -08:00
parent 0107e93cc6
commit 4506f4c2d0
17 changed files with 395 additions and 308 deletions

View File

@@ -13,32 +13,21 @@ go_library(
srcs = [
"doc.go",
"fake.go",
"provider.go",
"types.go",
"util.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/kubelet/leaky:go_default_library",
"//vendor:github.com/docker/engine-api/types/container",
],
)
go_test(
name = "go_default_test",
srcs = [
"provider_test.go",
"util_test.go",
],
srcs = ["util_test.go"],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api/testing:go_default_library",
"//pkg/api/v1:go_default_library",
"//vendor:github.com/docker/engine-api/types/container",
],
deps = ["//pkg/api/v1:go_default_library"],
)
filegroup(

View File

@@ -19,8 +19,6 @@ package securitycontext
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
dockercontainer "github.com/docker/engine-api/types/container"
)
// ValidSecurityContextWithContainerDefaults creates a valid security context provider based on
@@ -33,18 +31,6 @@ func ValidSecurityContextWithContainerDefaults() *v1.SecurityContext {
}
}
// NewFakeSecurityContextProvider creates a new, no-op security context provider.
func NewFakeSecurityContextProvider() SecurityContextProvider {
return FakeSecurityContextProvider{}
}
type FakeSecurityContextProvider struct{}
func (p FakeSecurityContextProvider) ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config) {
}
func (p FakeSecurityContextProvider) ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) {
}
// ValidInternalSecurityContextWithContainerDefaults creates a valid security context provider based on
// empty container defaults. Used for testing.
func ValidInternalSecurityContextWithContainerDefaults() *api.SecurityContext {

View File

@@ -1,274 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package securitycontext
import (
"fmt"
"strconv"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/kubelet/leaky"
dockercontainer "github.com/docker/engine-api/types/container"
)
// NewSimpleSecurityContextProvider creates a new SimpleSecurityContextProvider.
func NewSimpleSecurityContextProvider() SecurityContextProvider {
return SimpleSecurityContextProvider{}
}
// SimpleSecurityContextProvider is the default implementation of a SecurityContextProvider.
type SimpleSecurityContextProvider struct{}
// ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which
// the container is created.
func (p SimpleSecurityContextProvider) ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config) {
effectiveSC := DetermineEffectiveSecurityContext(pod, container)
if effectiveSC == nil {
return
}
if effectiveSC.RunAsUser != nil {
config.User = strconv.Itoa(int(*effectiveSC.RunAsUser))
}
}
// ModifyHostConfig is called before the Docker runContainer call. The
// security context provider can make changes to the HostConfig, affecting
// security options, whether the container is privileged, volume binds, etc.
func (p SimpleSecurityContextProvider) ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64) {
// Apply supplemental groups
if container.Name != leaky.PodInfraContainerName {
// TODO: We skip application of supplemental groups to the
// infra container to work around a runc issue which
// requires containers to have the '/etc/group'. For
// more information see:
// https://github.com/opencontainers/runc/pull/313
// This can be removed once the fix makes it into the
// required version of docker.
if pod.Spec.SecurityContext != nil {
for _, group := range pod.Spec.SecurityContext.SupplementalGroups {
hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.Itoa(int(group)))
}
if pod.Spec.SecurityContext.FSGroup != nil {
hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.Itoa(int(*pod.Spec.SecurityContext.FSGroup)))
}
}
for _, group := range supplementalGids {
hostConfig.GroupAdd = append(hostConfig.GroupAdd, strconv.Itoa(int(group)))
}
}
// Apply effective security context for container
effectiveSC := DetermineEffectiveSecurityContext(pod, container)
if effectiveSC == nil {
return
}
if effectiveSC.Privileged != nil {
hostConfig.Privileged = *effectiveSC.Privileged
}
if effectiveSC.Capabilities != nil {
add, drop := MakeCapabilities(effectiveSC.Capabilities.Add, effectiveSC.Capabilities.Drop)
hostConfig.CapAdd = add
hostConfig.CapDrop = drop
}
if effectiveSC.SELinuxOptions != nil {
hostConfig.SecurityOpt = ModifySecurityOptions(hostConfig.SecurityOpt, effectiveSC.SELinuxOptions)
}
}
// ModifySecurityOptions adds SELinux options to config.
func ModifySecurityOptions(config []string, selinuxOpts *v1.SELinuxOptions) []string {
config = modifySecurityOption(config, DockerLabelUser, selinuxOpts.User)
config = modifySecurityOption(config, DockerLabelRole, selinuxOpts.Role)
config = modifySecurityOption(config, DockerLabelType, selinuxOpts.Type)
config = modifySecurityOption(config, DockerLabelLevel, selinuxOpts.Level)
return config
}
// modifySecurityOption adds the security option of name to the config array with value in the form
// of name:value
func modifySecurityOption(config []string, name, value string) []string {
if len(value) > 0 {
config = append(config, fmt.Sprintf("%s:%s", name, value))
}
return config
}
// MakeCapabilities creates string slices from Capability slices
func MakeCapabilities(capAdd []v1.Capability, capDrop []v1.Capability) ([]string, []string) {
var (
addCaps []string
dropCaps []string
)
for _, cap := range capAdd {
addCaps = append(addCaps, string(cap))
}
for _, cap := range capDrop {
dropCaps = append(dropCaps, string(cap))
}
return addCaps, dropCaps
}
func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1.SecurityContext {
effectiveSc := securityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext
if effectiveSc == nil && containerSc == nil {
return nil
}
if effectiveSc != nil && containerSc == nil {
return effectiveSc
}
if effectiveSc == nil && containerSc != nil {
return containerSc
}
if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(v1.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
}
if containerSc.Capabilities != nil {
effectiveSc.Capabilities = new(v1.Capabilities)
*effectiveSc.Capabilities = *containerSc.Capabilities
}
if containerSc.Privileged != nil {
effectiveSc.Privileged = new(bool)
*effectiveSc.Privileged = *containerSc.Privileged
}
if containerSc.RunAsUser != nil {
effectiveSc.RunAsUser = new(int64)
*effectiveSc.RunAsUser = *containerSc.RunAsUser
}
if containerSc.RunAsNonRoot != nil {
effectiveSc.RunAsNonRoot = new(bool)
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
}
if containerSc.ReadOnlyRootFilesystem != nil {
effectiveSc.ReadOnlyRootFilesystem = new(bool)
*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
}
return effectiveSc
}
func securityContextFromPodSecurityContext(pod *v1.Pod) *v1.SecurityContext {
if pod.Spec.SecurityContext == nil {
return nil
}
synthesized := &v1.SecurityContext{}
if pod.Spec.SecurityContext.SELinuxOptions != nil {
synthesized.SELinuxOptions = &v1.SELinuxOptions{}
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
}
if pod.Spec.SecurityContext.RunAsUser != nil {
synthesized.RunAsUser = new(int64)
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
}
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
synthesized.RunAsNonRoot = new(bool)
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
}
return synthesized
}
// TODO: remove the duplicate code
func InternalDetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *api.SecurityContext {
effectiveSc := internalSecurityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext
if effectiveSc == nil && containerSc == nil {
return nil
}
if effectiveSc != nil && containerSc == nil {
return effectiveSc
}
if effectiveSc == nil && containerSc != nil {
return containerSc
}
if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(api.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
}
if containerSc.Capabilities != nil {
effectiveSc.Capabilities = new(api.Capabilities)
*effectiveSc.Capabilities = *containerSc.Capabilities
}
if containerSc.Privileged != nil {
effectiveSc.Privileged = new(bool)
*effectiveSc.Privileged = *containerSc.Privileged
}
if containerSc.RunAsUser != nil {
effectiveSc.RunAsUser = new(int64)
*effectiveSc.RunAsUser = *containerSc.RunAsUser
}
if containerSc.RunAsNonRoot != nil {
effectiveSc.RunAsNonRoot = new(bool)
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
}
if containerSc.ReadOnlyRootFilesystem != nil {
effectiveSc.ReadOnlyRootFilesystem = new(bool)
*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
}
return effectiveSc
}
func internalSecurityContextFromPodSecurityContext(pod *api.Pod) *api.SecurityContext {
if pod.Spec.SecurityContext == nil {
return nil
}
synthesized := &api.SecurityContext{}
if pod.Spec.SecurityContext.SELinuxOptions != nil {
synthesized.SELinuxOptions = &api.SELinuxOptions{}
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
}
if pod.Spec.SecurityContext.RunAsUser != nil {
synthesized.RunAsUser = new(int64)
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
}
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
synthesized.RunAsNonRoot = new(bool)
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
}
return synthesized
}

View File

@@ -1,334 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package securitycontext
import (
"fmt"
"reflect"
"strconv"
"testing"
dockercontainer "github.com/docker/engine-api/types/container"
apitesting "k8s.io/kubernetes/pkg/api/testing"
"k8s.io/kubernetes/pkg/api/v1"
)
func TestModifyContainerConfig(t *testing.T) {
var uid int64 = 123
var overrideUid int64 = 321
cases := []struct {
name string
podSc *v1.PodSecurityContext
sc *v1.SecurityContext
expected *dockercontainer.Config
}{
{
name: "container.SecurityContext.RunAsUser set",
sc: &v1.SecurityContext{
RunAsUser: &uid,
},
expected: &dockercontainer.Config{
User: strconv.FormatInt(uid, 10),
},
},
{
name: "no RunAsUser value set",
sc: &v1.SecurityContext{},
expected: &dockercontainer.Config{},
},
{
name: "pod.Spec.SecurityContext.RunAsUser set",
podSc: &v1.PodSecurityContext{
RunAsUser: &uid,
},
expected: &dockercontainer.Config{
User: strconv.FormatInt(uid, 10),
},
},
{
name: "container.SecurityContext.RunAsUser overrides pod.Spec.SecurityContext.RunAsUser",
podSc: &v1.PodSecurityContext{
RunAsUser: &uid,
},
sc: &v1.SecurityContext{
RunAsUser: &overrideUid,
},
expected: &dockercontainer.Config{
User: strconv.FormatInt(overrideUid, 10),
},
},
}
provider := NewSimpleSecurityContextProvider()
dummyContainer := &v1.Container{}
for _, tc := range cases {
pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc
dockerCfg := &dockercontainer.Config{}
provider.ModifyContainerConfig(pod, dummyContainer, dockerCfg)
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
t.Errorf("%v: unexpected modification of docker config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
}
}
}
func TestModifyHostConfig(t *testing.T) {
priv := true
setPrivSC := &v1.SecurityContext{}
setPrivSC.Privileged = &priv
setPrivHC := &dockercontainer.HostConfig{
Privileged: true,
}
setCapsHC := &dockercontainer.HostConfig{
CapAdd: []string{"addCapA", "addCapB"},
CapDrop: []string{"dropCapA", "dropCapB"},
}
setSELinuxHC := &dockercontainer.HostConfig{}
setSELinuxHC.SecurityOpt = []string{
fmt.Sprintf("%s:%s", DockerLabelUser, "user"),
fmt.Sprintf("%s:%s", DockerLabelRole, "role"),
fmt.Sprintf("%s:%s", DockerLabelType, "type"),
fmt.Sprintf("%s:%s", DockerLabelLevel, "level"),
}
// seLinuxLabelsSC := fullValidSecurityContext()
// seLinuxLabelsHC := fullValidHostConfig()
cases := []struct {
name string
podSc *v1.PodSecurityContext
sc *v1.SecurityContext
expected *dockercontainer.HostConfig
}{
{
name: "fully set container.SecurityContext",
sc: fullValidSecurityContext(),
expected: fullValidHostConfig(),
},
{
name: "container.SecurityContext.Privileged",
sc: setPrivSC,
expected: setPrivHC,
},
{
name: "container.SecurityContext.Capabilities",
sc: &v1.SecurityContext{
Capabilities: inputCapabilities(),
},
expected: setCapsHC,
},
{
name: "container.SecurityContext.SELinuxOptions",
sc: &v1.SecurityContext{
SELinuxOptions: inputSELinuxOptions(),
},
expected: setSELinuxHC,
},
{
name: "pod.Spec.SecurityContext.SELinuxOptions",
podSc: &v1.PodSecurityContext{
SELinuxOptions: inputSELinuxOptions(),
},
expected: setSELinuxHC,
},
{
name: "container.SecurityContext overrides pod.Spec.SecurityContext",
podSc: overridePodSecurityContext(),
sc: fullValidSecurityContext(),
expected: fullValidHostConfig(),
},
}
provider := NewSimpleSecurityContextProvider()
dummyContainer := &v1.Container{}
for _, tc := range cases {
pod := &v1.Pod{Spec: v1.PodSpec{SecurityContext: tc.podSc}}
dummyContainer.SecurityContext = tc.sc
dockerCfg := &dockercontainer.HostConfig{}
provider.ModifyHostConfig(pod, dummyContainer, dockerCfg, nil)
if e, a := tc.expected, dockerCfg; !reflect.DeepEqual(e, a) {
t.Errorf("%v: unexpected modification of host config\nExpected:\n\n%#v\n\nGot:\n\n%#v", tc.name, e, a)
}
}
}
func TestModifyHostConfigPodSecurityContext(t *testing.T) {
supplementalGroupsSC := &v1.PodSecurityContext{}
supplementalGroupsSC.SupplementalGroups = []int64{2222}
supplementalGroupHC := fullValidHostConfig()
supplementalGroupHC.GroupAdd = []string{"2222"}
fsGroupHC := fullValidHostConfig()
fsGroupHC.GroupAdd = []string{"1234"}
extraSupplementalGroupHC := fullValidHostConfig()
extraSupplementalGroupHC.GroupAdd = []string{"1234"}
bothHC := fullValidHostConfig()
bothHC.GroupAdd = []string{"2222", "1234"}
fsGroup := int64(1234)
extraSupplementalGroup := []int64{1234}
testCases := map[string]struct {
securityContext *v1.PodSecurityContext
expected *dockercontainer.HostConfig
extraSupplementalGroups []int64
}{
"nil": {
securityContext: nil,
expected: fullValidHostConfig(),
extraSupplementalGroups: nil,
},
"SupplementalGroup": {
securityContext: supplementalGroupsSC,
expected: supplementalGroupHC,
extraSupplementalGroups: nil,
},
"FSGroup": {
securityContext: &v1.PodSecurityContext{FSGroup: &fsGroup},
expected: fsGroupHC,
extraSupplementalGroups: nil,
},
"FSGroup + SupplementalGroups": {
securityContext: &v1.PodSecurityContext{
SupplementalGroups: []int64{2222},
FSGroup: &fsGroup,
},
expected: bothHC,
extraSupplementalGroups: nil,
},
"ExtraSupplementalGroup": {
securityContext: nil,
expected: extraSupplementalGroupHC,
extraSupplementalGroups: extraSupplementalGroup,
},
"ExtraSupplementalGroup + SupplementalGroups": {
securityContext: supplementalGroupsSC,
expected: bothHC,
extraSupplementalGroups: extraSupplementalGroup,
},
}
provider := NewSimpleSecurityContextProvider()
dummyContainer := &v1.Container{}
dummyContainer.SecurityContext = fullValidSecurityContext()
dummyPod := &v1.Pod{
Spec: apitesting.V1DeepEqualSafePodSpec(),
}
for k, v := range testCases {
dummyPod.Spec.SecurityContext = v.securityContext
dockerCfg := &dockercontainer.HostConfig{}
provider.ModifyHostConfig(dummyPod, dummyContainer, dockerCfg, v.extraSupplementalGroups)
if !reflect.DeepEqual(v.expected, dockerCfg) {
t.Errorf("unexpected modification of host config for %s. Expected: %#v Got: %#v", k, v.expected, dockerCfg)
}
}
}
func TestModifySecurityOption(t *testing.T) {
testCases := []struct {
name string
config []string
optName string
optVal string
expected []string
}{
{
name: "Empty val",
config: []string{"a:b", "c:d"},
optName: "optA",
optVal: "",
expected: []string{"a:b", "c:d"},
},
{
name: "Valid",
config: []string{"a:b", "c:d"},
optName: "e",
optVal: "f",
expected: []string{"a:b", "c:d", "e:f"},
},
}
for _, tc := range testCases {
actual := modifySecurityOption(tc.config, tc.optName, tc.optVal)
if !reflect.DeepEqual(tc.expected, actual) {
t.Errorf("Failed to apply options correctly for tc: %s. Expected: %v but got %v", tc.name, tc.expected, actual)
}
}
}
func overridePodSecurityContext() *v1.PodSecurityContext {
return &v1.PodSecurityContext{
SELinuxOptions: &v1.SELinuxOptions{
User: "user2",
Role: "role2",
Type: "type2",
Level: "level2",
},
}
}
func fullValidPodSecurityContext() *v1.PodSecurityContext {
return &v1.PodSecurityContext{
SELinuxOptions: inputSELinuxOptions(),
}
}
func fullValidSecurityContext() *v1.SecurityContext {
priv := true
return &v1.SecurityContext{
Privileged: &priv,
Capabilities: inputCapabilities(),
SELinuxOptions: inputSELinuxOptions(),
}
}
func inputCapabilities() *v1.Capabilities {
return &v1.Capabilities{
Add: []v1.Capability{"addCapA", "addCapB"},
Drop: []v1.Capability{"dropCapA", "dropCapB"},
}
}
func inputSELinuxOptions() *v1.SELinuxOptions {
return &v1.SELinuxOptions{
User: "user",
Role: "role",
Type: "type",
Level: "level",
}
}
func fullValidHostConfig() *dockercontainer.HostConfig {
return &dockercontainer.HostConfig{
Privileged: true,
CapAdd: []string{"addCapA", "addCapB"},
CapDrop: []string{"dropCapA", "dropCapB"},
SecurityOpt: []string{
fmt.Sprintf("%s:%s", DockerLabelUser, "user"),
fmt.Sprintf("%s:%s", DockerLabelRole, "role"),
fmt.Sprintf("%s:%s", DockerLabelType, "type"),
fmt.Sprintf("%s:%s", DockerLabelLevel, "level"),
},
}
}

View File

@@ -1,49 +0,0 @@
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package securitycontext
import (
"k8s.io/kubernetes/pkg/api/v1"
dockercontainer "github.com/docker/engine-api/types/container"
)
type SecurityContextProvider interface {
// ModifyContainerConfig is called before the Docker createContainer call.
// The security context provider can make changes to the Config with which
// the container is created.
ModifyContainerConfig(pod *v1.Pod, container *v1.Container, config *dockercontainer.Config)
// ModifyHostConfig is called before the Docker createContainer call.
// The security context provider can make changes to the HostConfig, affecting
// security options, whether the container is privileged, volume binds, etc.
// An error is returned if it's not possible to secure the container as requested
// with a security context.
//
// - pod: the pod to modify the docker hostconfig for
// - container: the container to modify the hostconfig for
// - supplementalGids: additional supplemental GIDs associated with the pod's volumes
ModifyHostConfig(pod *v1.Pod, container *v1.Container, hostConfig *dockercontainer.HostConfig, supplementalGids []int64)
}
const (
DockerLabelUser string = "label:user"
DockerLabelRole string = "label:role"
DockerLabelType string = "label:type"
DockerLabelLevel string = "label:level"
DockerLabelDisable string = "label:disable"
)

View File

@@ -20,6 +20,7 @@ import (
"fmt"
"strings"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/v1"
)
@@ -87,3 +88,146 @@ func HasRunAsUser(container *v1.Container) bool {
func HasRootRunAsUser(container *v1.Container) bool {
return HasRunAsUser(container) && HasRootUID(container)
}
func DetermineEffectiveSecurityContext(pod *v1.Pod, container *v1.Container) *v1.SecurityContext {
effectiveSc := securityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext
if effectiveSc == nil && containerSc == nil {
return nil
}
if effectiveSc != nil && containerSc == nil {
return effectiveSc
}
if effectiveSc == nil && containerSc != nil {
return containerSc
}
if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(v1.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
}
if containerSc.Capabilities != nil {
effectiveSc.Capabilities = new(v1.Capabilities)
*effectiveSc.Capabilities = *containerSc.Capabilities
}
if containerSc.Privileged != nil {
effectiveSc.Privileged = new(bool)
*effectiveSc.Privileged = *containerSc.Privileged
}
if containerSc.RunAsUser != nil {
effectiveSc.RunAsUser = new(int64)
*effectiveSc.RunAsUser = *containerSc.RunAsUser
}
if containerSc.RunAsNonRoot != nil {
effectiveSc.RunAsNonRoot = new(bool)
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
}
if containerSc.ReadOnlyRootFilesystem != nil {
effectiveSc.ReadOnlyRootFilesystem = new(bool)
*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
}
return effectiveSc
}
func securityContextFromPodSecurityContext(pod *v1.Pod) *v1.SecurityContext {
if pod.Spec.SecurityContext == nil {
return nil
}
synthesized := &v1.SecurityContext{}
if pod.Spec.SecurityContext.SELinuxOptions != nil {
synthesized.SELinuxOptions = &v1.SELinuxOptions{}
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
}
if pod.Spec.SecurityContext.RunAsUser != nil {
synthesized.RunAsUser = new(int64)
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
}
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
synthesized.RunAsNonRoot = new(bool)
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
}
return synthesized
}
// TODO: remove the duplicate code
func InternalDetermineEffectiveSecurityContext(pod *api.Pod, container *api.Container) *api.SecurityContext {
effectiveSc := internalSecurityContextFromPodSecurityContext(pod)
containerSc := container.SecurityContext
if effectiveSc == nil && containerSc == nil {
return nil
}
if effectiveSc != nil && containerSc == nil {
return effectiveSc
}
if effectiveSc == nil && containerSc != nil {
return containerSc
}
if containerSc.SELinuxOptions != nil {
effectiveSc.SELinuxOptions = new(api.SELinuxOptions)
*effectiveSc.SELinuxOptions = *containerSc.SELinuxOptions
}
if containerSc.Capabilities != nil {
effectiveSc.Capabilities = new(api.Capabilities)
*effectiveSc.Capabilities = *containerSc.Capabilities
}
if containerSc.Privileged != nil {
effectiveSc.Privileged = new(bool)
*effectiveSc.Privileged = *containerSc.Privileged
}
if containerSc.RunAsUser != nil {
effectiveSc.RunAsUser = new(int64)
*effectiveSc.RunAsUser = *containerSc.RunAsUser
}
if containerSc.RunAsNonRoot != nil {
effectiveSc.RunAsNonRoot = new(bool)
*effectiveSc.RunAsNonRoot = *containerSc.RunAsNonRoot
}
if containerSc.ReadOnlyRootFilesystem != nil {
effectiveSc.ReadOnlyRootFilesystem = new(bool)
*effectiveSc.ReadOnlyRootFilesystem = *containerSc.ReadOnlyRootFilesystem
}
return effectiveSc
}
func internalSecurityContextFromPodSecurityContext(pod *api.Pod) *api.SecurityContext {
if pod.Spec.SecurityContext == nil {
return nil
}
synthesized := &api.SecurityContext{}
if pod.Spec.SecurityContext.SELinuxOptions != nil {
synthesized.SELinuxOptions = &api.SELinuxOptions{}
*synthesized.SELinuxOptions = *pod.Spec.SecurityContext.SELinuxOptions
}
if pod.Spec.SecurityContext.RunAsUser != nil {
synthesized.RunAsUser = new(int64)
*synthesized.RunAsUser = *pod.Spec.SecurityContext.RunAsUser
}
if pod.Spec.SecurityContext.RunAsNonRoot != nil {
synthesized.RunAsNonRoot = new(bool)
*synthesized.RunAsNonRoot = *pod.Spec.SecurityContext.RunAsNonRoot
}
return synthesized
}