From 6a58aa1cf2e4e86dc175a7e91292d57f6d10f340 Mon Sep 17 00:00:00 2001 From: Dan Gerdesmeier Date: Mon, 11 Mar 2019 18:07:48 +0000 Subject: [PATCH] Add conformance test for setting user This change adds a conformance test to validate that a user set in the securityContext is reflected in the container. This change also adds the group information to the runtime test image, but we do not validate this as 1. it is not currently part of the runtime contract and 2. Setting group is currently an alpha feature that does not work on many Kubernetes clusters. See https://github.com/kubernetes/enhancements/issues/213 Related to: #3223 --- test/configuration.go | 1 + test/conformance/user_test.go | 65 ++++++++++++++++++++ test/crd.go | 9 +-- test/test_images/runtime/handlers/runtime.go | 1 + test/test_images/runtime/handlers/user.go | 31 ++++++++++ test/test_images/runtime/service.yaml | 2 + test/types/runtime.go | 12 +++- 7 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 test/conformance/user_test.go create mode 100644 test/test_images/runtime/handlers/user.go diff --git a/test/configuration.go b/test/configuration.go index 7dc4c95d1833..d77d9fed89b3 100644 --- a/test/configuration.go +++ b/test/configuration.go @@ -36,6 +36,7 @@ type Options struct { RevisionTimeoutSeconds int64 ContainerResources corev1.ResourceRequirements ReadinessProbe *corev1.Probe + SecurityContext *corev1.SecurityContext } // CreateConfiguration create a configuration resource in namespace with the name names.Config diff --git a/test/conformance/user_test.go b/test/conformance/user_test.go new file mode 100644 index 000000000000..86dbf299b7d6 --- /dev/null +++ b/test/conformance/user_test.go @@ -0,0 +1,65 @@ +// +build e2e + +/* +Copyright 2019 The Knative 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 conformance + +import ( + "strconv" + "testing" + + "github.com/knative/serving/test" + "k8s.io/apimachinery/pkg/api/resource" + + corev1 "k8s.io/api/core/v1" +) + +const userId = 2020 + +// TestMustRunAsUser verifies that a supplied runAsUser through securityContext takes +// effect as delared by "MUST" in the runtime-contract. +func TestMustRunAsUser(t *testing.T) { + t.Parallel() + clients := setup(t) + + securityContext := &corev1.SecurityContext{ + runAsUser: userId, + } + + ri, err := fetchRuntimeInfo(t, clients, &test.Options{SecurityContext: securityContext}) + if err != nil { + t.Fatalf("Error fetching runtime info: %v", err) + } + + if ri.Host == nil { + t.Fatal("Missing host information from runtime info.") + } + + if ri.Host.User == nil { + t.Fatal("Missing user information from runtime info.") + } + + if got, want := ri.Host.User.Uid, userId; got != want { + t.Errorf("uid = %d, want: %d", got, want) + } + + // We expect the effective userId to match the userId as we + // did not use setuid. + if got, want := ri.Host.User.Euid, userId; got != want { + t.Errorf("euid = %d, want: %d", got, want) + } +} diff --git a/test/crd.go b/test/crd.go index b8f556b476c6..9b791d35e839 100644 --- a/test/crd.go +++ b/test/crd.go @@ -119,10 +119,11 @@ func ConfigurationSpec(imagePath string, options *Options) *v1alpha1.Configurati RevisionTemplate: v1alpha1.RevisionTemplateSpec{ Spec: v1alpha1.RevisionSpec{ Container: corev1.Container{ - Image: imagePath, - Resources: options.ContainerResources, - ReadinessProbe: options.ReadinessProbe, - Ports: options.ContainerPorts, + Image: imagePath, + Resources: options.ContainerResources, + ReadinessProbe: options.ReadinessProbe, + Ports: options.ContainerPorts, + SecurityContext: options.SecurityContext, }, ContainerConcurrency: v1alpha1.RevisionContainerConcurrencyType(options.ContainerConcurrency), }, diff --git a/test/test_images/runtime/handlers/runtime.go b/test/test_images/runtime/handlers/runtime.go index a674e70b8fa2..dcc993403b90 100644 --- a/test/test_images/runtime/handlers/runtime.go +++ b/test/test_images/runtime/handlers/runtime.go @@ -31,6 +31,7 @@ func runtimeHandler(w http.ResponseWriter, r *http.Request) { Cgroups: cgroups(cgroupPaths...), Mounts: mounts(), Stdin: stdin(), + User: userInfo(), }, } diff --git a/test/test_images/runtime/handlers/user.go b/test/test_images/runtime/handlers/user.go new file mode 100644 index 000000000000..ac78d2ff0339 --- /dev/null +++ b/test/test_images/runtime/handlers/user.go @@ -0,0 +1,31 @@ +/* +Copyright 2019 The Knative 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 handlers + +import ( + "os" + + "github.com/knative/serving/test/types" +) + +func userInfo() *types.UserInfo { + return &types.UserInfo{ + Uid: os.Getuid(), + Euid: os.Geteuid(), + Gid: os.Getgid(), + Egid: os.Getegid()} +} diff --git a/test/test_images/runtime/service.yaml b/test/test_images/runtime/service.yaml index bea0744ca64e..c0e3b8eed0d1 100644 --- a/test/test_images/runtime/service.yaml +++ b/test/test_images/runtime/service.yaml @@ -10,3 +10,5 @@ spec: spec: container: image: github.com/knative/serving/test/test_images/runtime + securityContext: + runAsUser: 2020 diff --git a/test/types/runtime.go b/test/types/runtime.go index 497f5d0fce80..2eb676734d57 100644 --- a/test/types/runtime.go +++ b/test/types/runtime.go @@ -49,8 +49,9 @@ type HostInfo struct { // Cgroups is a list of cgroup information. Cgroups []*Cgroup `json:"cgroups"` // Mounts is a list of mounted volume information, or error. - Mounts []*Mount `json:"mounts"` - Stdin *Stdin `json:"stdin"` + Mounts []*Mount `json:"mounts"` + Stdin *Stdin `json:"stdin"` + User *UserInfo `json:"user"` } // Stdin contains information about the Stdin file descriptor for the container. @@ -61,6 +62,13 @@ type Stdin struct { Error string `json:"error,omitempty"` } +type UserInfo struct { + Uid int `json:"uid"` + Euid int `json:"euid"` + Gid int `json:"gid"` + Egid int `json:"egid"` +} + // FileInfo contains the metadata for a given file. type FileInfo struct { // Name is the full filename.