mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
CORDA-1476 Adding TLS certificate CRL extension point configs (#3140)
* Adding TLS certificate CRL extension point configs * Addressing review comments * Addressing review comments - round 3
This commit is contained in:
parent
27803cdc9e
commit
0ee116a1d9
@ -205,6 +205,13 @@ absolute path to the node's base directory.
|
||||
|
||||
.. note:: This is temporary feature for onboarding network participants that limits their visibility for privacy reasons.
|
||||
|
||||
:tlsCertCrlDistPoint: CRL distribution point (i.e. URL) for the TLS certificate. Default value is NULL, which indicates no CRL availability for the TLS certificate.
|
||||
Note: If crlCheckSoftFail is FALSE (meaning that there is the strict CRL checking mode) this value needs to be set.
|
||||
|
||||
:tlsCertCrlIssuer: CRL issuer (given in the X500 name format) for the TLS certificate. Default value is NULL,
|
||||
which indicates that the issuer of the TLS certificate is also the issuer of the CRL.
|
||||
Note: If this parameter is set then the tlsCertCrlDistPoint needs to be set as well.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
|
@ -12,6 +12,7 @@ import net.corda.node.services.config.rpc.NodeRpcOptions
|
||||
import net.corda.nodeapi.internal.config.*
|
||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
||||
import net.corda.tools.shell.SSHDConfiguration
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.slf4j.Logger
|
||||
import java.net.URL
|
||||
import java.nio.file.Path
|
||||
@ -52,6 +53,8 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
||||
// do not change this value without syncing it with ScheduledFlowsDrainingModeTest
|
||||
val drainingModePollPeriod: Duration get() = Duration.ofSeconds(5)
|
||||
val extraNetworkMapKeys: List<UUID>
|
||||
val tlsCertCrlDistPoint: URL?
|
||||
val tlsCertCrlIssuer: String?
|
||||
|
||||
fun validate(): List<String>
|
||||
|
||||
@ -133,6 +136,8 @@ data class NodeConfigurationImpl(
|
||||
override val crlCheckSoftFail: Boolean,
|
||||
override val dataSourceProperties: Properties,
|
||||
override val compatibilityZoneURL: URL? = null,
|
||||
override val tlsCertCrlDistPoint: URL? = null,
|
||||
override val tlsCertCrlIssuer: String? = null,
|
||||
override val rpcUsers: List<User>,
|
||||
override val security: SecurityConfiguration? = null,
|
||||
override val verifierType: VerifierType,
|
||||
@ -179,10 +184,29 @@ data class NodeConfigurationImpl(
|
||||
}.asOptions(fallbackSslOptions)
|
||||
}
|
||||
|
||||
private fun validateTlsCertCrlConfig(): List<String> {
|
||||
val errors = mutableListOf<String>()
|
||||
if (tlsCertCrlIssuer != null) {
|
||||
if (tlsCertCrlDistPoint == null) {
|
||||
errors += "tlsCertCrlDistPoint needs to be specified when tlsCertCrlIssuer is not NULL"
|
||||
}
|
||||
try {
|
||||
X500Name(tlsCertCrlIssuer)
|
||||
} catch (e: Exception) {
|
||||
errors += "Error when parsing tlsCertCrlIssuer: ${e.message}"
|
||||
}
|
||||
}
|
||||
if (!crlCheckSoftFail && tlsCertCrlDistPoint == null) {
|
||||
errors += "tlsCertCrlDistPoint needs to be specified when crlCheckSoftFail is FALSE"
|
||||
}
|
||||
return errors
|
||||
}
|
||||
|
||||
override fun validate(): List<String> {
|
||||
val errors = mutableListOf<String>()
|
||||
errors += validateDevModeOptions()
|
||||
errors += validateRpcOptions(rpcOptions)
|
||||
errors += validateTlsCertCrlConfig()
|
||||
return errors
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ package net.corda.node.utilities.registration
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.node.NodeRegistrationOption
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.nodeapi.internal.config.SSLConfiguration
|
||||
@ -12,6 +13,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.openssl.jcajce.JcaPEMWriter
|
||||
import org.bouncycastle.util.io.pem.PemObject
|
||||
import java.io.StringWriter
|
||||
@ -216,6 +218,10 @@ class NodeRegistrationHelper(private val config: NodeConfiguration, certService:
|
||||
CORDA_CLIENT_CA,
|
||||
CertRole.NODE_CA) {
|
||||
|
||||
companion object {
|
||||
val logger = contextLogger()
|
||||
}
|
||||
|
||||
override fun onSuccess(nodeCAKeyPair: KeyPair, certificates: List<X509Certificate>) {
|
||||
createSSLKeystore(nodeCAKeyPair, certificates)
|
||||
createTruststore(certificates.last())
|
||||
@ -230,7 +236,10 @@ class NodeRegistrationHelper(private val config: NodeConfiguration, certService:
|
||||
certificates.first(),
|
||||
nodeCAKeyPair,
|
||||
config.myLegalName.x500Principal,
|
||||
sslKeyPair.public)
|
||||
sslKeyPair.public,
|
||||
crlDistPoint = config.tlsCertCrlDistPoint?.toString(),
|
||||
crlIssuer = if (config.tlsCertCrlIssuer != null) X500Name(config.tlsCertCrlIssuer) else null)
|
||||
logger.info("Generated TLS certificate: $sslCert")
|
||||
setPrivateKey(CORDA_CLIENT_TLS, sslKeyPair.private, listOf(sslCert) + certificates)
|
||||
}
|
||||
println("SSL private key and certificate stored in ${config.sslKeystore}.")
|
||||
|
@ -13,6 +13,7 @@ import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Test
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import kotlin.test.assertFalse
|
||||
@ -28,6 +29,27 @@ class NodeConfigurationImplTest {
|
||||
configDebugOptions(false, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can't have tlsCertCrlDistPoint null when tlsCertCrlIssuer is given`() {
|
||||
val configValidationResult = configTlsCertCrlOptions(null, "C=US, L=New York, OU=Corda, O=R3 HoldCo LLC, CN=Corda Root CA").validate()
|
||||
assertTrue { configValidationResult.isNotEmpty() }
|
||||
assertThat(configValidationResult.first()).contains("tlsCertCrlDistPoint needs to be specified when tlsCertCrlIssuer is not NULL")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `tlsCertCrlIssuer validation fails when misconfigured`() {
|
||||
val configValidationResult = configTlsCertCrlOptions(URL("http://test.com/crl"), "Corda Root CA").validate()
|
||||
assertTrue { configValidationResult.isNotEmpty() }
|
||||
assertThat(configValidationResult.first()).contains("Error when parsing tlsCertCrlIssuer:")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `can't have tlsCertCrlDistPoint null when crlCheckSoftFail is false`() {
|
||||
val configValidationResult = configTlsCertCrlOptions(null, null, false).validate()
|
||||
assertTrue { configValidationResult.isNotEmpty() }
|
||||
assertThat(configValidationResult.first()).contains("tlsCertCrlDistPoint needs to be specified when crlCheckSoftFail is FALSE")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `check devModeOptions flag helper`() {
|
||||
assertTrue { configDebugOptions(true, null).shouldCheckCheckpoints() }
|
||||
@ -114,8 +136,8 @@ class NodeConfigurationImplTest {
|
||||
return testConfiguration.copy(devMode = devMode, devModeOptions = devModeOptions)
|
||||
}
|
||||
|
||||
private fun testConfiguration(dataSourceProperties: Properties): NodeConfigurationImpl {
|
||||
return testConfiguration.copy(dataSourceProperties = dataSourceProperties)
|
||||
private fun configTlsCertCrlOptions(tlsCertCrlDistPoint: URL?, tlsCertCrlIssuer: String?, crlCheckSoftFail: Boolean = true): NodeConfiguration {
|
||||
return testConfiguration.copy(tlsCertCrlDistPoint = tlsCertCrlDistPoint, tlsCertCrlIssuer = tlsCertCrlIssuer, crlCheckSoftFail = crlCheckSoftFail)
|
||||
}
|
||||
|
||||
private val testConfiguration = testNodeConfiguration()
|
||||
@ -147,7 +169,8 @@ class NodeConfigurationImplTest {
|
||||
devMode = true,
|
||||
noLocalShell = false,
|
||||
rpcSettings = rpcSettings,
|
||||
crlCheckSoftFail = true
|
||||
crlCheckSoftFail = true,
|
||||
tlsCertCrlDistPoint = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,8 @@ class NetworkRegistrationHelperTest {
|
||||
doReturn("cordacadevpass").whenever(it).keyStorePassword
|
||||
doReturn(nodeLegalName).whenever(it).myLegalName
|
||||
doReturn("").whenever(it).emailAddress
|
||||
doReturn(null).whenever(it).tlsCertCrlDistPoint
|
||||
doReturn(null).whenever(it).tlsCertCrlIssuer
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user