Skip to content

Commit

Permalink
Merge pull request #2 from tobilarscheid/master
Browse files Browse the repository at this point in the history
Fixes JENKINS-39383, JENKINS-37201

Automatically mask credentials from build log
  • Loading branch information
ptierno committed Nov 16, 2016
2 parents b8c7fcb + 2c3ac82 commit 0781c25
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 31 deletions.
@@ -0,0 +1,37 @@
package com.datapipe.jenkins.vault;

import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.AbstractBuild;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.List;

public class MaskingConsoleLogFilter extends ConsoleLogFilter implements Serializable {
private static final long serialVersionUID = 1L;

private final String charsetName;
private List<String> valuesToMask;


public MaskingConsoleLogFilter(final String charsetName, List<String> valuesToMask) {
this.charsetName = charsetName;
this.valuesToMask = valuesToMask;
}

@Override
public OutputStream decorateLogger(AbstractBuild abstractBuild, final OutputStream logger) throws IOException, InterruptedException {
return new LineTransformationOutputStream() {
@Override
protected void eol(byte[] b, int len) throws IOException {
String logEntry = new String(b, 0, len, charsetName);
for (String value : valuesToMask) {
logEntry = logEntry.replace(value, "****");
}
logger.write(logEntry.getBytes(charsetName));
}
};
}
}
44 changes: 21 additions & 23 deletions src/main/java/com/datapipe/jenkins/vault/VaultBuildWrapper.java
Expand Up @@ -23,37 +23,28 @@
*/
package com.datapipe.jenkins.vault;

import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;

import javax.annotation.CheckForNull;

import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.StaplerRequest;

import com.bettercloud.vault.Vault;
import com.bettercloud.vault.VaultConfig;
import com.bettercloud.vault.VaultException;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.*;
import hudson.console.ConsoleLogFilter;
import hudson.model.*;
import hudson.tasks.BuildWrapper;
import hudson.util.Secret;
import jenkins.tasks.SimpleBuildWrapper;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.StaplerRequest;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Sample {@link BuildWrapper}.
Expand All @@ -77,6 +68,7 @@ public class VaultBuildWrapper extends SimpleBuildWrapper {
private String vaultUrl;
private Secret authToken;
private List<VaultSecret> vaultSecrets;
private List<String> valuesToMask = new ArrayList<>();

// Possibly add these later
// private final int openTimeout;
Expand Down Expand Up @@ -157,6 +149,7 @@ public void setUp(Context context, Run<?, ?> build, FilePath workspace,
vault.logical().read(vaultSecret.getPath()).getData();

for (VaultSecretValue value : vaultSecret.getSecretValues()) {
valuesToMask.add(values.get(value.getVaultKey()));
context.env(value.getEnvVar(), values.get(value.getVaultKey()));
}

Expand All @@ -167,6 +160,11 @@ public void setUp(Context context, Run<?, ?> build, FilePath workspace,
}
}

@Override
public ConsoleLogFilter createLoggerDecorator(@Nonnull final Run<?, ?> build) {
return new MaskingConsoleLogFilter(build.getCharset().name(), valuesToMask);
}

/**
* Descriptor for {@link VaultBuildWrapper}. Used as a singleton. The class is marked as public so
* that it can be accessed from views.
Expand Down
Expand Up @@ -2,18 +2,21 @@

import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.CoreMatchers.is;

import java.util.List;
import java.io.Serializable;
import java.util.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.HashMap;
import java.util.regex.Pattern;

import com.bettercloud.vault.Vault;
import com.bettercloud.vault.VaultConfig;
import com.bettercloud.vault.VaultException;

import hudson.Launcher;
import hudson.tasks.Builder;
import org.jvnet.hudson.test.JenkinsRule;

import hudson.model.*;
Expand Down Expand Up @@ -108,14 +111,17 @@ public void testSingleSecret()
this.project.getBuildersList().add(new Shell("echo $envVar1"));

FreeStyleBuild build = this.project.scheduleBuild2(0).get();

String log = FileUtils.readFileToString(build.getLogFile());

assertThat(log, containsString("+ echo value1"));
assertThat(log, containsString("+ echo ****"));
assertThat(log, not(containsString("+ echo value1")));

}

/**
* Tests the {@link VaultBuildWrapper} against multiple {@link VaultSecret}'s
*
*
* @throws ExecutionException
* @throws InterruptedException
* @throws IOException
Expand Down Expand Up @@ -148,13 +154,16 @@ public void testMultipleSecrets()
String log = FileUtils.readFileToString(build.getLogFile());

for (int i = 1; i <= 10; i++) {
assertThat(log, containsString("+ echo value" + i));
assertThat(log, not(containsString("echo value"+i)));
}
//count number of occurences as of http://stackoverflow.com/a/770069
assertThat(log.split("\\+ echo \\*\\*\\*\\*", -1).length-1, is(10));

}

/**
* Utility method to create the test secrets in the vault.
*
*
* @throws VaultException
*/
private static void writeTestSecrets() throws VaultException {
Expand Down

0 comments on commit 0781c25

Please sign in to comment.