Make Network registration process more verbose (#251)

* Make the network registration process more verbose
* removed gradle task for building standalone jar for the certificate signing request utility
* Added a flag "--initial-registration" to the corda jar to start the registration
This commit is contained in:
Patrick Kuo
2017-02-20 13:22:37 +00:00
committed by GitHub
parent 99721bf8f1
commit 9a0a9567f3
13 changed files with 192 additions and 189 deletions

View File

@ -9,14 +9,14 @@ as possible.
However this is not secure for the real network. This documentation will explain the procedure of obtaining a signed
certificate for TestNet.
.. warning:: The TestNet has not been setup yet as of Milestone 6 release. You will not be able to connect to the
.. warning:: The TestNet has not been setup yet as of Milestone 8 release. You will not be able to connect to the
certificate signing server.
Certificate signing request utility
-----------------------------------
Initial Registration
--------------------
The utility creates certificate signing request based on node information obtained from the node configuration.
The following information from the node configuration file is needed to generate a certificate signing request.
The certificate signing request will be created based on node information obtained from the node configuration.
The following information from the node configuration file is needed to generate the request.
:myLegalName: Your company's legal name. e.g. "Mega Corp LLC". This needs to be unique on the network. If another node
has already been permissioned with this name then the permissioning server will automatically reject the request. The
@ -32,40 +32,25 @@ The following information from the node configuration file is needed to generate
:certificateSigningService: Certificate signing server URL. A certificate signing server will be hosted by R3 in the near
future. e.g."https://testnet.certificate.corda.net"
A new pair of private and public keys will be generated by the utility and will be used to create the request.
A new pair of private and public keys generated by the Corda node will be used to create the request.
The utility will submit the request to the network permissioning server and poll for a result periodically to retrieve the certificates.
Once the request has been approved and the certificates downloaded from the server, the utility will create the key store and trust store using the certificates and the generated private key.
Once the request has been approved and the certificates downloaded from the server, the node will create the keystore and trust store using the certificates and the generated private key.
.. note:: You can exit the utility at any time if the approval process is taking longer than expected. The request process will resume on restart.
This process only needs to be done once when the node connects to the network for the first time, or when the certificate expires.
Building the utility
--------------------
The utility will be created as part of the gradle ``:node`` module ``buildCordaJAR`` task.
You can also build the utility JAR by run the following command from the Corda project root directory.
**Windows**::
gradlew.bat :node:buildCertSigningRequestUtilityJAR
**Other**::
./gradlew :node:buildCertSigningRequestUtilityJAR
The utility JAR will be created in ``<Project Root Dir>/node/build/libs/certSigningRequestUtility.jar``
This process only is needed when the node connects to the network for the first time, or when the certificate expires.
Running the utility
-------------------
Starting the Registration
-------------------------
You will need to specify the working directory of your Corda node using ``--base-dir`` flag. This is defaulted to current directory if left blank.
You can also specify the location of ``node.conf`` with ``--config-file`` flag if it's not in the working directory.
**Running the Utility**::
**To start the registration**::
java -jar certSigningRequestUtility.jar --base-dir <<optional>> --config-file <<optional>>
java -jar corda.jar --initial-registration --base-dir <<optional>> --config-file <<optional>>
A ``certificates`` folder containing the keystore and trust store will be created in the base directory when the process is completed.

View File

@ -48,7 +48,7 @@ dependencies {
compile project(':node')
}
task buildCordaJAR(type: FatCapsule, dependsOn: ['buildCertSigningRequestUtilityJAR']) {
task buildCordaJAR(type: FatCapsule) {
applicationClass 'net.corda.node.Corda'
archiveName "corda-${corda_version}.jar"
applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/CordaCaplet.class', 'config/dev/log4j2.xml')
@ -78,15 +78,6 @@ task buildCordaJAR(type: FatCapsule, dependsOn: ['buildCertSigningRequestUtility
}
}
task buildCertSigningRequestUtilityJAR(type: FatCapsule) {
applicationClass 'net.corda.node.utilities.certsigning.CertificateSignerKt'
archiveName 'certSigningRequestUtility.jar'
capsuleManifest {
systemProperties['log4j.configuration'] = 'log4j2.xml'
minJavaVersion = '1.8.0'
}
}
artifacts {
runtimeArtifacts buildCordaJAR
publish buildCordaJAR {

View File

@ -29,6 +29,7 @@ class ArgsParser {
.defaultsTo(Level.INFO)
private val logToConsoleArg = optionParser.accepts("log-to-console", "If set, prints logging to the console as well as to a file.")
private val isWebserverArg = optionParser.accepts("webserver")
private val isRegistrationArg = optionParser.accepts("initial-registration", "Start initial node registration with Corda network to obtain certificate from the permissioning server.")
private val helpArg = optionParser.accepts("help").forHelp()
fun parse(vararg args: String): CmdLineOptions {
@ -42,7 +43,8 @@ class ArgsParser {
val loggingLevel = optionSet.valueOf(loggerLevel)
val logToConsole = optionSet.has(logToConsoleArg)
val isWebserver = optionSet.has(isWebserverArg)
return CmdLineOptions(baseDirectory, configFile, help, loggingLevel, logToConsole, isWebserver)
val isRegistration = optionSet.has(isRegistrationArg)
return CmdLineOptions(baseDirectory, configFile, help, loggingLevel, logToConsole, isWebserver, isRegistration)
}
fun printHelp(sink: PrintStream) = optionParser.printHelpOn(sink)
@ -53,7 +55,8 @@ data class CmdLineOptions(val baseDirectory: Path,
val help: Boolean,
val loggingLevel: Level,
val logToConsole: Boolean,
val isWebserver: Boolean) {
val isWebserver: Boolean,
val isRegistration: Boolean) {
fun loadConfig(allowMissingConfig: Boolean = false, configOverrides: Map<String, Any?> = emptyMap()): Config {
return ConfigHelper.loadConfig(baseDirectory, configFile, allowMissingConfig, configOverrides)
}

View File

@ -8,6 +8,8 @@ import net.corda.core.utilities.Emoji
import net.corda.node.internal.Node
import net.corda.node.services.config.FullNodeConfiguration
import net.corda.node.utilities.ANSIProgressObserver
import net.corda.node.utilities.registration.HTTPNetworkRegistrationService
import net.corda.node.utilities.registration.NetworkRegistrationHelper
import net.corda.node.webserver.WebServer
import org.fusesource.jansi.Ansi
import org.fusesource.jansi.AnsiConsole
@ -72,6 +74,17 @@ fun main(args: Array<String>) {
exitProcess(2)
}
if (cmdlineOptions.isRegistration) {
println()
println("******************************************************************")
println("* *")
println("* Registering as a new participant with Corda network *")
println("* *")
println("******************************************************************")
NetworkRegistrationHelper(conf, HTTPNetworkRegistrationService(conf.certificateSigningService)).buildKeystore()
exitProcess(0)
}
log.info("Main class: ${FullNodeConfiguration::class.java.protectionDomain.codeSource.location.toURI().path}")
val info = ManagementFactory.getRuntimeMXBean()
log.info("CommandLine Args: ${info.inputArguments.joinToString(" ")}")
@ -81,7 +94,7 @@ fun main(args: Array<String>) {
log.info("VM ${info.vmName} ${info.vmVendor} ${info.vmVersion}")
log.info("Machine: ${InetAddress.getLocalHost().hostName}")
log.info("Working Directory: ${cmdlineOptions.baseDirectory}")
if(cmdlineOptions.isWebserver) {
if (cmdlineOptions.isWebserver) {
log.info("Starting as webserver on ${conf.webAddress}")
} else {
log.info("Starting as node on ${conf.artemisAddress}")

View File

@ -191,7 +191,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
log.warn("Corda node is running in dev mode.")
configuration.configureWithDevSSLCertificate()
}
require(hasSSLCertificates()) { "SSL certificates not found." }
require(hasSSLCertificates()) { "Identity certificate not found. " +
"Please either copy your existing identity key and certificate from another node, " +
"or if you don't have one yet, fill out the config file and run corda.jar --initial-registration. " +
"Read more at: https://docs.corda.net/permissioning.html" }
log.info("Node starting up ...")

View File

@ -10,6 +10,7 @@ import net.corda.node.serialization.NodeClock
import net.corda.node.services.User
import net.corda.node.services.network.NetworkMapService
import net.corda.node.utilities.TestClock
import java.net.URL
import java.nio.file.Path
import java.util.*
@ -32,6 +33,7 @@ interface NodeConfiguration : SSLConfiguration {
val dataSourceProperties: Properties get() = Properties()
val rpcUsers: List<User> get() = emptyList()
val devMode: Boolean
val certificateSigningService: URL
}
/**
@ -46,6 +48,7 @@ class FullNodeConfiguration(override val baseDirectory: Path, val config: Config
override val trustStorePassword: String by config
override val dataSourceProperties: Properties by config
override val devMode: Boolean by config.getOrElse { false }
override val certificateSigningService: URL by config
override val networkMapService: NetworkMapInfo? = config.getOptionalConfig("networkMapService")?.run {
NetworkMapInfo(
HostAndPort.fromString(getString("address")),

View File

@ -1,131 +0,0 @@
package net.corda.node.utilities.certsigning
import net.corda.core.*
import net.corda.core.crypto.X509Utilities
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA_PRIVATE_KEY
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.core.crypto.X509Utilities.addOrReplaceCertificate
import net.corda.core.crypto.X509Utilities.addOrReplaceKey
import net.corda.core.utilities.loggerFor
import net.corda.node.ArgsParser
import net.corda.node.services.config.FullNodeConfiguration
import net.corda.node.services.config.NodeConfiguration
import net.corda.node.services.config.getValue
import net.corda.node.utilities.certsigning.CertificateSigner.Companion.log
import java.net.URL
import java.security.KeyPair
import java.security.cert.Certificate
import kotlin.system.exitProcess
/**
* This check the [certificatePath] for certificates required to connect to the Corda network.
* If the certificates are not found, a [PKCS10CertificationRequest] will be submitted to Corda network permissioning server using [CertificateSigningService].
* This process will enter a slow polling loop until the request has been approved, and then
* the certificate chain will be downloaded and stored in [KeyStore] reside in [certificatePath].
*/
class CertificateSigner(val config: NodeConfiguration, val certService: CertificateSigningService) {
companion object {
val pollInterval = 1.minutes
val log = loggerFor<CertificateSigner>()
}
fun buildKeyStore() {
config.certificatesDirectory.createDirectories()
val caKeyStore = X509Utilities.loadOrCreateKeyStore(config.keyStoreFile, config.keyStorePassword)
if (!caKeyStore.containsAlias(CORDA_CLIENT_CA)) {
// No certificate found in key store, create certificate signing request and post request to signing server.
log.info("No certificate found in key store, creating certificate signing request...")
// Create or load key pair from the key store.
val keyPair = X509Utilities.loadOrCreateKeyPairFromKeyStore(config.keyStoreFile, config.keyStorePassword,
config.keyStorePassword, CORDA_CLIENT_CA_PRIVATE_KEY) {
X509Utilities.createSelfSignedCACert(config.myLegalName)
}
log.info("Submitting certificate signing request to Corda certificate signing server.")
val requestId = submitCertificateSigningRequest(keyPair)
log.info("Successfully submitted request to Corda certificate signing server, request ID : $requestId")
log.info("Start polling server for certificate signing approval.")
val certificates = pollServerForCertificates(requestId)
log.info("Certificate signing request approved, installing new certificates.")
// Save private key and certificate chain to the key store.
caKeyStore.addOrReplaceKey(CORDA_CLIENT_CA_PRIVATE_KEY, keyPair.private,
config.keyStorePassword.toCharArray(), certificates)
// Assumes certificate chain always starts with client certificate and end with root certificate.
caKeyStore.addOrReplaceCertificate(CORDA_CLIENT_CA, certificates.first())
X509Utilities.saveKeyStore(caKeyStore, config.keyStoreFile, config.keyStorePassword)
// Save certificates to trust store.
val trustStore = X509Utilities.loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword)
// Assumes certificate chain always starts with client certificate and end with root certificate.
trustStore.addOrReplaceCertificate(CORDA_ROOT_CA, certificates.last())
X509Utilities.saveKeyStore(trustStore, config.trustStoreFile, config.trustStorePassword)
} else {
log.trace("Certificate already exists, exiting certificate signer...")
}
}
/**
* Poll Certificate Signing Server for approved certificate,
* enter a slow polling loop if server return null.
* @param requestId Certificate signing request ID.
* @return Map of certificate chain.
*/
private fun pollServerForCertificates(requestId: String): Array<Certificate> {
// Poll server to download the signed certificate once request has been approved.
var certificates = certService.retrieveCertificates(requestId)
while (certificates == null) {
Thread.sleep(pollInterval.toMillis())
certificates = certService.retrieveCertificates(requestId)
}
return certificates
}
/**
* Submit Certificate Signing Request to Certificate signing service if request ID not found in file system
* New request ID will be stored in requestId.txt
* @param keyPair Public Private key pair generated for SSL certification.
* @return Request ID return from the server.
*/
private fun submitCertificateSigningRequest(keyPair: KeyPair): String {
val requestIdStore = config.certificatesDirectory / "certificate-request-id.txt"
// Retrieve request id from file if exists, else post a request to server.
return if (!requestIdStore.exists()) {
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, config.nearestCity, config.emailAddress, keyPair)
// Post request to signing server via http.
val requestId = certService.submitRequest(request)
// Persists request ID to file in case of node shutdown.
requestIdStore.writeLines(listOf(requestId))
requestId
} else {
requestIdStore.readLines { it.findFirst().get() }
}
}
}
fun main(args: Array<String>) {
val argsParser = ArgsParser()
val cmdlineOptions = try {
argsParser.parse(*args)
} catch (ex: Exception) {
log.error("Unable to parse args", ex)
argsParser.printHelp(System.out)
exitProcess(1)
}
val config = cmdlineOptions.loadConfig(allowMissingConfig = true)
val configuration = object : NodeConfiguration by FullNodeConfiguration(cmdlineOptions.baseDirectory, config) {
val certificateSigningService: URL by config
}
// TODO: Use HTTPS instead
CertificateSigner(configuration, HTTPCertificateSigningService(configuration.certificateSigningService)).buildKeyStore()
}

View File

@ -1,4 +1,4 @@
package net.corda.node.utilities.certsigning
package net.corda.node.utilities.registration
import net.corda.core.crypto.CertificateStream
import org.apache.commons.io.IOUtils
@ -11,12 +11,13 @@ import java.security.cert.Certificate
import java.util.*
import java.util.zip.ZipInputStream
class HTTPCertificateSigningService(val server: URL) : CertificateSigningService {
class HTTPNetworkRegistrationService(val server: URL) : NetworkRegistrationService {
companion object {
// TODO: Propagate version information from gradle
val clientVersion = "1.0"
}
@Throws(CertificateRequestException::class)
override fun retrieveCertificates(requestId: String): Array<Certificate>? {
// Poll server to download the signed certificate once request has been approved.
val url = URL("$server/api/certificate/$requestId")
@ -34,7 +35,7 @@ class HTTPCertificateSigningService(val server: URL) : CertificateSigningService
certificates.toTypedArray()
}
HTTP_NO_CONTENT -> null
HTTP_UNAUTHORIZED -> throw IOException("Certificate signing request has been rejected: ${conn.errorMessage}")
HTTP_UNAUTHORIZED -> throw CertificateRequestException("Certificate signing request has been rejected: ${conn.errorMessage}")
else -> throwUnexpectedResponseCode(conn)
}
}

View File

@ -0,0 +1,130 @@
package net.corda.node.utilities.registration
import net.corda.core.*
import net.corda.core.crypto.X509Utilities
import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_CA
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.core.crypto.X509Utilities.addOrReplaceCertificate
import net.corda.core.crypto.X509Utilities.addOrReplaceKey
import net.corda.node.services.config.NodeConfiguration
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
import org.bouncycastle.util.io.pem.PemObject
import java.io.StringWriter
import java.security.KeyPair
import java.security.cert.Certificate
import kotlin.system.exitProcess
/**
* This checks the [config.certificatesDirectory] for certificates required to connect to a Corda network.
* If the certificates are not found, a [PKCS10CertificationRequest] will be submitted to Corda network permissioning server using [NetworkRegistrationService].
* This process will enter a polling loop until the request has been approved, and then
* the certificate chain will be downloaded and stored in [Keystore] reside in [config.certificatesDirectory].
*/
class NetworkRegistrationHelper(val config: NodeConfiguration, val certService: NetworkRegistrationService) {
companion object {
val pollInterval = 10.seconds
val SELF_SIGNED_PRIVATE_KEY = "Self Signed Private Key"
}
private val requestIdStore = config.certificatesDirectory / "certificate-request-id.txt"
private val keystorePassword = config.keyStorePassword
// TODO: Use different password for private key.
private val privateKeyPassword = config.keyStorePassword
fun buildKeystore() {
config.certificatesDirectory.createDirectories()
val caKeyStore = X509Utilities.loadOrCreateKeyStore(config.keyStoreFile, keystorePassword)
if (!caKeyStore.containsAlias(CORDA_CLIENT_CA)) {
// Create or load self signed keypair from the key store.
// We use the self sign certificate to store the key temporarily in the keystore while waiting for the request approval.
if (!caKeyStore.containsAlias(SELF_SIGNED_PRIVATE_KEY)) {
val selfSignCert = X509Utilities.createSelfSignedCACert(config.myLegalName)
// Save to the key store.
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, selfSignCert.keyPair.private, privateKeyPassword.toCharArray(), arrayOf(selfSignCert.certificate))
X509Utilities.saveKeyStore(caKeyStore, config.keyStoreFile, keystorePassword)
}
val keyPair = X509Utilities.loadKeyPairFromKeyStore(config.keyStoreFile, keystorePassword, privateKeyPassword, SELF_SIGNED_PRIVATE_KEY)
val requestId = submitOrResumeCertificateSigningRequest(keyPair)
val certificates = try {
pollServerForCertificates(requestId)
} catch (e: CertificateRequestException) {
System.err.println(e.message)
println("Please make sure the details in configuration file are correct and try again.")
println("Corda node will now terminate.")
requestIdStore.deleteIfExists()
exitProcess(1)
}
println("Certificate signing request approved, storing private key with the certificate chain.")
// Save private key and certificate chain to the key store.
caKeyStore.addOrReplaceKey(CORDA_CLIENT_CA, keyPair.private, privateKeyPassword.toCharArray(), certificates)
caKeyStore.deleteEntry(SELF_SIGNED_PRIVATE_KEY)
X509Utilities.saveKeyStore(caKeyStore, config.keyStoreFile, keystorePassword)
// Save root certificates to trust store.
val trustStore = X509Utilities.loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword)
// Assumes certificate chain always starts with client certificate and end with root certificate.
trustStore.addOrReplaceCertificate(CORDA_ROOT_CA, certificates.last())
X509Utilities.saveKeyStore(trustStore, config.trustStoreFile, config.trustStorePassword)
println("Certificate and private key stored in ${config.keyStoreFile}.")
// All done, clean up temp files.
requestIdStore.deleteIfExists()
} else {
println("Certificate already exists, Corda node will now terminate...")
}
}
/**
* Poll Certificate Signing Server for approved certificate,
* enter a slow polling loop if server return null.
* @param requestId Certificate signing request ID.
* @return Map of certificate chain.
*/
private fun pollServerForCertificates(requestId: String): Array<Certificate> {
println("Start polling server for certificate signing approval.")
// Poll server to download the signed certificate once request has been approved.
var certificates = certService.retrieveCertificates(requestId)
while (certificates == null) {
Thread.sleep(pollInterval.toMillis())
certificates = certService.retrieveCertificates(requestId)
}
return certificates
}
/**
* Submit Certificate Signing Request to Certificate signing service if request ID not found in file system
* New request ID will be stored in requestId.txt
* @param keyPair Public Private key pair generated for SSL certification.
* @return Request ID return from the server.
*/
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
// Retrieve request id from file if exists, else post a request to server.
return if (!requestIdStore.exists()) {
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, config.nearestCity, config.emailAddress, keyPair)
val writer = StringWriter()
JcaPEMWriter(writer).use {
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
}
println("Certificate signing request with the following information will be submitted to the Corda certificate signing server.")
println()
println("Legal Name: ${config.myLegalName}")
println("Nearest City: ${config.nearestCity}")
println("Email: ${config.emailAddress}")
println()
println("Public Key: ${keyPair.public}")
println()
println("$writer")
// Post request to signing server via http.
println("Submitting certificate signing request to Corda certificate signing server.")
val requestId = certService.submitRequest(request)
// Persists request ID to file in case of node shutdown.
requestIdStore.writeLines(listOf(requestId))
println("Successfully submitted request to Corda certificate signing server, request ID: $requestId.")
requestId
} else {
val requestId = requestIdStore.readLines { it.findFirst().get() }
println("Resuming from previous certificate signing request, request ID: $requestId.")
requestId
}
}
}

View File

@ -1,12 +1,15 @@
package net.corda.node.utilities.certsigning
package net.corda.node.utilities.registration
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.security.cert.Certificate
interface CertificateSigningService {
interface NetworkRegistrationService {
/** Submits a CSR to the signing service and returns an opaque request ID. */
fun submitRequest(request: PKCS10CertificationRequest): String
/** Poll Certificate Signing Server for the request and returns a chain of certificates if request has been approved, null otherwise. */
@Throws(CertificateRequestException::class)
fun retrieveCertificates(requestId: String): Array<Certificate>?
}
class CertificateRequestException(message: String) : Exception(message)

View File

@ -20,7 +20,8 @@ class ArgsParserTest {
help = false,
logToConsole = false,
loggingLevel = Level.INFO,
isWebserver = false))
isWebserver = false,
isRegistration = false))
}
@Test

View File

@ -1,13 +1,11 @@
package net.corda.node.utilities.certsigning
package net.corda.node.utilities.registration
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.mock
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.X509Utilities
import net.corda.core.div
import net.corda.core.exists
import net.corda.core.readLines
import net.corda.testing.TestNodeConfiguration
import org.junit.Rule
import org.junit.Test
@ -16,7 +14,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class CertificateSignerTest {
class NetworkRegistrationHelperTest {
@Rule
@JvmField
val tempFolder = TemporaryFolder()
@ -29,7 +27,7 @@ class CertificateSignerTest {
X509Utilities.createSelfSignedCACert("CORDA_INTERMEDIATE_CA").certificate,
X509Utilities.createSelfSignedCACert("CORDA_ROOT_CA").certificate)
val certService: CertificateSigningService = mock {
val certService: NetworkRegistrationService = mock {
on { submitRequest(any()) }.then { id }
on { retrieveCertificates(eq(id)) }.then { certs }
}
@ -42,13 +40,15 @@ class CertificateSignerTest {
assertFalse(config.keyStoreFile.exists())
assertFalse(config.trustStoreFile.exists())
CertificateSigner(config, certService).buildKeyStore()
NetworkRegistrationHelper(config, certService).buildKeystore()
assertTrue(config.keyStoreFile.exists())
assertTrue(config.trustStoreFile.exists())
X509Utilities.loadKeyStore(config.keyStoreFile, config.keyStorePassword).run {
assertTrue(containsAlias(X509Utilities.CORDA_CLIENT_CA_PRIVATE_KEY))
assertFalse(containsAlias(X509Utilities.CORDA_CLIENT_CA_PRIVATE_KEY))
val certificateChain = getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
assertEquals(3, certificateChain.size)
assertTrue(containsAlias(X509Utilities.CORDA_CLIENT_CA))
assertFalse(containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA))
assertFalse(containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA_PRIVATE_KEY))
@ -64,7 +64,5 @@ class CertificateSignerTest {
assertTrue(containsAlias(X509Utilities.CORDA_ROOT_CA))
assertFalse(containsAlias(X509Utilities.CORDA_ROOT_CA_PRIVATE_KEY))
}
assertEquals(id, (config.certificatesDirectory / "certificate-request-id.txt").readLines { it.findFirst().get() })
}
}

View File

@ -1,5 +1,6 @@
@file:Suppress("UNUSED_PARAMETER", "UNCHECKED_CAST")
@file:JvmName("CoreTestUtils")
package net.corda.testing
import com.google.common.net.HostAndPort
@ -23,6 +24,7 @@ import net.corda.testing.node.MockIdentityService
import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties
import java.net.ServerSocket
import java.net.URL
import java.nio.file.Path
import java.security.KeyPair
import java.util.*
@ -155,6 +157,7 @@ data class TestNodeConfiguration(
override val nearestCity: String = "Null Island",
override val emailAddress: String = "",
override val exportJMXto: String = "",
override val devMode: Boolean = true) : NodeConfiguration
override val devMode: Boolean = true,
override val certificateSigningService: URL = URL("http://localhost")) : NodeConfiguration
fun Config.getHostAndPort(name: String) = HostAndPort.fromString(getString(name))