Switch to github.com/golang/dep for vendoring

Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
Mrunal Patel 2017-01-31 16:45:59 -08:00
parent d6ab91be27
commit 8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions

55
vendor/k8s.io/kubernetes/pkg/securitycontext/BUILD generated vendored Normal file
View file

@ -0,0 +1,55 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_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",
],
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",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

18
vendor/k8s.io/kubernetes/pkg/securitycontext/doc.go generated vendored Normal file
View file

@ -0,0 +1,18 @@
/*
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 contains security context api implementations
package securitycontext // import "k8s.io/kubernetes/pkg/securitycontext"

56
vendor/k8s.io/kubernetes/pkg/securitycontext/fake.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
/*
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"
"k8s.io/kubernetes/pkg/api/v1"
dockercontainer "github.com/docker/engine-api/types/container"
)
// ValidSecurityContextWithContainerDefaults creates a valid security context provider based on
// empty container defaults. Used for testing.
func ValidSecurityContextWithContainerDefaults() *v1.SecurityContext {
priv := false
return &v1.SecurityContext{
Capabilities: &v1.Capabilities{},
Privileged: &priv,
}
}
// 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 {
priv := false
return &api.SecurityContext{
Capabilities: &api.Capabilities{},
Privileged: &priv,
}
}

View file

@ -0,0 +1,274 @@
/*
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

@ -0,0 +1,334 @@
/*
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"),
},
}
}

49
vendor/k8s.io/kubernetes/pkg/securitycontext/types.go generated vendored Normal file
View file

@ -0,0 +1,49 @@
/*
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"
)

89
vendor/k8s.io/kubernetes/pkg/securitycontext/util.go generated vendored Normal file
View file

@ -0,0 +1,89 @@
/*
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"
"strings"
"k8s.io/kubernetes/pkg/api/v1"
)
// HasPrivilegedRequest returns the value of SecurityContext.Privileged, taking into account
// the possibility of nils
func HasPrivilegedRequest(container *v1.Container) bool {
if container.SecurityContext == nil {
return false
}
if container.SecurityContext.Privileged == nil {
return false
}
return *container.SecurityContext.Privileged
}
// HasCapabilitiesRequest returns true if Adds or Drops are defined in the security context
// capabilities, taking into account nils
func HasCapabilitiesRequest(container *v1.Container) bool {
if container.SecurityContext == nil {
return false
}
if container.SecurityContext.Capabilities == nil {
return false
}
return len(container.SecurityContext.Capabilities.Add) > 0 || len(container.SecurityContext.Capabilities.Drop) > 0
}
const expectedSELinuxFields = 4
// ParseSELinuxOptions parses a string containing a full SELinux context
// (user, role, type, and level) into an SELinuxOptions object. If the
// context is malformed, an error is returned.
func ParseSELinuxOptions(context string) (*v1.SELinuxOptions, error) {
fields := strings.SplitN(context, ":", expectedSELinuxFields)
if len(fields) != expectedSELinuxFields {
return nil, fmt.Errorf("expected %v fields in selinux; got %v (context: %v)", expectedSELinuxFields, len(fields), context)
}
return &v1.SELinuxOptions{
User: fields[0],
Role: fields[1],
Type: fields[2],
Level: fields[3],
}, nil
}
// HasNonRootUID returns true if the runAsUser is set and is greater than 0.
func HasRootUID(container *v1.Container) bool {
if container.SecurityContext == nil {
return false
}
if container.SecurityContext.RunAsUser == nil {
return false
}
return *container.SecurityContext.RunAsUser == 0
}
// HasRunAsUser determines if the sc's runAsUser field is set.
func HasRunAsUser(container *v1.Container) bool {
return container.SecurityContext != nil && container.SecurityContext.RunAsUser != nil
}
// HasRootRunAsUser returns true if the run as user is set and it is set to 0.
func HasRootRunAsUser(container *v1.Container) bool {
return HasRunAsUser(container) && HasRootUID(container)
}

View file

@ -0,0 +1,178 @@
/*
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 (
"testing"
"k8s.io/kubernetes/pkg/api/v1"
)
func TestParseSELinuxOptions(t *testing.T) {
cases := []struct {
name string
input string
expected *v1.SELinuxOptions
}{
{
name: "simple",
input: "user_t:role_t:type_t:s0",
expected: &v1.SELinuxOptions{
User: "user_t",
Role: "role_t",
Type: "type_t",
Level: "s0",
},
},
{
name: "simple + categories",
input: "user_t:role_t:type_t:s0:c0",
expected: &v1.SELinuxOptions{
User: "user_t",
Role: "role_t",
Type: "type_t",
Level: "s0:c0",
},
},
{
name: "not enough fields",
input: "type_t:s0:c0",
},
}
for _, tc := range cases {
result, err := ParseSELinuxOptions(tc.input)
if err != nil {
if tc.expected == nil {
continue
} else {
t.Errorf("%v: unexpected error: %v", tc.name, err)
}
}
compareContexts(tc.name, tc.expected, result, t)
}
}
func compareContexts(name string, ex, ac *v1.SELinuxOptions, t *testing.T) {
if e, a := ex.User, ac.User; e != a {
t.Errorf("%v: expected user: %v, got: %v", name, e, a)
}
if e, a := ex.Role, ac.Role; e != a {
t.Errorf("%v: expected role: %v, got: %v", name, e, a)
}
if e, a := ex.Type, ac.Type; e != a {
t.Errorf("%v: expected type: %v, got: %v", name, e, a)
}
if e, a := ex.Level, ac.Level; e != a {
t.Errorf("%v: expected level: %v, got: %v", name, e, a)
}
}
func containerWithUser(ptr *int64) *v1.Container {
return &v1.Container{SecurityContext: &v1.SecurityContext{RunAsUser: ptr}}
}
func TestHaRootUID(t *testing.T) {
var nonRoot int64 = 1
var root int64 = 0
tests := map[string]struct {
container *v1.Container
expect bool
}{
"nil sc": {
container: &v1.Container{SecurityContext: nil},
},
"nil runAsuser": {
container: containerWithUser(nil),
},
"runAsUser non-root": {
container: containerWithUser(&nonRoot),
},
"runAsUser root": {
container: containerWithUser(&root),
expect: true,
},
}
for k, v := range tests {
actual := HasRootUID(v.container)
if actual != v.expect {
t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual)
}
}
}
func TestHasRunAsUser(t *testing.T) {
var runAsUser int64 = 0
tests := map[string]struct {
container *v1.Container
expect bool
}{
"nil sc": {
container: &v1.Container{SecurityContext: nil},
},
"nil runAsUser": {
container: containerWithUser(nil),
},
"valid runAsUser": {
container: containerWithUser(&runAsUser),
expect: true,
},
}
for k, v := range tests {
actual := HasRunAsUser(v.container)
if actual != v.expect {
t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual)
}
}
}
func TestHasRootRunAsUser(t *testing.T) {
var nonRoot int64 = 1
var root int64 = 0
tests := map[string]struct {
container *v1.Container
expect bool
}{
"nil sc": {
container: &v1.Container{SecurityContext: nil},
},
"nil runAsuser": {
container: containerWithUser(nil),
},
"runAsUser non-root": {
container: containerWithUser(&nonRoot),
},
"runAsUser root": {
container: containerWithUser(&root),
expect: true,
},
}
for k, v := range tests {
actual := HasRootRunAsUser(v.container)
if actual != v.expect {
t.Errorf("%s failed, expected %t but received %t", k, v.expect, actual)
}
}
}