Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-31256] Use credentials in waitForServerToBack #67

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 35 additions & 35 deletions src/main/java/hudson/remoting/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.security.AccessController;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedActionException;
Expand All @@ -42,7 +43,6 @@
import java.util.logging.Level;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.NotThreadSafe;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
Expand Down Expand Up @@ -214,46 +214,15 @@ public void run() {
Throwable firstError=null;
String host=null;
String port=null;
SSLSocketFactory sslSocketFactory = null;
if (candidateCertificates != null && !candidateCertificates.isEmpty()) {
KeyStore keyStore = getCacertsKeyStore();
// load the keystore
keyStore.load(null, null);
int i = 0;
for (X509Certificate c : candidateCertificates) {
keyStore.setCertificateEntry(String.format("alias-%d", i++), c);
}
// prepare the trust manager
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// prepare the SSL context
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustManagerFactory.getTrustManagers(), null);
// now we have our custom socket factory
sslSocketFactory = ctx.getSocketFactory();
}
SSLSocketFactory sslSocketFactory = getSSLSocketFactory();

for (URL url : candidateUrls) {
String s = url.toExternalForm();
if(!s.endsWith("/")) s+='/';
URL salURL = new URL(s+"tcpSlaveAgentListener/");

// find out the TCP port
HttpURLConnection con = (HttpURLConnection)Util.openURLConnection(salURL);
if (con instanceof HttpsURLConnection && sslSocketFactory != null) {
((HttpsURLConnection) con).setSSLSocketFactory(sslSocketFactory);
}
if (credentials != null) {
// TODO /tcpSlaveAgentListener is unprotected so why do we need to pass any credentials?
String encoding = Base64.encode(credentials.getBytes("UTF-8"));
con.setRequestProperty("Authorization", "Basic " + encoding);
}

if (proxyCredentials != null) {
String encoding = Base64.encode(proxyCredentials.getBytes("UTF-8"));
con.setRequestProperty("Proxy-Authorization", "Basic " + encoding);
}
HttpURLConnection con = (HttpURLConnection)Util.openURLConnection(salURL, credentials, proxyCredentials, sslSocketFactory);
try {
try {
con.setConnectTimeout(30000);
Expand Down Expand Up @@ -424,6 +393,12 @@ private Socket connect(String host, String port) throws IOException, Interrupted
private void waitForServerToBack() throws InterruptedException {
Thread t = Thread.currentThread();
String oldName = t.getName();
SSLSocketFactory sslSocketFactory = null;
try {
sslSocketFactory = getSSLSocketFactory();
} catch (Throwable e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is being used in other places of this file. It is not LGTM, but it does not increase the technical debt

events.error(e);
}
try {
int retries=0;
while(true) {
Expand All @@ -435,7 +410,7 @@ private void waitForServerToBack() throws InterruptedException {
retries++;
t.setName(oldName+": trying "+url+" for "+retries+" times");

HttpURLConnection con = (HttpURLConnection) url.openConnection();
HttpURLConnection con = (HttpURLConnection)Util.openURLConnection(url, credentials, proxyCredentials, sslSocketFactory);
con.setConnectTimeout(5000);
con.setReadTimeout(5000);
con.connect();
Expand Down Expand Up @@ -562,6 +537,31 @@ public FileInputStream run() throws Exception {
});
}

private SSLSocketFactory getSSLSocketFactory()
throws PrivilegedActionException, KeyStoreException, NoSuchProviderException, CertificateException,
NoSuchAlgorithmException, IOException, KeyManagementException {
SSLSocketFactory sslSocketFactory = null;
if (candidateCertificates != null && !candidateCertificates.isEmpty()) {
KeyStore keyStore = getCacertsKeyStore();
// load the keystore
keyStore.load(null, null);
int i = 0;
for (X509Certificate c : candidateCertificates) {
keyStore.setCertificateEntry(String.format("alias-%d", i++), c);
}
// prepare the trust manager
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
// prepare the SSL context
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, trustManagerFactory.getTrustManagers(), null);
// now we have our custom socket factory
sslSocketFactory = ctx.getSocketFactory();
}
return sslSocketFactory;
}

/**
* @deprecated Use {@link JnlpProtocol#GREETING_SUCCESS}.
*/
Expand Down
33 changes: 32 additions & 1 deletion src/main/java/hudson/remoting/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import java.util.Iterator;

/**
Expand Down Expand Up @@ -110,8 +112,9 @@ static String indent(String s) {
/**
* Gets URL connection.
* If http_proxy environment variable exists, the connection uses the proxy.
* Credentials can be passed e.g. to support running Jenkins behind a (reverse) proxy requiring authorization
*/
static URLConnection openURLConnection(URL url) throws IOException {
static URLConnection openURLConnection(URL url, String credentials, String proxyCredentials, SSLSocketFactory sslSocketFactory) throws IOException {
String httpProxy = null;
// If http.proxyHost property exists, openConnection() uses it.
if (System.getProperty("http.proxyHost") == null) {
Expand All @@ -131,9 +134,37 @@ static URLConnection openURLConnection(URL url) throws IOException {
} else {
con = url.openConnection();
}
if (credentials != null) {
String encoding = Base64.encode(credentials.getBytes("UTF-8"));
con.setRequestProperty("Authorization", "Basic " + encoding);
}
if (proxyCredentials != null) {
String encoding = Base64.encode(proxyCredentials.getBytes("UTF-8"));
con.setRequestProperty("Proxy-Authorization", "Basic " + encoding);
}
if (con instanceof HttpsURLConnection && sslSocketFactory != null) {
((HttpsURLConnection) con).setSSLSocketFactory(sslSocketFactory);
}
return con;
}

/**
* Gets URL connection.
* If http_proxy environment variable exists, the connection uses the proxy.
* Credentials can be passed e.g. to support running Jenkins behind a (reverse) proxy requiring authorization
*/
static URLConnection openURLConnection(URL url, String credentials, String proxyCredentials) throws IOException {
return openURLConnection(url, credentials, proxyCredentials, null);
}

/**
* Gets URL connection.
* If http_proxy environment variable exists, the connection uses the proxy.
*/
static URLConnection openURLConnection(URL url) throws IOException {
return openURLConnection(url, null, null, null);
}

static InetSocketAddress getResolvedHttpProxyAddress(String host, int port) throws IOException {
InetSocketAddress targetAddress = null;
Iterator<Proxy> proxies = ProxySelector.getDefault().select(URI.create(String.format("http://%s:%d", host, port))).iterator();
Expand Down