|
34 | 34 | import com.gargoylesoftware.htmlunit.WebRequest;
|
35 | 35 | import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
|
36 | 36 | import com.gargoylesoftware.htmlunit.html.HtmlElementUtil;
|
| 37 | +import com.gargoylesoftware.htmlunit.html.HtmlFileInput; |
37 | 38 | import com.gargoylesoftware.htmlunit.html.HtmlForm;
|
38 | 39 | import com.gargoylesoftware.htmlunit.html.HtmlPage;
|
39 | 40 | import com.google.common.base.Predicate;
|
|
48 | 49 | import hudson.model.queue.QueueTaskFuture;
|
49 | 50 |
|
50 | 51 |
|
| 52 | +import java.io.File; |
51 | 53 | import java.io.IOException;
|
52 | 54 |
|
53 | 55 | import hudson.security.ACL;
|
54 | 56 | import hudson.security.ACLContext;
|
55 | 57 | import hudson.util.Secret;
|
56 | 58 | import jenkins.model.IdStrategy;
|
| 59 | +import jenkins.model.InterruptedBuildAction; |
57 | 60 | import jenkins.model.Jenkins;
|
58 | 61 | import org.apache.commons.lang.StringUtils;
|
59 | 62 | import org.jenkinsci.plugins.plaincredentials.impl.StringCredentialsImpl;
|
|
63 | 66 | import org.jenkinsci.plugins.workflow.graphanalysis.DepthFirstScanner;
|
64 | 67 | import org.jenkinsci.plugins.workflow.job.WorkflowJob;
|
65 | 68 | import org.jenkinsci.plugins.workflow.job.WorkflowRun;
|
66 |
| -import org.junit.Assert; |
67 | 69 | import org.junit.ClassRule;
|
68 | 70 | import org.junit.Rule;
|
69 | 71 | import org.junit.Test;
|
70 | 72 | import org.jvnet.hudson.test.BuildWatcher;
|
| 73 | +import org.jvnet.hudson.test.FlagRule; |
71 | 74 | import org.jvnet.hudson.test.Issue;
|
72 | 75 | import org.jvnet.hudson.test.JenkinsRule;
|
73 | 76 |
|
|
80 | 83 | import edu.umd.cs.findbugs.annotations.Nullable;
|
81 | 84 | import org.jvnet.hudson.test.recipes.LocalData;
|
82 | 85 |
|
| 86 | +import static org.hamcrest.MatcherAssert.assertThat; |
| 87 | +import static org.hamcrest.Matchers.allOf; |
| 88 | +import static org.hamcrest.Matchers.containsString; |
| 89 | +import static org.hamcrest.Matchers.hasItem; |
| 90 | +import static org.hamcrest.Matchers.instanceOf; |
| 91 | +import static org.hamcrest.Matchers.not; |
| 92 | +import static org.junit.Assert.assertEquals; |
| 93 | +import static org.junit.Assert.assertFalse; |
| 94 | +import static org.junit.Assert.assertTrue; |
| 95 | +import static org.junit.Assert.assertNotNull; |
| 96 | + |
83 | 97 | /**
|
84 | 98 | * @author Kohsuke Kawaguchi
|
85 | 99 | */
|
86 |
| -public class InputStepTest extends Assert { |
| 100 | +public class InputStepTest { |
87 | 101 | @Rule public JenkinsRule j = new JenkinsRule();
|
88 | 102 |
|
89 | 103 | @ClassRule
|
90 | 104 | public static BuildWatcher buildWatcher = new BuildWatcher();
|
91 | 105 |
|
| 106 | + @Rule public FlagRule<String> allowUnsafeParams = FlagRule.systemProperty(InputStepExecution.UNSAFE_PARAMETER_ALLOWED_PROPERTY_NAME, null); |
| 107 | + |
92 | 108 | /**
|
93 | 109 | * Try out a parameter.
|
94 | 110 | */
|
@@ -475,6 +491,59 @@ public void passwordParameters() throws Exception {
|
475 | 491 | j.assertLogContains("Password is mySecret", b);
|
476 | 492 | }
|
477 | 493 |
|
| 494 | + @Issue("SECURITY-2705") |
| 495 | + @Test |
| 496 | + public void fileParameterWithEscapeHatch() throws Exception { |
| 497 | + System.setProperty(InputStepExecution.UNSAFE_PARAMETER_ALLOWED_PROPERTY_NAME, "true"); |
| 498 | + WorkflowJob foo = j.jenkins.createProject(WorkflowJob.class, "foo"); |
| 499 | + foo.setDefinition(new CpsFlowDefinition("node {\n" + |
| 500 | + "input message: 'Please provide a file', parameters: [file('paco.txt')], id: 'Id' \n" + |
| 501 | + " }",true)); |
| 502 | + |
| 503 | + // get the build going, and wait until workflow pauses |
| 504 | + QueueTaskFuture<WorkflowRun> q = foo.scheduleBuild2(0); |
| 505 | + WorkflowRun b = q.waitForStart(); |
| 506 | + j.waitForMessage("Input requested", b); |
| 507 | + |
| 508 | + InputAction action = b.getAction(InputAction.class); |
| 509 | + assertEquals(1, action.getExecutions().size()); |
| 510 | + |
| 511 | + // submit the input, and expect a failure, no need to set any file value as the check we are testing takes |
| 512 | + // place before we try to interact with the file |
| 513 | + JenkinsRule.WebClient wc = j.createWebClient(); |
| 514 | + HtmlPage p = wc.getPage(b, action.getUrlName()); |
| 515 | + HtmlForm f = p.getFormByName("Id"); |
| 516 | + HtmlFileInput fileInput = f.getInputByName("file"); |
| 517 | + fileInput.setValueAttribute("dummy.txt"); |
| 518 | + fileInput.setContentType("text/csv"); |
| 519 | + String currentTime = "Current time " + System.currentTimeMillis(); |
| 520 | + fileInput.setData(currentTime.getBytes()); |
| 521 | + j.submit(f, "proceed"); |
| 522 | + |
| 523 | + j.assertBuildStatus(Result.SUCCESS, j.waitForCompletion(b)); |
| 524 | + assertTrue(new File(b.getRootDir(), "paco.txt").exists()); |
| 525 | + assertThat(JenkinsRule.getLog(b), |
| 526 | + allOf(containsString(InputStepExecution.UNSAFE_PARAMETER_ALLOWED_PROPERTY_NAME), |
| 527 | + containsString("will be removed in a future release"), |
| 528 | + containsString("https://jenkins.io/redirect/plugin/pipeline-input-step/file-parameters"))); |
| 529 | + } |
| 530 | + |
| 531 | + @Issue("SECURITY-2705") |
| 532 | + @Test |
| 533 | + public void fileParameterShouldFailAtRuntime() throws Exception { |
| 534 | + WorkflowJob foo = j.jenkins.createProject(WorkflowJob.class, "foo"); |
| 535 | + foo.setDefinition(new CpsFlowDefinition("input message: 'Please provide a file', parameters: [file('paco.txt')], id: 'Id'",true)); |
| 536 | + |
| 537 | + // get the build going, and wait until workflow pauses |
| 538 | + QueueTaskFuture<WorkflowRun> q = foo.scheduleBuild2(0); |
| 539 | + WorkflowRun b = q.waitForStart(); |
| 540 | + |
| 541 | + j.assertBuildStatus(Result.FAILURE, j.waitForCompletion(b)); |
| 542 | + assertThat(JenkinsRule.getLog(b), |
| 543 | + allOf(not(containsString(InputStepExecution.UNSAFE_PARAMETER_ALLOWED_PROPERTY_NAME)), |
| 544 | + containsString("https://jenkins.io/redirect/plugin/pipeline-input-step/file-parameters"))); |
| 545 | + } |
| 546 | + |
478 | 547 | @LocalData
|
479 | 548 | @Test public void serialForm() throws Exception {
|
480 | 549 | WorkflowJob p = j.jenkins.getItemByFullName("p", WorkflowJob.class);
|
|
0 commit comments