Add switchable HTTPS to Node web server

Explain change of cipher

Include extracted Dev Corda Root certificate so that it can be installed by HTTPS users.
This commit is contained in:
Matthew Nesbit 2016-08-26 18:08:48 +01:00
parent 89419f2444
commit 8756b49794
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