提交 a9385647 编写于 作者: K Kohsuke Kawaguchi

Merge branch 'SECURITY-54'

......@@ -64,6 +64,9 @@ Upcoming changes</a>
<li class=bug>
surefire-reports not detected for android-maven-plugin
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-16776">issue 16776</a>)
<li class=rfe>
JNLP slave installers can now work transparently with secured Jenkins.
(SECURITY-54 / despite the ticket marker, this is not a security vulnerability)
<li class=rfe>
Bundlin JNA 3.5.1 now (up from 3.3.0 + JNA-184)
</ul>
......
......@@ -24,6 +24,7 @@
package hudson.slaves;
import hudson.model.*;
import hudson.util.IOException2;
import hudson.util.IOUtils;
import hudson.util.io.ReopenableRotatingFileOutputStream;
import jenkins.model.Jenkins.MasterComputer;
......@@ -40,12 +41,14 @@ import hudson.AbortException;
import hudson.remoting.Launcher;
import static hudson.slaves.SlaveComputer.LogHolder.SLAVE_LOG_HANDLER;
import hudson.slaves.OfflineCause.ChannelTermination;
import hudson.util.Secret;
import java.io.File;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.security.SecureRandom;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
......@@ -58,6 +61,14 @@ import java.util.concurrent.Future;
import java.security.Security;
import hudson.util.io.ReopenableFileOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.RequestDispatcher;
import jenkins.model.Jenkins;
import jenkins.slaves.JnlpSlaveAgentProtocol;
import org.kohsuke.stapler.StaplerRequest;
......@@ -67,7 +78,11 @@ import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpRedirect;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponseWrapper;
import org.kohsuke.stapler.ResponseImpl;
import org.kohsuke.stapler.WebMethod;
import org.kohsuke.stapler.compression.FilterServletOutputStream;
/**
* {@link Computer} for {@link Slave}s.
......@@ -129,6 +144,9 @@ public class SlaveComputer extends Computer {
return acceptingTasks;
}
/**
* @since 1.498
*/
public String getJnlpMac() {
return JnlpSlaveAgentProtocol.SLAVE_SECRET.mac(getName());
}
......@@ -535,6 +553,43 @@ public class SlaveComputer extends Computer {
return new Slave.JnlpJar(fileName);
}
@WebMethod(name="slave-agent.jnlp")
public void doSlaveAgentJnlp(StaplerRequest req, StaplerResponse res) throws IOException, ServletException {
RequestDispatcher view = req.getView(this, "slave-agent.jnlp.jelly");
if ("true".equals(req.getParameter("encrypt"))) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
StaplerResponse temp = new ResponseImpl(req.getStapler(), new HttpServletResponseWrapper(res) {
@Override public ServletOutputStream getOutputStream() throws IOException {
return new FilterServletOutputStream(baos);
}
@Override public PrintWriter getWriter() throws IOException {
throw new IllegalStateException();
}
});
view.forward(req, temp);
byte[] iv = new byte[128/8];
new SecureRandom().nextBytes(iv);
byte[] jnlpMac = JnlpSlaveAgentProtocol.SLAVE_SECRET.mac(getName().getBytes("UTF-8"));
SecretKey key = new SecretKeySpec(jnlpMac, 0, /* export restrictions */ 128 / 8, "AES");
byte[] encrypted;
try {
Cipher c = Secret.getCipher("AES/CFB8/NoPadding");
c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
encrypted = c.doFinal(baos.toByteArray());
} catch (GeneralSecurityException x) {
throw new IOException2(x);
}
res.setContentType("application/octet-stream");
res.getOutputStream().write(iv);
res.getOutputStream().write(encrypted);
} else {
checkPermission(CONNECT);
view.forward(req, res);
}
}
@Override
protected void kill() {
super.kill();
......
......@@ -3567,6 +3567,8 @@ public class Jenkins extends AbstractCIBase implements ModifiableTopLevelItemGro
|| rest.startsWith("/adjuncts/")
|| rest.startsWith("/signup")
|| rest.startsWith("/tcpSlaveAgentListener")
// XXX SlaveComputer.doSlaveAgentJnlp; there should be an annotation to request unprotected access
|| rest.matches("/computer/.+/slave-agent[.]jnlp") && "true".equals(Stapler.getCurrentRequest().getParameter("encrypt"))
|| rest.startsWith("/cli")
|| rest.startsWith("/federatedLoginService/")
|| rest.startsWith("/securityRealm"))
......
......@@ -65,7 +65,8 @@ THE SOFTWARE.
<p>
${%Run from slave command line:}
</p>
<pre>java -jar <a href="${rootURL}/jnlpJars/slave.jar">slave.jar</a> -jnlpUrl ${h.inferHudsonURL(request)}${it.url}slave-agent.jnlp -jnlpCredentials ${app.authentication.name}:<a href="${rootURL}/user/${app.authentication.name}/configure" target="_blank">your-API-token</a></pre>
<!-- XXX conceal secret w/ JS if possible -->
<pre>java -jar <a href="${rootURL}/jnlpJars/slave.jar">slave.jar</a> -jnlpUrl ${h.inferHudsonURL(request)}${it.url}slave-agent.jnlp -secret ${it.jnlpMac}</pre>
</li>
</j:otherwise>
</j:choose>
......@@ -85,4 +86,4 @@ THE SOFTWARE.
</p>
</j:otherwise>
</j:choose>
</j:jelly>
\ No newline at end of file
</j:jelly>
......@@ -31,8 +31,6 @@ THE SOFTWARE.
<!--
See http://www.dallaway.com/acad/webstart/ for obtaining the certificate.
-->
<j:getStatic var="connect" className="hudson.model.Computer" field="CONNECT"/>
${it.checkPermission(connect)}
<!-- See http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/syntax.html for the syntax -->
<jnlp spec="1.0+"
......
......@@ -187,7 +187,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>remoting</artifactId>
<version>2.21</version>
<version>2.22</version>
</dependency>
<dependency>
......
......@@ -83,7 +83,7 @@ public class JnlpAccessWithSecuredHudsonTest extends HudsonTestCase {
assertTrue(jarResource.getWebResponse().getContentType().toLowerCase(Locale.ENGLISH).startsWith("application/"));
}
// XXX this should be the only part with ANONYMOUS_READONLY
try {
jnlp = (XmlPage) jnlpAgent.goTo("computer/test/slave-agent.jnlp", "application/x-java-jnlp-file");
fail("anonymous users must not be able to get secrets");
......@@ -91,4 +91,7 @@ public class JnlpAccessWithSecuredHudsonTest extends HudsonTestCase {
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, x.getStatusCode());
}
}
// XXX try to use -secret
}
......@@ -117,6 +117,11 @@ THE SOFTWARE.
<artifactId>ssh-cli-auth</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.modules</groupId>
<artifactId>slave-installer</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.modules</groupId>
<artifactId>windows-slave-installer</artifactId>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册