diff --git a/test/extended/builds/contextdir.go b/test/extended/builds/contextdir.go index 92d1ec00ebc4..cc57c62cadf7 100644 --- a/test/extended/builds/contextdir.go +++ b/test/extended/builds/contextdir.go @@ -21,13 +21,11 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] builds with a context dir appFixture = exutil.FixturePath("testdata", "builds", "test-context-build.json") oc = exutil.NewCLIWithPodSecurityLevel("contextdir", admissionapi.LevelBaseline) s2iBuildConfigName = "s2icontext" - s2iBuildName = "s2icontext-1" dcName = "frontend" deploymentName = "frontend-1" dcLabel = exutil.ParseLabelsOrDie(fmt.Sprintf("deployment=%s", deploymentName)) serviceName = "frontend" dockerBuildConfigName = "dockercontext" - dockerBuildName = "dockercontext-1" ) g.Context("", func() { @@ -45,23 +43,34 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] builds with a context dir }) g.Describe("s2i context directory build", func() { - g.It(fmt.Sprintf("should s2i build an application using a context directory [apigroup:build.openshift.io]"), func() { - + testSourceBuild := func(logsMustMatchRegexp, patch string) { exutil.WaitForOpenShiftNamespaceImageStreams(oc) g.By(fmt.Sprintf("calling oc create -f %q", appFixture)) err := oc.Run("create").Args("-f", appFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) + if patch != "" { + g.By("applying patch to build config for context directory build") + err := oc.Run("patch").Args("bc/"+s2iBuildConfigName, "-p", patch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + g.By("starting a build") - err = oc.Run("start-build").Args(s2iBuildConfigName).Execute() + br, err := exutil.StartBuildAndWait(oc, s2iBuildConfigName) o.Expect(err).NotTo(o.HaveOccurred()) g.By("waiting for build to finish") - err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), s2iBuildName, exutil.CheckBuildSuccess, exutil.CheckBuildFailed, nil) + err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), br.BuildName, exutil.CheckBuildSuccess, exutil.CheckBuildFailed, nil) if err != nil { - exutil.DumpBuildLogs("s2icontext", oc) + exutil.DumpBuildLogs(s2iBuildConfigName, oc) } o.Expect(err).NotTo(o.HaveOccurred()) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } // oc.KubeFramework().WaitForAnEndpoint currently will wait forever; for now, prefacing with our WaitForADeploymentToComplete, // which does have a timeout, since in most cases a failure in the service coming up stems from a failed deployment @@ -95,16 +104,22 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] builds with a context dir out, err := oc.Run("exec").Args(pod.Name, "-c", pod.Spec.Containers[0].Name, "--", "ls", "/opt/app-root/src").Output() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(out).NotTo(o.ContainSubstring("2.3")) + } + g.It(fmt.Sprintf("should s2i build an application using a context directory [apigroup:build.openshift.io]"), func() { + testSourceBuild(buildInDefaultUserNSRegexp, buildInDefaultUserNSPatch("sourceStrategy", 5)) + }) + g.It(fmt.Sprintf("should unprivileged s2i build an application using a context directory [apigroup:build.openshift.io]"), func() { + testSourceBuild(buildInUserNSRegexp, buildInUserNSPatch("sourceStrategy", 5)) }) }) g.Describe("docker context directory build", func() { - g.It(fmt.Sprintf("should docker build an application using a context directory [apigroup:build.openshift.io]"), func() { + testDockerBuild := func(logsMustMatchRegexp, patch string) { g.By("initializing local repo") repo, err := exutil.NewGitRepo("contextdir") o.Expect(err).NotTo(o.HaveOccurred()) defer repo.Remove() - err = repo.AddAndCommit("2.3/Dockerfile", fmt.Sprintf("FROM %s", image.ShellImage())) + err = repo.AddAndCommit("2.3/Dockerfile", fmt.Sprintf("FROM %s\nRUN pwd", image.ShellImage())) o.Expect(err).NotTo(o.HaveOccurred()) exutil.WaitForOpenShiftNamespaceImageStreams(oc) @@ -112,17 +127,35 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] builds with a context dir err = oc.Run("create").Args("-f", appFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) + if patch != "" { + g.By("applying patch to build config for context directory build") + err := oc.Run("patch").Args("bc/"+dockerBuildConfigName, "-p", patch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + g.By("starting a build") - err = oc.Run("start-build").Args(dockerBuildConfigName, "--from-repo", repo.RepoPath).Execute() + br, err := exutil.StartBuildAndWait(oc, dockerBuildConfigName, "--from-repo", repo.RepoPath) o.Expect(err).NotTo(o.HaveOccurred()) // build will fail if we don't use the right context dir because there won't be a dockerfile present. g.By("waiting for build to finish") - err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), dockerBuildName, exutil.CheckBuildSuccess, exutil.CheckBuildFailed, nil) + err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), br.BuildName, exutil.CheckBuildSuccess, exutil.CheckBuildFailed, nil) if err != nil { - exutil.DumpBuildLogs("dockercontext", oc) + exutil.DumpBuildLogs(dockerBuildConfigName, oc) } o.Expect(err).NotTo(o.HaveOccurred()) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + g.It(fmt.Sprintf("should docker build an application using a context directory [apigroup:build.openshift.io]"), func() { + testDockerBuild(buildInDefaultUserNSRegexp, buildInDefaultUserNSPatch("dockerStrategy", 5)) + }) + g.It(fmt.Sprintf("should unprivileged docker build an application using a context directory [apigroup:build.openshift.io]"), func() { + testDockerBuild(buildInUserNSRegexp, buildInUserNSPatch("dockerStrategy", 5)) }) }) }) diff --git a/test/extended/builds/controllers.go b/test/extended/builds/controllers.go index 03bab2192197..b70a90e7fa3c 100644 --- a/test/extended/builds/controllers.go +++ b/test/extended/builds/controllers.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "strings" "time" corev1 "k8s.io/api/core/v1" @@ -40,8 +41,36 @@ const ( // BuildCancelledEventMessage is the message associated with the event registered when build is cancelled. BuildCancelledEventMessage = "Build %s/%s has been cancelled" additionalAllowedRegistriesEnvVar = "ADDITIONAL_ALLOWED_REGISTRIES" + + // buildInUserNSRegexp is a message that the builder will log at level + // 2 or higher if it detects that it's not running with a user + // namespace whose mappings don't match the node's at large. + buildInUserNSRegexp = `Started in kernel user namespace as [0-9]+:[0-9]+ with UID map \[\(0:[^:]*:65536\)] and GID map \[\(0:[^:]*:65536\)]\.` + + // buildInDefaultUserNSRegexp is a message that the builder will log at + // level 2 or higher if it detects that it's running in a user + // namespace whose ID mappings map every possible UID or GID to itself, + // as things are by default on the node + buildInDefaultUserNSRegexp = `Started in node \(default\) kernel user namespace as [0-9]+:[0-9]+\.` + + // buildInUserNSEnvVar is the environment variable and value that we + // use to tell the build controller to ask the node to run the build + // pod with fewer privileges. + buildInUserNSEnvVar = "BUILD_PRIVILEGED=false" ) +func buildInDefaultUserNSPatch(strategyType string, buildLogLevel int) string { + return fmt.Sprintf(`{"spec":{"strategy":{"%s":{"env":[{"name":"BUILD_LOGLEVEL","value":"%d"}]}}}}`, strategyType, buildLogLevel) +} + +func buildInUserNSPatch(strategyType string, buildLogLevel int) string { + envName, envValue, set := strings.Cut(buildInUserNSEnvVar, "=") + if !set { + panic(fmt.Sprintf(`environment variable %q is supposed to have a "=" in it to separate the environment variable's name and its value`, buildInUserNSEnvVar)) + } + return fmt.Sprintf(`{"spec":{"strategy":{"%s":{"env":[{"name":"%s","value":"%s"},{"name":"BUILD_LOGLEVEL","value":"%d"}]}}}}`, strategyType, envName, envValue, buildLogLevel) +} + var ( //TODO: Make these externally configurable diff --git a/test/extended/builds/custom_build.go b/test/extended/builds/custom_build.go index 8f2403a793d2..8dc735ec43f7 100644 --- a/test/extended/builds/custom_build.go +++ b/test/extended/builds/custom_build.go @@ -11,11 +11,22 @@ import ( exutil "github.com/openshift/origin/test/extended/util" ) +const ( + // failedToReadNodeCredsRegexp is the message that we expect the + // builder to log when it can't read the node's pull secrets + failedToReadNodeCredsRegexp = `proceeding without node credentials: open /var/lib/kubelet/config.json: permission denied` + // failedToPullWithoutCredsRegexp is the message that we expect the + // builder to log when it can't pull an image because it doesn't have + // the right credentials to access the registry + failedToPullWithoutCredsRegexp = `Error pulling image ".*": initializing source .*: unable to retrieve auth token: invalid username/password: unauthorized:` +) + var _ = g.Describe("[sig-builds][Feature:Builds] custom build with buildah", func() { defer g.GinkgoRecover() var ( oc = exutil.NewCLIWithPodSecurityLevel("custom-build", admissionapi.LevelBaseline) customBuildAdd = exutil.FixturePath("testdata", "builds", "custom-build") + customBuildAddAnon = exutil.FixturePath("testdata", "builds", "custom-build-anon") customBuildFixture = exutil.FixturePath("testdata", "builds", "test-custom-build.yaml") ) @@ -34,21 +45,75 @@ var _ = g.Describe("[sig-builds][Feature:Builds] custom build with buildah", fun }) g.Describe("being created from new-build", func() { - g.It("should complete build with custom builder image [apigroup:build.openshift.io]", func() { + testCustomBuild := func(customBuilderImageDir, logsMustMatchRegexp, dockerPatch, customPatch string) { g.By("create custom builder image") err := oc.Run("new-build").Args("--binary", "--strategy=docker", "--name=custom-builder-image").Execute() o.Expect(err).NotTo(o.HaveOccurred()) - br, _ := exutil.StartBuildAndWait(oc, "custom-builder-image", fmt.Sprintf("--from-dir=%s", customBuildAdd)) + + if dockerPatch != "" { + g.By("applying patch to build config for creating custom builder image") + err := oc.Run("patch").Args("bc/custom-builder-image", "-p", dockerPatch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + + br, err := exutil.StartBuildAndWait(oc, "custom-builder-image", fmt.Sprintf("--from-dir=%s", customBuilderImageDir)) + o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() - g.By("start custom build and build should complete") + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log for creating the custom builder image included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + + g.By("create build config using custom builder image") err = oc.AsAdmin().Run("create").Args("-f", customBuildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) - err = oc.AsAdmin().Run("start-build").Args("sample-custom-build").Execute() + + if customPatch != "" { + g.By("applying patch to build config using custom builder image") + err = oc.AsAdmin().Run("patch").Args("bc/sample-custom-build", "-p", customPatch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + + g.By("start custom build and build should complete") + br, err = exutil.StartBuildAndWait(oc.AsAdmin(), "sample-custom-build") + o.Expect(err).NotTo(o.HaveOccurred()) - err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), "sample-custom-build"+"-1", nil, nil, nil) + + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + + g.It("should complete build with custom builder image built from base image pulled using node secrets [apigroup:build.openshift.io]", func() { + testCustomBuild(customBuildAdd, buildInDefaultUserNSRegexp, buildInDefaultUserNSPatch("dockerStrategy", 2), buildInDefaultUserNSPatch("customStrategy", 2)) + }) + g.It("should complete unprivileged build with custom builder image built from base image pulled anonymously [apigroup:build.openshift.io]", func() { + testCustomBuild(customBuildAddAnon, buildInUserNSRegexp, buildInUserNSPatch("dockerStrategy", 2), buildInUserNSPatch("customStrategy", 2)) + }) + g.It("should fail to build the custom builder image without node credentials [apigroup:build.openshift.io]", func() { + g.By("create custom builder image") + err := oc.Run("new-build").Args("--binary", "--strategy=docker", "--name=custom-builder-image", "--env", buildInUserNSEnvVar, "--env", "BUILD_LOGLEVEL=2").Execute() o.Expect(err).NotTo(o.HaveOccurred()) + br, err := exutil.StartBuildAndWait(oc, "custom-builder-image", fmt.Sprintf("--from-dir=%s", customBuildAdd)) + o.Expect(err).NotTo(o.HaveOccurred()) + br.AssertFailure() + logsMustMatchRegexps := []string{ + buildInUserNSRegexp, + failedToReadNodeCredsRegexp, + failedToPullWithoutCredsRegexp, + } + for _, logsMustMatchRegexp := range logsMustMatchRegexps { + g.By(fmt.Sprintf("verify that the build log for failing to create the custom builder image included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } }) - }) }) }) diff --git a/test/extended/builds/docker_pullsearch.go b/test/extended/builds/docker_pullsearch.go index cf390de5d056..e11e1aabdffc 100644 --- a/test/extended/builds/docker_pullsearch.go +++ b/test/extended/builds/docker_pullsearch.go @@ -1,6 +1,8 @@ package builds import ( + "fmt" + g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" @@ -31,17 +33,29 @@ var _ = g.Describe("[sig-builds][Feature:Builds][pullsearch] docker build where }) g.Describe("Building from a Dockerfile whose FROM image ref does not specify the image registry", func() { - g.It("should create a docker build that has buildah search from our predefined list of image registries and succeed [apigroup:build.openshift.io]", func() { - + testDockerBuild := func(logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By("creating a BuildConfig whose base image does not have a fully qualified registry name") err := oc.Run("create").Args("-f", buildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build") - br, err := exutil.StartBuildAndWait(oc, "ubi") + br, err := exutil.StartBuildAndWait(oc, append([]string{"ubi"}, startBuildAddArgs...)...) o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + g.It("should create a docker build that can search from our predefined list of image registries and succeed [apigroup:build.openshift.io]", func() { + testDockerBuild(buildInDefaultUserNSRegexp) + }) + + g.It("should create an unprivileged docker build that can still search our predefined list of image registries and shortnames and succeed [apigroup:build.openshift.io]", func() { + testDockerBuild(buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) }) diff --git a/test/extended/builds/docker_pullsecret.go b/test/extended/builds/docker_pullsecret.go index a1e03457e4c3..3d3379e8e0e1 100644 --- a/test/extended/builds/docker_pullsecret.go +++ b/test/extended/builds/docker_pullsecret.go @@ -38,22 +38,42 @@ var _ = g.Describe("[sig-builds][Feature:Builds][pullsecret] docker build using }) g.Describe("Building from a template", func() { - g.It("should create a docker build that pulls using a secret run it [apigroup:build.openshift.io]", func() { - + testDockerBuild := func(logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By(fmt.Sprintf("calling oc create -f %q", buildFixture)) err := oc.Run("create").Args("-f", buildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build") - br, err := exutil.StartBuildAndWait(oc, "docker-build") + br, err := exutil.StartBuildAndWait(oc, append([]string{"docker-build"}, startBuildAddArgs...)...) o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + g.By("starting a second build that pulls the image from the first build") - br, err = exutil.StartBuildAndWait(oc, "docker-build-pull") + br, err = exutil.StartBuildAndWait(oc, append([]string{"docker-build-pull"}, startBuildAddArgs...)...) o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the second build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + + g.It("should create a docker build that pulls using a secret and run it [apigroup:build.openshift.io]", func() { + testDockerBuild(buildInDefaultUserNSRegexp) + }) + + g.It("should create an unprivileged docker build that pulls using a secret and run it [apigroup:build.openshift.io]", func() { + testDockerBuild(buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) }) diff --git a/test/extended/builds/dockerfile.go b/test/extended/builds/dockerfile.go index c952e2ba4ef8..23b7959adaf1 100644 --- a/test/extended/builds/dockerfile.go +++ b/test/extended/builds/dockerfile.go @@ -3,10 +3,12 @@ package builds import ( "context" "fmt" + "strings" g "github.com/onsi/ginkgo/v2" o "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/openshift/api/image/docker10" @@ -33,6 +35,11 @@ USER 1001 FROM scratch USER 1001 ` + testDockerfile4 = fmt.Sprintf(` +FROM %s +USER 1001 +RUN id +`, image.ShellImage()) dockerfileAddEnv = exutil.FixturePath("testdata", "builds", "docker-add", "docker-add-env") ) @@ -159,6 +166,43 @@ USER 1001 o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(logs).ToNot(o.ContainSubstring("/f\": no such file or directory")) }) + + g.It("should be able to build an image with fewer node-level privileges [apigroup:build.openshift.io]", func() { + g.By("calling oc new-build with Dockerfile") + err := oc.Run("new-build").Args("-D", "-", "--to", "dockerfile-unprivileged", "--env", buildInUserNSEnvVar, "--env", "BUILD_LOGLEVEL=2").InputString(testDockerfile4).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("checking the buildconfig contents") + bc, err := oc.BuildClient().BuildV1().BuildConfigs(oc.Namespace()).Get(context.Background(), "dockerfile-unprivileged", metav1.GetOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(bc.Spec.Source.Git).To(o.BeNil()) + o.Expect(*bc.Spec.Source.Dockerfile).To(o.Equal(testDockerfile4)) + o.Expect(bc.Spec.Strategy.DockerStrategy).ToNot(o.BeNil()) + buildInUserNSEnvVarName, buildInUserNSEnvVarValue, ok := strings.Cut(buildInUserNSEnvVar, "=") + o.Expect(ok).To(o.BeTrue()) + buildInUserNSEnvVarAsCoreEnv := corev1.EnvVar{ + Name: buildInUserNSEnvVarName, + Value: buildInUserNSEnvVarValue, + } + o.Expect(bc.Spec.Strategy.DockerStrategy.Env).To(o.ContainElement(buildInUserNSEnvVarAsCoreEnv)) + o.Expect(bc.Spec.Output.To).ToNot(o.BeNil()) + o.Expect(bc.Spec.Output.To.Name).To(o.Equal("dockerfile-unprivileged:latest")) + + buildName := "dockerfile-unprivileged-1" + g.By("waiting for the automatically triggered unprivileged Dockerfile build to finish") + err = exutil.WaitForABuild(oc.BuildClient().BuildV1().Builds(oc.Namespace()), buildName, nil, nil, nil) + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("retrieving build logs for the automatically triggered unprivileged Dockerfile build") + b, err := oc.BuildClient().BuildV1().Builds(oc.Namespace()).Get(context.Background(), buildName, metav1.GetOptions{}) + o.Expect(err).NotTo(o.HaveOccurred()) + br := exutil.NewBuildResult(oc, b) + + g.By("verifying that the automatically triggered unprivileged Dockerfile build ran in a user namespace") + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(buildInUserNSRegexp)) + }) }) }) }) diff --git a/test/extended/builds/gitauth.go b/test/extended/builds/gitauth.go index b2735ec2eee4..8c0db4a31ac1 100644 --- a/test/extended/builds/gitauth.go +++ b/test/extended/builds/gitauth.go @@ -42,17 +42,24 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use private repositor } }) - testGitAuth := func(sourceURL string, sourceSecretName string) { + testGitAuth := func(sourceURL string, sourceSecretName string, logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By(fmt.Sprintf("creating a new BuildConfig to clone source via %s", sourceURL)) err := oc.Run("new-app").Args("-f", testBuildFixture, "-p", fmt.Sprintf("SOURCE_SECRET=%s", sourceSecretName), "-p", fmt.Sprintf("SOURCE_URL=%s", sourceURL)).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a test build and waiting for success") - br, _ := exutil.StartBuildAndWait(oc, buildConfigName) + br, _ := exutil.StartBuildAndWait(oc, append([]string{buildConfigName}, startBuildAddArgs...)...) if !br.BuildSuccess { exutil.DumpBuildLogs(buildConfigName, oc) } br.AssertSuccess() + + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build logs included a message that matched %q", logsMustMatchRegexp)) + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(logsMustMatchRegexp)) + } } g.Describe("build using an HTTP token", func() { @@ -76,7 +83,11 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use private repositor }) g.It("should be able to clone source code via an HTTP token [apigroup:build.openshift.io]", func() { - testGitAuth("https://github.com/openshift-github-testing/nodejs-ex-private.git", "github-http-token") + testGitAuth("https://github.com/openshift-github-testing/nodejs-ex-private.git", "github-http-token", buildInDefaultUserNSRegexp) + }) + + g.It("should be able to clone source code via an HTTP token without privileges [apigroup:build.openshift.io]", func() { + testGitAuth("https://github.com/openshift-github-testing/nodejs-ex-private.git", "github-http-token", buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) @@ -111,11 +122,19 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use private repositor }) g.It("should be able to clone source code via ssh [apigroup:build.openshift.io]", func() { - testGitAuth("ssh://git@github.com/openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey") + testGitAuth("ssh://git@github.com/openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey", buildInDefaultUserNSRegexp) }) g.It("should be able to clone source code via ssh using SCP-style URIs [apigroup:build.openshift.io]", func() { - testGitAuth("git@github.com:openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey") + testGitAuth("git@github.com:openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey", buildInDefaultUserNSRegexp) + }) + + g.It("should be able to clone source code via ssh without privileges [apigroup:build.openshift.io]", func() { + testGitAuth("ssh://git@github.com/openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey", buildInUserNSRegexp, "--env", buildInUserNSEnvVar) + }) + + g.It("should be able to clone source code via ssh using SCP-style URIs without privileges [apigroup:build.openshift.io]", func() { + testGitAuth("git@github.com:openshift-github-testing/nodejs-ex-private.git", "github-ssh-privatekey", buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) }) diff --git a/test/extended/builds/pullsecret.go b/test/extended/builds/pullsecret.go index d258a8755940..acf1be646bc4 100644 --- a/test/extended/builds/pullsecret.go +++ b/test/extended/builds/pullsecret.go @@ -38,10 +38,26 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] using pull secrets in a b g.Describe("binary builds", func() { g.It("should be able to run a build that is implicitly pulling from the internal registry [apigroup:build.openshift.io]", func() { g.By("creating a build") - err := oc.Run("new-build").Args("--binary", "--strategy=docker", "--name=docker").Execute() + err := oc.Run("new-build").Args("--binary", "--strategy=docker", "--name=docker", "--env", "BUILD_LOGLEVEL=2").Execute() o.Expect(err).NotTo(o.HaveOccurred()) - br, err := exutil.StartBuildAndWait(oc, "docker", fmt.Sprintf("--from-dir=%s", exampleBuild)) + br, err := exutil.StartBuildAndWait(oc, "docker", fmt.Sprintf("--from-dir=%s", exampleBuild), "--build-loglevel=2") br.AssertSuccess() + g.By("verifying that the build ran in the node's user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInDefaultUserNSRegexp)) + }) + + g.It("should be able to run an unprivileged build that is implicitly pulling from the internal registry [apigroup:build.openshift.io]", func() { + g.By("creating a build") + err := oc.Run("new-build").Args("--binary", "--strategy=docker", "--name=docker-unprivileged", "--env", "BUILD_LOGLEVEL=2", "--env", buildInUserNSEnvVar).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + br, err := exutil.StartBuildAndWait(oc, "docker-unprivileged", fmt.Sprintf("--from-dir=%s", exampleBuild)) + br.AssertSuccess() + g.By("verifying that the build ran in a user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) }) }) @@ -79,6 +95,24 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] using pull secrets in a b br, err := exutil.StartBuildAndWait(oc, "pullsecret-nodejs", "--build-loglevel=6") o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + g.By("verifying that the build with a pull secret ran in the node's user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInDefaultUserNSRegexp)) + }) + + g.It("should be able to use a pull secret in an unprivileged build [apigroup:build.openshift.io]", func() { + g.By("creating build config") + err := oc.Run("create").Args("-f", pullSecretBuild).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + g.By("starting build with a pull secret") + br, err := exutil.StartBuildAndWait(oc, "pullsecret-nodejs", "--build-loglevel=6", "--env", buildInUserNSEnvVar) + o.Expect(err).NotTo(o.HaveOccurred()) + br.AssertSuccess() + g.By("verifying that the build with a pull secret ran in a user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) }) g.It("should be able to use a pull secret linked to the builder service account [apigroup:build.openshift.io]", func() { @@ -92,6 +126,27 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] using pull secrets in a b br, err := exutil.StartBuildAndWait(oc, "linked-nodejs", "--build-loglevel=6") o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + g.By("verifying that the build ran in the node's user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInDefaultUserNSRegexp)) + }) + + g.It("should be able to use a pull secret linked to the builder service account in an unprivileged build [apigroup:build.openshift.io]", func() { + g.By("linking pull secret with the builder service account") + err := oc.Run("secrets").Args("link", "builder", "local-ps").Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + g.By("creating build config") + err = oc.Run("create").Args("-f", linkedBuild).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + g.By("starting an unprivileged build") + br, err := exutil.StartBuildAndWait(oc, "linked-nodejs", "--build-loglevel=6", "--env", buildInUserNSEnvVar) + o.Expect(err).NotTo(o.HaveOccurred()) + br.AssertSuccess() + g.By("verifying that the unprivileged build ran in a user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) }) }) }) diff --git a/test/extended/builds/run_fs_verification.go b/test/extended/builds/run_fs_verification.go index bc776e450ca9..da2a9034e564 100644 --- a/test/extended/builds/run_fs_verification.go +++ b/test/extended/builds/run_fs_verification.go @@ -144,6 +144,58 @@ valid_fields.json br, err := exutil.StartBuildAndWait(oc, "verify-run-fs") o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() + + g.By("veirfy that the build ran in the node's user namespace") + logs, err := br.LogsNoTimestamp() + o.Expect(logs).To(o.MatchRegexp(buildInDefaultUserNSRegexp)) + }) + }) + + g.Describe("are writeable in unprivileged builds", func() { + g.It("using a simple Docker Strategy Build [apigroup:build.openshift.io]", func() { + g.By("calling oc create with yaml") + err := oc.Run("create").Args("-f", "-").InputString(testVerityRunFSWriteableBuildConfigYaml).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("start and wait for build") + br, err := exutil.StartBuildAndWait(oc, "verify-run-fs", "--env", buildInUserNSEnvVar) + o.Expect(err).NotTo(o.HaveOccurred()) + br.AssertSuccess() + + g.By("verify that the build ran in a user namespace") + logs, err := br.LogsNoTimestamp() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) + }) + }) + + g.Describe("do not have unexpected content in unprivileged builds", func() { + g.It("using a simple Docker Strategy Build [apigroup:build.openshift.io]", func() { + g.By("calling oc create with yaml") + err := oc.Run("create").Args("-f", "-").InputString(testVerifyRunFSContentsBuildConfigYaml).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("start and wait for build") + br, err := exutil.StartBuildAndWait(oc, "verify-run-fs", "--env", buildInUserNSEnvVar) + o.Expect(err).NotTo(o.HaveOccurred()) + br.AssertSuccess() + + g.By("check build logs for ls -R /run/secrets") + logs, err := br.LogsNoTimestamp() + o.Expect(err).NotTo(o.HaveOccurred()) + hasRightListing := false + if strings.Contains(logs, lsRSlashRun) || + strings.Contains(logs, lsRSlashRunFIPS) || + strings.Contains(logs, lsRSlashRunOKD) || + strings.Contains(logs, lsRSlashRunRhel7) { + + hasRightListing = true + } + o.Expect(hasRightListing).To(o.BeTrue()) + + g.By("verify that the build ran in a user namespace") + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) }) }) }) diff --git a/test/extended/builds/s2i_dropcaps.go b/test/extended/builds/s2i_dropcaps.go index a2c092ff0e3c..67616b3a8616 100644 --- a/test/extended/builds/s2i_dropcaps.go +++ b/test/extended/builds/s2i_dropcaps.go @@ -48,6 +48,32 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] Capabilities should be dr g.By("start the root-access-build which attempts root access") br2, _ := exutil.StartBuildAndWait(oc, "root-access-build") br2.AssertFailure() + + g.By("patching the rootable-builder buildconfig to run unprivileged") + err = oc.Run("patch").Args("bc/rootable-ruby", "-p", buildInUserNSPatch("dockerStrategy", 2)).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("starting the unprivileged rootable-ruby build") + br, _ = exutil.StartBuildAndWait(oc, "rootable-ruby", fmt.Sprintf("--from-dir=%s", s2ibuilderFixture)) + br.AssertSuccess() + + g.By("verify that the unprivileged rootable-ruby build ran in a user namespace") + logs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) + + g.By("patching to run unprivileged the buildconfig that tries to gain root access via su") + err = oc.Run("patch").Args("bc/root-access-build", "-p", buildInUserNSPatch("sourceStrategy", 2)).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + + g.By("start the unprivileged root-access-build which attempts root access") + br2, _ = exutil.StartBuildAndWait(oc, "root-access-build") + br2.AssertFailure() + + g.By("verify that the unprivileged root-access-build which attempts root access ran in a user namespace") + logs, err = br2.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(logs).To(o.MatchRegexp(buildInUserNSRegexp)) }) }) }) diff --git a/test/extended/builds/secrets.go b/test/extended/builds/secrets.go index fa4d79e10d84..14e9d4ce5821 100644 --- a/test/extended/builds/secrets.go +++ b/test/extended/builds/secrets.go @@ -2,6 +2,7 @@ package builds import ( "context" + "fmt" "path/filepath" g "github.com/onsi/ginkgo/v2" @@ -61,11 +62,17 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use build secrets", f o.Expect(err).NotTo(o.HaveOccurred()) }) - g.It("should contain secrets during the source strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() { + testSourceBuild := func(logsMustMatchRegexp, patch string) { g.By("creating test build config") err := oc.Run("create").Args("-f", sourceBuildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) + if patch != "" { + g.By("applying patch to build config") + err := oc.Run("patch").Args("bc/test", "-p", patch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + g.By("starting the test source build") br, _ := exutil.StartBuildAndWait(oc, "test", "--from-dir", sourceBuildBinDir) br.AssertSuccess() @@ -90,13 +97,33 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use build secrets", f "testconfig2/red=hat", "testconfig2/this=that", }) + + if logsMustMatchRegexp != "" { + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + + g.It("should contain secrets during the source strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() { + testSourceBuild(buildInDefaultUserNSRegexp, buildInDefaultUserNSPatch("sourceStrategy", 5)) + }) + + g.It("should contain secrets during the unprivileged source strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() { + testSourceBuild(buildInUserNSRegexp, buildInUserNSPatch("sourceStrategy", 5)) }) - g.It("should contain secrets during the docker strategy build", func() { + testDockerBuild := func(logsMustMatchRegexp, patch string) { g.By("creating test build config") err := oc.Run("create").Args("-f", dockerBuildFixture).Execute() o.Expect(err).NotTo(o.HaveOccurred()) + if patch != "" { + g.By("applying patch to build config") + err := oc.Run("patch").Args("bc/test", "-p", patch).Execute() + o.Expect(err).NotTo(o.HaveOccurred()) + } + g.By("starting the test docker build") br, _ := exutil.StartBuildAndWait(oc, "test", "--from-file", dockerBuildDockerfile) br.AssertSuccess() @@ -113,6 +140,21 @@ var _ = g.Describe("[sig-builds][Feature:Builds][Slow] can use build secrets", f "foo=bar", "relative-this=that", }) + + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + buildPodLogs, err := br.Logs() + o.Expect(err).NotTo(o.HaveOccurred()) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } + } + + g.It("should contain secrets during the docker strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() { + testDockerBuild(buildInDefaultUserNSRegexp, buildInDefaultUserNSPatch("dockerStrategy", 2)) + }) + + g.It("should contain secrets during the unprivileged docker strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]", func() { + testDockerBuild(buildInUserNSRegexp, buildInUserNSPatch("dockerStrategy", 2)) }) }) }) diff --git a/test/extended/builds/volumes.go b/test/extended/builds/volumes.go index 0048ccf85818..91a5f44af952 100644 --- a/test/extended/builds/volumes.go +++ b/test/extended/builds/volumes.go @@ -3,6 +3,7 @@ package builds import ( "fmt" "path/filepath" + "strings" "time" g "github.com/onsi/ginkgo/v2" @@ -51,9 +52,20 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() exutil.DumpConfigMapStates(oc) exutil.DumpPodLogsStartingWith("", oc) } + + if strings.Contains(g.CurrentGinkgoTestDescription().TestText, "docker strategy") { + g.By("deleting deployment config and build config") + oc.Run("delete").Args("-f", dockerBuildConfig, "--wait=true").Execute() + oc.Run("delete").Args("-f", dockerDeploymentConfig, "--wait=true").Execute() + } + if strings.Contains(g.CurrentGinkgoTestDescription().TestText, "source strategy") { + g.By("deleting deployment config and build config") + oc.Run("delete").Args("-f", s2iBuildConfig, "--wait=true").Execute() + oc.Run("delete").Args("-f", s2iDeploymentConfig, "--wait=true").Execute() + } }) - g.It("should mount given secrets and configmaps into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild := func(logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By("creating an imagestream") err := oc.Run("create").Args("-f", s2iImageStream).Execute() o.Expect(err).NotTo(o.HaveOccurred()) @@ -63,7 +75,8 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build and waiting for it to complete") - br, _ := exutil.StartBuildAndWait(oc, "mys2itest") + br, err := exutil.StartBuildAndWait(oc, append([]string{"mys2itest"}, startBuildAddArgs...)...) + o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() g.By("ensuring that the build pod logs contain the provided secret and configmap values") @@ -71,6 +84,10 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(buildPodLogs).To(o.ContainSubstring("my-secret-value")) o.Expect(buildPodLogs).To(o.ContainSubstring("my-configmap-value")) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } g.By("creating a deployment config") err = oc.Run("create").Args("-f", s2iDeploymentConfig).Execute() @@ -89,9 +106,9 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() out, err = oc.Run("rsh").Args("dc/mys2itest", "cat", "/var/run/configmaps/some-configmap/key").Output() o.Expect(err).To(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("cat: /var/run/configmaps/some-configmap/key: No such file or directory")) - }) + } - g.It("should mount given secrets and configmaps into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild := func(logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By("creating an imagestream") err := oc.Run("create").Args("-f", dockerImageStream).Execute() o.Expect(err).NotTo(o.HaveOccurred()) @@ -101,7 +118,8 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build and waiting for it to complete") - br, _ := exutil.StartBuildAndWait(oc, "mydockertest") + br, err := exutil.StartBuildAndWait(oc, append([]string{"mydockertest"}, startBuildAddArgs...)...) + o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() g.By("ensuring that the build pod logs contain the provided secret and configmap values") @@ -109,6 +127,10 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(buildPodLogs).To(o.ContainSubstring("my-secret-value")) o.Expect(buildPodLogs).To(o.ContainSubstring("my-configmap-value")) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } g.By("creating a deployment config") err = oc.Run("create").Args("-f", dockerDeploymentConfig).Execute() @@ -127,6 +149,21 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] build volumes", func() out, err = oc.Run("rsh").Args("dc/mydockertest", "cat", "/var/run/configmaps/some-configmap/key").Output() o.Expect(err).To(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("cat: /var/run/configmaps/some-configmap/key: No such file or directory")) + } + g.It("should mount given secrets and configmaps into the build pod for privileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(buildInDefaultUserNSRegexp) + }) + + g.It("should mount given secrets and configmaps into the build pod for privileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild(buildInDefaultUserNSRegexp) + }) + + g.It("should mount given secrets and configmaps into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(buildInUserNSRegexp, "--env", buildInUserNSEnvVar) + }) + + g.It("should mount given secrets and configmaps into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild(buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) }) @@ -147,7 +184,7 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with csiSharedRoleBinding = filepath.Join(baseDir, "csi-sharedresourcerolebinding.yaml") csiS2iBuildConfig = filepath.Join(baseDir, "csi-s2i-buildconfig.yaml") csiDockerBuildConfig = filepath.Join(baseDir, "csi-docker-buildconfig.yaml") - csiWihthoutResourceRefreshS2iBuildConfig = filepath.Join(baseDir, "csi-without-rr-s2i-buildconfig.yaml") + csiWithoutResourceRefreshS2iBuildConfig = filepath.Join(baseDir, "csi-without-rr-s2i-buildconfig.yaml") csiWithoutResourceRefreshDockerBuildConfig = filepath.Join(baseDir, "csi-without-rr-docker-buildconfig.yaml") ) @@ -196,23 +233,28 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with } }) - g.It("should mount given csi shared resource secret into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild := func(buildConfig, logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By("creating an imagestream") err := oc.Run("create").Args("-f", s2iImageStream).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("creating a build config") - err = oc.Run("create").Args("-f", csiS2iBuildConfig).Execute() + err = oc.Run("create").Args("-f", buildConfig).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build and waiting for it to complete") - br, _ := exutil.StartBuildAndWait(oc, "mys2itest") + br, err := exutil.StartBuildAndWait(oc, append([]string{"mys2itest"}, startBuildAddArgs...)...) + o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() g.By("ensuring that the build pod logs contain the provided shared secret") buildPodLogs, err := br.Logs() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(buildPodLogs).To(o.ContainSubstring("my-secret-value")) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } g.By("creating a deployment config") err = oc.Run("create").Args("-f", s2iDeploymentConfig).Execute() @@ -226,6 +268,10 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with out, err := oc.Run("rsh").Args("dc/mys2itest", "cat", "/var/run/secrets/some-secret/key").Output() o.Expect(err).To(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("cat: /var/run/secrets/some-secret/key: No such file or directory")) + } + + g.It("should mount given csi shared resource secret into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(csiS2iBuildConfig, "") }) g.It("should mount given csi shared resource secret without resource refresh into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { @@ -234,7 +280,7 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with o.Expect(err).NotTo(o.HaveOccurred()) g.By("creating a build config") - err = oc.Run("create").Args("-f", csiWihthoutResourceRefreshS2iBuildConfig).Execute() + err = oc.Run("create").Args("-f", csiWithoutResourceRefreshS2iBuildConfig).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build and waiting for it to complete") @@ -260,23 +306,40 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with o.Expect(out).To(o.ContainSubstring("cat: /var/run/secrets/some-secret/key: No such file or directory")) }) - g.It("should mount given csi shared resource secret into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + g.It("should mount given csi shared resource secret without resource refresh into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(csiWithoutResourceRefreshS2iBuildConfig, buildInDefaultUserNSRegexp) + }) + + g.It("should mount given csi shared resource secret into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(csiS2iBuildConfig, buildInUserNSRegexp, "--env", buildInUserNSEnvVar) + }) + + g.It("should mount given csi shared resource secret without resource refresh into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testSourceBuild(csiWithoutResourceRefreshS2iBuildConfig, buildInUserNSRegexp, "--env", buildInUserNSEnvVar) + }) + + testDockerBuild := func(buildConfig, logsMustMatchRegexp string, startBuildAddArgs ...string) { g.By("creating an imagestream") err := oc.Run("create").Args("-f", dockerImageStream).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("creating a build config") - err = oc.Run("create").Args("-f", csiDockerBuildConfig).Execute() + err = oc.Run("create").Args("-f", buildConfig).Execute() o.Expect(err).NotTo(o.HaveOccurred()) g.By("starting a build and waiting for it to complete") - br, _ := exutil.StartBuildAndWait(oc, "mydockertest") + br, err := exutil.StartBuildAndWait(oc, append([]string{"mydockertest"}, startBuildAddArgs...)...) + o.Expect(err).NotTo(o.HaveOccurred()) br.AssertSuccess() g.By("ensuring that the build pod logs contain the provided shared") buildPodLogs, err := br.Logs() o.Expect(err).NotTo(o.HaveOccurred()) o.Expect(buildPodLogs).To(o.ContainSubstring("my-secret-value")) + if logsMustMatchRegexp != "" { + g.By(fmt.Sprintf("verify that the build log included a message that matched %q", logsMustMatchRegexp)) + o.Expect(buildPodLogs).To(o.MatchRegexp(logsMustMatchRegexp)) + } g.By("creating a deployment config") err = oc.Run("create").Args("-f", dockerDeploymentConfig).Execute() @@ -290,38 +353,22 @@ var _ = g.Describe("[sig-builds][Feature:Builds][volumes] csi build volumes with out, err := oc.Run("rsh").Args("dc/mydockertest", "cat", "/var/run/secrets/some-secret/key").Output() o.Expect(err).To(o.HaveOccurred()) o.Expect(out).To(o.ContainSubstring("cat: /var/run/secrets/some-secret/key: No such file or directory")) + } + + g.It("should mount given csi shared resource secret into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild(csiDockerBuildConfig, buildInDefaultUserNSRegexp, "--build-loglevel=2") }) g.It("should mount given csi shared resource secret without resource refresh into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { - g.By("creating an imagestream") - err := oc.Run("create").Args("-f", dockerImageStream).Execute() - o.Expect(err).NotTo(o.HaveOccurred()) - - g.By("creating a build config") - err = oc.Run("create").Args("-f", csiWithoutResourceRefreshDockerBuildConfig).Execute() - o.Expect(err).NotTo(o.HaveOccurred()) - - g.By("starting a build and waiting for it to complete") - br, _ := exutil.StartBuildAndWait(oc, "mydockertest") - br.AssertSuccess() - - g.By("ensuring that the build pod logs contain the provided shared") - buildPodLogs, err := br.Logs() - o.Expect(err).NotTo(o.HaveOccurred()) - o.Expect(buildPodLogs).To(o.ContainSubstring("my-secret-value")) - - g.By("creating a deployment config") - err = oc.Run("create").Args("-f", dockerDeploymentConfig).Execute() - o.Expect(err).NotTo(o.HaveOccurred()) + testDockerBuild(csiWithoutResourceRefreshDockerBuildConfig, buildInDefaultUserNSRegexp, "--build-loglevel=2") + }) - g.By("waiting for the deployment to complete") - _, err = deploymentutil.WaitForDeployerToComplete(oc, "mydockertest-1", 5*time.Minute) - o.Expect(err).NotTo(o.HaveOccurred()) + g.It("should mount given csi shared resource secret into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild(csiDockerBuildConfig, buildInUserNSRegexp, "--env", buildInUserNSEnvVar) + }) - g.By("ensuring that the shared secret does not exist in the build image") - out, err := oc.Run("rsh").Args("dc/mydockertest", "cat", "/var/run/secrets/some-secret/key").Output() - o.Expect(err).To(o.HaveOccurred()) - o.Expect(out).To(o.ContainSubstring("cat: /var/run/secrets/some-secret/key: No such file or directory")) + g.It("should mount given csi shared resource secret without resource refresh into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]", func() { + testDockerBuild(csiWithoutResourceRefreshDockerBuildConfig, buildInUserNSRegexp, "--env", buildInUserNSEnvVar) }) }) }) diff --git a/test/extended/testdata/bindata.go b/test/extended/testdata/bindata.go index 88fe15021aa5..835bba89d56e 100644 --- a/test/extended/testdata/bindata.go +++ b/test/extended/testdata/bindata.go @@ -87,6 +87,9 @@ // test/extended/testdata/builds/custom-build/Dockerfile // test/extended/testdata/builds/custom-build/Dockerfile.sample // test/extended/testdata/builds/custom-build/build.sh +// test/extended/testdata/builds/custom-build-anon/Dockerfile +// test/extended/testdata/builds/custom-build-anon/Dockerfile.sample +// test/extended/testdata/builds/custom-build-anon/build.sh // test/extended/testdata/builds/docker-add/Dockerfile // test/extended/testdata/builds/docker-add/docker-add-env/Dockerfile // test/extended/testdata/builds/docker-add/docker-add-env/foo @@ -18324,10 +18327,31 @@ func testExtendedTestdataBuildsCustomBuildDockerfileSample() (*asset, error) { return a, nil } -var _testExtendedTestdataBuildsCustomBuildBuildSh = []byte(`#!/bin/sh +var _testExtendedTestdataBuildsCustomBuildBuildSh = []byte(`#!/bin/bash set -euo pipefail +# Figure out if we're in a user namespace with non-default ID mappings, and if +# so, output the same diagnostic that the docker-builder does when its log +# level is 2 or higher. +readidmap() { + local idmap + while read host container size ; do + idmap="${idmap:+${idmap},}(${host}:${container}:${size})" + done + echo ["$idmap"] +} + +UIDMAP=$(readidmap < /proc/self/uid_map) +GIDMAP=$(readidmap < /proc/self/gid_map) +if test "${BUILD_LOGLEVEL:-0}" -ge 2; then + if test "$UIDMAP" != '[(0:0:4294967295)]' || test "$GIDMAP" != '[(0:0:4294967295)]' ; then + echo Started in kernel user namespace as $(id -u):$(id -g) with UID map "$UIDMAP" and GID map "$GIDMAP". + else + echo "Started in node (default) kernel user namespace as $(id -u):$(id -g)." + fi +fi + # Note that in this case the build inputs are part of the custom builder image, but normally this # would be retrieved from an external source. cd /tmp/input @@ -18345,7 +18369,6 @@ echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/push/.dockercfg)}" > /tmp buildah --authfile /tmp/.pull --storage-driver vfs bud --isolation chroot -t ${TAG} . # push the new image to the target for the build buildah --authfile /tmp/.push --storage-driver vfs push ${TAG} - `) func testExtendedTestdataBuildsCustomBuildBuildShBytes() ([]byte, error) { @@ -18363,6 +18386,115 @@ func testExtendedTestdataBuildsCustomBuildBuildSh() (*asset, error) { return a, nil } +var _testExtendedTestdataBuildsCustomBuildAnonDockerfile = []byte(`# This base image should be comparable to the base image used by the default +# Dockerfile in ../custom-build, but can be pulled without requiring any +# credentials. Otherwise this Dockerfile should look just like that one. +FROM quay.io/buildah/stable:latest +# For simplicity, /tmp/build contains the inputs we’ll be building when we +# run this custom builder image. Normally the custom builder image would +# fetch this content from some location at build time. (e.g. via git clone). +ADD Dockerfile.sample /tmp/input/Dockerfile +ADD build.sh /usr/bin +RUN chmod a+x /usr/bin/build.sh +# /tmp/build/build.sh contains the actual custom build logic that will be executed when +# this custom builder image is executed. +ENTRYPOINT ["/usr/bin/build.sh"] +`) + +func testExtendedTestdataBuildsCustomBuildAnonDockerfileBytes() ([]byte, error) { + return _testExtendedTestdataBuildsCustomBuildAnonDockerfile, nil +} + +func testExtendedTestdataBuildsCustomBuildAnonDockerfile() (*asset, error) { + bytes, err := testExtendedTestdataBuildsCustomBuildAnonDockerfileBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/builds/custom-build-anon/Dockerfile", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataBuildsCustomBuildAnonDockerfileSample = []byte(`FROM image-registry.openshift-image-registry.svc:5000/openshift/tools:latest +RUN touch /tmp/built +`) + +func testExtendedTestdataBuildsCustomBuildAnonDockerfileSampleBytes() ([]byte, error) { + return _testExtendedTestdataBuildsCustomBuildAnonDockerfileSample, nil +} + +func testExtendedTestdataBuildsCustomBuildAnonDockerfileSample() (*asset, error) { + bytes, err := testExtendedTestdataBuildsCustomBuildAnonDockerfileSampleBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/builds/custom-build-anon/Dockerfile.sample", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _testExtendedTestdataBuildsCustomBuildAnonBuildSh = []byte(`#!/bin/bash + +set -euo pipefail + +# Figure out if we're in a user namespace with non-default ID mappings, and if +# so, output the same diagnostic that the docker-builder does when its log +# level is 2 or higher. +readidmap() { + local idmap + while read host container size ; do + idmap="${idmap:+${idmap},}(${host}:${container}:${size})" + done + echo ["$idmap"] +} + +UIDMAP=$(readidmap < /proc/self/uid_map) +GIDMAP=$(readidmap < /proc/self/gid_map) +if test "${BUILD_LOGLEVEL:-0}" -ge 2; then + if test "$UIDMAP" != '[(0:0:4294967295)]' || test "$GIDMAP" != '[(0:0:4294967295)]' ; then + echo Started in kernel user namespace as $(id -u):$(id -g) with UID map "$UIDMAP" and GID map "$GIDMAP". + else + echo "Started in node (default) kernel user namespace as $(id -u):$(id -g)." + fi +fi + +# Note that in this case the build inputs are part of the custom builder image, but normally this +# would be retrieved from an external source. +cd /tmp/input +# OUTPUT_REGISTRY and OUTPUT_IMAGE are env variables provided by the custom +# build framework +TAG="${OUTPUT_REGISTRY}/${OUTPUT_IMAGE}" + +cp -R /var/run/configs/openshift.io/certs/certs.d/* /etc/containers/certs.d/ + +# buildah requires a slight modification to the push secret provided by the service account in order to use it for pushing the image +echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/pull/.dockercfg)}" > /tmp/.pull +echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/push/.dockercfg)}" > /tmp/.push + +# performs the build of the new image defined by Dockerfile.sample +buildah --authfile /tmp/.pull --storage-driver vfs bud --isolation chroot -t ${TAG} . +# push the new image to the target for the build +buildah --authfile /tmp/.push --storage-driver vfs push ${TAG} + +`) + +func testExtendedTestdataBuildsCustomBuildAnonBuildShBytes() ([]byte, error) { + return _testExtendedTestdataBuildsCustomBuildAnonBuildSh, nil +} + +func testExtendedTestdataBuildsCustomBuildAnonBuildSh() (*asset, error) { + bytes, err := testExtendedTestdataBuildsCustomBuildAnonBuildShBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "test/extended/testdata/builds/custom-build-anon/build.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + var _testExtendedTestdataBuildsDockerAddDockerfile = []byte(`FROM image-registry.openshift-image-registry.svc:5000/openshift/tools:latest ADD no-exist-file . `) @@ -53981,6 +54113,9 @@ var _bindata = map[string]func() (*asset, error){ "test/extended/testdata/builds/custom-build/Dockerfile": testExtendedTestdataBuildsCustomBuildDockerfile, "test/extended/testdata/builds/custom-build/Dockerfile.sample": testExtendedTestdataBuildsCustomBuildDockerfileSample, "test/extended/testdata/builds/custom-build/build.sh": testExtendedTestdataBuildsCustomBuildBuildSh, + "test/extended/testdata/builds/custom-build-anon/Dockerfile": testExtendedTestdataBuildsCustomBuildAnonDockerfile, + "test/extended/testdata/builds/custom-build-anon/Dockerfile.sample": testExtendedTestdataBuildsCustomBuildAnonDockerfileSample, + "test/extended/testdata/builds/custom-build-anon/build.sh": testExtendedTestdataBuildsCustomBuildAnonBuildSh, "test/extended/testdata/builds/docker-add/Dockerfile": testExtendedTestdataBuildsDockerAddDockerfile, "test/extended/testdata/builds/docker-add/docker-add-env/Dockerfile": testExtendedTestdataBuildsDockerAddDockerAddEnvDockerfile, "test/extended/testdata/builds/docker-add/docker-add-env/foo": testExtendedTestdataBuildsDockerAddDockerAddEnvFoo, @@ -54560,6 +54695,11 @@ var _bintree = &bintree{nil, map[string]*bintree{ "Dockerfile.sample": {testExtendedTestdataBuildsCustomBuildDockerfileSample, map[string]*bintree{}}, "build.sh": {testExtendedTestdataBuildsCustomBuildBuildSh, map[string]*bintree{}}, }}, + "custom-build-anon": {nil, map[string]*bintree{ + "Dockerfile": {testExtendedTestdataBuildsCustomBuildAnonDockerfile, map[string]*bintree{}}, + "Dockerfile.sample": {testExtendedTestdataBuildsCustomBuildAnonDockerfileSample, map[string]*bintree{}}, + "build.sh": {testExtendedTestdataBuildsCustomBuildAnonBuildSh, map[string]*bintree{}}, + }}, "docker-add": {nil, map[string]*bintree{ "Dockerfile": {testExtendedTestdataBuildsDockerAddDockerfile, map[string]*bintree{}}, "docker-add-env": {nil, map[string]*bintree{ diff --git a/test/extended/testdata/builds/custom-build-anon/Dockerfile b/test/extended/testdata/builds/custom-build-anon/Dockerfile new file mode 100644 index 000000000000..d086de6f541e --- /dev/null +++ b/test/extended/testdata/builds/custom-build-anon/Dockerfile @@ -0,0 +1,13 @@ +# This base image should be comparable to the base image used by the default +# Dockerfile in ../custom-build, but can be pulled without requiring any +# credentials. Otherwise this Dockerfile should look just like that one. +FROM quay.io/buildah/stable:latest +# For simplicity, /tmp/build contains the inputs we’ll be building when we +# run this custom builder image. Normally the custom builder image would +# fetch this content from some location at build time. (e.g. via git clone). +ADD Dockerfile.sample /tmp/input/Dockerfile +ADD build.sh /usr/bin +RUN chmod a+x /usr/bin/build.sh +# /tmp/build/build.sh contains the actual custom build logic that will be executed when +# this custom builder image is executed. +ENTRYPOINT ["/usr/bin/build.sh"] diff --git a/test/extended/testdata/builds/custom-build-anon/Dockerfile.sample b/test/extended/testdata/builds/custom-build-anon/Dockerfile.sample new file mode 100644 index 000000000000..b4dd5a3a63d3 --- /dev/null +++ b/test/extended/testdata/builds/custom-build-anon/Dockerfile.sample @@ -0,0 +1,2 @@ +FROM image-registry.openshift-image-registry.svc:5000/openshift/tools:latest +RUN touch /tmp/built diff --git a/test/extended/testdata/builds/custom-build-anon/build.sh b/test/extended/testdata/builds/custom-build-anon/build.sh new file mode 100644 index 000000000000..260d038368d7 --- /dev/null +++ b/test/extended/testdata/builds/custom-build-anon/build.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -euo pipefail + +# Figure out if we're in a user namespace with non-default ID mappings, and if +# so, output the same diagnostic that the docker-builder does when its log +# level is 2 or higher. +readidmap() { + local idmap + while read host container size ; do + idmap="${idmap:+${idmap},}(${host}:${container}:${size})" + done + echo ["$idmap"] +} + +UIDMAP=$(readidmap < /proc/self/uid_map) +GIDMAP=$(readidmap < /proc/self/gid_map) +if test "${BUILD_LOGLEVEL:-0}" -ge 2; then + if test "$UIDMAP" != '[(0:0:4294967295)]' || test "$GIDMAP" != '[(0:0:4294967295)]' ; then + echo Started in kernel user namespace as $(id -u):$(id -g) with UID map "$UIDMAP" and GID map "$GIDMAP". + else + echo "Started in node (default) kernel user namespace as $(id -u):$(id -g)." + fi +fi + +# Note that in this case the build inputs are part of the custom builder image, but normally this +# would be retrieved from an external source. +cd /tmp/input +# OUTPUT_REGISTRY and OUTPUT_IMAGE are env variables provided by the custom +# build framework +TAG="${OUTPUT_REGISTRY}/${OUTPUT_IMAGE}" + +cp -R /var/run/configs/openshift.io/certs/certs.d/* /etc/containers/certs.d/ + +# buildah requires a slight modification to the push secret provided by the service account in order to use it for pushing the image +echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/pull/.dockercfg)}" > /tmp/.pull +echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/push/.dockercfg)}" > /tmp/.push + +# performs the build of the new image defined by Dockerfile.sample +buildah --authfile /tmp/.pull --storage-driver vfs bud --isolation chroot -t ${TAG} . +# push the new image to the target for the build +buildah --authfile /tmp/.push --storage-driver vfs push ${TAG} + diff --git a/test/extended/testdata/builds/custom-build/build.sh b/test/extended/testdata/builds/custom-build/build.sh index 9762ed8d3d36..d4782d3152c3 100644 --- a/test/extended/testdata/builds/custom-build/build.sh +++ b/test/extended/testdata/builds/custom-build/build.sh @@ -1,7 +1,28 @@ -#!/bin/sh +#!/bin/bash set -euo pipefail +# Figure out if we're in a user namespace with non-default ID mappings, and if +# so, output the same diagnostic that the docker-builder does when its log +# level is 2 or higher. +readidmap() { + local idmap + while read host container size ; do + idmap="${idmap:+${idmap},}(${host}:${container}:${size})" + done + echo ["$idmap"] +} + +UIDMAP=$(readidmap < /proc/self/uid_map) +GIDMAP=$(readidmap < /proc/self/gid_map) +if test "${BUILD_LOGLEVEL:-0}" -ge 2; then + if test "$UIDMAP" != '[(0:0:4294967295)]' || test "$GIDMAP" != '[(0:0:4294967295)]' ; then + echo Started in kernel user namespace as $(id -u):$(id -g) with UID map "$UIDMAP" and GID map "$GIDMAP". + else + echo "Started in node (default) kernel user namespace as $(id -u):$(id -g)." + fi +fi + # Note that in this case the build inputs are part of the custom builder image, but normally this # would be retrieved from an external source. cd /tmp/input @@ -19,4 +40,3 @@ echo "{ \"auths\": $(cat /var/run/secrets/openshift.io/push/.dockercfg)}" > /tmp buildah --authfile /tmp/.pull --storage-driver vfs bud --isolation chroot -t ${TAG} . # push the new image to the target for the build buildah --authfile /tmp/.push --storage-driver vfs push ${TAG} - diff --git a/test/extended/util/annotate/generated/zz_generated.annotations.go b/test/extended/util/annotate/generated/zz_generated.annotations.go index e96c3af5b8bd..f8be54caef85 100644 --- a/test/extended/util/annotate/generated/zz_generated.annotations.go +++ b/test/extended/util/annotate/generated/zz_generated.annotations.go @@ -383,7 +383,11 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds] buildconfig secret injector should inject secrets to the appropriate buildconfigs [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-builds][Feature:Builds] custom build with buildah being created from new-build should complete build with custom builder image [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds] custom build with buildah being created from new-build should complete build with custom builder image built from base image pulled using node secrets [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds] custom build with buildah being created from new-build should complete unprivileged build with custom builder image built from base image pulled anonymously [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds] custom build with buildah being created from new-build should fail to build the custom builder image without node credentials [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds] imagechangetriggers imagechangetriggers should trigger builds of all types [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", @@ -417,8 +421,12 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds] s2i build with a root user image should create a root build and pass with a privileged SCC [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds] verify /run filesystem contents are writeable in unprivileged builds using a simple Docker Strategy Build [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds] verify /run filesystem contents are writeable using a simple Docker Strategy Build [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds] verify /run filesystem contents do not have unexpected content in unprivileged builds using a simple Docker Strategy Build [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds] verify /run filesystem contents do not have unexpected content using a simple Docker Strategy Build [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][Serial][Slow][Disruptive] alter builds via cluster configuration build config no ocm rollout [apigroup:config.openshift.io] Apply default proxy configuration to docker build pod through env vars [apigroup:build.openshift.io]": "", @@ -447,6 +455,8 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds][Slow] Capabilities should be dropped for s2i builders s2i build with a rootable builder should not be able to switch to root with an assemble script [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] build can have Dockerfile input being created from new-build should be able to build an image with fewer node-level privileges [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] build can have Dockerfile input being created from new-build should be able to start a build from Dockerfile with FROM reference to scratch [apigroup:build.openshift.io]": "", "[sig-builds][Feature:Builds][Slow] build can have Dockerfile input being created from new-build should create a image via new-build [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", @@ -487,18 +497,32 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds][Slow] builds with a context directory docker context directory build should docker build an application using a context directory [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] builds with a context directory docker context directory build should unprivileged docker build an application using a context directory [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] builds with a context directory s2i context directory build should s2i build an application using a context directory [apigroup:build.openshift.io]": "", - "[sig-builds][Feature:Builds][Slow] can use build secrets build with secrets and configMaps should contain secrets during the docker strategy build": "", + "[sig-builds][Feature:Builds][Slow] builds with a context directory s2i context directory build should unprivileged s2i build an application using a context directory [apigroup:build.openshift.io]": "", + + "[sig-builds][Feature:Builds][Slow] can use build secrets build with secrets and configMaps should contain secrets during the docker strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", "[sig-builds][Feature:Builds][Slow] can use build secrets build with secrets and configMaps should contain secrets during the source strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] can use build secrets build with secrets and configMaps should contain secrets during the unprivileged docker strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", + + "[sig-builds][Feature:Builds][Slow] can use build secrets build with secrets and configMaps should contain secrets during the unprivileged source strategy build [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an HTTP token should be able to clone source code via an HTTP token [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an HTTP token should be able to clone source code via an HTTP token without privileges [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an ssh private key should be able to clone source code via ssh [apigroup:build.openshift.io]": "", "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an ssh private key should be able to clone source code via ssh using SCP-style URIs [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an ssh private key should be able to clone source code via ssh using SCP-style URIs without privileges [apigroup:build.openshift.io]": "", + + "[sig-builds][Feature:Builds][Slow] can use private repositories as build input build using an ssh private key should be able to clone source code via ssh without privileges [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] completed builds should have digest of the image in their status Docker build started with log level >5 should save the image digest when finished [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", "[sig-builds][Feature:Builds][Slow] completed builds should have digest of the image in their status Docker build started with normal log level should save the image digest when finished [apigroup:build.openshift.io][apigroup:image.openshift.io]": "", @@ -591,13 +615,23 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context binary builds should be able to run a build that is implicitly pulling from the internal registry [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context binary builds should be able to run an unprivileged build that is implicitly pulling from the internal registry [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context pulling from an external authenticated registry should be able to use a pull secret in a build [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context pulling from an external authenticated registry should be able to use a pull secret in an unprivileged build [apigroup:build.openshift.io]": "", + "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context pulling from an external authenticated registry should be able to use a pull secret linked to the builder service account [apigroup:build.openshift.io]": "", - "[sig-builds][Feature:Builds][pullsearch] docker build where the registry is not specified Building from a Dockerfile whose FROM image ref does not specify the image registry should create a docker build that has buildah search from our predefined list of image registries and succeed [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][Slow] using pull secrets in a build start-build test context pulling from an external authenticated registry should be able to use a pull secret linked to the builder service account in an unprivileged build [apigroup:build.openshift.io]": "", + + "[sig-builds][Feature:Builds][pullsearch] docker build where the registry is not specified Building from a Dockerfile whose FROM image ref does not specify the image registry should create a docker build that can search from our predefined list of image registries and succeed [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-builds][Feature:Builds][pullsecret] docker build using a pull secret Building from a template should create a docker build that pulls using a secret run it [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][pullsearch] docker build where the registry is not specified Building from a Dockerfile whose FROM image ref does not specify the image registry should create an unprivileged docker build that can still search our predefined list of image registries and shortnames and succeed [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][pullsecret] docker build using a pull secret Building from a template should create a docker build that pulls using a secret and run it [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][pullsecret] docker build using a pull secret Building from a template should create an unprivileged docker build that pulls using a secret and run it [apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][timing] capture build stages and durations should record build stages and durations for docker [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", @@ -611,18 +645,30 @@ var Annotations = map[string]string{ "[sig-builds][Feature:Builds][valueFrom] process valueFrom in build strategy environment variables should successfully resolve valueFrom in s2i build environment variables [apigroup:build.openshift.io]": " [Skipped:Disconnected] [Suite:openshift/conformance/parallel]", - "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for privileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for privileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", - "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][volumes] build volumes should mount given secrets and configmaps into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret without resource refresh into the build pod for docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret without resource refresh into the build pod for source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret without resource refresh into the build pod for unprivileged docker strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + + "[sig-builds][Feature:Builds][volumes] csi build volumes within Tech Preview enabled cluster [apigroup:config.openshift.io] should mount given csi shared resource secret without resource refresh into the build pod for unprivileged source strategy builds [apigroup:image.openshift.io][apigroup:build.openshift.io][apigroup:apps.openshift.io]": " [Suite:openshift/conformance/parallel]", + "[sig-builds][Feature:Builds][webhook] TestWebhook [apigroup:build.openshift.io][apigroup:image.openshift.io]": " [Suite:openshift/conformance/parallel]", "[sig-builds][Feature:Builds][webhook] TestWebhookGitHubPing [apigroup:image.openshift.io][apigroup:build.openshift.io]": " [Suite:openshift/conformance/parallel]", diff --git a/test/extended/util/framework.go b/test/extended/util/framework.go index c72666a952f6..d5dbe4ca2a42 100644 --- a/test/extended/util/framework.go +++ b/test/extended/util/framework.go @@ -846,7 +846,7 @@ func (t *BuildResult) Logs() (string, error) { return t.LogDumper(t.Oc, t) } - buildOuput, buildErr, err := t.Oc.Run("logs").Args("-f", t.BuildPath, "--timestamps", "--v", "10").Outputs() + buildOuput, buildErr, err := t.Oc.Run("logs").Args("-f", t.BuildPath, "--all-containers=true", "--timestamps", "--v", "10").Outputs() if err != nil { return "", fmt.Errorf("Error retrieving logs for build %q: (%s) %v", t.BuildName, buildErr, err) }