Skip to content

Commit 1a10a53

Browse files
committed
fix SECURITY-2128
1 parent 1cd8fc9 commit 1a10a53

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

splunk-devops-extend/pom.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
<email>xiao.xj@outlook.com</email>
2828
</developer>
2929
</developers>
30-
30+
<properties>
31+
<useBeta>true</useBeta>
32+
</properties>
3133
<dependencies>
3234
<dependency>
3335
<groupId>${project.groupId}</groupId>

splunk-devops-extend/src/main/java/com/splunk/splunkjenkins/console/SplunkTaskListenerFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import edu.umd.cs.findbugs.annotations.CheckForNull;
1414
import edu.umd.cs.findbugs.annotations.NonNull;
15+
1516
import java.io.IOException;
1617
import java.util.concurrent.ExecutionException;
1718
import java.util.logging.Level;
@@ -37,6 +38,14 @@ public SplunkConsoleTaskListenerDecorator load(WorkflowRun key) {
3738
}
3839
});
3940

41+
@Override
42+
/*
43+
data stream is passed to splunk decorator first (it sees data in the last due to decorator behavior)
44+
*/
45+
public boolean isAppliedBeforeMainDecorator() {
46+
return true;
47+
}
48+
4049
@CheckForNull
4150
@Override
4251
public TaskListenerDecorator of(@NonNull FlowExecutionOwner flowExecutionOwner) {

splunk-devops-extend/src/test/java/com/splunk/splunkjenkins/SplunkConsoleTaskListenerDecoratorTest.java

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.splunk.splunkjenkins;
22

33
import com.splunk.splunkjenkins.console.ConsoleRecordCacheUtils;
4+
import hudson.console.LineTransformationOutputStream;
5+
import hudson.model.AbstractBuild;
46
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
57
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
68
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
@@ -10,8 +12,18 @@
1012
import org.junit.Rule;
1113
import org.junit.Test;
1214
import org.jvnet.hudson.test.BuildWatcher;
15+
import org.jvnet.hudson.test.Issue;
1316
import org.jvnet.hudson.test.JenkinsRule;
17+
import org.jvnet.hudson.test.TestExtension;
18+
import org.kohsuke.stapler.DataBoundConstructor;
19+
import org.jenkinsci.plugins.workflow.steps.*;
20+
import hudson.console.ConsoleLogFilter;
1421

22+
import java.io.IOException;
23+
import java.io.OutputStream;
24+
import java.io.Serializable;
25+
import java.util.Collections;
26+
import java.util.Set;
1527
import java.util.UUID;
1628

1729
import static com.splunk.splunkjenkins.SplunkConfigUtil.checkTokenAvailable;
@@ -25,6 +37,8 @@ public class SplunkConsoleTaskListenerDecoratorTest {
2537
String id = UUID.randomUUID().toString();
2638
@Rule
2739
public JenkinsRule r = new JenkinsRule();
40+
private static final String TEST_SECRET = "secret";
41+
private static final String TEST_REPLACEMENT = "xxxx";
2842
private String jobScript = "node{\n" +
2943
" parallel first: {sh \"echo SplunkConsoleTaskListenerDecoratorTest\"},\n" +
3044
" second: {sh \"echo " + id + "\"}\n" +
@@ -57,4 +71,93 @@ public void testSendConsole() throws Exception {
5771
verifySplunkSearchResult("source=" + b1.getUrl() + "console " + id, startTime, 2);
5872
verifySplunkSearchResult("source=" + b1.getUrl() + "console parallel_label=first", startTime, 1);
5973
}
74+
75+
76+
@Issue("SECURITY-2128")
77+
@Test
78+
public void testDataFilter() throws Exception {
79+
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "mask-job");
80+
p.setDefinition(new CpsFlowDefinition("withTestMaskFilter {node {echo 'hello" + TEST_SECRET + "'}}", false));
81+
long startTime = System.currentTimeMillis();
82+
WorkflowRun b1 = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
83+
assertFalse(b1.isBuilding());
84+
String testStr = "hello" + TEST_REPLACEMENT;
85+
r.assertLogContains(testStr, b1);
86+
verifySplunkSearchResult("source=" + b1.getUrl() + "console " + testStr, startTime, 1);
87+
}
88+
89+
/**
90+
* simply replace secret with xxxx
91+
*/
92+
public static final class FilterStep extends Step {
93+
@DataBoundConstructor
94+
public FilterStep() {
95+
}
96+
97+
@Override
98+
public StepExecution start(StepContext context) throws Exception {
99+
return new Execution(context);
100+
}
101+
102+
private static final class Execution extends StepExecution {
103+
private static final long serialVersionUID = 1L;
104+
105+
Execution(StepContext context) {
106+
super(context);
107+
}
108+
109+
@Override
110+
public boolean start() throws Exception {
111+
getContext().newBodyInvoker().withContext(new Filter()).withCallback(BodyExecutionCallback.wrap(getContext())).start();
112+
return false;
113+
}
114+
}
115+
116+
private static final class Filter extends ConsoleLogFilter implements Serializable {
117+
private static final long serialVersionUID = 1L;
118+
119+
@SuppressWarnings("rawtypes")
120+
@Override
121+
public OutputStream decorateLogger(AbstractBuild _ignore, OutputStream logger) throws IOException, InterruptedException {
122+
return new MaskingOutputStream(logger);
123+
}
124+
}
125+
126+
public static class MaskingOutputStream extends LineTransformationOutputStream.Delegating {
127+
128+
129+
protected MaskingOutputStream(OutputStream out) {
130+
super(out);
131+
}
132+
133+
@Override
134+
protected void eol(byte[] b, int len) throws IOException {
135+
if (len < TEST_SECRET.length()) {
136+
out.write(b, 0, len);
137+
return;
138+
}
139+
String content = new String(b, 0, len, "utf-8");
140+
out.write(content.replaceAll(TEST_SECRET, TEST_REPLACEMENT).getBytes());
141+
}
142+
}
143+
144+
@TestExtension
145+
public static final class DescriptorImpl extends StepDescriptor {
146+
@Override
147+
public Set<? extends Class<?>> getRequiredContext() {
148+
return Collections.emptySet();
149+
}
150+
151+
@Override
152+
public String getFunctionName() {
153+
return "withTestMaskFilter";
154+
}
155+
156+
@Override
157+
public boolean takesImplicitBlockArgument() {
158+
return true;
159+
}
160+
}
161+
}
162+
60163
}

0 commit comments

Comments
 (0)