mirror of
https://github.com/corda/corda.git
synced 2025-01-30 16:14:39 +00:00
CORDA-1661 Reverting DEV certificates (#3422)
* CORDA-1661 Reverting DEV certificates * Addressing review comments * Removed the intermediate certificate from the trust store and added some test cases for the revocation check
This commit is contained in:
parent
868763f82b
commit
e00c7706c3
Binary file not shown.
Binary file not shown.
@ -0,0 +1,41 @@
|
|||||||
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
|
import net.corda.core.internal.validate
|
||||||
|
import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_FILE
|
||||||
|
import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_PASS
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
import java.security.cert.TrustAnchor
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
|
class DevCertificatesTest {
|
||||||
|
private companion object {
|
||||||
|
const val OLD_DEV_KEYSTORE_PASS = "password"
|
||||||
|
const val OLD_NODE_DEV_KEYSTORE_FILE_NAME = "nodekeystore.jks"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
val tempFolder = TemporaryFolder()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `create server certificate in keystore for SSL`() {
|
||||||
|
// given
|
||||||
|
val newTrustStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/$DEV_CA_TRUST_STORE_FILE"), DEV_CA_TRUST_STORE_PASS)
|
||||||
|
val newTrustRoot = newTrustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
|
||||||
|
val newTrustAnchor = TrustAnchor(newTrustRoot, null)
|
||||||
|
|
||||||
|
val oldNodeCaKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("regression-test/$OLD_NODE_DEV_KEYSTORE_FILE_NAME"), OLD_DEV_KEYSTORE_PASS)
|
||||||
|
val oldX509Certificates = oldNodeCaKeyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA).map {
|
||||||
|
it as X509Certificate
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
val certPath = X509Utilities.buildCertPath(*oldX509Certificates)
|
||||||
|
|
||||||
|
// when
|
||||||
|
certPath.validate(newTrustAnchor)
|
||||||
|
|
||||||
|
// then no exception is thrown
|
||||||
|
}
|
||||||
|
}
|
BIN
node-api/src/test/resources/regression-test/nodekeystore.jks
Normal file
BIN
node-api/src/test/resources/regression-test/nodekeystore.jks
Normal file
Binary file not shown.
BIN
node-api/src/test/resources/regression-test/sslkeystore.jks
Normal file
BIN
node-api/src/test/resources/regression-test/sslkeystore.jks
Normal file
Binary file not shown.
@ -94,7 +94,7 @@ class CertificateRevocationListNodeTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Simple AMPQ Client to Server connection works`() {
|
fun `Simple AMPQ Client to Server connection works and soft fail is enabled`() {
|
||||||
val crlCheckSoftFail = true
|
val crlCheckSoftFail = true
|
||||||
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
||||||
amqpServer.use {
|
amqpServer.use {
|
||||||
@ -126,7 +126,39 @@ class CertificateRevocationListNodeTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `AMPQ Client to Server connection fails when client's certificate is revoked`() {
|
fun `Simple AMPQ Client to Server connection works and soft fail is disabled`() {
|
||||||
|
val crlCheckSoftFail = false
|
||||||
|
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
||||||
|
amqpServer.use {
|
||||||
|
amqpServer.start()
|
||||||
|
val receiveSubs = amqpServer.onReceive.subscribe {
|
||||||
|
assertEquals(BOB_NAME.toString(), it.sourceLegalName)
|
||||||
|
assertEquals(P2P_PREFIX + "Test", it.topic)
|
||||||
|
assertEquals("Test", String(it.payload))
|
||||||
|
it.complete(true)
|
||||||
|
}
|
||||||
|
val (amqpClient, _) = createClient(serverPort, crlCheckSoftFail)
|
||||||
|
amqpClient.use {
|
||||||
|
val serverConnected = amqpServer.onConnection.toFuture()
|
||||||
|
val clientConnected = amqpClient.onConnection.toFuture()
|
||||||
|
amqpClient.start()
|
||||||
|
val serverConnect = serverConnected.get()
|
||||||
|
assertEquals(true, serverConnect.connected)
|
||||||
|
val clientConnect = clientConnected.get()
|
||||||
|
assertEquals(true, clientConnect.connected)
|
||||||
|
val msg = amqpClient.createMessage("Test".toByteArray(),
|
||||||
|
P2P_PREFIX + "Test",
|
||||||
|
ALICE_NAME.toString(),
|
||||||
|
emptyMap())
|
||||||
|
amqpClient.write(msg)
|
||||||
|
assertEquals(MessageStatus.Acknowledged, msg.onComplete.get())
|
||||||
|
receiveSubs.unsubscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `AMPQ Client to Server connection fails when client's certificate is revoked and soft fail is enabled`() {
|
||||||
val crlCheckSoftFail = true
|
val crlCheckSoftFail = true
|
||||||
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
||||||
amqpServer.use {
|
amqpServer.use {
|
||||||
@ -146,6 +178,27 @@ class CertificateRevocationListNodeTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `AMPQ Client to Server connection fails when client's certificate is revoked and soft fail is disabled`() {
|
||||||
|
val crlCheckSoftFail = false
|
||||||
|
val (amqpServer, _) = createServer(serverPort, crlCheckSoftFail = crlCheckSoftFail)
|
||||||
|
amqpServer.use {
|
||||||
|
amqpServer.start()
|
||||||
|
amqpServer.onReceive.subscribe {
|
||||||
|
it.complete(true)
|
||||||
|
}
|
||||||
|
val (amqpClient, clientCert) = createClient(serverPort, crlCheckSoftFail)
|
||||||
|
revokedNodeCerts.add(clientCert.serialNumber)
|
||||||
|
amqpClient.use {
|
||||||
|
val serverConnected = amqpServer.onConnection.toFuture()
|
||||||
|
amqpClient.onConnection.toFuture()
|
||||||
|
amqpClient.start()
|
||||||
|
val serverConnect = serverConnected.get()
|
||||||
|
assertEquals(false, serverConnect.connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `AMPQ Client to Server connection fails when servers's certificate is revoked`() {
|
fun `AMPQ Client to Server connection fails when servers's certificate is revoked`() {
|
||||||
val crlCheckSoftFail = true
|
val crlCheckSoftFail = true
|
||||||
|
@ -15,12 +15,10 @@ import net.corda.core.flows.FlowException
|
|||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.AbstractAttachment
|
import net.corda.core.internal.AbstractAttachment
|
||||||
import net.corda.core.internal.x500Name
|
|
||||||
import net.corda.core.serialization.*
|
import net.corda.core.serialization.*
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
|
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
|
||||||
import net.corda.nodeapi.internal.DEV_INTERMEDIATE_CA
|
|
||||||
import net.corda.nodeapi.internal.crypto.ContentSignerBuilder
|
import net.corda.nodeapi.internal.crypto.ContentSignerBuilder
|
||||||
import net.corda.serialization.internal.*
|
import net.corda.serialization.internal.*
|
||||||
import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive
|
import net.corda.serialization.internal.amqp.SerializerFactory.Companion.isPrimitive
|
||||||
@ -35,6 +33,7 @@ import org.apache.qpid.proton.amqp.*
|
|||||||
import org.apache.qpid.proton.codec.DecoderImpl
|
import org.apache.qpid.proton.codec.DecoderImpl
|
||||||
import org.apache.qpid.proton.codec.EncoderImpl
|
import org.apache.qpid.proton.codec.EncoderImpl
|
||||||
import org.assertj.core.api.Assertions.*
|
import org.assertj.core.api.Assertions.*
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.cert.X509v2CRLBuilder
|
import org.bouncycastle.cert.X509v2CRLBuilder
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
|
import org.bouncycastle.cert.jcajce.JcaX509CRLConverter
|
||||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||||
@ -657,8 +656,8 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
val scheme = AMQPServerSerializationScheme(emptyList())
|
val scheme = AMQPServerSerializationScheme(emptyList())
|
||||||
val func = scheme::class.superclasses.single { it.simpleName == "AbstractAMQPSerializationScheme" }
|
val func = scheme::class.superclasses.single { it.simpleName == "AbstractAMQPSerializationScheme" }
|
||||||
.java.getDeclaredMethod("registerCustomSerializers",
|
.java.getDeclaredMethod("registerCustomSerializers",
|
||||||
SerializationContext::class.java,
|
SerializationContext::class.java,
|
||||||
SerializerFactory::class.java)
|
SerializerFactory::class.java)
|
||||||
func.isAccessible = true
|
func.isAccessible = true
|
||||||
|
|
||||||
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
val factory = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader())
|
||||||
@ -1011,7 +1010,7 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun emptyCrl(): X509CRL {
|
private fun emptyCrl(): X509CRL {
|
||||||
val builder = X509v2CRLBuilder(CordaX500Name.build(DEV_INTERMEDIATE_CA.certificate.issuerX500Principal).x500Name, Date())
|
val builder = X509v2CRLBuilder(X500Name("CN=Corda Root CA, O=R3 HoldCo LLC, L=New York, C=US"), Date())
|
||||||
val provider = BouncyCastleProvider()
|
val provider = BouncyCastleProvider()
|
||||||
val crlHolder = builder.build(ContentSignerBuilder.build(Crypto.RSA_SHA256, Crypto.generateKeyPair(Crypto.RSA_SHA256).private, provider))
|
val crlHolder = builder.build(ContentSignerBuilder.build(Crypto.RSA_SHA256, Crypto.generateKeyPair(Crypto.RSA_SHA256).private, provider))
|
||||||
return JcaX509CRLConverter().setProvider(provider).getCRL(crlHolder)
|
return JcaX509CRLConverter().setProvider(provider).getCRL(crlHolder)
|
||||||
@ -1320,12 +1319,12 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DataClassByInterface<V> {
|
interface DataClassByInterface<V> {
|
||||||
val v : V
|
val v: V
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun dataClassBy() {
|
fun dataClassBy() {
|
||||||
data class C (val s: String) : DataClassByInterface<String> {
|
data class C(val s: String) : DataClassByInterface<String> {
|
||||||
override val v: String = "-- $s"
|
override val v: String = "-- $s"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,8 +1338,8 @@ class SerializationOutputTests(private val compression: CordaSerializationEncodi
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
val i2 = DeserializationInput(testDefaultFactory()).deserialize(bytes)
|
val i2 = DeserializationInput(testDefaultFactory()).deserialize(bytes)
|
||||||
} catch (e : NotSerializableException) {
|
} catch (e: NotSerializableException) {
|
||||||
throw Error ("Deserializing serialized \$C should not throw")
|
throw Error("Deserializing serialized \$C should not throw")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user