|
|
@@ -0,0 +1,77 @@ |
|
|
import java.security._ |
|
|
import java.net.URL |
|
|
import javax.net.ssl.{KeyManagerFactory, TrustManagerFactory} |
|
|
import org.apache.http.conn.ssl.SSLSocketFactory |
|
|
import org.apache.http.conn.scheme.Scheme |
|
|
import dispatch._ |
|
|
|
|
|
// Gist trait for doing SSL with mutual certificate exchange using dispatch. |
|
|
// This works without having to set up global JDK-wide keystore and truststore files. |
|
|
// |
|
|
// Assumes the following: |
|
|
// You have the server certificate from the site you are calling and you have created a JKS |
|
|
// format keystore containing this file, which will act as your truststore: |
|
|
// > keytool -import -alias foo -file server.crt -keystore my.truststore |
|
|
// |
|
|
// You have been issued with a client certificate and private key and these have been issued |
|
|
// as a pkcs12 format keystore. |
|
|
// |
|
|
trait SSLCommunications { |
|
|
|
|
|
// Implement these methods to define the keystore and truststore locations and the passwords for each |
|
|
protected val keystoreLocation: String |
|
|
protected val keystorePassword: Array[Char] |
|
|
protected val truststoreLocation: String |
|
|
protected val truststorePassword: Array[Char] |
|
|
|
|
|
// Usage: |
|
|
// val targetUrl = new URL("https://www.example.com/someResource") |
|
|
// val req = url(targetUrl.toString) |
|
|
// Https(targetUrl)(req as_str)) |
|
|
// |
|
|
def Https(targetUrl: URL) = new Http { |
|
|
schemeFor(targetUrl, sslSocketFactory) foreach { scheme => |
|
|
client.getConnectionManager.getSchemeRegistry.register(scheme) |
|
|
} |
|
|
} |
|
|
|
|
|
private val SSLPort = 443 |
|
|
|
|
|
private def schemeFor(url: URL, sslSocketFactory: SSLSocketFactory) = { |
|
|
val port = if ( url.getPort == -1 ) SSLPort else url.getPort |
|
|
|
|
|
if ( url.getProtocol == "https" ) Some(new Scheme("https", port, sslSocketFactory)) else None |
|
|
} |
|
|
|
|
|
private lazy val sslSocketFactory = createSSLSocketFactory |
|
|
|
|
|
private def createSSLSocketFactory = { |
|
|
val sslContext = javax.net.ssl.SSLContext.getInstance("TLS") |
|
|
sslContext.init(keyManagers, trustManagers, new SecureRandom()) |
|
|
new SSLSocketFactory(sslContext) |
|
|
} |
|
|
|
|
|
private def keyManagers = { |
|
|
val factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm) |
|
|
factory.init(populateKeystore("PKCS12", keystoreLocation, keystorePassword), keystorePassword) |
|
|
factory.getKeyManagers |
|
|
} |
|
|
|
|
|
private def trustManagers = { |
|
|
val factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm) |
|
|
factory.init(populateKeystore("JKS", truststoreLocation, truststorePassword)) |
|
|
factory.getTrustManagers |
|
|
} |
|
|
|
|
|
private def populateKeystore(keystoreType: String, location: String, password: Array[Char]) = { |
|
|
val keyStore = KeyStore.getInstance(keystoreType) |
|
|
val is = getClass.getResourceAsStream(location) |
|
|
if ( is == null ) throw new IllegalArgumentException("Unable to load the keystore at the given location: " + location) |
|
|
try { |
|
|
keyStore.load(is, password) |
|
|
} finally { |
|
|
is.close() |
|
|
} |
|
|
keyStore |
|
|
} |
|
|
} |