Skip to content

Commit

Permalink
[JENKINS-32624] [JENKINS-27152] Use a standardized temporary director…
Browse files Browse the repository at this point in the history
…y when possible.
  • Loading branch information
jglick committed Feb 29, 2016
1 parent c4d2197 commit d2e0f53
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 23 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
package com.cloudbees.jenkins.plugins.sshagent; package com.cloudbees.jenkins.plugins.sshagent;


import hudson.ExtensionPoint; import hudson.ExtensionPoint;
import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.Util;
import hudson.model.TaskListener; import hudson.model.TaskListener;
import javax.annotation.CheckForNull;


/** /**
* Extension point for ssh-agent providers. * Extension point for ssh-agent providers.
Expand All @@ -48,13 +51,25 @@ public abstract class RemoteAgentFactory implements ExtensionPoint {
*/ */
public abstract boolean isSupported(Launcher launcher, TaskListener listener); public abstract boolean isSupported(Launcher launcher, TaskListener listener);


@Deprecated
public RemoteAgent start(Launcher launcher, TaskListener listener) throws Throwable {
return start(launcher, listener, null);
}

/** /**
* Start a ssh-agent on the specified launcher. * Start a ssh-agent on the specified launcher.
* *
* @param launcher the launcher on which to start a ssh-agent. * @param launcher the launcher on which to start a ssh-agent.
* @param listener a listener for any diagnostics. * @param listener a listener for any diagnostics.
* @param temp a temporary directory to use; null if unspecified
* @return the agent. * @return the agent.
* @throws Throwable if the agent cannot be started. * @throws Throwable if the agent cannot be started.
*/ */
public abstract RemoteAgent start(Launcher launcher, TaskListener listener) throws Throwable; public /*abstract*/ RemoteAgent start(Launcher launcher, TaskListener listener, @CheckForNull FilePath temp) throws Throwable {
if (Util.isOverridden(RemoteAgentFactory.class, getClass(), "start", Launcher.class, TaskListener.class)) {
return start(launcher, listener);
} else {
throw new AbstractMethodError("you must implement the start method");
}
}
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import hudson.Extension; import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.Util; import hudson.Util;
import hudson.model.AbstractBuild; import hudson.model.AbstractBuild;
Expand All @@ -56,6 +57,7 @@
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import jenkins.model.Jenkins; import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
Expand Down Expand Up @@ -243,7 +245,7 @@ public Environment setUp(AbstractBuild build, final Launcher launcher, BuildList
private SSHAgentEnvironment createSSHAgentEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener) private SSHAgentEnvironment createSSHAgentEnvironment(AbstractBuild build, Launcher launcher, BuildListener listener)
throws IOException, InterruptedException { throws IOException, InterruptedException {
try { try {
return new SSHAgentEnvironment(launcher, listener); return new SSHAgentEnvironment(launcher, listener, build.getWorkspace());
} catch (IOException e) { } catch (IOException e) {
throw new IOException2(Messages.SSHAgentBuildWrapper_CouldNotStartAgent(), e); throw new IOException2(Messages.SSHAgentBuildWrapper_CouldNotStartAgent(), e);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Expand Down Expand Up @@ -334,6 +336,11 @@ public SSHAgentEnvironment(Launcher launcher, final BuildListener listener,
} }
} }


@Deprecated
public SSHAgentEnvironment(Launcher launcher, final BuildListener listener) throws Throwable {
this(launcher, listener, (FilePath) null);
}

/** /**
* Construct the environment and initialize on the remote node. * Construct the environment and initialize on the remote node.
* *
Expand All @@ -342,15 +349,15 @@ public SSHAgentEnvironment(Launcher launcher, final BuildListener listener,
* @throws Throwable if things go wrong. * @throws Throwable if things go wrong.
* @since 1.9 * @since 1.9
*/ */
public SSHAgentEnvironment(Launcher launcher, final BuildListener listener) throws Throwable { public SSHAgentEnvironment(Launcher launcher, BuildListener listener, @CheckForNull FilePath workspace) throws Throwable {
RemoteAgent agent = null; RemoteAgent agent = null;
listener.getLogger().println("[ssh-agent] Looking for ssh-agent implementation..."); listener.getLogger().println("[ssh-agent] Looking for ssh-agent implementation...");
Map<String, Throwable> faults = new LinkedHashMap<String, Throwable>(); Map<String, Throwable> faults = new LinkedHashMap<String, Throwable>();
for (RemoteAgentFactory factory : Jenkins.getActiveInstance().getExtensionList(RemoteAgentFactory.class)) { for (RemoteAgentFactory factory : Jenkins.getActiveInstance().getExtensionList(RemoteAgentFactory.class)) {
if (factory.isSupported(launcher, listener)) { if (factory.isSupported(launcher, listener)) {
try { try {
listener.getLogger().println("[ssh-agent] " + factory.getDisplayName()); listener.getLogger().println("[ssh-agent] " + factory.getDisplayName());
agent = factory.start(launcher, listener); agent = factory.start(launcher, listener, workspace != null ? SSHAgentStepExecution.tempDir(workspace) : null);
break; break;
} catch (Throwable t) { } catch (Throwable t) {
faults.put(factory.getDisplayName(), t); faults.put(factory.getDisplayName(), t);
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.CredentialsProvider;
import com.google.inject.Inject; import com.google.inject.Inject;
import hudson.EnvVars; import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.model.Run; import hudson.model.Run;
import hudson.model.TaskListener; import hudson.model.TaskListener;
import hudson.slaves.WorkspaceList;
import hudson.util.Secret; import hudson.util.Secret;
import jenkins.model.Jenkins; import jenkins.model.Jenkins;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
Expand All @@ -32,6 +34,9 @@ public class SSHAgentStepExecution extends AbstractStepExecutionImpl {
@StepContextParameter @StepContextParameter
private transient Launcher launcher; private transient Launcher launcher;


@StepContextParameter
private transient FilePath workspace;

@Inject(optional = true) @Inject(optional = true)
private SSHAgentStep step; private SSHAgentStep step;


Expand Down Expand Up @@ -82,6 +87,11 @@ public void onResume() {
} }
} }


// TODO use https://github.com/jenkinsci/jenkins/pull/2066
static FilePath tempDir(FilePath ws) {
return ws.sibling(ws.getName() + System.getProperty(WorkspaceList.class.getName(), "@") + "tmp");
}

private static class Callback extends BodyExecutionCallback { private static class Callback extends BodyExecutionCallback {


private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
Expand Down Expand Up @@ -149,7 +159,7 @@ private void initRemoteAgent() throws IOException {
if (factory.isSupported(launcher, listener)) { if (factory.isSupported(launcher, listener)) {
try { try {
listener.getLogger().println("[ssh-agent] " + factory.getDisplayName()); listener.getLogger().println("[ssh-agent] " + factory.getDisplayName());
agent = factory.start(launcher, listener); agent = factory.start(launcher, listener, tempDir(workspace));
break; break;
} catch (Throwable t) { } catch (Throwable t) {
faults.put(factory.getDisplayName(), t); faults.put(factory.getDisplayName(), t);
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
*/ */
package com.cloudbees.jenkins.plugins.sshagent.jna; package com.cloudbees.jenkins.plugins.sshagent.jna;


import java.security.PublicKey; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.List;
import jnr.enxio.channels.NativeSelectorProvider; import jnr.enxio.channels.NativeSelectorProvider;
import jnr.posix.POSIXFactory; import jnr.posix.POSIXFactory;
import jnr.unixsocket.UnixServerSocket; import jnr.unixsocket.UnixServerSocket;
Expand All @@ -41,12 +40,10 @@
import java.util.Iterator; import java.util.Iterator;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.apache.sshd.common.util.Pair; import javax.annotation.CheckForNull;
import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer;


import static org.apache.sshd.agent.SshAgentConstants.SSH2_AGENTC_REQUEST_IDENTITIES;
import static org.apache.sshd.agent.SshAgentConstants.SSH2_AGENT_IDENTITIES_ANSWER;




/** /**
Expand All @@ -62,13 +59,15 @@ public class AgentServer {
private UnixServerSocket socket; private UnixServerSocket socket;
private Selector selector; private Selector selector;
private volatile boolean selectable = true; private volatile boolean selectable = true;
private final @CheckForNull File temp;


public AgentServer() { public AgentServer(File temp) {
this(new AgentImpl()); this(new AgentImpl(), temp);
} }


public AgentServer(SshAgent agent) { public AgentServer(SshAgent agent, File temp) {
this.agent = agent; this.agent = agent;
this.temp = temp;
} }


public SshAgent getAgent() { public SshAgent getAgent() {
Expand All @@ -87,6 +86,9 @@ public String start() throws Exception {
channel.register(selector, SelectionKey.OP_ACCEPT, new SshAgentServerSocketHandler()); channel.register(selector, SelectionKey.OP_ACCEPT, new SshAgentServerSocketHandler());


POSIXFactory.getPOSIX().chmod(authSocket, 0600); POSIXFactory.getPOSIX().chmod(authSocket, 0600);
if (!new File(authSocket).exists()) {
throw new IllegalStateException("failed to create " + authSocket + " of length " + authSocket.length() + " (check UNIX_PATH_MAX)");
}


thread = new Thread(new AgentSocketAcceptor(), "SSH Agent socket acceptor " + authSocket); thread = new Thread(new AgentSocketAcceptor(), "SSH Agent socket acceptor " + authSocket);
thread.setDaemon(true); thread.setDaemon(true);
Expand Down Expand Up @@ -130,14 +132,22 @@ public void run() {
} }
} }


static String createLocalSocketAddress() throws IOException { @SuppressFBWarnings(value="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", justification="createTempFile will fail anyway if there is a problem with mkdirs")
private String createLocalSocketAddress() throws IOException {
String name; String name;
if (temp != null) {
temp.mkdirs();
}
if (OsUtils.isUNIX()) { if (OsUtils.isUNIX()) {
File socket = File.createTempFile("jenkins", ".jnr"); File socket = File.createTempFile("ssh", "", temp);
if (socket.getAbsolutePath().length() >= /*UNIX_PATH_MAX*/108) {
LOGGER.log(Level.WARNING, "Cannot use {0} due to UNIX_PATH_MAX; falling back to system temp dir", socket);
socket = File.createTempFile("ssh", "");
}
FileUtils.deleteQuietly(socket); FileUtils.deleteQuietly(socket);
name = socket.getAbsolutePath(); name = socket.getAbsolutePath();
} else { } else {
File socket = File.createTempFile("jenkins", ".jnr"); File socket = File.createTempFile("ssh", "", temp);
FileUtils.deleteQuietly(socket); FileUtils.deleteQuietly(socket);
name = "\\\\.\\pipe\\" + socket.getName(); name = "\\\\.\\pipe\\" + socket.getName();
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.cloudbees.jenkins.plugins.sshagent.Messages; import com.cloudbees.jenkins.plugins.sshagent.Messages;
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent; import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent;
import hudson.model.TaskListener; import hudson.model.TaskListener;
import java.io.File;
import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.common.util.SecurityUtils;
import org.bouncycastle.openssl.PEMKeyPair; import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder;
Expand All @@ -38,6 +39,7 @@
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.security.KeyPair; import java.security.KeyPair;
import javax.annotation.CheckForNull;


/** /**
* An implementation that uses Apache SSH to provide the Agent over JNR's UnixSocket implementation. * An implementation that uses Apache SSH to provide the Agent over JNR's UnixSocket implementation.
Expand All @@ -62,9 +64,9 @@ public class JNRRemoteAgent implements RemoteAgent {
* @param listener the listener. * @param listener the listener.
* @throws Exception if the agent could not start. * @throws Exception if the agent could not start.
*/ */
public JNRRemoteAgent(TaskListener listener) throws Exception { public JNRRemoteAgent(TaskListener listener, @CheckForNull File temp) throws Exception {
this.listener = listener; this.listener = listener;
agent = new AgentServer(); agent = new AgentServer(temp);
socket = agent.start(); socket = agent.start();
} }


Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent; import com.cloudbees.jenkins.plugins.sshagent.RemoteAgent;
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory; import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory;
import hudson.Extension; import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.model.TaskListener; import hudson.model.TaskListener;


Expand Down Expand Up @@ -57,8 +58,8 @@ public boolean isSupported(Launcher launcher, final TaskListener listener) {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public RemoteAgent start(Launcher launcher, final TaskListener listener) throws Throwable { public RemoteAgent start(Launcher launcher, final TaskListener listener, FilePath temp) throws Throwable {
return launcher.getChannel().call(new JNRRemoteAgentStarter(listener)); return launcher.getChannel().call(new JNRRemoteAgentStarter(listener, temp != null ? temp.getRemote() : null));
} }


} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@


import hudson.model.TaskListener; import hudson.model.TaskListener;
import hudson.remoting.Channel; import hudson.remoting.Channel;
import java.io.File;
import javax.annotation.CheckForNull;


/** /**
* Callable to start the remote agent. * Callable to start the remote agent.
Expand All @@ -47,20 +49,23 @@ public class JNRRemoteAgentStarter extends MasterToSlaveCallable<RemoteAgent, Th
*/ */
private final TaskListener listener; private final TaskListener listener;


private final @CheckForNull String tempDir;

/** /**
* Constructor. * Constructor.
* *
* @param listener the listener to pass to the agent. * @param listener the listener to pass to the agent.
*/ */
public JNRRemoteAgentStarter(TaskListener listener) { public JNRRemoteAgentStarter(TaskListener listener, String tempDir) {
this.listener = listener; this.listener = listener;
this.tempDir = tempDir;
} }


/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public RemoteAgent call() throws Throwable { public RemoteAgent call() throws Throwable {
final JNRRemoteAgent instance = new JNRRemoteAgent(listener); final JNRRemoteAgent instance = new JNRRemoteAgent(listener, tempDir != null ? new File(tempDir) : null);
final Channel channel = Channel.current(); final Channel channel = Channel.current();
return channel == null ? instance : channel.export(RemoteAgent.class, instance); return channel == null ? instance : channel.export(RemoteAgent.class, instance);
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory; import com.cloudbees.jenkins.plugins.sshagent.RemoteAgentFactory;


import hudson.Extension; import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.model.TaskListener; import hudson.model.TaskListener;


Expand Down Expand Up @@ -64,7 +65,8 @@ public boolean isSupported(Launcher launcher, final TaskListener listener) {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public RemoteAgent start(Launcher launcher, final TaskListener listener) throws Throwable { public RemoteAgent start(Launcher launcher, final TaskListener listener, FilePath temp) throws Throwable {
// TODO temp directory currently ignored
return launcher.getChannel().call(new MinaRemoteAgentStarter(listener)); return launcher.getChannel().call(new MinaRemoteAgentStarter(listener));
} }


Expand Down

0 comments on commit d2e0f53

Please sign in to comment.