mirror of
https://github.com/corda/corda.git
synced 2025-01-14 16:59:52 +00:00
Fix post-merge issues:
- Update Doorman to reflect the X500 naming and configuration changes - Minor other changes
This commit is contained in:
parent
dfb63231e3
commit
550be76787
@ -1,17 +1,45 @@
|
|||||||
package com.r3.corda.doorman
|
package com.r3.corda.doorman
|
||||||
|
|
||||||
import com.r3.corda.doorman.OptionParserHelper.toConfigWithOptions
|
import com.r3.corda.doorman.OptionParserHelper.toConfigWithOptions
|
||||||
import com.typesafe.config.Config
|
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.typesafe.config.ConfigParseOptions
|
import com.typesafe.config.ConfigParseOptions
|
||||||
import net.corda.core.div
|
import net.corda.core.div
|
||||||
import net.corda.nodeapi.config.getOrElse
|
import net.corda.node.utilities.getPath
|
||||||
import net.corda.nodeapi.config.getValue
|
import net.corda.nodeapi.config.parseAs
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class DoormanParameters(vararg args: String) {
|
data class DoormanParameters(val basedir: Path,
|
||||||
private val argConfig = args.toConfigWithOptions {
|
val keystorePassword: String?,
|
||||||
|
val caPrivateKeyPassword: String?,
|
||||||
|
val rootKeystorePassword: String?,
|
||||||
|
val rootPrivateKeyPassword: String?,
|
||||||
|
val host: String,
|
||||||
|
val port: Int,
|
||||||
|
val dataSourceProperties: Properties,
|
||||||
|
val keygen: Boolean = false,
|
||||||
|
val rootKeygen: Boolean = false,
|
||||||
|
val jiraConfig: JiraConfig? = null,
|
||||||
|
val keystorePath: Path = basedir / "certificates" / "caKeystore.jks",
|
||||||
|
val rootStorePath: Path = basedir / "certificates" / "rootCAKeystore.jks"
|
||||||
|
) {
|
||||||
|
val mode = if (rootKeygen) Mode.ROOT_KEYGEN else if (keygen) Mode.CA_KEYGEN else Mode.DOORMAN
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
DOORMAN, CA_KEYGEN, ROOT_KEYGEN
|
||||||
|
}
|
||||||
|
|
||||||
|
data class JiraConfig(
|
||||||
|
val address: String,
|
||||||
|
val projectCode: String,
|
||||||
|
val username: String,
|
||||||
|
val password: String,
|
||||||
|
val doneTransitionCode: Int
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseParameters(vararg args: String): DoormanParameters {
|
||||||
|
val argConfig = args.toConfigWithOptions {
|
||||||
accepts("basedir", "Overriding configuration filepath, default to current directory.").withRequiredArg().defaultsTo(".").describedAs("filepath")
|
accepts("basedir", "Overriding configuration filepath, default to current directory.").withRequiredArg().defaultsTo(".").describedAs("filepath")
|
||||||
accepts("configFile", "Overriding configuration file, default to <<current directory>>/node.conf.").withRequiredArg().describedAs("filepath")
|
accepts("configFile", "Overriding configuration file, default to <<current directory>>/node.conf.").withRequiredArg().describedAs("filepath")
|
||||||
accepts("keygen", "Generate CA keypair and certificate using provide Root CA key.").withOptionalArg()
|
accepts("keygen", "Generate CA keypair and certificate using provide Root CA key.").withOptionalArg()
|
||||||
@ -25,33 +53,12 @@ class DoormanParameters(vararg args: String) {
|
|||||||
accepts("host", "Doorman web service host override").withRequiredArg().describedAs("hostname")
|
accepts("host", "Doorman web service host override").withRequiredArg().describedAs("hostname")
|
||||||
accepts("port", "Doorman web service port override").withRequiredArg().ofType(Int::class.java).describedAs("port number")
|
accepts("port", "Doorman web service port override").withRequiredArg().ofType(Int::class.java).describedAs("port number")
|
||||||
}
|
}
|
||||||
private val basedir: Path by argConfig
|
|
||||||
private val configFile by argConfig.getOrElse { basedir / "node.conf" }
|
|
||||||
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
|
|
||||||
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
|
|
||||||
val jiraConfig = if (config.hasPath("jiraConfig")) JiraConfig(config.getConfig("jiraConfig")) else null
|
|
||||||
private val keygen: Boolean by config.getOrElse { false }
|
|
||||||
private val rootKeygen: Boolean by config.getOrElse { false }
|
|
||||||
|
|
||||||
val mode = if (rootKeygen) Mode.ROOT_KEYGEN else if (keygen) Mode.CA_KEYGEN else Mode.DOORMAN
|
val configFile = if (argConfig.hasPath("configFile")) {
|
||||||
|
argConfig.getPath("configFile")
|
||||||
enum class Mode {
|
} else {
|
||||||
DOORMAN, CA_KEYGEN, ROOT_KEYGEN
|
argConfig.getPath("basedir") / "node.conf"
|
||||||
}
|
|
||||||
|
|
||||||
class JiraConfig(config: Config) {
|
|
||||||
val address: String by config
|
|
||||||
val projectCode: String by config
|
|
||||||
val username: String by config
|
|
||||||
val password: String by config
|
|
||||||
val doneTransitionCode: Int by config
|
|
||||||
}
|
}
|
||||||
|
val config = argConfig.withFallback(ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true))).resolve()
|
||||||
|
return config.parseAs<DoormanParameters>()
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package com.r3.corda.doorman
|
|||||||
import com.r3.corda.doorman.persistence.CertificateResponse
|
import com.r3.corda.doorman.persistence.CertificateResponse
|
||||||
import com.r3.corda.doorman.persistence.CertificationRequestData
|
import com.r3.corda.doorman.persistence.CertificationRequestData
|
||||||
import com.r3.corda.doorman.persistence.CertificationRequestStorage
|
import com.r3.corda.doorman.persistence.CertificationRequestStorage
|
||||||
import net.corda.core.crypto.X509Utilities.CACertAndKey
|
import net.corda.core.crypto.CertificateAndKey
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
|
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_INTERMEDIATE_CA
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
@ -26,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.
|
* Provides functionality for asynchronous submission of certificate signing requests and retrieval of the results.
|
||||||
*/
|
*/
|
||||||
@Path("")
|
@Path("")
|
||||||
class DoormanWebService(val intermediateCACertAndKey: CACertAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage, val serverStatus: DoormanServerStatus) {
|
class DoormanWebService(val intermediateCACertAndKey: CertificateAndKey, val rootCert: Certificate, val storage: CertificationRequestStorage, val serverStatus: DoormanServerStatus) {
|
||||||
@Context lateinit var request: HttpServletRequest
|
@Context lateinit var request: HttpServletRequest
|
||||||
/**
|
/**
|
||||||
* Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificationRequestStorage] for approval.
|
* Accept stream of [PKCS10CertificationRequest] from user and persists in [CertificationRequestStorage] for approval.
|
||||||
|
@ -7,22 +7,19 @@ import com.r3.corda.doorman.persistence.CertificationRequestStorage
|
|||||||
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
|
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
|
||||||
import com.r3.corda.doorman.persistence.JiraCertificateRequestStorage
|
import com.r3.corda.doorman.persistence.JiraCertificateRequestStorage
|
||||||
import net.corda.core.createDirectories
|
import net.corda.core.createDirectories
|
||||||
import net.corda.core.crypto.X509Utilities
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.crypto.X509Utilities.CACertAndKey
|
import net.corda.core.crypto.KeyStoreUtilities.loadKeyStore
|
||||||
|
import net.corda.core.crypto.KeyStoreUtilities.loadOrCreateKeyStore
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA_PRIVATE_KEY
|
import net.corda.core.crypto.X509Utilities.CORDA_INTERMEDIATE_CA_PRIVATE_KEY
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
|
||||||
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA_PRIVATE_KEY
|
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA_PRIVATE_KEY
|
||||||
import net.corda.core.crypto.X509Utilities.addOrReplaceKey
|
|
||||||
import net.corda.core.crypto.X509Utilities.createIntermediateCert
|
import net.corda.core.crypto.X509Utilities.createIntermediateCert
|
||||||
import net.corda.core.crypto.X509Utilities.createServerCert
|
import net.corda.core.crypto.X509Utilities.createServerCert
|
||||||
import net.corda.core.crypto.X509Utilities.loadCertificateAndKey
|
|
||||||
import net.corda.core.crypto.X509Utilities.loadKeyStore
|
|
||||||
import net.corda.core.crypto.X509Utilities.loadOrCreateKeyStore
|
|
||||||
import net.corda.core.crypto.X509Utilities.saveKeyStore
|
|
||||||
import net.corda.core.seconds
|
import net.corda.core.seconds
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||||
import org.eclipse.jetty.server.Server
|
import org.eclipse.jetty.server.Server
|
||||||
import org.eclipse.jetty.server.ServerConnector
|
import org.eclipse.jetty.server.ServerConnector
|
||||||
@ -45,7 +42,7 @@ import kotlin.system.exitProcess
|
|||||||
* The server will require keystorePath, keystore password and key password via command line input.
|
* 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]
|
* 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 {
|
class DoormanServer(webServerAddr: HostAndPort, val caCertAndKey: CertificateAndKey, val rootCACert: Certificate, val storage: CertificationRequestStorage) : Closeable {
|
||||||
val serverStatus = DoormanServerStatus()
|
val serverStatus = DoormanServerStatus()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -147,9 +144,9 @@ private fun DoormanParameters.generateRootKeyPair() {
|
|||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val selfSignCert = X509Utilities.createSelfSignedCACert(CORDA_ROOT_CA)
|
val selfSignCert = X509Utilities.createSelfSignedCACert(X500Name(CORDA_ROOT_CA))
|
||||||
rootStore.addOrReplaceKey(CORDA_ROOT_CA_PRIVATE_KEY, selfSignCert.keyPair.private, rootPrivateKeyPassword.toCharArray(), arrayOf(selfSignCert.certificate))
|
rootStore.addOrReplaceKey(CORDA_ROOT_CA_PRIVATE_KEY, selfSignCert.keyPair.private, rootPrivateKeyPassword.toCharArray(), arrayOf(selfSignCert.certificate))
|
||||||
saveKeyStore(rootStore, rootStorePath, rootKeystorePassword)
|
rootStore.save(rootStorePath, rootKeystorePassword)
|
||||||
|
|
||||||
println("Root CA keypair and certificate stored in $rootStorePath.")
|
println("Root CA keypair and certificate stored in $rootStorePath.")
|
||||||
println(loadKeyStore(rootStorePath, rootKeystorePassword).getCertificate(CORDA_ROOT_CA_PRIVATE_KEY).publicKey)
|
println(loadKeyStore(rootStorePath, rootKeystorePassword).getCertificate(CORDA_ROOT_CA_PRIVATE_KEY).publicKey)
|
||||||
@ -162,7 +159,7 @@ private fun DoormanParameters.generateCAKeyPair() {
|
|||||||
val rootPrivateKeyPassword = rootPrivateKeyPassword ?: readPassword("Root Private Key Password: ")
|
val rootPrivateKeyPassword = rootPrivateKeyPassword ?: readPassword("Root Private Key Password: ")
|
||||||
val rootKeyStore = loadKeyStore(rootStorePath, rootKeystorePassword)
|
val rootKeyStore = loadKeyStore(rootStorePath, rootKeystorePassword)
|
||||||
|
|
||||||
val rootKeyAndCert = loadCertificateAndKey(rootKeyStore, rootPrivateKeyPassword, CORDA_ROOT_CA_PRIVATE_KEY)
|
val rootKeyAndCert = rootKeyStore.getCertificateAndKey(rootPrivateKeyPassword, CORDA_ROOT_CA_PRIVATE_KEY)
|
||||||
|
|
||||||
val keystorePassword = keystorePassword ?: readPassword("Keystore Password: ")
|
val keystorePassword = keystorePassword ?: readPassword("Keystore Password: ")
|
||||||
val caPrivateKeyPassword = caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
val caPrivateKeyPassword = caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
||||||
@ -177,10 +174,10 @@ private fun DoormanParameters.generateCAKeyPair() {
|
|||||||
exitProcess(1)
|
exitProcess(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val intermediateKeyAndCert = createIntermediateCert(CORDA_INTERMEDIATE_CA, rootKeyAndCert)
|
val intermediateKeyAndCert = createIntermediateCert(X500Name(CORDA_INTERMEDIATE_CA), rootKeyAndCert)
|
||||||
keyStore.addOrReplaceKey(CORDA_INTERMEDIATE_CA_PRIVATE_KEY, intermediateKeyAndCert.keyPair.private,
|
keyStore.addOrReplaceKey(CORDA_INTERMEDIATE_CA_PRIVATE_KEY, intermediateKeyAndCert.keyPair.private,
|
||||||
caPrivateKeyPassword.toCharArray(), arrayOf(intermediateKeyAndCert.certificate, rootKeyAndCert.certificate))
|
caPrivateKeyPassword.toCharArray(), arrayOf(intermediateKeyAndCert.certificate, rootKeyAndCert.certificate))
|
||||||
saveKeyStore(keyStore, keystorePath, keystorePassword)
|
keyStore.save(keystorePath, keystorePassword)
|
||||||
println("Intermediate CA keypair and certificate stored in $keystorePath.")
|
println("Intermediate CA keypair and certificate stored in $keystorePath.")
|
||||||
println(loadKeyStore(keystorePath, keystorePassword).getCertificate(CORDA_INTERMEDIATE_CA_PRIVATE_KEY).publicKey)
|
println(loadKeyStore(keystorePath, keystorePassword).getCertificate(CORDA_INTERMEDIATE_CA_PRIVATE_KEY).publicKey)
|
||||||
}
|
}
|
||||||
@ -190,9 +187,10 @@ private fun DoormanParameters.startDoorman() {
|
|||||||
// Get password from console if not in config.
|
// Get password from console if not in config.
|
||||||
val keystorePassword = keystorePassword ?: readPassword("Keystore Password: ")
|
val keystorePassword = keystorePassword ?: readPassword("Keystore Password: ")
|
||||||
val caPrivateKeyPassword = caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
val caPrivateKeyPassword = caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
||||||
val keystore = X509Utilities.loadKeyStore(keystorePath, keystorePassword)
|
|
||||||
|
val keystore = loadOrCreateKeyStore(keystorePath, keystorePassword)
|
||||||
val rootCACert = keystore.getCertificateChain(CORDA_INTERMEDIATE_CA_PRIVATE_KEY).last()
|
val rootCACert = keystore.getCertificateChain(CORDA_INTERMEDIATE_CA_PRIVATE_KEY).last()
|
||||||
val caCertAndKey = X509Utilities.loadCertificateAndKey(keystore, caPrivateKeyPassword, CORDA_INTERMEDIATE_CA_PRIVATE_KEY)
|
val caCertAndKey = keystore.getCertificateAndKey(caPrivateKeyPassword, CORDA_INTERMEDIATE_CA_PRIVATE_KEY)
|
||||||
// Create DB connection.
|
// Create DB connection.
|
||||||
val (datasource, database) = configureDatabase(dataSourceProperties)
|
val (datasource, database) = configureDatabase(dataSourceProperties)
|
||||||
|
|
||||||
@ -218,7 +216,7 @@ private fun DoormanParameters.startDoorman() {
|
|||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
try {
|
try {
|
||||||
// TODO : Remove config overrides and solely use config file after testnet is finalized.
|
// TODO : Remove config overrides and solely use config file after testnet is finalized.
|
||||||
DoormanParameters(*args).run {
|
parseParameters(*args).run {
|
||||||
when (mode) {
|
when (mode) {
|
||||||
DoormanParameters.Mode.ROOT_KEYGEN -> generateRootKeyPair()
|
DoormanParameters.Mode.ROOT_KEYGEN -> generateRootKeyPair()
|
||||||
DoormanParameters.Mode.CA_KEYGEN -> generateCAKeyPair()
|
DoormanParameters.Mode.CA_KEYGEN -> generateCAKeyPair()
|
||||||
|
@ -24,7 +24,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
// Create table if not exists.
|
// Create table if not exists.
|
||||||
databaseTransaction(database) {
|
database.transaction {
|
||||||
SchemaUtils.create(DataTable)
|
SchemaUtils.create(DataTable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
override fun saveRequest(certificationData: CertificationRequestData): String {
|
override fun saveRequest(certificationData: CertificationRequestData): String {
|
||||||
val legalName = certificationData.request.subject.commonName
|
val legalName = certificationData.request.subject.commonName
|
||||||
val requestId = SecureHash.randomSHA256().toString()
|
val requestId = SecureHash.randomSHA256().toString()
|
||||||
databaseTransaction(database) {
|
database.transaction {
|
||||||
val duplicate = DataTable.select {
|
val duplicate = DataTable.select {
|
||||||
// A duplicate legal name is one where a previously approved, or currently pending, request has the same legal name.
|
// A duplicate legal name is one where a previously approved, or currently pending, request has the same legal name.
|
||||||
// A rejected request with the same legal name doesn't count as a duplicate
|
// A rejected request with the same legal name doesn't count as a duplicate
|
||||||
@ -65,7 +65,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getResponse(requestId: String): CertificateResponse {
|
override fun getResponse(requestId: String): CertificateResponse {
|
||||||
return databaseTransaction(database) {
|
return database.transaction {
|
||||||
val response = DataTable
|
val response = DataTable
|
||||||
.select { DataTable.requestId eq requestId and DataTable.processTimestamp.isNotNull() }
|
.select { DataTable.requestId eq requestId and DataTable.processTimestamp.isNotNull() }
|
||||||
.map { Pair(it[DataTable.certificate], it[DataTable.rejectReason]) }
|
.map { Pair(it[DataTable.certificate], it[DataTable.rejectReason]) }
|
||||||
@ -84,7 +84,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun approveRequest(requestId: String, generateCertificate: CertificationRequestData.() -> Certificate) {
|
override fun approveRequest(requestId: String, generateCertificate: CertificationRequestData.() -> Certificate) {
|
||||||
databaseTransaction(database) {
|
database.transaction {
|
||||||
val request = singleRequestWhere { DataTable.requestId eq requestId and DataTable.processTimestamp.isNull() }
|
val request = singleRequestWhere { DataTable.requestId eq requestId and DataTable.processTimestamp.isNull() }
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
withFinalizables { finalizables ->
|
withFinalizables { finalizables ->
|
||||||
@ -98,7 +98,7 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun rejectRequest(requestId: String, rejectReason: String) {
|
override fun rejectRequest(requestId: String, rejectReason: String) {
|
||||||
databaseTransaction(database) {
|
database.transaction {
|
||||||
val request = singleRequestWhere { DataTable.requestId eq requestId and DataTable.processTimestamp.isNull() }
|
val request = singleRequestWhere { DataTable.requestId eq requestId and DataTable.processTimestamp.isNull() }
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
DataTable.update({ DataTable.requestId eq requestId }) {
|
DataTable.update({ DataTable.requestId eq requestId }) {
|
||||||
@ -110,13 +110,13 @@ class DBCertificateRequestStorage(private val database: Database) : Certificatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getRequest(requestId: String): CertificationRequestData? {
|
override fun getRequest(requestId: String): CertificationRequestData? {
|
||||||
return databaseTransaction(database) {
|
return database.transaction {
|
||||||
singleRequestWhere { DataTable.requestId eq requestId }
|
singleRequestWhere { DataTable.requestId eq requestId }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPendingRequestIds(): List<String> {
|
override fun getPendingRequestIds(): List<String> {
|
||||||
return databaseTransaction(database) {
|
return database.transaction {
|
||||||
DataTable.select { DataTable.processTimestamp.isNull() }.map { it[DataTable.requestId] }
|
DataTable.select { DataTable.processTimestamp.isNull() }.map { it[DataTable.requestId] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,29 +9,32 @@ import kotlin.test.assertFailsWith
|
|||||||
|
|
||||||
class DoormanParametersTest {
|
class DoormanParametersTest {
|
||||||
private val testDummyPath = ".${File.separator}testDummyPath.jks"
|
private val testDummyPath = ".${File.separator}testDummyPath.jks"
|
||||||
|
private val validConfigPath = javaClass.getResource("/node.conf").path
|
||||||
|
private val invalidConfigPath = javaClass.getResource("/node_fail.conf").path
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `parse mode flag arg correctly`() {
|
fun `parse mode flag arg correctly`() {
|
||||||
assertEquals(DoormanParameters.Mode.CA_KEYGEN, DoormanParameters("--keygen").mode)
|
assertEquals(DoormanParameters.Mode.CA_KEYGEN, parseParameters("--keygen", "--configFile", validConfigPath).mode)
|
||||||
assertEquals(DoormanParameters.Mode.ROOT_KEYGEN, DoormanParameters("--rootKeygen").mode)
|
assertEquals(DoormanParameters.Mode.ROOT_KEYGEN, parseParameters("--rootKeygen", "--configFile", validConfigPath).mode)
|
||||||
assertEquals(DoormanParameters.Mode.DOORMAN, DoormanParameters().mode)
|
assertEquals(DoormanParameters.Mode.DOORMAN, parseParameters("--configFile", validConfigPath).mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `command line arg should override config file`() {
|
fun `command line arg should override config file`() {
|
||||||
val params = DoormanParameters("--keystorePath", testDummyPath, "--port", "1000", "--configFile", javaClass.getResource("/node.conf").path)
|
val params = parseParameters("--keystorePath", testDummyPath, "--port", "1000", "--configFile", validConfigPath)
|
||||||
assertEquals(testDummyPath, params.keystorePath.toString())
|
assertEquals(testDummyPath, params.keystorePath.toString())
|
||||||
assertEquals(1000, params.port)
|
assertEquals(1000, params.port)
|
||||||
|
|
||||||
val params2 = DoormanParameters("--configFile", javaClass.getResource("/node.conf").path)
|
val params2 = parseParameters("--configFile", validConfigPath)
|
||||||
assertEquals(Paths.get("/opt/doorman/certificates/caKeystore.jks"), params2.keystorePath)
|
assertEquals(Paths.get("/opt/doorman/certificates/caKeystore.jks"), params2.keystorePath)
|
||||||
assertEquals(8080, params2.port)
|
assertEquals(8080, params2.port)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should fail when config missing`() {
|
fun `should fail when config missing`() {
|
||||||
// dataSourceProperties is missing from node_fail.conf and it should fail when accessed, and shouldn't use default from reference.conf.
|
// dataSourceProperties is missing from node_fail.conf and it should fail during parsing, and shouldn't use default from reference.conf.
|
||||||
val params = DoormanParameters("--keygen", "--keystorePath", testDummyPath, "--configFile", javaClass.getResource("/node_fail.conf").path)
|
assertFailsWith<ConfigException.Missing> {
|
||||||
assertFailsWith<ConfigException.Missing> { params.dataSourceProperties }
|
parseParameters("--keygen", "--keystorePath", testDummyPath, "--configFile", invalidConfigPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ import com.nhaarman.mockito_kotlin.*
|
|||||||
import com.r3.corda.doorman.persistence.CertificateResponse
|
import com.r3.corda.doorman.persistence.CertificateResponse
|
||||||
import com.r3.corda.doorman.persistence.CertificationRequestData
|
import com.r3.corda.doorman.persistence.CertificationRequestData
|
||||||
import com.r3.corda.doorman.persistence.CertificationRequestStorage
|
import com.r3.corda.doorman.persistence.CertificationRequestStorage
|
||||||
import net.corda.core.crypto.CertificateStream
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
|
||||||
import net.corda.core.crypto.X509Utilities
|
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
@ -26,8 +26,8 @@ import javax.ws.rs.core.MediaType
|
|||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class DoormanServiceTest {
|
class DoormanServiceTest {
|
||||||
private val rootCA = X509Utilities.createSelfSignedCACert("Corda Node Root CA")
|
private val rootCA = X509Utilities.createSelfSignedCACert(X500Name("CN=Corda Node Root CA,L=London"))
|
||||||
private val intermediateCA = X509Utilities.createSelfSignedCACert("Corda Node Intermediate CA")
|
private val intermediateCA = X509Utilities.createSelfSignedCACert(X500Name("CN=Corda Node Intermediate CA,L=London"))
|
||||||
private lateinit var doormanServer: DoormanServer
|
private lateinit var doormanServer: DoormanServer
|
||||||
|
|
||||||
private fun startSigningServer(storage: CertificationRequestStorage) {
|
private fun startSigningServer(storage: CertificationRequestStorage) {
|
||||||
@ -50,8 +50,8 @@ class DoormanServiceTest {
|
|||||||
|
|
||||||
startSigningServer(storage)
|
startSigningServer(storage)
|
||||||
|
|
||||||
val keyPair = X509Utilities.generateECDSAKeyPairForSSL()
|
val keyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val request = X509Utilities.createCertificateSigningRequest("LegalName", "London", "admin@test.com", keyPair)
|
val request = X509Utilities.createCertificateSigningRequest(X500Name("CN=LegalName"), keyPair)
|
||||||
// Post request to signing server via http.
|
// Post request to signing server via http.
|
||||||
|
|
||||||
assertEquals(id, submitRequest(request))
|
assertEquals(id, submitRequest(request))
|
||||||
@ -62,7 +62,7 @@ class DoormanServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `retrieve certificate`() {
|
fun `retrieve certificate`() {
|
||||||
val keyPair = X509Utilities.generateECDSAKeyPairForSSL()
|
val keyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val id = SecureHash.randomSHA256().toString()
|
val id = SecureHash.randomSHA256().toString()
|
||||||
|
|
||||||
// Mock Storage behaviour.
|
// Mock Storage behaviour.
|
||||||
@ -74,7 +74,7 @@ class DoormanServiceTest {
|
|||||||
on { approveRequest(eq(id), any()) }.then {
|
on { approveRequest(eq(id), any()) }.then {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val certGen = it.arguments[1] as ((CertificationRequestData) -> Certificate)
|
val certGen = it.arguments[1] as ((CertificationRequestData) -> Certificate)
|
||||||
val request = CertificationRequestData("", "", X509Utilities.createCertificateSigningRequest("LegalName", "London", "admin@test.com", keyPair))
|
val request = CertificationRequestData("", "", X509Utilities.createCertificateSigningRequest(X500Name("CN=LegalName,L=London"), keyPair))
|
||||||
certificateStore[id] = certGen(request)
|
certificateStore[id] = certGen(request)
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,13 @@ package com.r3.corda.doorman.internal.persistence
|
|||||||
import com.r3.corda.doorman.persistence.CertificateResponse
|
import com.r3.corda.doorman.persistence.CertificateResponse
|
||||||
import com.r3.corda.doorman.persistence.CertificationRequestData
|
import com.r3.corda.doorman.persistence.CertificationRequestData
|
||||||
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
|
import com.r3.corda.doorman.persistence.DBCertificateRequestStorage
|
||||||
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.X509Utilities
|
import net.corda.core.crypto.X509Utilities
|
||||||
|
import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.testing.node.makeTestDataSourceProperties
|
import net.corda.testing.node.makeTestDataSourceProperties
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -18,7 +21,7 @@ import kotlin.test.assertNotNull
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class DBCertificateRequestStorageTest {
|
class DBCertificateRequestStorageTest {
|
||||||
private val intermediateCA = X509Utilities.createSelfSignedCACert("Corda Node Intermediate CA")
|
private val intermediateCA = X509Utilities.createSelfSignedCACert(X500Name("CN=Corda Node Intermediate CA"))
|
||||||
private var closeDb: Closeable? = null
|
private var closeDb: Closeable? = null
|
||||||
private lateinit var storage: DBCertificateRequestStorage
|
private lateinit var storage: DBCertificateRequestStorage
|
||||||
|
|
||||||
@ -106,28 +109,12 @@ class DBCertificateRequestStorageTest {
|
|||||||
assertThat(storage.getResponse(requestId2)).isInstanceOf(CertificateResponse.Ready::class.java)
|
assertThat(storage.getResponse(requestId2)).isInstanceOf(CertificateResponse.Ready::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `request with equals symbol in legal name`() {
|
|
||||||
val requestId = storage.saveRequest(createRequest("Bank=A").first)
|
|
||||||
assertThat(storage.getPendingRequestIds()).isEmpty()
|
|
||||||
val response = storage.getResponse(requestId) as CertificateResponse.Unauthorised
|
|
||||||
assertThat(response.message).contains("=")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `request with comma in legal name`() {
|
|
||||||
val requestId = storage.saveRequest(createRequest("Bank,A").first)
|
|
||||||
assertThat(storage.getPendingRequestIds()).isEmpty()
|
|
||||||
val response = storage.getResponse(requestId) as CertificateResponse.Unauthorised
|
|
||||||
assertThat(response.message).contains(",")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createRequest(legalName: String): Pair<CertificationRequestData, KeyPair> {
|
private fun createRequest(legalName: String): Pair<CertificationRequestData, KeyPair> {
|
||||||
val keyPair = X509Utilities.generateECDSAKeyPairForSSL()
|
val keyPair = Crypto.generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val request = CertificationRequestData(
|
val request = CertificationRequestData(
|
||||||
"hostname",
|
"hostname",
|
||||||
"0.0.0.0",
|
"0.0.0.0",
|
||||||
X509Utilities.createCertificateSigningRequest(legalName, "London", "admin@test.com", keyPair))
|
X509Utilities.createCertificateSigningRequest(X500Name("CN=$legalName"), keyPair))
|
||||||
return Pair(request, keyPair)
|
return Pair(request, keyPair)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ import java.net.URL
|
|||||||
import java.security.cert.Certificate
|
import java.security.cert.Certificate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
import javax.ws.rs.core.MediaType
|
|
||||||
|
|
||||||
class HTTPNetworkRegistrationService(val server: URL) : NetworkRegistrationService {
|
class HTTPNetworkRegistrationService(val server: URL) : NetworkRegistrationService {
|
||||||
companion object {
|
companion object {
|
||||||
@ -46,7 +45,7 @@ class HTTPNetworkRegistrationService(val server: URL) : NetworkRegistrationServi
|
|||||||
val conn = URL("$server/api/certificate").openConnection() as HttpURLConnection
|
val conn = URL("$server/api/certificate").openConnection() as HttpURLConnection
|
||||||
conn.doOutput = true
|
conn.doOutput = true
|
||||||
conn.requestMethod = "POST"
|
conn.requestMethod = "POST"
|
||||||
conn.setRequestProperty("Content-Type", MediaType.APPLICATION_OCTET_STREAM)
|
conn.setRequestProperty("Content-Type", MediaType.OCTET_STREAM.toString())
|
||||||
conn.setRequestProperty("Client-Version", clientVersion)
|
conn.setRequestProperty("Client-Version", clientVersion)
|
||||||
conn.outputStream.write(request.encoded)
|
conn.outputStream.write(request.encoded)
|
||||||
|
|
||||||
|
@ -3,21 +3,33 @@
|
|||||||
package com.r3.enclaves.txverify
|
package com.r3.enclaves.txverify
|
||||||
|
|
||||||
import com.esotericsoftware.minlog.Log
|
import com.esotericsoftware.minlog.Log
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.Attachment
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.contracts.StateRef
|
||||||
|
import net.corda.core.contracts.TransactionResolutionException
|
||||||
|
import net.corda.core.contracts.TransactionState
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.ServicesForResolution
|
import net.corda.core.node.ServicesForResolution
|
||||||
import net.corda.core.node.services.AttachmentStorage
|
import net.corda.core.node.services.AttachmentStorage
|
||||||
import net.corda.core.node.services.AttachmentsStorageService
|
import net.corda.core.node.services.AttachmentsStorageService
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.core.serialization.SerializedBytes
|
||||||
|
import net.corda.core.serialization.createTestKryo
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import java.security.PublicKey
|
||||||
|
|
||||||
// This file implements the functionality of the SGX transaction verification enclave.
|
// This file implements the functionality of the SGX transaction verification enclave.
|
||||||
|
|
||||||
private class ServicesForVerification(dependenciesList: List<WireTransaction>, attachments: Array<ByteArray>) : ServicesForResolution, IdentityService, AttachmentsStorageService, AttachmentStorage {
|
private class ServicesForVerification(dependenciesList: List<WireTransaction>, attachments: Array<ByteArray>) : ServicesForResolution, IdentityService, AttachmentsStorageService, AttachmentStorage {
|
||||||
|
override val attachmentsClassLoaderEnabled: Boolean
|
||||||
|
get() = TODO("not implemented")
|
||||||
override var automaticallyExtractAttachments: Boolean
|
override var automaticallyExtractAttachments: Boolean
|
||||||
get() = throw UnsupportedOperationException()
|
get() = throw UnsupportedOperationException()
|
||||||
set(value) = throw UnsupportedOperationException()
|
set(value) = throw UnsupportedOperationException()
|
||||||
@ -37,10 +49,12 @@ private class ServicesForVerification(dependenciesList: List<WireTransaction>, a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Identities: this stuff will all change in future so we don't bother implementing it now.
|
// Identities: this stuff will all change in future so we don't bother implementing it now.
|
||||||
override fun registerIdentity(party: Party) = throw UnsupportedOperationException()
|
override fun registerIdentity(party: net.corda.core.identity.Party) = TODO("not implemented")
|
||||||
override fun partyFromKey(key: CompositeKey): Party? = null
|
|
||||||
override fun partyFromName(name: String): Party? = null
|
override fun partyFromKey(key: PublicKey): net.corda.core.identity.Party? = null
|
||||||
override fun partyFromAnonymous(party: AnonymousParty) = null
|
override fun partyFromName(name: String): net.corda.core.identity.Party? = null
|
||||||
|
override fun partyFromX500Name(principal: X500Name): net.corda.core.identity.Party? = null
|
||||||
|
override fun partyFromAnonymous(party: AnonymousParty): net.corda.core.identity.Party? = null
|
||||||
|
|
||||||
// TODO: Implement attachments.
|
// TODO: Implement attachments.
|
||||||
override val attachments: AttachmentStorage = this
|
override val attachments: AttachmentStorage = this
|
||||||
|
Loading…
Reference in New Issue
Block a user