-
-
Save abevoelker/a6c87246fe0835fbb24f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment