mirror of
https://github.com/corda/corda.git
synced 2025-02-27 11:36:42 +00:00
Merged in pat-doorman-status (pull request #27)
Doorman server status * added doorman server status for monitoring * minor changes * Addressed PR issues Fixed project dependency after rebased from corda master Approved-by: Shams Asari <shams.asari@r3.com>
This commit is contained in:
parent
6bb47e1214
commit
523c37079e
@ -41,6 +41,7 @@ dependencies {
|
||||
|
||||
compile project(":core")
|
||||
compile project(":node")
|
||||
compile project(":node-api")
|
||||
testCompile project(":test-utils")
|
||||
|
||||
// Log4J: logging framework (with SLF4J bindings)
|
||||
|
@ -5,8 +5,8 @@ import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigParseOptions
|
||||
import net.corda.core.div
|
||||
import net.corda.node.services.config.getOrElse
|
||||
import net.corda.node.services.config.getValue
|
||||
import net.corda.nodeapi.config.getOrElse
|
||||
import net.corda.nodeapi.config.getValue
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
|
||||
@ -30,10 +30,10 @@ class DoormanParameters(vararg args: String) {
|
||||
private val config = argConfig.withFallback(ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true))).resolve()
|
||||
val keystorePath: Path by config.getOrElse { basedir / "certificates" / "caKeystore.jks" }
|
||||
val rootStorePath: Path by config.getOrElse { basedir / "certificates" / "rootCAKeystore.jks" }
|
||||
val keystorePassword: String? by config.getOrElse { null }
|
||||
val caPrivateKeyPassword: String? by config.getOrElse { null }
|
||||
val rootKeystorePassword: String? by config.getOrElse { null }
|
||||
val rootPrivateKeyPassword: String? by config.getOrElse { null }
|
||||
val keystorePassword: String? by config
|
||||
val caPrivateKeyPassword: String? by config
|
||||
val rootKeystorePassword: String? by config
|
||||
val rootPrivateKeyPassword: String? by config
|
||||
val host: String by config
|
||||
val port: Int by config
|
||||
val dataSourceProperties: Properties by config
|
||||
|
@ -8,6 +8,7 @@ import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
||||
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||
import org.codehaus.jackson.map.ObjectMapper
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.InputStream
|
||||
import java.security.cert.Certificate
|
||||
@ -25,7 +26,7 @@ import javax.ws.rs.core.Response.Status.UNAUTHORIZED
|
||||
* Provides functionality for asynchronous submission of certificate signing requests and retrieval of the results.
|
||||
*/
|
||||
@Path("")
|
||||
class DoormanWebService(val intermediateCACertAndKey: CACertAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage) {
|
||||
class DoormanWebService(val intermediateCACertAndKey: CACertAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage, val serverStatus: DoormanServerStatus) {
|
||||
@Context lateinit var request: HttpServletRequest
|
||||
/**
|
||||
* Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificationRequestStorage] for approval.
|
||||
@ -81,4 +82,11 @@ class DoormanWebService(val intermediateCACertAndKey: CACertAndKey, val rootCert
|
||||
is CertificateResponse.Unauthorised -> status(UNAUTHORIZED).entity(response.message)
|
||||
}.build()
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("status")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
fun status(): Response {
|
||||
return ok(ObjectMapper().writeValueAsString(serverStatus)).build()
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ import java.lang.Thread.sleep
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.URI
|
||||
import java.security.cert.Certificate
|
||||
import java.time.Instant
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@ -44,8 +45,9 @@ import kotlin.system.exitProcess
|
||||
* The server will require keystorePath, keystore password and key password via command line input.
|
||||
* The Intermediate CA certificate,Intermediate CA private key and Root CA Certificate should use alias name specified in [X509Utilities]
|
||||
*/
|
||||
|
||||
class DoormanServer(webServerAddr: HostAndPort, val caCertAndKey: CACertAndKey, val rootCACert: Certificate, val storage: CertificationRequestStorage) : Closeable {
|
||||
val serverStatus = DoormanServerStatus()
|
||||
|
||||
companion object {
|
||||
val logger = loggerFor<DoormanServer>()
|
||||
}
|
||||
@ -72,6 +74,31 @@ class DoormanServer(webServerAddr: HostAndPort, val caCertAndKey: CACertAndKey,
|
||||
logger.info("Starting Doorman Web Services...")
|
||||
server.start()
|
||||
logger.info("Doorman Web Services started on $hostAndPort")
|
||||
serverStatus.serverStartTime = Instant.now()
|
||||
|
||||
// Thread approving request periodically.
|
||||
thread(name = "Request Approval Thread") {
|
||||
while (true) {
|
||||
try {
|
||||
sleep(10.seconds.toMillis())
|
||||
// TODO: Handle rejected request?
|
||||
serverStatus.lastRequestCheckTime = Instant.now()
|
||||
for (id in storage.getApprovedRequestIds()) {
|
||||
storage.approveRequest(id) {
|
||||
val request = JcaPKCS10CertificationRequest(request)
|
||||
createServerCert(request.subject, request.publicKey, caCertAndKey,
|
||||
if (ipAddress == hostName) listOf() else listOf(hostName), listOf(ipAddress))
|
||||
}
|
||||
logger.info("Approved request $id")
|
||||
serverStatus.lastApprovalTime = Instant.now()
|
||||
serverStatus.approvedRequests++
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// Log the error and carry on.
|
||||
logger.error("Error encountered when approving request.", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildServletContextHandler(): ServletContextHandler {
|
||||
@ -79,7 +106,7 @@ class DoormanServer(webServerAddr: HostAndPort, val caCertAndKey: CACertAndKey,
|
||||
contextPath = "/"
|
||||
val resourceConfig = ResourceConfig().apply {
|
||||
// Add your API provider classes (annotated for JAX-RS) here
|
||||
register(DoormanWebService(caCertAndKey, rootCACert, storage))
|
||||
register(DoormanWebService(caCertAndKey, rootCACert, storage, serverStatus))
|
||||
}
|
||||
val jerseyServlet = ServletHolder(ServletContainer(resourceConfig)).apply {
|
||||
initOrder = 0 // Initialise at server start
|
||||
@ -89,6 +116,11 @@ class DoormanServer(webServerAddr: HostAndPort, val caCertAndKey: CACertAndKey,
|
||||
}
|
||||
}
|
||||
|
||||
data class DoormanServerStatus(var serverStartTime: Instant? = null,
|
||||
var lastRequestCheckTime: Instant? = null,
|
||||
var lastApprovalTime: Instant? = null,
|
||||
var approvedRequests: Int = 0)
|
||||
|
||||
/** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */
|
||||
private fun readPassword(fmt: String): String {
|
||||
return if (System.console() != null) {
|
||||
@ -178,21 +210,6 @@ private fun DoormanParameters.startDoorman() {
|
||||
JiraCertificateRequestStorage(requestStorage, jiraClient, jiraConfig.projectCode, jiraConfig.doneTransitionCode)
|
||||
}
|
||||
|
||||
// Daemon thread approving request periodically.
|
||||
thread(name = "Request Approval Daemon") {
|
||||
while (true) {
|
||||
sleep(10.seconds.toMillis())
|
||||
// TODO: Handle rejected request?
|
||||
for (id in storage.getApprovedRequestIds()) {
|
||||
storage.approveRequest(id) {
|
||||
val request = JcaPKCS10CertificationRequest(request)
|
||||
createServerCert(request.subject, request.publicKey, caCertAndKey,
|
||||
if (ipAddress == hostName) listOf() else listOf(hostName), listOf(ipAddress))
|
||||
}
|
||||
logger.info("Approved request $id")
|
||||
}
|
||||
}
|
||||
}
|
||||
val doorman = DoormanServer(HostAndPort.fromParts(host, port), caCertAndKey, rootCACert, storage)
|
||||
doorman.start()
|
||||
Runtime.getRuntime().addShutdownHook(thread(start = false) { doorman.close() })
|
||||
|
@ -28,3 +28,4 @@ include 'samples:network-visualiser'
|
||||
include 'samples:simm-valuation-demo'
|
||||
include 'samples:raft-notary-demo'
|
||||
include 'samples:bank-of-corda-demo'
|
||||
include 'doorman'
|
||||
|
Loading…
x
Reference in New Issue
Block a user