package org.jfrog.hudson.pipeline.docker.proxy; import hudson.FilePath; import hudson.model.Node; import hudson.remoting.Callable; import jenkins.model.Jenkins; import net.lightbody.bmp.mitm.PemFileCertificateSource; import net.lightbody.bmp.mitm.TrustSource; import net.lightbody.bmp.mitm.manager.ImpersonatingMitmManager; import org.littleshoot.proxy.HttpProxyServer; import org.littleshoot.proxy.impl.DefaultHttpProxyServer; import java.io.File; import java.io.IOException; import java.io.InvalidClassException; import java.io.Serializable; import java.util.List; import java.util.logging.Logger; /** * Created by romang on 7/10/16. */ public class BuildInfoProxy implements Serializable { private static final long serialVersionUID = 1L; private static HttpProxyServer server = null; private static String agentName; public static void start(int proxyPort, String proxyPublicKey, String proxyPrivateKey, String agentName) { stop(); getLogger().info("Starting Build-Info proxy"); PemFileCertificateSource fileCertificateSource = CertManager.getCertificateSource(proxyPublicKey, proxyPrivateKey); ImpersonatingMitmManager mitmManager = ImpersonatingMitmManager.builder() .rootCertificateSource(fileCertificateSource) .trustSource(TrustSource.defaultTrustSource()) .build(); server = DefaultHttpProxyServer.bootstrap() .withPort(proxyPort) .withAllowLocalOnly(false) .withFiltersSource(new BuildInfoHttpFiltersSource()) .withManInTheMiddle(mitmManager) .withConnectTimeout(0) .start(); getLogger().info("Build-Info proxy certificate public key path: " + proxyPublicKey); getLogger().info("Build-Info proxy certificate private key path: " + proxyPrivateKey); BuildInfoProxy.agentName = agentName; } public static boolean isUp() { return server != null; } public static void stop() { if (server != null) { server.stop(); server = null; } } public static String getAgentName() { return agentName; } public static void stopAll() throws IOException, InterruptedException { stop(); List<Node> nodes = Jenkins.getInstance().getNodes(); for (Node node : nodes) { if (node == null || node.getChannel() == null) { continue; } try { node.getChannel().call(new Callable<Boolean, IOException>() { public Boolean call() throws IOException { BuildInfoProxy.stop(); return true; } }); } catch (InvalidClassException e) { getLogger().warning("Failed stopping Build-Info proxy on agent: '" + node.getDisplayName() + "'. It could be because the agent uses a different JDK than the master. " + e.getMessage()); e.printStackTrace(); } } } public static void startAll(final int port) throws IOException, InterruptedException { File jenkinsHome = new File(Jenkins.getInstance().getRootDir().getPath()); File publicCert = new File(jenkinsHome, CertManager.DEFAULT_RELATIVE_CERT_PATH); File privateCert = new File(jenkinsHome, CertManager.DEFAULT_RELATIVE_KEY_PATH); start(port, publicCert.getPath(), privateCert.getPath(), Jenkins.getInstance().getDisplayName()); List<Node> nodes = Jenkins.getInstance().getNodes(); for (Node node : nodes) { if (node == null || node.getChannel() == null) { continue; } final String agentCertPath = node.getRootPath() + "/" + CertManager.DEFAULT_RELATIVE_CERT_PATH; final String agentKeyPath = node.getRootPath() + "/" + CertManager.DEFAULT_RELATIVE_KEY_PATH; final String agentName = node.getDisplayName(); FilePath remoteCertPath = new FilePath(node.getChannel(), agentCertPath); FilePath localCertPath = new FilePath(publicCert); localCertPath.copyTo(remoteCertPath); FilePath remoteKeyPath = new FilePath(node.getChannel(), agentKeyPath); FilePath localKeyPath = new FilePath(privateCert); localKeyPath.copyTo(remoteKeyPath); try { node.getChannel().call(new Callable<Boolean, IOException>() { public Boolean call() throws IOException { BuildInfoProxy.start(port, agentCertPath, agentKeyPath, agentName); return true; } }); } catch (InvalidClassException e) { getLogger().warning("Failed starting Build-Info proxy on agent: '" + node.getDisplayName() + "'. It could be because the agent uses a different JDK than the master. " + e.getMessage()); e.printStackTrace(); } } } private static Logger getLogger() { return Logger.getLogger(BuildInfoProxy.class.getName()); } }