mirror of
https://github.com/corda/corda.git
synced 2024-12-28 16:58:55 +00:00
Rename netpermission to doorman
This commit is contained in:
parent
0c1a6aad6b
commit
6ff8d73402
@ -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'
|
@ -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()
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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()
|
@ -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()
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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))
|
@ -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'
|
||||
|
Loading…
Reference in New Issue
Block a user