Rename netpermission to doorman

This commit is contained in:
Patrick Kuo 2017-02-06 14:56:00 +00:00
parent 0c1a6aad6b
commit 6ff8d73402
9 changed files with 55 additions and 56 deletions

View File

@ -13,9 +13,9 @@ repositories {
}
}
task buildCertSignerJAR(type: FatCapsule, dependsOn: 'jar') {
applicationClass 'com.r3.corda.netpermission.MainKt'
archiveName 'certSigner.jar'
task buildDoormanJAR(type: FatCapsule, dependsOn: 'jar') {
applicationClass 'com.r3.corda.doorman.MainKt'
archiveName 'doorman.jar'
capsuleManifest {
systemProperties['log4j.configuration'] = 'log4j2.xml'

View File

@ -1,8 +1,8 @@
package com.r3.corda.netpermission.internal
package com.r3.corda.doorman
import com.r3.corda.netpermission.internal.persistence.CertificateResponse
import com.r3.corda.netpermission.internal.persistence.CertificationData
import com.r3.corda.netpermission.internal.persistence.CertificationRequestStorage
import com.r3.corda.doorman.persistence.CertificateResponse
import com.r3.corda.doorman.persistence.CertificationRequestData
import com.r3.corda.doorman.persistence.CertificationRequestStorage
import net.corda.core.crypto.X509Utilities.CACertAndKey
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
@ -25,7 +25,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 CertificateSigningService(val intermediateCACertAndKey: CACertAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage) {
class DoormanWebService(val intermediateCACertAndKey: CACertAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage) {
@Context lateinit var request: HttpServletRequest
/**
* Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificationRequestStorage] for approval.
@ -42,7 +42,7 @@ class CertificateSigningService(val intermediateCACertAndKey: CACertAndKey, val
// TODO: Certificate signing request verifications.
// TODO: Use jira api / slack bot to semi automate the approval process?
// TODO: Acknowledge to user we have received the request via email?
val requestId = storage.saveRequest(CertificationData(request.remoteHost, request.remoteAddr, certificationRequest))
val requestId = storage.saveRequest(CertificationRequestData(request.remoteHost, request.remoteAddr, certificationRequest))
return ok(requestId).build()
}

View File

@ -1,8 +1,7 @@
package com.r3.corda.netpermission
package com.r3.corda.doorman
import com.google.common.net.HostAndPort
import com.r3.corda.netpermission.internal.CertificateSigningService
import com.r3.corda.netpermission.internal.persistence.DBCertificateRequestStorage
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
import joptsimple.ArgumentAcceptingOptionSpec
import joptsimple.OptionParser
import net.corda.core.crypto.X509Utilities
@ -30,20 +29,22 @@ 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 CertificateSigningServer(val webServerAddr: HostAndPort, val certSigningService: CertificateSigningService) : Closeable {
class DoormanServer(val webServerAddr: HostAndPort, val doormanWebService: DoormanWebService) : Closeable {
companion object {
val log = loggerFor<CertificateSigningServer>()
fun Server.hostAndPort(): HostAndPort {
val connector = server.connectors.first() as ServerConnector
return HostAndPort.fromParts(connector.host, connector.localPort)
}
val log = loggerFor<DoormanServer>()
}
val server: Server = initWebServer()
private val server: Server = initWebServer()
val hostAndPort: HostAndPort get() = server.connectors
.map { it as? ServerConnector }
.filterNotNull()
.map { HostAndPort.fromParts(it.host, it.localPort) }
.first()
override fun close() {
log.info("Shutting down CertificateSigningService...")
server.stop()
server.join()
}
private fun initWebServer(): Server {
@ -53,7 +54,7 @@ class CertificateSigningServer(val webServerAddr: HostAndPort, val certSigningSe
addHandler(buildServletContextHandler())
}
start()
log.info("CertificateSigningService started on ${server.hostAndPort()}")
log.info("CertificateSigningService started on $hostAndPort")
}
}
@ -62,7 +63,7 @@ class CertificateSigningServer(val webServerAddr: HostAndPort, val certSigningSe
contextPath = "/"
val resourceConfig = ResourceConfig().apply {
// Add your API provider classes (annotated for JAX-RS) here
register(certSigningService)
register(doormanWebService)
}
val jerseyServlet = ServletHolder(ServletContainer(resourceConfig)).apply {
initOrder = 0 // Initialise at server start
@ -79,7 +80,7 @@ object ParamsSpec {
}
fun main(args: Array<String>) {
val log = CertificateSigningServer.log
val log = DoormanServer.log
log.info("Starting certificate signing server.")
try {
ParamsSpec.parser.parse(*args)
@ -97,9 +98,8 @@ fun main(args: Array<String>) {
// Create DB connection.
val (datasource, database) = configureDatabase(config.getProperties("dataSourceProperties"))
val storage = DBCertificateRequestStorage(database)
val service = CertificateSigningService(intermediateCACertAndKey, rootCA, storage)
val service = DoormanWebService(intermediateCACertAndKey, rootCA, storage)
// Background thread approving all request periodically.
var stopSigner = false
@ -123,14 +123,12 @@ fun main(args: Array<String>) {
null
}
CertificateSigningServer(HostAndPort.fromParts(config.getString("host"), config.getInt("port")), service).use {
DoormanServer(HostAndPort.fromParts(config.getString("host"), config.getInt("port")), service).use {
Runtime.getRuntime().addShutdownHook(thread(false) {
stopSigner = true
certSinger?.join()
it.close()
datasource.close()
})
it.server.join()
}
}
}

View File

@ -1,4 +1,4 @@
package com.r3.corda.netpermission.internal.persistence
package com.r3.corda.doorman.persistence
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.security.cert.Certificate
@ -11,12 +11,12 @@ interface CertificationRequestStorage {
* Persist [certificationData] in storage for further approval if it's a valid request. If not then it will be automically
* rejected and not subject to any approval process. In both cases a randomly generated request ID is returned.
*/
fun saveRequest(certificationData: CertificationData): String
fun saveRequest(certificationData: CertificationRequestData): String
/**
* Retrieve certificate singing request and Host/IP information using [requestId].
*/
fun getRequest(requestId: String): CertificationData?
fun getRequest(requestId: String): CertificationRequestData?
/**
* Return the response for a previously saved request with ID [requestId].
@ -26,7 +26,7 @@ interface CertificationRequestStorage {
/**
* Approve the given request by generating and storing a new certificate using the provided generator.
*/
fun approveRequest(requestId: String, certificateGenerator: (CertificationData) -> Certificate)
fun approveRequest(requestId: String, certificateGenerator: (CertificationRequestData) -> Certificate)
/**
* Reject the given request using the given reason.
@ -40,7 +40,7 @@ interface CertificationRequestStorage {
fun getPendingRequestIds(): List<String>
}
data class CertificationData(val hostName: String, val ipAddress: String, val request: PKCS10CertificationRequest)
data class CertificationRequestData(val hostName: String, val ipAddress: String, val request: PKCS10CertificationRequest)
sealed class CertificateResponse {
object NotReady : CertificateResponse()

View File

@ -1,4 +1,4 @@
package com.r3.corda.netpermission.internal.persistence
package com.r3.corda.doorman.persistence
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.commonName
@ -29,7 +29,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
}
}
override fun saveRequest(certificationData: CertificationData): String {
override fun saveRequest(certificationData: CertificationRequestData): String {
val legalName = certificationData.request.subject.commonName
val requestId = SecureHash.randomSHA256().toString()
databaseTransaction(database) {
@ -83,7 +83,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
}
}
override fun approveRequest(requestId: String, certificateGenerator: (CertificationData) -> Certificate) {
override fun approveRequest(requestId: String, certificateGenerator: (CertificationRequestData) -> Certificate) {
databaseTransaction(database) {
val request = singleRequestWhere { DataTable.requestId eq requestId and DataTable.processTimestamp.isNull() }
if (request != null) {
@ -109,7 +109,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
}
}
override fun getRequest(requestId: String): CertificationData? {
override fun getRequest(requestId: String): CertificationRequestData? {
return databaseTransaction(database) {
singleRequestWhere { DataTable.requestId eq requestId }
}
@ -121,10 +121,10 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
}
}
private fun singleRequestWhere(where: SqlExpressionBuilder.() -> Op<Boolean>): CertificationData? {
private fun singleRequestWhere(where: SqlExpressionBuilder.() -> Op<Boolean>): CertificationRequestData? {
return DataTable
.select(where)
.map { CertificationData(it[DataTable.hostName], it[DataTable.ipAddress], deserializeFromBlob(it[DataTable.request])) }
.map { CertificationRequestData(it[DataTable.hostName], it[DataTable.ipAddress], deserializeFromBlob(it[DataTable.request])) }
.singleOrNull()
}
}

View File

@ -1,12 +1,10 @@
package com.r3.corda.netpermission
package com.r3.corda.doorman
import com.google.common.net.HostAndPort
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.netpermission.CertificateSigningServer.Companion.hostAndPort
import com.r3.corda.netpermission.internal.CertificateSigningService
import com.r3.corda.netpermission.internal.persistence.CertificateResponse
import com.r3.corda.netpermission.internal.persistence.CertificationData
import com.r3.corda.netpermission.internal.persistence.CertificationRequestStorage
import com.r3.corda.doorman.persistence.CertificateResponse
import com.r3.corda.doorman.persistence.CertificationRequestData
import com.r3.corda.doorman.persistence.CertificationRequestStorage
import net.corda.core.crypto.CertificateStream
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.X509Utilities
@ -27,18 +25,18 @@ import java.util.zip.ZipInputStream
import javax.ws.rs.core.MediaType
import kotlin.test.assertEquals
class CertificateSigningServiceTest {
class DoormanServiceTest {
private val rootCA = X509Utilities.createSelfSignedCACert("Corda Node Root CA")
private val intermediateCA = X509Utilities.createSelfSignedCACert("Corda Node Intermediate CA")
private lateinit var signingServer: CertificateSigningServer
private lateinit var doormanServer: DoormanServer
private fun startSigningServer(storage: CertificationRequestStorage) {
signingServer = CertificateSigningServer(HostAndPort.fromParts("localhost", 0), CertificateSigningService(intermediateCA, rootCA.certificate, storage))
doormanServer = DoormanServer(HostAndPort.fromParts("localhost", 0), DoormanWebService(intermediateCA, rootCA.certificate, storage))
}
@After
fun close() {
signingServer.close()
doormanServer.close()
}
@Test
@ -74,8 +72,8 @@ class CertificateSigningServiceTest {
}
on { approveRequest(eq(id), any()) }.then {
@Suppress("UNCHECKED_CAST")
val certGen = it.arguments[1] as ((CertificationData) -> Certificate)
val request = CertificationData("", "", X509Utilities.createCertificateSigningRequest("LegalName", "London", "admin@test.com", keyPair))
val certGen = it.arguments[1] as ((CertificationRequestData) -> Certificate)
val request = CertificationRequestData("", "", X509Utilities.createCertificateSigningRequest("LegalName", "London", "admin@test.com", keyPair))
certificateStore[id] = certGen(request)
Unit
}
@ -123,7 +121,7 @@ class CertificateSigningServiceTest {
}
private fun submitRequest(request: PKCS10CertificationRequest): String {
val conn = URL("http://${signingServer.server.hostAndPort()}/api/certificate").openConnection() as HttpURLConnection
val conn = URL("http://${doormanServer.hostAndPort}/api/certificate").openConnection() as HttpURLConnection
conn.doOutput = true
conn.requestMethod = "POST"
conn.setRequestProperty("Content-Type", MediaType.APPLICATION_OCTET_STREAM)
@ -132,7 +130,7 @@ class CertificateSigningServiceTest {
}
private fun pollForResponse(id: String): PollResponse {
val url = URL("http://${signingServer.server.hostAndPort()}/api/certificate/$id")
val url = URL("http://${doormanServer.hostAndPort}/api/certificate/$id")
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"

View File

@ -1,5 +1,8 @@
package com.r3.corda.netpermission.internal.persistence
package com.r3.corda.doorman.internal.persistence
import com.r3.corda.doorman.persistence.CertificateResponse
import com.r3.corda.doorman.persistence.CertificationRequestData
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
import net.corda.core.crypto.X509Utilities
import net.corda.node.utilities.configureDatabase
import net.corda.testing.node.makeTestDataSourceProperties
@ -119,9 +122,9 @@ class DBCertificateRequestStorageTest {
assertThat(response.message).contains(",")
}
private fun createRequest(legalName: String): Pair<CertificationData, KeyPair> {
private fun createRequest(legalName: String): Pair<CertificationRequestData, KeyPair> {
val keyPair = X509Utilities.generateECDSAKeyPairForSSL()
val request = CertificationData(
val request = CertificationRequestData(
"hostname",
"0.0.0.0",
X509Utilities.createCertificateSigningRequest(legalName, "London", "admin@test.com", keyPair))

View File

@ -7,7 +7,7 @@ include 'core'
include 'node'
include 'node:capsule'
include 'client'
include 'netpermission'
include 'doorman'
include 'experimental'
include 'experimental:sandbox'
include 'test-utils'