diff --git a/pkg/app/sleep.go b/pkg/app/sleep.go index 9f4d21c5..01447bd6 100644 --- a/pkg/app/sleep.go +++ b/pkg/app/sleep.go @@ -26,9 +26,12 @@ import ( ) type sleep struct { - ns string - injectSidecar bool - tproxy bool + ns string + injectSidecar bool + tproxy bool + securityContext bool + runAsUser int + runAsGroup int } var _ App = &sleep{} @@ -45,6 +48,16 @@ func SleepTroxy(ns string) App { return &sleep{ns: ns, injectSidecar: true, tproxy: true} } +func SleepSecurityContext(ns string, uid, gid int) App { + return &sleep{ + ns: ns, + injectSidecar: true, + securityContext: true, + runAsUser: uid, + runAsGroup: gid, + } +} + func (a *sleep) Name() string { return "sleep" } @@ -66,10 +79,14 @@ func (a *sleep) Uninstall(t test.TestHelper) { func (a *sleep) values(t test.TestHelper) map[string]interface{} { proxy := oc.GetProxy(t) return map[string]interface{}{ - "InjectSidecar": a.injectSidecar, - "HttpProxy": proxy.HTTPProxy, - "HttpsProxy": proxy.HTTPSProxy, - "NoProxy": proxy.NoProxy, + "InjectSidecar": a.injectSidecar, + "HttpProxy": proxy.HTTPProxy, + "HttpsProxy": proxy.HTTPSProxy, + "NoProxy": proxy.NoProxy, + "Tproxy": a.tproxy, + "securityContext": a.securityContext, + "runAsUser": a.runAsUser, + "runAsGroup": a.runAsGroup, } } @@ -204,6 +221,11 @@ spec: volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume + {{ if .securityContext }} + securityContext: + runAsUser: {{ .runAsUser }} + runAsGroup: {{ .runAsGroup }} + {{ end }} volumes: - name: secret-volume secret: diff --git a/pkg/tests/ossm/privileged_pods_test.go b/pkg/tests/ossm/privileged_pods_test.go new file mode 100644 index 00000000..ec609f4b --- /dev/null +++ b/pkg/tests/ossm/privileged_pods_test.go @@ -0,0 +1,93 @@ +// Copyright 2024 Red Hat, Inc. +// +// 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 ossm + +import ( + "testing" + + "github.com/maistra/maistra-test-tool/pkg/app" + "github.com/maistra/maistra-test-tool/pkg/util/check/assert" + "github.com/maistra/maistra-test-tool/pkg/util/env" + "github.com/maistra/maistra-test-tool/pkg/util/ns" + "github.com/maistra/maistra-test-tool/pkg/util/oc" + "github.com/maistra/maistra-test-tool/pkg/util/pod" + "github.com/maistra/maistra-test-tool/pkg/util/shell" + "github.com/maistra/maistra-test-tool/pkg/util/version" + + . "github.com/maistra/maistra-test-tool/pkg/util/test" +) + +func TestInjectionInPrivelegedPods(t *testing.T) { + NewTest(t).Groups(Full, Disconnected, ARM).Run(func(t TestHelper) { + if env.GetOperatorVersion().LessThan(version.OPERATOR_2_6_2) { + t.Skip("This test requires the operator version to be at least 2.6.2") + } + t.Log("Reference: https://issues.redhat.com/browse/OSSM-8001") + + t.Cleanup(func() { + app.Uninstall(t, app.Httpbin(ns.Foo)) + oc.RecreateNamespace(t, meshNamespace) + }) + + t.LogStep("Deploy smcp") + DeployControlPlane(t) + + t.LogStep("Patch SMCP to enable mTLS in dataPlane and controlPlane") + oc.Patch(t, meshNamespace, "smcp", smcpName, "merge", ` +spec: + security: + dataPlane: + mtls: true + controlPlane: + mtls: true +`) + + t.LogStep("Deploy httpbin") + app.InstallAndWaitReady(t, app.Httpbin(ns.Foo)) + + t.NewSubTest("Check sleep with explicitly defined SecurityContext with same uid/gid (1001)").Run(func(t TestHelper) { + runSecurityContextTest(t, 1001, 1001, "uid=1002(1002) gid=1002 groups=1002") + }) + + t.NewSubTest("Check sleep with explicitly defined SecurityContext with root uid/gid").Run(func(t TestHelper) { + runSecurityContextTest(t, 0, 0, "uid=1(bin) gid=1(bin) groups=1(bin)") + }) + }) +} + +func runSecurityContextTest(t TestHelper, uid, gid int, expectedIDOutput string) { + t.Cleanup(func() { + app.Uninstall(t, app.SleepSecurityContext(ns.Foo, uid, gid)) + }) + + t.LogStep("Provide privileged policy to sleep SA") + shell.Execute(t, "oc adm policy add-scc-to-user privileged -z sleep -n foo") + + t.LogStep("Deploy sleep") + app.InstallAndWaitReady(t, + app.SleepSecurityContext(ns.Foo, uid, gid), + ) + + t.LogStepf("Verify that UID, GID and Groups were changed to: %s", expectedIDOutput) + oc.Exec(t, pod.MatchingSelector("app=sleep", ns.Foo), "istio-proxy", + "id", + assert.OutputContains( + expectedIDOutput, + "UID, GID and Groups were changed", + "UID, GID and Groups were not changed")) + + t.LogStep("Verify that a request from sleep to httpbin returns 200") + app.AssertSleepPodRequestSuccess(t, ns.Foo, "http://httpbin:8000/ip") +} diff --git a/pkg/util/version/operator_version.go b/pkg/util/version/operator_version.go index a43ee3e0..11760f4e 100644 --- a/pkg/util/version/operator_version.go +++ b/pkg/util/version/operator_version.go @@ -17,4 +17,5 @@ package version var ( OPERATOR_2_5_2 = ParseVersion("2.5.2") OPERATOR_2_6_0 = ParseVersion("2.6.0") + OPERATOR_2_6_2 = ParseVersion("2.6.2") )