Skip to content

Commit b857bd2

Browse files
committed
Add support for system ssh-agent
Support the system ssh-agent (or pageant on windows when using putty) via jsch-agent-proxy. Introduces a new agent function, clj-ssh.ssh/ssh-agent.
1 parent 7c86536 commit b857bd2

File tree

4 files changed

+63
-2
lines changed

4 files changed

+63
-2
lines changed

pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@
9797
<dependency>
9898
<groupId>com.jcraft</groupId>
9999
<artifactId>jsch</artifactId>
100-
<version>0.1.44-1</version>
100+
<version>${jsch.version}</version>
101+
</dependency>
102+
<dependency>
103+
<groupId>jsch-agent-proxy</groupId>
104+
<artifactId>jsch-agent-proxy</artifactId>
105+
<version>0.0.4-SNAPSHOT</version>
101106
</dependency>
102107
<dependency>
103108
<groupId>log4j</groupId>
@@ -149,5 +154,6 @@
149154
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
150155
<clojure.version>1.2.0</clojure.version>
151156
<slingshot.version>0.2.0</slingshot.version>
157+
<jsch.version>0.1.48</jsch.version>
152158
</properties>
153159
</project>

src/clj_ssh/agent.clj

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
(ns clj-ssh.agent
2+
"Agent integration (using jsch-agent-proxy)"
3+
(:require
4+
[clojure.tools.logging :as logging])
5+
(:import
6+
com.jcraft.jsch.JSch
7+
[com.jcraft.jsch.agentproxy
8+
AgentProxyException Connector RemoteIdentityRepository]
9+
[com.jcraft.jsch.agentproxy.connector
10+
PageantConnector SSHAgentConnector]
11+
com.jcraft.jsch.agentproxy.usocket.JNAUSocketFactory))
12+
13+
(defn sock-agent-connector
14+
[]
15+
(when (SSHAgentConnector/isConnectorAvailable)
16+
(try
17+
(let [usf (JNAUSocketFactory.)]
18+
(SSHAgentConnector. usf))
19+
(catch AgentProxyException e
20+
(logging/warnf
21+
e "Failed to load JNA connector, although SSH_AUTH_SOCK is set")))))
22+
23+
(defn pageant-connector
24+
[]
25+
(when (PageantConnector/isConnectorAvailable)
26+
(try
27+
(PageantConnector.)
28+
(catch AgentProxyException e
29+
(logging/warn
30+
e "Failed to load Pageant connector, although running on windows")))))
31+
32+
(defn connect
33+
"Connect the specified jsch object to the system ssh-agent."
34+
[^JSch jsch]
35+
(when-let [connector (or (sock-agent-connector) (pageant-connector))]
36+
(doto jsch
37+
;(.setConfig "PreferredAuthentications" "publickey")
38+
(.setIdentityRepository (RemoteIdentityRepository. connector)))))

src/clj_ssh/ssh.clj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Leiningen (http://github.com/technomancy/leiningen).
3838
3939
Licensed under EPL (http://www.eclipse.org/legal/epl-v10.html)"
4040
(:require
41+
[clj-ssh.agent :as agent]
4142
[clj-ssh.keychain :as keychain]
4243
[clj-ssh.reflect :as reflect]
4344
[clojure.java.io :as io]
@@ -177,6 +178,11 @@ Licensed under EPL (http://www.eclipse.org/legal/epl-v10.html)"
177178
(logging/error "Passphrase required, but none findable."))
178179
(add-identity agent identity))))))
179180

181+
(defn ssh-agent
182+
"Create an agent that uses the system ssh-agent (or paegant on windows)."
183+
[]
184+
(doto (JSch.) (agent/connect)))
185+
180186
(defn create-ssh-agent
181187
"Create an ssh-agent. By default try and add the current user's id_rsa key."
182188
([] (create-ssh-agent true))

test/clj_ssh/ssh_test.clj

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,18 @@ list, Alan Dipert and MeikelBrandmeyer."
137137
(.getBytes (slurp (public-key-path)))
138138
nil)
139139
(is (= 1 (count (.getIdentityNames *ssh-agent*))))
140-
(is (= "name" (first (.getIdentityNames *ssh-agent*)))))))
140+
(is (= "name" (first (.getIdentityNames *ssh-agent*))))))
141+
(testing "ssh-agent"
142+
(with-ssh-agent (ssh-agent)
143+
(let [n (count (.getIdentityNames *ssh-agent*))]
144+
(add-identity
145+
*ssh-agent*
146+
"name"
147+
(.getBytes (slurp (private-key-path)))
148+
(.getBytes (slurp (public-key-path)))
149+
nil)
150+
(is (= (inc n) (count (.getIdentityNames *ssh-agent*)))))
151+
(is (some #(= "name" %) (.getIdentityNames *ssh-agent*))))))
141152

142153
(deftest has-identity?-test
143154
(let [key (private-key-path)]

0 commit comments

Comments
 (0)