Skip to content

Commit

Permalink
[FIXED JENKINS-27486] Mask passwords accidentally sent to log.
Browse files Browse the repository at this point in the history
  • Loading branch information
jglick committed Mar 30, 2015
1 parent 6673cd9 commit 9d48a10
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 9 deletions.
10 changes: 5 additions & 5 deletions pom.xml
Expand Up @@ -18,7 +18,7 @@
</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/Credentials+Binding+Plugin</url>
<properties>
<workflow.version>1.5-SNAPSHOT</workflow.version> <!-- TODO SecretPickle-JENKINS-27631 @ 05916afaa456187a5618b36c64aa6b45ce4d4ae5 -->
<workflow.version>1.5-SNAPSHOT</workflow.version> <!-- TODO ConsoleLogFilter-JENKINS-27392 @ 38cd1ea642bd45e45331e89c8cef7ffb8e3740fa -->
</properties>
<licenses>
<license>
Expand Down Expand Up @@ -61,25 +61,25 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>1.5-20150330.224744-3</version>
<version>1.5-20150330.234604-4</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-aggregator</artifactId>
<version>1.5-20150330.224936-3</version>
<version>1.5-20150330.234758-4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>1.5-20150330.224744-3</version>
<version>1.5-20150330.234604-4</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>1.5-20150330.224810-3</version>
<version>1.5-20150330.234631-4</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
Expand Down
Expand Up @@ -29,14 +29,22 @@
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.AbstractBuild;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.Secret;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.jenkinsci.plugins.credentialsbinding.MultiBinding;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepExecutionImpl;
Expand Down Expand Up @@ -81,7 +89,7 @@ public static final class Execution extends AbstractStepExecutionImpl {
unbinders.add(environment.getUnbinder());
overrides.putAll(environment.getValues());
}
getContext().newBodyInvoker().withContext(new Overrider(overrides)).withCallback(new Callback(unbinders)).start();
getContext().newBodyInvoker().withContexts(new Overrider(overrides), new Filter(overrides.values())).withCallback(new Callback(unbinders)).start();
return false;
}

Expand Down Expand Up @@ -111,6 +119,41 @@ private static final class Overrider extends EnvironmentExpander {

}

/** Similar to {@code MaskPasswordsOutputStream}. */
private static final class Filter extends ConsoleLogFilter implements Serializable {

private static final long serialVersionUID = 1;

private final Secret pattern;

Filter(Collection<String> secrets) {
StringBuilder b = new StringBuilder();
for (String secret : secrets) {
if (b.length() > 0) {
b.append('|');
}
b.append(Pattern.quote(secret));
}
pattern = Secret.fromString(b.toString());
}

@Override public OutputStream decorateLogger(AbstractBuild _ignore, final OutputStream logger) throws IOException, InterruptedException {
final Pattern p = Pattern.compile(pattern.getPlainText());
return new LineTransformationOutputStream() {
@Override protected void eol(byte[] b, int len) throws IOException {
Matcher m = p.matcher(new String(b, 0, len));
if (m.find()) {
logger.write(m.replaceAll("****").getBytes());
} else {
// Avoid byte → char → byte conversion unless we are actually doing something.
logger.write(b, 0, len);
}
}
};
}

}

private static final class Callback extends BodyExecutionCallback {

private static final long serialVersionUID = 1;
Expand Down
Expand Up @@ -53,7 +53,6 @@
import org.jenkinsci.plugins.workflow.steps.StepConfigTester;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import static org.junit.Assert.*;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
Expand Down Expand Up @@ -219,7 +218,6 @@ public class BindingStepTest {
});
}

@Ignore("TODO reproduced")
@Issue("JENKINS-27486")
@Test public void masking() {
story.addStep(new Statement() {
Expand All @@ -235,7 +233,9 @@ public class BindingStepTest {
+ " sh 'echo $SECRET > oops'\n"
+ " }\n"
+ "}", true));
story.j.assertLogNotContains(secret, story.j.assertBuildStatusSuccess(p.scheduleBuild2(0).get()));
WorkflowRun b = story.j.assertBuildStatusSuccess(p.scheduleBuild2(0).get());
story.j.assertLogNotContains(secret, b);
story.j.assertLogContains("echo ****", b);
}
});
}
Expand Down

0 comments on commit 9d48a10

Please sign in to comment.