提交 2492e6d5 编写于 作者: J Jesse Glick 提交者: Oliver Gondža

[JENKINS-36476] Underprivileged users could not use the default value of a...

[JENKINS-36476] Underprivileged users could not use the default value of a password parameter (#2454)

* [FIXED JENKINS-36476] Do not even send the default password in encrypted form; leave the text field blank, and apply the default upon submission.

* [JENKINS-36476] Use a special token, not the empty string, as the marker for the default value.

(cherry picked from commit c31392d1)
上级 90b977ea
......@@ -153,6 +153,7 @@ import org.kohsuke.stapler.jelly.InternationalizedStringExpression.RawHtmlArgume
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import hudson.model.PasswordParameterDefinition;
import hudson.util.RunList;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.CheckForNull;
......@@ -1756,7 +1757,7 @@ public class Functions {
}
return ((Secret) o).getEncryptedValue();
}
if (getIsUnitTest()) {
if (getIsUnitTest() && !o.equals(PasswordParameterDefinition.DEFAULT_VALUE)) {
throw new SecurityException("attempted to render plaintext ‘" + o + "’ in password field; use a getter of type Secret instead");
}
return o.toString();
......
......@@ -31,6 +31,7 @@ import hudson.Extension;
import hudson.util.Secret;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.DoNotUse;
import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* Parameter whose value is a {@link Secret} and is hidden from the UI.
......@@ -40,6 +41,9 @@ import org.kohsuke.accmod.restrictions.DoNotUse;
*/
public class PasswordParameterDefinition extends SimpleParameterDefinition {
@Restricted(NoExternalUse.class)
public static final String DEFAULT_VALUE = "<DEFAULT>";
private Secret defaultValue;
@DataBoundConstructor
......@@ -66,6 +70,9 @@ public class PasswordParameterDefinition extends SimpleParameterDefinition {
@Override
public PasswordParameterValue createValue(StaplerRequest req, JSONObject jo) {
PasswordParameterValue value = req.bindJSON(PasswordParameterValue.class, jo);
if (value.getValue().getPlainText().equals(DEFAULT_VALUE)) {
value = new PasswordParameterValue(getName(), getDefaultValue());
}
value.setDescription(getDescription());
return value;
}
......
......@@ -29,7 +29,7 @@ THE SOFTWARE.
<f:entry title="${it.name}" description="${it.formattedDescription}">
<div name="parameter">
<input type="hidden" name="name" value="${it.name}" />
<f:password name="value" value="${it.defaultValueAsSecret}" />
<f:password name="value" value="${it.DEFAULT_VALUE}"/>
</div>
</f:entry>
</j:jelly>
\ No newline at end of file
......@@ -24,10 +24,18 @@
package hudson.model;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPasswordInput;
import hudson.Launcher;
import java.io.IOException;
import jenkins.model.Jenkins;
import static org.junit.Assert.assertEquals;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.TestBuilder;
public class PasswordParameterDefinitionTest {
......@@ -40,4 +48,52 @@ public class PasswordParameterDefinitionTest {
assertEquals("s3cr3t", ((PasswordParameterDefinition) p.getProperty(ParametersDefinitionProperty.class).getParameterDefinition("p")).getDefaultValue());
}
@Issue("JENKINS-36476")
@Test public void defaultValueAlwaysAvailable() throws Exception {
j.jenkins.setSecurityRealm(j.createDummySecurityRealm());
j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().
grant(Jenkins.ADMINISTER).everywhere().to("admin").
grant(Jenkins.READ, Item.READ, Item.BUILD).everywhere().to("dev"));
FreeStyleProject p = j.createFreeStyleProject();
p.addProperty(new ParametersDefinitionProperty(new PasswordParameterDefinition("secret", "s3cr3t", "")));
p.getBuildersList().add(new TestBuilder() {
@Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
listener.getLogger().println("I heard about a " + build.getEnvironment(listener).get("secret") + "!");
return true;
}
});
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false); // ParametersDefinitionProperty/index.jelly sends a 405 but really it is OK
// Control case: admin can use default value.
j.submit(wc.login("admin").getPage(p, "build?delay=0sec").getFormByName("parameters"));
j.waitUntilNoActivity();
FreeStyleBuild b1 = p.getLastBuild();
assertEquals(1, b1.getNumber());
j.assertLogContains("I heard about a s3cr3t!", j.assertBuildStatusSuccess(b1));
// Another control case: anyone can enter a different value.
HtmlForm form = wc.login("dev").getPage(p, "build?delay=0sec").getFormByName("parameters");
HtmlPasswordInput input = form.getInputByName("value");
input.setText("rumor");
j.submit(form);
j.waitUntilNoActivity();
FreeStyleBuild b2 = p.getLastBuild();
assertEquals(2, b2.getNumber());
j.assertLogContains("I heard about a rumor!", j.assertBuildStatusSuccess(b2));
// Test case: anyone can use default value.
j.submit(wc.login("dev").getPage(p, "build?delay=0sec").getFormByName("parameters"));
j.waitUntilNoActivity();
FreeStyleBuild b3 = p.getLastBuild();
assertEquals(3, b3.getNumber());
j.assertLogContains("I heard about a s3cr3t!", j.assertBuildStatusSuccess(b3));
// Another control case: blank values.
form = wc.login("dev").getPage(p, "build?delay=0sec").getFormByName("parameters");
input = form.getInputByName("value");
input.setText("");
j.submit(form);
j.waitUntilNoActivity();
FreeStyleBuild b4 = p.getLastBuild();
assertEquals(4, b4.getNumber());
j.assertLogContains("I heard about a !", j.assertBuildStatusSuccess(b4));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册