From b75282facb9f1c9ef11045ceb578f11356db908d Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Thu, 25 Jan 2018 14:10:44 +0100 Subject: [PATCH] Set --user on exec --- .../docker/workflow/WithContainerStep.java | 17 +++++++-- .../docker/workflow/client/DockerClient.java | 2 +- .../workflow/client/WindowsDockerClient.java | 8 +++-- .../workflow/WithContainerStepTest.java | 36 +++++++++++++++++++ .../client/WindowsDockerClientTest.java | 1 + 5 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java index 8c6ccfb1a..a848f9064 100644 --- a/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java +++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/WithContainerStep.java @@ -24,6 +24,7 @@ package org.jenkinsci.plugins.docker.workflow; import com.google.common.base.Optional; +import hudson.util.ArgumentListBuilder; import com.google.inject.Inject; import hudson.AbortException; import hudson.EnvVars; @@ -195,8 +196,9 @@ public Execution() { volumes.put(tmp, tmp); } + final String userId = dockerClient.whoAmI(); String command = launcher.isUnix() ? "cat" : "cmd.exe"; - container = dockerClient.run(env, step.image, step.args, ws, volumes, volumesFromContainers, envReduced, dockerClient.whoAmI(), /* expected to hang until killed */ command); + container = dockerClient.run(env, step.image, step.args, ws, volumes, volumesFromContainers, envReduced, userId, /* expected to hang until killed */ command); final List ps = dockerClient.listProcess(env, container); if (!ps.contains(command)) { listener.error( @@ -209,7 +211,7 @@ public Execution() { DockerFingerprints.addRunFacet(dockerClient.getContainerRecord(env, container), run); ImageAction.add(step.image, run); getContext().newBodyInvoker(). - withContext(BodyInvoker.mergeLauncherDecorators(getContext().get(LauncherDecorator.class), new Decorator(container, envHost, ws, toolName, dockerVersion))). + withContext(BodyInvoker.mergeLauncherDecorators(getContext().get(LauncherDecorator.class), new Decorator(container, envHost, ws, userId, toolName, dockerVersion))). withCallback(new Callback(container, toolName)). start(); return false; @@ -244,17 +246,19 @@ private static class Decorator extends LauncherDecorator implements Serializable private final String container; private final String[] envHost; private final String ws; + private final String user; private final @CheckForNull String toolName; private final boolean hasEnv; private final boolean hasWorkdir; - Decorator(String container, EnvVars envHost, String ws, String toolName, VersionNumber dockerVersion) { + Decorator(String container, EnvVars envHost, String ws, String user, String toolName, VersionNumber dockerVersion) { this.container = container; this.envHost = Util.mapToEnv(envHost); this.ws = ws; this.toolName = toolName; this.hasEnv = dockerVersion != null && dockerVersion.compareTo(new VersionNumber("1.13.0")) >= 0; this.hasWorkdir = dockerVersion != null && dockerVersion.compareTo(new VersionNumber("17.12")) >= 0; + this.user = user; } @Override public Launcher decorate(final Launcher launcher, final Node node) { @@ -266,8 +270,15 @@ private static class Decorator extends LauncherDecorator implements Serializable } catch (InterruptedException x) { throw new IOException(x); } + List prefix = new ArrayList<>(Arrays.asList(executable, "exec")); List masksPrefixList = new ArrayList<>(Arrays.asList(false, false)); + if (user != null) { + prefix.add("-u"); + masksPrefixList.add(false); + prefix.add(user); + masksPrefixList.add(false); + } if (ws != null) { FilePath cwd = starter.pwd(); if (cwd != null) { diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/client/DockerClient.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/client/DockerClient.java index 6562606fb..5230bb15c 100644 --- a/src/main/java/org/jenkinsci/plugins/docker/workflow/client/DockerClient.java +++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/client/DockerClient.java @@ -103,7 +103,7 @@ public DockerClient(@Nonnull Launcher launcher, @CheckForNull Node node, @CheckF * @param command The command to execute in the image container being run. * @return The container ID. */ - public String run(@Nonnull EnvVars launchEnv, @Nonnull String image, @CheckForNull String args, @CheckForNull String workdir, @Nonnull Map volumes, @Nonnull Collection volumesFromContainers, @Nonnull EnvVars containerEnv, @Nonnull String user, @Nonnull String... command) throws IOException, InterruptedException { + public String run(@Nonnull EnvVars launchEnv, @Nonnull String image, @CheckForNull String args, @CheckForNull String workdir, @Nonnull Map volumes, @Nonnull Collection volumesFromContainers, @Nonnull EnvVars containerEnv, @CheckForNull String user, @Nonnull String... command) throws IOException, InterruptedException { ArgumentListBuilder argb = new ArgumentListBuilder(); argb.add("run", "-t", "-d"); diff --git a/src/main/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClient.java b/src/main/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClient.java index 77b117e9d..21a196a5e 100644 --- a/src/main/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClient.java +++ b/src/main/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClient.java @@ -29,12 +29,14 @@ public WindowsDockerClient(@Nonnull Launcher launcher, @CheckForNull Node node, } @Override - public String run(@Nonnull EnvVars launchEnv, @Nonnull String image, @CheckForNull String args, @CheckForNull String workdir, @Nonnull Map volumes, @Nonnull Collection volumesFromContainers, @Nonnull EnvVars containerEnv, @Nonnull String user, @Nonnull String... command) throws IOException, InterruptedException { - ArgumentListBuilder argb = new ArgumentListBuilder("docker", "run", "-d", "-t"); + public String run(@Nonnull EnvVars launchEnv, @Nonnull String image, @CheckForNull String args, @CheckForNull String workdir, @Nonnull Map volumes, @Nonnull Collection volumesFromContainers, @Nonnull EnvVars containerEnv, @CheckForNull String user, boolean detached, @Nonnull String... command) throws IOException, InterruptedException { + ArgumentListBuilder argb = new ArgumentListBuilder("docker", "run", "-t"); + if (detached) { + argb.add("-d"); + } if (args != null) { argb.addTokenized(args); } - if (workdir != null) { argb.add("-w", workdir); } diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java index e0245c236..633de5727 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/WithContainerStepTest.java @@ -243,6 +243,42 @@ public class WithContainerStepTest { }); } + @Test public void withInitAndExecAsUser() throws Exception { + story.addStep(new Statement() { + @Override + public void evaluate() throws Throwable { + DockerTestUtil.assumeDocker(); + WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + p.setDefinition(new CpsFlowDefinition( + "node {" + + " withDockerContainer(args: '-e BUILDER_UID=1000 -e BUILDER_GID=1000 -e BUILDER_USER=jenkins -e BUILDER_GROUP=jenkins -e HOME=/home/jenkins', image: 'dockcross/manylinux-x64') {" + + " sh 'id'\n" + + " }" + + "}", true)); + WorkflowRun b = story.j.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0)); + } + }); + } + + @Test public void withInitAsRootAndExecAsUser() throws Exception { + story.addStep(new Statement() { + @Override + public void evaluate() throws Throwable { + DockerTestUtil.assumeDocker(); + WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "prj"); + p.setDefinition(new CpsFlowDefinition( + "node {\n" + + " withDockerContainer(args: '--user root:root -e BUILDER_UID=1000 -e BUILDER_GID=1000 -e BUILDER_USER=jenkins -e BUILDER_GROUP=jenkins -e HOME=/home/jenkins', image: 'dockcross/manylinux-x64') {\n" + + " sh 'id'\n" + + " }\n" + + "}\n", true)); + WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0).get()); + story.j.assertLogContains("uid=1000", b); + } + }); + } + + @Issue("JENKINS-27152") @Test public void configFile() throws Exception { story.addStep(new Statement() { diff --git a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java index c390e0735..52f278db1 100644 --- a/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java +++ b/src/test/java/org/jenkinsci/plugins/docker/workflow/client/WindowsDockerClientTest.java @@ -39,6 +39,7 @@ public void test_run() throws IOException, InterruptedException { Collections.emptyList(), new EnvVars(), dockerClient.whoAmI(), + true, "cat"); Assert.assertEquals(64, containerId.length());