Merged in mnesbit-https-support (pull request #306)

Add switchable HTTPS to Node web server
This commit is contained in:
Matthew Nesbit 2016-08-30 13:18:06 +01:00
commit eee765237e
8 changed files with 56 additions and 9 deletions

View File

@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICCjCCAbCgAwIBAgIINo1Qd4LJ1RUwCgYIKoZIzj0EAwIwWDEbMBkGA1UEAwwS
Q29yZGEgTm9kZSBSb290IENBMQswCQYDVQQKDAJSMzEOMAwGA1UECwwFY29yZGEx
DzANBgNVBAcMBkxvbmRvbjELMAkGA1UEBhMCVUswHhcNMTYwNzE5MDAwMDAwWhcN
MjYwNzE3MDAwMDAwWjBYMRswGQYDVQQDDBJDb3JkYSBOb2RlIFJvb3QgQ0ExCzAJ
BgNVBAoMAlIzMQ4wDAYDVQQLDAVjb3JkYTEPMA0GA1UEBwwGTG9uZG9uMQswCQYD
VQQGEwJVSzBWMBAGByqGSM49AgEGBSuBBAAKA0IABHtaVzCVCvNqp+Jhy5/hC25h
yHomwW5gJpNCPUdgVpLnSUXm+NRzf0ia+1SevkaEPSf5kzk47K1Po6KBWVTPbUaj
ZzBlMB0GA1UdDgQWBBSNU2aUShmUQCadxpzs+WWMQTSMJTASBgNVHRMBAf8ECDAG
AQH/AgECMAsGA1UdDwQEAwIBtjAjBgNVHSUEHDAaBggrBgEFBQcDAQYIKwYBBQUH
AwIGBFUdJQAwCgYIKoZIzj0EAwIDSAAwRQIgaHrsbm0ZZ5uFXCfntTcDddJmttiX
IXi6aN7mIIsl/5kCIQC4RCyclxoeZD/TaraTDzOVeSaooxLA/SrwQMzd0pxCcg==
-----END CERTIFICATE-----

View File

@ -12,3 +12,4 @@ mapService : {
address : "localhost:12345",
identity : "Notary Service"
}
useHTTPS : false

View File

@ -12,3 +12,4 @@ mapService : {
address : "localhost:12345",
identity : "Notary Service"
}
useHTTPS : false

View File

@ -11,4 +11,5 @@ mapService : {
hostServiceLocally : true,
address : ${artemisAddress},
identity : ${myLegalName}
}
}
useHTTPS : false

View File

@ -36,7 +36,9 @@ object X509Utilities {
val SIGNATURE_ALGORITHM = "SHA256withECDSA"
val KEY_GENERATION_ALGORITHM = "ECDSA"
val ECDSA_CURVE = "secp256k1" // TLS implementations only support standard SEC2 curves, although internally Corda uses newer EDDSA keys
// TLS implementations only support standard SEC2 curves, although internally Corda uses newer EDDSA keys.
// Also browsers like Chrome don't seem to support the secp256k1, only the secp256r1 curve.
val ECDSA_CURVE = "secp256r1"
val KEYSTORE_TYPE = "JKS"
val CA_CERT_ALIAS = "CA Cert"

View File

@ -9,6 +9,7 @@ import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.utilities.loggerFor
import com.r3corda.node.serialization.NodeClock
import com.r3corda.node.services.api.MessagingServiceInternal
import com.r3corda.node.services.config.FullNodeConfiguration
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.messaging.ArtemisMessagingClient
import com.r3corda.node.services.messaging.ArtemisMessagingServer
@ -17,11 +18,12 @@ import com.r3corda.node.servlets.Config
import com.r3corda.node.servlets.DataUploadServlet
import com.r3corda.node.servlets.ResponseFilter
import com.r3corda.node.utilities.AffinityExecutor
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.server.*
import org.eclipse.jetty.server.handler.HandlerCollection
import org.eclipse.jetty.servlet.DefaultServlet
import org.eclipse.jetty.servlet.ServletContextHandler
import org.eclipse.jetty.servlet.ServletHolder
import org.eclipse.jetty.util.ssl.SslContextFactory
import org.eclipse.jetty.webapp.WebAppContext
import org.glassfish.jersey.server.ResourceConfig
import org.glassfish.jersey.server.ServerProperties
@ -117,9 +119,7 @@ class Node(dir: Path, val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
}()
if (networkMapService != null) {
return ArtemisMessagingClient(dir, configuration, serverAddr, services.storageService.myLegalIdentityKey.public, serverThread)
}
else
{
} else {
return ArtemisMessagingClient(dir, configuration, serverAddr, null, serverThread)
}
}
@ -141,8 +141,6 @@ class Node(dir: Path, val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
private fun initWebServer(): Server {
// Note that the web server handlers will all run concurrently, and not on the node thread.
val server = Server(InetSocketAddress(webServerAddr.hostText, webServerAddr.port))
val handlerCollection = HandlerCollection()
// Export JMX monitoring statistics and data over REST/JSON.
@ -159,6 +157,35 @@ class Node(dir: Path, val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
// API, data upload and download to services (attachments, rates oracles etc)
handlerCollection.addHandler(buildServletContextHandler())
val server = Server()
if (configuration is FullNodeConfiguration && configuration.useHTTPS) {
val httpsConfiguration = HttpConfiguration()
httpsConfiguration.outputBufferSize = 32768
httpsConfiguration.addCustomizer(SecureRequestCustomizer())
val sslContextFactory = SslContextFactory()
val keyStorePath = dir.resolve("certificates").resolve("sslkeystore.jks")
val trustStorePath = dir.resolve("certificates").resolve("truststore.jks")
sslContextFactory.setKeyStorePath(keyStorePath.toString())
sslContextFactory.setKeyStorePassword(configuration.keyStorePassword)
sslContextFactory.setKeyManagerPassword(configuration.keyStorePassword)
sslContextFactory.setTrustStorePath(trustStorePath.toString())
sslContextFactory.setTrustStorePassword(configuration.trustStorePassword)
sslContextFactory.setExcludeProtocols("SSL.*", "TLSv1", "TLSv1.1")
sslContextFactory.setIncludeProtocols("TLSv1.2")
sslContextFactory.setExcludeCipherSuites(".*NULL.*", ".*RC4.*", ".*MD5.*", ".*DES.*", ".*DSS.*")
sslContextFactory.setIncludeCipherSuites(".*AES.*GCM.*")
val sslConnector = ServerConnector(server, SslConnectionFactory(sslContextFactory, "http/1.1"), HttpConnectionFactory(httpsConfiguration))
sslConnector.port = webServerAddr.port
server.connectors = arrayOf<Connector>(sslConnector)
} else {
val httpConfiguration = HttpConfiguration()
httpConfiguration.outputBufferSize = 32768
val httpConnector = ServerConnector(server, HttpConnectionFactory(httpConfiguration))
httpConnector.port = webServerAddr.port
server.connectors = arrayOf<Connector>(httpConnector)
}
server.handler = handlerCollection
server.start()
return server

View File

@ -103,6 +103,7 @@ class FullNodeConfiguration(conf: Config) : NodeConfiguration {
override val keyStorePassword: String by conf
override val trustStorePassword: String by conf
override val dataSourceProperties: Properties by conf
val useHTTPS: Boolean by conf
val artemisAddress: HostAndPort by conf
val webAddress: HostAndPort by conf
val messagingServerAddress: HostAndPort? = if (conf.hasPath("messagingServerAddress")) HostAndPort.fromString(conf.getString("messagingServerAddress")) else null

View File

@ -8,4 +8,5 @@ dataSourceProperties = {
"dataSource.url" = "jdbc:h2:"${basedir}"/persistence"
"dataSource.user" = sa
"dataSource.password" = ""
}
}
useHTTPS = false