mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
CORDA-3452: Node: Configure the input of custom string in CSR (#5844)
* CORDA-3452: Node: Configure the input of custom string in CSR to be used by Identity Service * CORDA-3452: Remove unused import * CORDA-3452: Add test for networkServices configuration
This commit is contained in:
parent
ce774e459a
commit
73a0782f5d
@ -1693,7 +1693,7 @@
|
||||
<ID>MaxLineLength:ConfigSections.kt$DatabaseConfigSpec$private val initialiseAppSchema by enum(SchemaInitializationType::class).optional().withDefaultValue(DatabaseConfig.Defaults.initialiseAppSchema)</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$DatabaseConfigSpec$private val transactionIsolationLevel by enum(TransactionIsolationLevel::class).optional().withDefaultValue(DatabaseConfig.Defaults.transactionIsolationLevel)</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$DatabaseConfigSpec$return valid(DatabaseConfig(configuration[initialiseSchema], configuration[initialiseAppSchema], configuration[transactionIsolationLevel], configuration[exportHibernateJMXStatistics], configuration[mappedSchemaCacheSize]))</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$NetworkServicesConfigSpec$return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred]))</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$NetworkServicesConfigSpec$return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred], configuration[csrToken]))</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$NodeRpcSettingsSpec$return valid(NodeRpcSettings(configuration[address], configuration[adminAddress], configuration[standAloneBroker], configuration[useSsl], configuration[ssl]))</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$NotaryConfigSpec$return valid(NotaryConfig(configuration[validating], configuration[serviceLegalName], configuration[className], configuration[etaMessageThresholdSeconds], configuration[extraConfig], configuration[raft], configuration[bftSMaRt]))</ID>
|
||||
<ID>MaxLineLength:ConfigSections.kt$SSHDConfigurationSpec$override fun parseValid(configuration: Config): Valid<SSHDConfiguration></ID>
|
||||
@ -3808,6 +3808,7 @@
|
||||
<ID>SpreadOperator:FxTransactionBuildTutorial.kt$ForeignExchangeFlow$(*ourOutputState.map { StateAndContract(it, Cash.PROGRAM_ID) }.toTypedArray())</ID>
|
||||
<ID>SpreadOperator:FxTransactionBuildTutorial.kt$ForeignExchangeFlow$(*theirInputStates.toTypedArray())</ID>
|
||||
<ID>SpreadOperator:FxTransactionBuildTutorial.kt$ForeignExchangeFlow$(*theirOutputState.map { StateAndContract(it, Cash.PROGRAM_ID) }.toTypedArray())</ID>
|
||||
<ID>SpreadOperator:HTTPNetworkRegistrationService.kt$HTTPNetworkRegistrationService$(OpaqueBytes(request.encoded), "Platform-Version" to "${versionInfo.platformVersion}", "Client-Version" to versionInfo.releaseVersion, "Private-Network-Map" to (config.pnm?.toString() ?: ""), *(config.csrToken?.let { arrayOf(CENM_SUBMISSION_TOKEN to it) } ?: arrayOf()))</ID>
|
||||
<ID>SpreadOperator:HibernateQueryCriteriaParser.kt$AbstractQueryCriteriaParser$(*leftPredicates.toTypedArray())</ID>
|
||||
<ID>SpreadOperator:HibernateQueryCriteriaParser.kt$AbstractQueryCriteriaParser$(*leftPredicates.toTypedArray(), *rightPredicates.toTypedArray())</ID>
|
||||
<ID>SpreadOperator:HibernateQueryCriteriaParser.kt$AbstractQueryCriteriaParser$(*rightPredicates.toTypedArray())</ID>
|
||||
|
@ -513,6 +513,15 @@ networkServices
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
csrToken
|
||||
Optional token to provide alongside the certificate signing request (CSR) as part of the HTTP header during node registration.
|
||||
The token can be used by certificate signing authority (or Identity Manager Service) to verify additional identity requirements.
|
||||
The maximum token length is limited by the maximum HTTP header size, which is normally 8KB, assuming that a few other internal
|
||||
attributes are also present in the header. Also, the token length itself may never exceed 8192, limited by the database structure.
|
||||
Only US-ASCII characters are allowed.
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
.. _corda_configuration_file_p2pAddress:
|
||||
|
||||
p2pAddress
|
||||
|
@ -175,12 +175,15 @@ data class NotaryConfig(
|
||||
* set explicitly ([inferred] == false) or weather they have been inferred via the compatibilityZoneURL parameter
|
||||
* ([inferred] == true) where both the network map and doorman are running on the same endpoint. Only one,
|
||||
* compatibilityZoneURL or networkServices, can be set at any one time.
|
||||
* @property csrToken Optional token to provide alongside the certificate signing request (CSR) as part of the HTTP header during
|
||||
* node registration.
|
||||
*/
|
||||
data class NetworkServicesConfig(
|
||||
val doormanURL: URL,
|
||||
val networkMapURL: URL,
|
||||
val pnm: UUID? = null,
|
||||
val inferred: Boolean = false
|
||||
val inferred: Boolean = false,
|
||||
val csrToken: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -149,9 +149,10 @@ internal object NetworkServicesConfigSpec : Configuration.Specification<NetworkS
|
||||
private val networkMapURL by string().mapValid(::toURL)
|
||||
private val pnm by string().mapValid(::toUUID).optional()
|
||||
private val inferred by boolean().optional().withDefaultValue(false)
|
||||
private val csrToken by string(sensitive = true).optional()
|
||||
|
||||
override fun parseValid(configuration: Config): Valid<NetworkServicesConfig> {
|
||||
return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred]))
|
||||
return valid(NetworkServicesConfig(configuration[doormanURL], configuration[networkMapURL], configuration[pnm], configuration[inferred], configuration[csrToken]))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,13 @@ import javax.naming.ServiceUnavailableException
|
||||
|
||||
class HTTPNetworkRegistrationService(
|
||||
val config : NetworkServicesConfig,
|
||||
val versionInfo: VersionInfo
|
||||
val versionInfo: VersionInfo,
|
||||
private val registrationURL: URL = URL("${config.doormanURL}/certificate")
|
||||
) : NetworkRegistrationService {
|
||||
private val registrationURL = URL("${config.doormanURL}/certificate")
|
||||
|
||||
companion object {
|
||||
private val TRANSIENT_ERROR_STATUS_CODES = setOf(HTTP_BAD_GATEWAY, HTTP_UNAVAILABLE, HTTP_GATEWAY_TIMEOUT)
|
||||
private const val CENM_SUBMISSION_TOKEN = "X-CENM-Submission-Token"
|
||||
}
|
||||
|
||||
@Throws(CertificateRequestException::class)
|
||||
@ -59,7 +60,8 @@ class HTTPNetworkRegistrationService(
|
||||
return String(registrationURL.post(OpaqueBytes(request.encoded),
|
||||
"Platform-Version" to "${versionInfo.platformVersion}",
|
||||
"Client-Version" to versionInfo.releaseVersion,
|
||||
"Private-Network-Map" to (config.pnm?.toString() ?: "")))
|
||||
"Private-Network-Map" to (config.pnm?.toString() ?: ""),
|
||||
*(config.csrToken?.let { arrayOf(CENM_SUBMISSION_TOKEN to it) } ?: arrayOf())))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,6 +263,18 @@ class NodeConfigurationImplTest {
|
||||
assertEquals(JmxReporterType.JOLOKIA.toString(), nodeConfig.jmxReporterType.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `network services`() {
|
||||
val rawConfig = getConfig("test-config-with-networkservices.conf")
|
||||
val nodeConfig = rawConfig.parseAsNodeConfiguration().value()
|
||||
nodeConfig.networkServices!!.apply {
|
||||
assertEquals("https://registration.example.com", doormanURL.toString())
|
||||
assertEquals("https://cz.example.com", networkMapURL.toString())
|
||||
assertEquals("3c23d1a1-aa63-4beb-af9f-c8579dd5f89c", pnm.toString())
|
||||
assertEquals("my-TOKEN", csrToken)
|
||||
}
|
||||
}
|
||||
|
||||
private fun configDebugOptions(devMode: Boolean, devModeOptions: DevModeOptions?): NodeConfigurationImpl {
|
||||
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
|
||||
}
|
||||
|
@ -0,0 +1,73 @@
|
||||
package net.corda.node.utilities.registration
|
||||
|
||||
import com.nhaarman.mockito_kotlin.anyOrNull
|
||||
import com.nhaarman.mockito_kotlin.doReturn
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.whenever
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.node.services.config.NetworkServicesConfig
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||
import org.junit.Test
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class HTTPNetworkRegistrationServiceTest {
|
||||
|
||||
@Test
|
||||
fun `post request properties`() {
|
||||
val versionInfo = VersionInfo.UNKNOWN
|
||||
val pnm = UUID.randomUUID();
|
||||
val config = rigorousMock<NetworkServicesConfig>().also {
|
||||
doReturn(pnm).whenever(it).pnm
|
||||
doReturn(null).whenever(it).csrToken
|
||||
}
|
||||
var header = submitDummyRequest(versionInfo, config).requestProperties
|
||||
assertEquals(4, header.size)
|
||||
assertEquals(listOf(pnm.toString()), header["Private-Network-Map"])
|
||||
assertEquals(listOf(versionInfo.platformVersion.toString()), header["Platform-Version"])
|
||||
assertEquals(listOf(versionInfo.releaseVersion), header["Client-Version"])
|
||||
assertEquals(listOf("application/octet-stream"), header["Content-Type"])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `post request properties with CSR token`() {
|
||||
val versionInfo = VersionInfo.UNKNOWN
|
||||
val config = rigorousMock<NetworkServicesConfig>().also {
|
||||
doReturn(null).whenever(it).pnm
|
||||
doReturn("My-TOKEN").whenever(it).csrToken
|
||||
}
|
||||
var header = submitDummyRequest(versionInfo, config).requestProperties
|
||||
assertEquals(5, header.size)
|
||||
assertEquals(listOf(""), header["Private-Network-Map"])
|
||||
assertEquals(listOf(versionInfo.platformVersion.toString()), header["Platform-Version"])
|
||||
assertEquals(listOf(versionInfo.releaseVersion), header["Client-Version"])
|
||||
assertEquals(listOf("application/octet-stream"), header["Content-Type"])
|
||||
assertEquals(listOf("My-TOKEN"), header["X-CENM-Submission-Token"])
|
||||
}
|
||||
|
||||
private fun submitDummyRequest(versionInfo: VersionInfo, config: NetworkServicesConfig) : HttpURLConnection {
|
||||
val request = rigorousMock<PKCS10CertificationRequest>().also {
|
||||
doReturn("dummy".toByteArray()).whenever(it).encoded
|
||||
}
|
||||
val inputStream = rigorousMock<InputStream>().also {
|
||||
doReturn(-1).whenever(it).read()
|
||||
}
|
||||
val connection = rigorousMock<HttpURLConnection>().also {
|
||||
doReturn(inputStream).whenever(it).inputStream
|
||||
doReturn(mock<OutputStream>()).whenever(it).outputStream
|
||||
doReturn(HttpURLConnection.HTTP_OK).whenever(it).responseCode
|
||||
}
|
||||
val url = rigorousMock<URL>().also {
|
||||
doReturn(connection).whenever(it).openConnection()
|
||||
doReturn(connection).whenever(it).openConnection(anyOrNull())
|
||||
}
|
||||
val service = HTTPNetworkRegistrationService(config, versionInfo, url)
|
||||
service.submitRequest(request)
|
||||
return connection
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
myLegalName = "O=Bank A,L=London,C=GB"
|
||||
p2pAddress = "my-corda-node:10002"
|
||||
rpcSettings {
|
||||
address = "my-corda-node:10003"
|
||||
adminAddress = "my-corda-node:10004"
|
||||
}
|
||||
devMode = false
|
||||
networkServices {
|
||||
doormanURL = "https://registration.example.com"
|
||||
networkMapURL = "https://cz.example.com"
|
||||
pnm = "3c23d1a1-aa63-4beb-af9f-c8579dd5f89c"
|
||||
csrToken = "my-TOKEN"
|
||||
}
|
Loading…
Reference in New Issue
Block a user