CORDA-3201 - Enforce separate key for notary identity (#6308)

This commit is contained in:
Oliver Knowles 2020-07-20 10:59:08 +01:00 committed by GitHub
parent e6d5842a23
commit a500084d38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 263 additions and 90 deletions

View File

@ -1435,7 +1435,7 @@
<ID>ThrowsCount:JarScanningCordappLoader.kt$JarScanningCordappLoader$private fun parseVersion(versionStr: String?, attributeName: String): Int</ID>
<ID>ThrowsCount:LedgerDSLInterpreter.kt$Verifies$ fun failsWith(expectedMessage: String?): EnforceVerifyOrFail</ID>
<ID>ThrowsCount:MockServices.kt$ fun &lt;T : SerializeAsToken&gt; createMockCordaService(serviceHub: MockServices, serviceConstructor: (AppServiceHub) -&gt; T): T</ID>
<ID>ThrowsCount:NetworkRegistrationHelper.kt$NetworkRegistrationHelper$private fun validateCertificates(registeringPublicKey: PublicKey, certificates: List&lt;X509Certificate&gt;)</ID>
<ID>ThrowsCount:NetworkRegistrationHelper.kt$NetworkRegistrationHelper$private fun validateCertificates( registeringPublicKey: PublicKey, registeringLegalName: CordaX500Name, expectedCertRole: CertRole, certificates: List&lt;X509Certificate&gt; )</ID>
<ID>ThrowsCount:NodeInfoFilesCopier.kt$NodeInfoFilesCopier$private fun atomicCopy(source: Path, destination: Path)</ID>
<ID>ThrowsCount:NodeVaultService.kt$NodeVaultService$@Throws(VaultQueryException::class) private fun &lt;T : ContractState&gt; _queryBy(criteria: QueryCriteria, paging_: PageSpecification, sorting: Sort, contractStateType: Class&lt;out T&gt;, skipPagingChecks: Boolean): Vault.Page&lt;T&gt;</ID>
<ID>ThrowsCount:NodeVaultService.kt$NodeVaultService$private fun makeUpdates(batch: Iterable&lt;CoreTransaction&gt;, statesToRecord: StatesToRecord, previouslySeen: Boolean): List&lt;Vault.Update&lt;ContractState&gt;&gt;</ID>

View File

@ -614,11 +614,22 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
val myNotaryIdentity = configuration.notary?.let {
if (it.serviceLegalName != null) {
val (notaryIdentity, notaryIdentityKeyPair) = loadNotaryClusterIdentity(it.serviceLegalName)
val (notaryIdentity, notaryIdentityKeyPair) = loadNotaryServiceIdentity(it.serviceLegalName)
keyPairs += notaryIdentityKeyPair
notaryIdentity
} else {
// In case of a single notary service myNotaryIdentity will be the node's single identity.
// The only case where the myNotaryIdentity will be the node's legal identity is for existing single notary services running
// an older version. Current single notary services (V4.6+) sign requests using a separate notary service identity so the
// notary identity will be different from the node's legal identity.
// This check is here to ensure that a user does not accidentally/intentionally remove the serviceLegalName configuration
// parameter after a notary has been registered. If that was possible then notary would start and sign incoming requests
// with the node's legal identity key, corrupting the data.
check (!cryptoService.containsKey(DISTRIBUTED_NOTARY_KEY_ALIAS)) {
"The notary service key exists in the key store but no notary service legal name has been configured. " +
"Either include the relevant 'notary.serviceLegalName' configuration or validate this key is not necessary " +
"and remove from the key store."
}
identity
}
}
@ -1057,8 +1068,12 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
}
}
/** Loads pre-generated notary service cluster identity. */
private fun loadNotaryClusterIdentity(serviceLegalName: CordaX500Name): Pair<PartyAndCertificate, KeyPair> {
/**
* Loads notary service identity. In the case of the experimental RAFT and BFT notary clusters, this loads the pre-generated
* cluster identity that all worker nodes share. In the case of a simple single notary, this loads the notary service identity
* that is generated during initial registration and is used to sign notarisation requests.
* */
private fun loadNotaryServiceIdentity(serviceLegalName: CordaX500Name): Pair<PartyAndCertificate, KeyPair> {
val privateKeyAlias = "$DISTRIBUTED_NOTARY_KEY_ALIAS"
val compositeKeyAlias = "$DISTRIBUTED_NOTARY_COMPOSITE_KEY_ALIAS"

View File

@ -151,7 +151,7 @@ fun NodeConfiguration.shouldInitCrashShell() = shouldStartLocalShell() || should
data class NotaryConfig(
/** Specifies whether the notary validates transactions or not. */
val validating: Boolean,
/** The legal name of cluster in case of a distributed notary service. */
/** The legal name of the notary service identity. */
val serviceLegalName: CordaX500Name? = null,
/** The name of the notary service class to load. */
val className: String? = null,

View File

@ -25,10 +25,10 @@ import org.bouncycastle.operator.ContentSigner
import org.bouncycastle.util.io.pem.PemObject
import java.io.IOException
import java.io.StringWriter
import java.lang.IllegalStateException
import java.net.ConnectException
import java.net.URL
import java.nio.file.Path
import java.security.KeyPair
import java.security.PublicKey
import java.security.cert.X509Certificate
import java.time.Duration
@ -63,6 +63,7 @@ open class NetworkRegistrationHelper(
private val requestIdStore = certificatesDirectory / "certificate-request-id.txt"
protected val rootTrustStore: X509KeyStore
protected val rootCert: X509Certificate
private val notaryServiceConfig: NotaryServiceConfig? = config.notaryServiceConfig
init {
require(networkRootTrustStorePath.exists()) {
@ -95,34 +96,70 @@ open class NetworkRegistrationHelper(
return
}
notaryServiceConfig?.let { validateNotaryServiceKeyAndCert(certStore, it.notaryServiceKeyAlias, it.notaryServiceLegalName) }
val tlsCrlIssuerCert = getTlsCrlIssuerCert()
// We use SELF_SIGNED_PRIVATE_KEY as progress indicator so we just store a dummy key and cert.
// When registration succeeds, this entry should be deleted.
certStore.query { setPrivateKey(SELF_SIGNED_PRIVATE_KEY, AliasPrivateKey(SELF_SIGNED_PRIVATE_KEY), listOf(NOT_YET_REGISTERED_MARKER_KEYS_AND_CERTS.ECDSAR1_CERT), certificateStore.entryPassword) }
val nodeCaPublicKey = loadOrGenerateKeyPair()
val (entityPublicKey, receivedCertificates) = generateKeyPairAndCertificate(nodeCaKeyAlias, myLegalName, certRole, certStore)
val requestId = submitOrResumeCertificateSigningRequest(nodeCaPublicKey, cryptoService.getSigner(nodeCaKeyAlias))
val nodeCaCertificates = pollServerForCertificates(requestId)
validateCertificates(nodeCaPublicKey, nodeCaCertificates)
certStore.setCertPathOnly(nodeCaKeyAlias, nodeCaCertificates)
certStore.value.internal.deleteEntry(SELF_SIGNED_PRIVATE_KEY)
certStore.value.save()
logProgress("Private key '$nodeCaKeyAlias' and its certificate-chain stored successfully.")
onSuccess(nodeCaPublicKey, cryptoService.getSigner(nodeCaKeyAlias), nodeCaCertificates, tlsCrlIssuerCert?.subjectX500Principal?.toX500Name())
onSuccess(entityPublicKey, cryptoService.getSigner(nodeCaKeyAlias), receivedCertificates, tlsCrlIssuerCert?.subjectX500Principal?.toX500Name())
// All done, clean up temp files.
requestIdStore.deleteIfExists()
}
private fun loadOrGenerateKeyPair(): PublicKey {
return if (cryptoService.containsKey(nodeCaKeyAlias)) {
cryptoService.getPublicKey(nodeCaKeyAlias)!!
private fun generateKeyPairAndCertificate(keyAlias: String, legalName: CordaX500Name, certificateRole: CertRole, certStore: CertificateStore): Pair<PublicKey, List<X509Certificate>> {
val entityPublicKey = loadOrGenerateKeyPair(keyAlias)
val requestId = submitOrResumeCertificateSigningRequest(entityPublicKey, legalName, certificateRole, cryptoService.getSigner(keyAlias))
val receivedCertificates = pollServerForCertificates(requestId)
validateCertificates(entityPublicKey, legalName, certificateRole, receivedCertificates)
certStore.setCertPathOnly(keyAlias, receivedCertificates)
certStore.value.internal.deleteEntry(SELF_SIGNED_PRIVATE_KEY)
certStore.value.save()
logProgress("Private key '$keyAlias' and its certificate-chain stored successfully.")
return Pair(entityPublicKey, receivedCertificates)
}
/**
* Used when registering a notary to validate that the shared notary service key and certificate can be accessed.
*
* In the case that the notary service certificate and key is not available, a new key key is generated and a separate CSR is
* submitted to the Identity Manager.
*
* If this method successfully completes then the [cryptoService] will contain the notary service key and the [certStore] will contain
* the notary service certificate chain.
*
* @throws IllegalStateException If the notary service certificate already exists but the private key is not available.
*/
private fun validateNotaryServiceKeyAndCert(certStore: CertificateStore, notaryServiceKeyAlias: String, notaryServiceLegalName: CordaX500Name) {
if (certStore.contains(notaryServiceKeyAlias) && !cryptoService.containsKey(notaryServiceKeyAlias)) {
throw IllegalStateException("Notary service identity certificate exists but key pair missing. " +
"Please check no old certificates exist in the certificate store.")
}
if (certStore.contains(notaryServiceKeyAlias)) {
logProgress("Notary service certificate already exists. Continuing with node registration...")
return
}
logProgress("Generating notary service identity for $notaryServiceLegalName...")
generateKeyPairAndCertificate(notaryServiceKeyAlias, notaryServiceLegalName, CertRole.SERVICE_IDENTITY, certStore)
// The request id store is reused for the next step - registering the node identity.
// Therefore we can remove this to enable it to be reused.
requestIdStore.deleteIfExists()
}
private fun loadOrGenerateKeyPair(keyAlias: String): PublicKey {
return if (cryptoService.containsKey(keyAlias)) {
cryptoService.getPublicKey(keyAlias)!!
} else {
cryptoService.generateKeyPair(nodeCaKeyAlias, cryptoService.defaultTLSSignatureScheme())
cryptoService.generateKeyPair(keyAlias, cryptoService.defaultTLSSignatureScheme())
}
}
@ -137,26 +174,31 @@ open class NetworkRegistrationHelper(
return tlsCrlIssuerCert
}
private fun validateCertificates(registeringPublicKey: PublicKey, certificates: List<X509Certificate>) {
val nodeCACertificate = certificates.first()
private fun validateCertificates(
registeringPublicKey: PublicKey,
registeringLegalName: CordaX500Name,
expectedCertRole: CertRole,
certificates: List<X509Certificate>
) {
val receivedCertificate = certificates.first()
val nodeCaSubject = try {
CordaX500Name.build(nodeCACertificate.subjectX500Principal)
val certificateSubject = try {
CordaX500Name.build(receivedCertificate.subjectX500Principal)
} catch (e: IllegalArgumentException) {
throw CertificateRequestException("Received node CA cert has invalid subject name: ${e.message}")
throw CertificateRequestException("Received cert has invalid subject name: ${e.message}")
}
if (nodeCaSubject != myLegalName) {
throw CertificateRequestException("Subject of received node CA cert doesn't match with node legal name: $nodeCaSubject")
if (certificateSubject != registeringLegalName) {
throw CertificateRequestException("Subject of received cert doesn't match with legal name: $certificateSubject")
}
val nodeCaCertRole = try {
CertRole.extract(nodeCACertificate)
val receivedCertRole = try {
CertRole.extract(receivedCertificate)
} catch (e: IllegalArgumentException) {
throw CertificateRequestException("Unable to extract cert role from received node CA cert: ${e.message}")
throw CertificateRequestException("Unable to extract cert role from received cert: ${e.message}")
}
if (certRole != nodeCaCertRole) {
throw CertificateRequestException("Received certificate contains invalid cert role, expected '$certRole', got '$nodeCaCertRole'.")
if (expectedCertRole != receivedCertRole) {
throw CertificateRequestException("Received certificate contains invalid cert role, expected '$expectedCertRole', got '$receivedCertRole'.")
}
// Validate returned certificate is for the correct public key.
@ -169,22 +211,6 @@ open class NetworkRegistrationHelper(
logProgress("Certificate signing request approved, storing private key with the certificate chain.")
}
private fun CertificateStore.loadOrCreateKeyPair(alias: String, entryPassword: String = password): KeyPair {
// 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 (alias !in this) {
// NODE_CA should be TLS compatible due to the cert hierarchy structure.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(myLegalName.x500Principal, keyPair)
// Save to the key store.
with(value) {
setPrivateKey(alias, keyPair.private, listOf(selfSignCert), keyPassword = entryPassword)
save()
}
}
return query { getCertificateAndKeyPair(alias, entryPassword) }.keyPair
}
/**
* Poll Certificate Signing Server for approved certificate,
* enter a slow polling loop if server return null.
@ -226,20 +252,27 @@ open class NetworkRegistrationHelper(
* 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 publicKey public key for which we need a certificate.
* @param legalName legal name of the entity for which we need a certificate.
* @param certRole desired role of the entities certificate.
* @param contentSigner the [ContentSigner] that will sign the CSR.
* @return Request ID return from the server.
*/
private fun submitOrResumeCertificateSigningRequest(publicKey: PublicKey, contentSigner: ContentSigner): String {
private fun submitOrResumeCertificateSigningRequest(
publicKey: PublicKey,
legalName: CordaX500Name,
certRole: CertRole,
contentSigner: ContentSigner
): String {
try {
// Retrieve request id from file if exists, else post a request to server.
return if (!requestIdStore.exists()) {
val request = X509Utilities.createCertificateSigningRequest(myLegalName.x500Principal, emailAddress, publicKey, contentSigner, certRole)
val request = X509Utilities.createCertificateSigningRequest(legalName.x500Principal, emailAddress, publicKey, contentSigner, certRole)
val writer = StringWriter()
JcaPEMWriter(writer).use {
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
}
logProgress("Certificate signing request with the following information will be submitted to the Corda certificate signing server.")
logProgress("Legal Name: $myLegalName")
logProgress("Legal Name: $legalName")
logProgress("Email: $emailAddress")
logProgress("Public Key: $publicKey")
logProgress("$writer")
@ -277,7 +310,8 @@ class NodeRegistrationConfiguration(
val certificatesDirectory: Path,
val emailAddress: String,
val cryptoService: CryptoService,
val certificateStore: CertificateStore) {
val certificateStore: CertificateStore,
val notaryServiceConfig: NotaryServiceConfig? = null) {
constructor(config: NodeConfiguration) : this(
p2pSslOptions = config.p2pSslOptions,
@ -287,10 +321,29 @@ class NodeRegistrationConfiguration(
certificatesDirectory = config.certificatesDirectory,
emailAddress = config.emailAddress,
cryptoService = BCCryptoService(config.myLegalName.x500Principal, config.signingCertificateStore),
certificateStore = config.signingCertificateStore.get(true)
certificateStore = config.signingCertificateStore.get(true),
notaryServiceConfig = config.notary?.let {
// Validation of the presence of the notary service legal name is only done here and not in the top level configuration
// file. This is to maintain backwards compatibility with older notaries using the legacy identity structure. Older
// notaries will be signing requests using the nodes legal identity key and therefore no separate notary service entity
// exists. Just having the validation here prevents any new notaries from being created with the legacy identity scheme
// but still allows drop in JAR replacements for old notaries.
requireNotNull(it.serviceLegalName) {
"The notary service legal name must be provided via the 'notary.serviceLegalName' configuration parameter"
}
require(it.serviceLegalName != config.myLegalName) {
"The notary service legal name must be different from the node legal name"
}
NotaryServiceConfig(X509Utilities.DISTRIBUTED_NOTARY_KEY_ALIAS, it.serviceLegalName!!)
}
)
}
data class NotaryServiceConfig(
val notaryServiceKeyAlias: String,
val notaryServiceLegalName: CordaX500Name
)
class NodeRegistrationException(
message: String?,
cause: Throwable?

View File

@ -28,6 +28,8 @@ import net.corda.testing.core.ALICE_NAME
import net.corda.testing.internal.createDevIntermediateCaCertPath
import net.corda.coretesting.internal.rigorousMock
import net.corda.coretesting.internal.stubs.CertificateStoreStubs
import net.corda.node.services.config.NotaryConfig
import net.corda.testing.core.DUMMY_NOTARY_NAME
import org.assertj.core.api.Assertions.*
import org.bouncycastle.asn1.x509.GeneralName
import org.bouncycastle.asn1.x509.GeneralSubtree
@ -37,6 +39,7 @@ import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import org.junit.After
import org.junit.Before
import org.junit.Test
import java.lang.IllegalStateException
import java.nio.file.Files
import java.security.PublicKey
import java.security.cert.CertPathValidatorException
@ -71,6 +74,7 @@ class NetworkRegistrationHelperTest {
doReturn(null).whenever(it).tlsCertCrlDistPoint
doReturn(null).whenever(it).tlsCertCrlIssuer
doReturn(true).whenever(it).crlCheckSoftFail
doReturn(null).whenever(it).notary
}
}
@ -120,7 +124,7 @@ class NetworkRegistrationHelperTest {
@Test(timeout=300_000)
fun `missing truststore`() {
val nodeCaCertPath = createNodeCaCertPath()
val nodeCaCertPath = createCertPath()
assertThatThrownBy {
createFixedResponseRegistrationHelper(nodeCaCertPath)
}.hasMessageContaining("This file must contain the root CA cert of your compatibility zone. Please contact your CZ operator.")
@ -128,7 +132,7 @@ class NetworkRegistrationHelperTest {
@Test(timeout=300_000)
fun `node CA with incorrect cert role`() {
val nodeCaCertPath = createNodeCaCertPath(type = CertificateType.TLS)
val nodeCaCertPath = createCertPath(type = CertificateType.TLS)
saveNetworkTrustStore(CORDA_ROOT_CA to nodeCaCertPath.last())
val registrationHelper = createFixedResponseRegistrationHelper(nodeCaCertPath)
assertThatExceptionOfType(CertificateRequestException::class.java)
@ -139,7 +143,7 @@ class NetworkRegistrationHelperTest {
@Test(timeout=300_000)
fun `node CA with incorrect subject`() {
val invalidName = CordaX500Name("Foo", "MU", "GB")
val nodeCaCertPath = createNodeCaCertPath(legalName = invalidName)
val nodeCaCertPath = createCertPath(legalName = invalidName)
saveNetworkTrustStore(CORDA_ROOT_CA to nodeCaCertPath.last())
val registrationHelper = createFixedResponseRegistrationHelper(nodeCaCertPath)
assertThatExceptionOfType(CertificateRequestException::class.java)
@ -220,36 +224,118 @@ class NetworkRegistrationHelperTest {
createRegistrationHelper(rootAndIntermediateCA = rootAndIntermediateCA).generateKeysAndRegister()
}
private fun createNodeCaCertPath(type: CertificateType = CertificateType.NODE_CA,
legalName: CordaX500Name = nodeLegalName,
publicKey: PublicKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME).public,
rootAndIntermediateCA: Pair<CertificateAndKeyPair, CertificateAndKeyPair> = createDevIntermediateCaCertPath()): List<X509Certificate> {
@Test(timeout=300_000)
fun `successful registration for notary node`() {
val notaryServiceLegalName = DUMMY_NOTARY_NAME
val notaryNodeConfig = createNotaryNodeConfiguration(notaryServiceLegalName = notaryServiceLegalName)
assertThat(notaryNodeConfig.notary).isNotNull
val rootAndIntermediateCA = createDevIntermediateCaCertPath().also {
saveNetworkTrustStore(CORDA_ROOT_CA to it.first.certificate)
}
// Mock out the registration service to ensure notary service registration is handled correctly
createRegistrationHelper(CertRole.NODE_CA, notaryNodeConfig) {
when {
it.subject == nodeLegalName.toX500Name() -> {
val certType = CertificateType.values().first { it.role == CertRole.NODE_CA }
createCertPath(rootAndIntermediateCA = rootAndIntermediateCA, publicKey = it.publicKey, type = certType)
}
it.subject == notaryServiceLegalName.toX500Name() -> {
val certType = CertificateType.values().first { it.role == CertRole.SERVICE_IDENTITY }
createCertPath(rootAndIntermediateCA = rootAndIntermediateCA, publicKey = it.publicKey, type = certType, legalName = notaryServiceLegalName)
}
else -> throw IllegalStateException("Unknown CSR")
}
}.generateKeysAndRegister()
val nodeKeystore = config.signingCertificateStore.get()
nodeKeystore.run {
assertFalse(contains(X509Utilities.CORDA_INTERMEDIATE_CA))
assertFalse(contains(CORDA_ROOT_CA))
assertFalse(contains(X509Utilities.CORDA_CLIENT_TLS))
assertThat(CertRole.extract(this[X509Utilities.CORDA_CLIENT_CA])).isEqualTo(CertRole.NODE_CA)
assertThat(CertRole.extract(this[DISTRIBUTED_NOTARY_KEY_ALIAS])).isEqualTo(CertRole.SERVICE_IDENTITY)
}
}
@Test(timeout=300_000)
fun `notary registration fails when no separate notary service identity configured`() {
val notaryNodeConfig = createNotaryNodeConfiguration(notaryServiceLegalName = null)
assertThat(notaryNodeConfig.notary).isNotNull
assertThatThrownBy {
createRegistrationHelper(nodeConfig = notaryNodeConfig)
}.isInstanceOf(IllegalArgumentException::class.java)
.hasMessageContaining("notary service legal name must be provided")
}
@Test(timeout=300_000)
fun `notary registration fails when notary service identity configured with same legal name as node`() {
val notaryNodeConfig = createNotaryNodeConfiguration(notaryServiceLegalName = config.myLegalName)
assertThat(notaryNodeConfig.notary).isNotNull
assertThatThrownBy {
createRegistrationHelper(nodeConfig = notaryNodeConfig)
}.isInstanceOf(IllegalArgumentException::class.java)
.hasMessageContaining("notary service legal name must be different from the node")
}
private fun createNotaryNodeConfiguration(notaryServiceLegalName: CordaX500Name?): NodeConfiguration {
return rigorousMock<NodeConfiguration>().also {
doReturn(config.baseDirectory).whenever(it).baseDirectory
doReturn(config.certificatesDirectory).whenever(it).certificatesDirectory
doReturn(CertificateStoreStubs.P2P.withCertificatesDirectory(config.certificatesDirectory)).whenever(it).p2pSslOptions
doReturn(CertificateStoreStubs.Signing.withCertificatesDirectory(config.certificatesDirectory)).whenever(it)
.signingCertificateStore
doReturn(nodeLegalName).whenever(it).myLegalName
doReturn("").whenever(it).emailAddress
doReturn(null).whenever(it).tlsCertCrlDistPoint
doReturn(null).whenever(it).tlsCertCrlIssuer
doReturn(true).whenever(it).crlCheckSoftFail
doReturn(NotaryConfig(validating = false, serviceLegalName = notaryServiceLegalName)).whenever(it).notary
}
}
private fun createCertPath(type: CertificateType = CertificateType.NODE_CA,
legalName: CordaX500Name = nodeLegalName,
publicKey: PublicKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME).public,
rootAndIntermediateCA: Pair<CertificateAndKeyPair, CertificateAndKeyPair> = createDevIntermediateCaCertPath()): List<X509Certificate> {
val (rootCa, intermediateCa) = rootAndIntermediateCA
val nameConstraints = if (type == CertificateType.NODE_CA) {
NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName.toX500Name()))), arrayOf())
} else {
null
}
val nodeCaCert = X509Utilities.createCertificate(
val cert = X509Utilities.createCertificate(
type,
intermediateCa.certificate,
intermediateCa.keyPair,
legalName.x500Principal,
publicKey,
nameConstraints = nameConstraints)
return listOf(nodeCaCert, intermediateCa.certificate, rootCa.certificate)
return listOf(cert, intermediateCa.certificate, rootCa.certificate)
}
private fun createFixedResponseRegistrationHelper(response: List<X509Certificate>, certRole: CertRole = CertRole.NODE_CA): NetworkRegistrationHelper {
return createRegistrationHelper(certRole) { response }
}
private fun createRegistrationHelper(certRole: CertRole = CertRole.NODE_CA, rootAndIntermediateCA: Pair<CertificateAndKeyPair, CertificateAndKeyPair> = createDevIntermediateCaCertPath()) = createRegistrationHelper(certRole) {
private fun createRegistrationHelper(
certRole: CertRole = CertRole.NODE_CA,
rootAndIntermediateCA: Pair<CertificateAndKeyPair, CertificateAndKeyPair> = createDevIntermediateCaCertPath(),
nodeConfig: NodeConfiguration = config
) = createRegistrationHelper(certRole, nodeConfig) {
val certType = CertificateType.values().first { it.role == certRole }
createNodeCaCertPath(rootAndIntermediateCA = rootAndIntermediateCA, publicKey = it.publicKey, type = certType)
createCertPath(rootAndIntermediateCA = rootAndIntermediateCA, publicKey = it.publicKey, type = certType)
}
private fun createRegistrationHelper(certRole: CertRole = CertRole.NODE_CA, dynamicResponse: (JcaPKCS10CertificationRequest) -> List<X509Certificate>): NetworkRegistrationHelper {
private fun createRegistrationHelper(
certRole: CertRole = CertRole.NODE_CA,
nodeConfig: NodeConfiguration = config,
dynamicResponse: (JcaPKCS10CertificationRequest) -> List<X509Certificate>
): NetworkRegistrationHelper {
val certService = rigorousMock<NetworkRegistrationService>().also {
val requests = mutableMapOf<String, JcaPKCS10CertificationRequest>()
doAnswer {
@ -265,11 +351,11 @@ class NetworkRegistrationHelperTest {
}
return when (certRole) {
CertRole.NODE_CA -> NodeRegistrationHelper(NodeRegistrationConfiguration(config), certService, NodeRegistrationOption(config.certificatesDirectory / networkRootTrustStoreFileName, networkRootTrustStorePassword))
CertRole.NODE_CA -> NodeRegistrationHelper(NodeRegistrationConfiguration(nodeConfig), certService, NodeRegistrationOption(nodeConfig.certificatesDirectory / networkRootTrustStoreFileName, networkRootTrustStorePassword))
CertRole.SERVICE_IDENTITY -> NetworkRegistrationHelper(
NodeRegistrationConfiguration(config),
NodeRegistrationConfiguration(nodeConfig),
certService,
config.certificatesDirectory / networkRootTrustStoreFileName,
nodeConfig.certificatesDirectory / networkRootTrustStoreFileName,
networkRootTrustStorePassword,
DISTRIBUTED_NOTARY_KEY_ALIAS,
CertRole.SERVICE_IDENTITY)

View File

@ -92,8 +92,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask,
cordapp project(':samples:attachment-demo:workflows')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating: true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating: true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
cordapps = []
rpcUsers = ext.rpcUsers

View File

@ -50,8 +50,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask,
cordapp project(':finance:contracts')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating: true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating: true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
address "localhost:10003"

View File

@ -27,8 +27,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask,
cordapp project(':samples:cordapp-configuration:workflows')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating : true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
port 10003

View File

@ -62,8 +62,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask])
cordapp project(':samples:irs-demo:cordapp:workflows-irs')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating : true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
address("localhost:10003")
@ -121,7 +123,9 @@ task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar', n
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
notary = [validating : true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
cordapps = ["${project(":finance").group}:contracts:$corda_release_version", "${project(":finance").group}:workflows:$corda_release_version"]
rpcUsers = rpcUsersList
useTestClock true

View File

@ -38,8 +38,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask])
cordapp project(':samples:network-verifier:workflows')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : false]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating : false,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
port 10003

View File

@ -55,13 +55,15 @@ task deployNodesSingle(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Notary Service,L=Zurich,C=CH"
name "O=Notary Node,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
adminAddress "localhost:10110"
}
notary = [validating: true]
notary = [validating: true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
}
}
@ -85,7 +87,7 @@ task deployNodesCustom(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Notary Service,L=Zurich,C=CH"
name "O=Notary Node,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
@ -93,7 +95,8 @@ task deployNodesCustom(type: Cordform, dependsOn: ['jar', nodeTask, webTask]) {
}
notary = [
validating: true,
className: "net.corda.notarydemo.MyCustomValidatingNotaryService"
className: "net.corda.notarydemo.MyCustomValidatingNotaryService",
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
}
}

View File

@ -93,8 +93,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask,
rpcUsers = [['username': "default", 'password': "default", 'permissions': [ 'ALL' ]]]
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating : true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
address "localhost:10014"

View File

@ -83,8 +83,10 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', nodeTask])
cordapp project(':samples:trader-demo:workflows-trader')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating : true]
name "O=Notary Node,L=Zurich,C=CH"
notary = [validating : true,
serviceLegalName: "O=Notary Service,L=Zurich,C=CH"
]
p2pPort 10002
rpcSettings {
address "localhost:10003"