Doorman generates trust store file, containing the root cert, instead of the .pem file (#241)

This commit is contained in:
Shams Asari 2017-12-21 13:54:10 +00:00 committed by GitHub
parent 269a4ba79d
commit 2a0eefd351
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 36 deletions

View File

@ -9,7 +9,7 @@ To build a fat jar containing all the doorman code you can simply invoke:
The built file will appear in: The built file will appear in:
``` ```
network-management/capsule/build/libs/doorman-<VERSION>.jar network-management/capsule/build/libs/doorman-<version>.jar
``` ```
## HSM signing server ## HSM signing server
To build a fat jar containing all the HSM signer code you can simply invoke: To build a fat jar containing all the HSM signer code you can simply invoke:
@ -19,7 +19,7 @@ To build a fat jar containing all the HSM signer code you can simply invoke:
The built file will appear in: The built file will appear in:
``` ```
network-management/capsule-hsm/build/libs/hsm-<VERSION>.jar network-management/capsule-hsm/build/libs/hsm-<version>.jar
``` ```
The binaries can also be obtained from artifactory after deployment in TeamCity. The binaries can also be obtained from artifactory after deployment in TeamCity.
@ -28,12 +28,13 @@ To run the HSM signing server:
``` ```
cd network-management cd network-management
java -jar capsule-hsm/build/libs/hsm-3.0-NETWORKMAP-20171204.134345-6.jar --configFile hsm.conf java -jar capsule-hsm/build/libs/hsm-<version>.jar --configFile hsm.conf
``` ```
For a list of options the HSM signing server takes, run with the `--help` option: For a list of options the HSM signing server takes, run with the `--help` option:
```
java -jar capsule-hsm/build/libs/hsm-3.0-NETWORKMAP-20171204.134345-6.jar --help java -jar capsule-hsm/build/libs/hsm-3.0-<version>.jar --help
```
#Configuring network management service #Configuring network management service
### Local signing ### Local signing
@ -143,8 +144,9 @@ networkMapConfig {
java -jar doorman-<version>.jar --mode CA_KEYGEN java -jar doorman-<version>.jar --mode CA_KEYGEN
``` ```
A root certificate `pem` file will also be created, this will be distributed to the client via a "out-of-band" process. A trust store file containing the root trust certificate will be produced in the location `distribute-nodes / truststore.jks`
Note: We will be distributing a trust store instead of the pem file in future updates. (relative to `rootStorePath`). `truststore.jks` must be copied to the `certificates` directory of each node before
they attempt to register. The trust store password is `trustpass`.
### 2. Start Doorman service for notary registration ### 2. Start Doorman service for notary registration
Start the network management server with the doorman service for initial bootstrapping. Network map service should be disabled at this point. Start the network management server with the doorman service for initial bootstrapping. Network map service should be disabled at this point.
@ -154,11 +156,11 @@ networkMapConfig {
``` ```
### 3. Create notary node and register with the doorman ### 3. Create notary node and register with the doorman
After the doorman service is started, copy the `rootcert.pem` file to the notaries' certificates folder and start the `initial-registration` process. After the doorman service is started, start the notary node for the `initial-registration` process.
### 4. Add notary identities to the network parameter ### 4. Add notary identities to the network parameters
The network parameter should contain the name and public key of the newly created notaries. The network parameters should contain the name and public key of the newly created notaries.
Example network parameter file: Example network parameters file:
notaries : [{ notaries : [{
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name" name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
@ -173,11 +175,11 @@ networkMapConfig {
maxMessageSize = 100 maxMessageSize = 100
maxTransactionSize = 100 maxTransactionSize = 100
Save the parameters to `parameter.conf` Save the parameters to `network-parameters.conf`
### 5. Load initial network parameters file for network map service ### 5. Load initial network parameters file for network map service
A network parameters file is required to start the network map service for the first time. The initial network parameters file can be loaded using the `--update-network-parameter` flag. A network parameters file is required to start the network map service for the first time. The initial network parameters file can be loaded using the `--update-network-parameter` flag.
We can now restart the network management server with both doorman and network map service. We can now restart the network management server with both doorman and network map service.
``` ```
java -jar doorman-<version>.jar --update-network-parameter parameter.conf java -jar doorman-<version>.jar --update-network-parameter network-parameters.conf
``` ```

View File

@ -39,6 +39,7 @@ fun Array<out String>.toConfigWithOptions(registerOptions: OptionParser.() -> Un
class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception() class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception()
// TODO Remove this as we already have InternalUtils.cert
fun X509CertificateHolder.toX509Certificate(): X509Certificate = X509CertificateFactory().generateCertificate(encoded.inputStream()) fun X509CertificateHolder.toX509Certificate(): X509Certificate = X509CertificateFactory().generateCertificate(encoded.inputStream())
fun buildCertPath(vararg certificates: Certificate): CertPath = X509CertificateFactory().delegate.generateCertPath(certificates.asList()) fun buildCertPath(vararg certificates: Certificate): CertPath = X509CertificateFactory().delegate.generateCertPath(certificates.asList())

View File

@ -34,7 +34,6 @@ data class NetworkManagementServerParameters(// TODO: Move local signing to sign
val rootKeystorePassword: String?, val rootKeystorePassword: String?,
// TODO Should be part of a localSigning sub-config // TODO Should be part of a localSigning sub-config
val rootPrivateKeyPassword: String? val rootPrivateKeyPassword: String?
) { ) {
companion object { companion object {
// TODO: Do we really need these defaults? // TODO: Do we really need these defaults?
@ -79,7 +78,6 @@ fun parseParameters(vararg args: String): NetworkManagementServerParameters {
.describedAs("filepath") .describedAs("filepath")
accepts("update-network-parameters", "Update network parameters filepath. Currently only network parameters initialisation is supported.") accepts("update-network-parameters", "Update network parameters filepath. Currently only network parameters initialisation is supported.")
.withRequiredArg() .withRequiredArg()
.describedAs("The new network map")
.describedAs("filepath") .describedAs("filepath")
accepts("mode", "Set the mode of this application") accepts("mode", "Set the mode of this application")
.withRequiredArg() .withRequiredArg()

View File

@ -5,7 +5,6 @@ import com.r3.corda.networkmanage.common.persistence.*
import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE
import com.r3.corda.networkmanage.common.signer.NetworkMapSigner import com.r3.corda.networkmanage.common.signer.NetworkMapSigner
import com.r3.corda.networkmanage.common.utils.ShowHelpException import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.doorman.signer.DefaultCsrHandler import com.r3.corda.networkmanage.doorman.signer.DefaultCsrHandler
import com.r3.corda.networkmanage.doorman.signer.JiraCsrHandler import com.r3.corda.networkmanage.doorman.signer.JiraCsrHandler
import com.r3.corda.networkmanage.doorman.signer.LocalSigner import com.r3.corda.networkmanage.doorman.signer.LocalSigner
@ -14,6 +13,7 @@ import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.cert
import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectories
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.serialization.internal.SerializationEnvironmentImpl import net.corda.core.serialization.internal.SerializationEnvironmentImpl
@ -169,52 +169,58 @@ internal fun readPassword(fmt: String): String {
} }
// Keygen utilities. // Keygen utilities.
// TODO: Move keygen methods to Utilities.kt fun generateRootKeyPair(rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?) {
fun generateRootKeyPair(rootStorePath: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?) {
println("Generating Root CA keypair and certificate.") println("Generating Root CA keypair and certificate.")
// Get password from console if not in config. // Get password from console if not in config.
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ") val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ")
// Ensure folder exists. // Ensure folder exists.
rootStorePath.parent.createDirectories() rootStoreFile.parent.createDirectories()
val rootStore = loadOrCreateKeyStore(rootStorePath, rootKeystorePassword) val rootStore = loadOrCreateKeyStore(rootStoreFile, rootKeystorePassword)
val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ") val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ")
if (rootStore.containsAlias(X509Utilities.CORDA_ROOT_CA)) { if (rootStore.containsAlias(X509Utilities.CORDA_ROOT_CA)) {
val oldKey = loadOrCreateKeyStore(rootStorePath, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey val oldKey = loadOrCreateKeyStore(rootStoreFile, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey
println("Key ${X509Utilities.CORDA_ROOT_CA} already exists in keystore, process will now terminate.") println("Key ${X509Utilities.CORDA_ROOT_CA} already exists in keystore, process will now terminate.")
println(oldKey) println(oldKey)
exitProcess(1) exitProcess(1)
} }
val selfSignKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val selfSignKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val selfSignCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Root CA", organisation = "R3 Ltd", locality = "London", country = "GB", organisationUnit = "Corda", state = null), selfSignKey) // TODO Make the cert subject configurable
val selfSignCert = X509Utilities.createSelfSignedCACertificate(
CordaX500Name(commonName = "Corda Root CA", organisation = "R3 Ltd", locality = "London", country = "GB", organisationUnit = "Corda", state = null),
selfSignKey).cert
rootStore.addOrReplaceKey(X509Utilities.CORDA_ROOT_CA, selfSignKey.private, rootPrivateKeyPassword.toCharArray(), arrayOf(selfSignCert)) rootStore.addOrReplaceKey(X509Utilities.CORDA_ROOT_CA, selfSignKey.private, rootPrivateKeyPassword.toCharArray(), arrayOf(selfSignCert))
rootStore.save(rootStorePath, rootKeystorePassword) rootStore.save(rootStoreFile, rootKeystorePassword)
// TODO: remove this once we create truststore for nodes. val nodeTrustStoreFile = (rootStoreFile.parent / "distribute-nodes").createDirectories() / "truststore.jks"
X509Utilities.saveCertificateAsPEMFile(selfSignCert.toX509Certificate(), rootStorePath.parent / "rootcert.pem") // TODO The password for trust store must be a config option
val nodeTrustStore = loadOrCreateKeyStore(nodeTrustStoreFile, "trustpass")
nodeTrustStore.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, selfSignCert)
nodeTrustStore.save(nodeTrustStoreFile, "trustpass")
println("Trust store for distribution to nodes created in $nodeTrustStore")
println("Root CA keypair and certificate stored in ${rootStorePath.toAbsolutePath()}.") println("Root CA keypair and certificate stored in ${rootStoreFile.toAbsolutePath()}.")
println(loadKeyStore(rootStorePath, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey) println(loadKeyStore(rootStoreFile, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey)
} }
fun generateCAKeyPair(keystorePath: Path, rootStorePath: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) { fun generateCAKeyPair(keystoreFile: Path, rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) {
println("Generating Intermediate CA keypair and certificate using root keystore $rootStorePath.") println("Generating Intermediate CA keypair and certificate using root keystore $rootStoreFile.")
// Get password from console if not in config. // Get password from console if not in config.
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ") val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ")
val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ") val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ")
val rootKeyStore = loadKeyStore(rootStorePath, rootKeystorePassword) val rootKeyStore = loadKeyStore(rootStoreFile, rootKeystorePassword)
val rootKeyAndCert = rootKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_ROOT_CA, rootPrivateKeyPassword) val rootKeyAndCert = rootKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_ROOT_CA, rootPrivateKeyPassword)
val keystorePassword = keystorePass ?: readPassword("Keystore Password: ") val keystorePassword = keystorePass ?: readPassword("Keystore Password: ")
val caPrivateKeyPassword = caPrivateKeyPass ?: readPassword("CA Private Key Password: ") val caPrivateKeyPassword = caPrivateKeyPass ?: readPassword("CA Private Key Password: ")
// Ensure folder exists. // Ensure folder exists.
keystorePath.parent.createDirectories() keystoreFile.parent.createDirectories()
val keyStore = loadOrCreateKeyStore(keystorePath, keystorePassword) val keyStore = loadOrCreateKeyStore(keystoreFile, keystorePassword)
if (keyStore.containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA)) { if (keyStore.containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA)) {
val oldKey = loadOrCreateKeyStore(keystorePath, rootKeystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey val oldKey = loadOrCreateKeyStore(keystoreFile, rootKeystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey
println("Key ${X509Utilities.CORDA_INTERMEDIATE_CA} already exists in keystore, process will now terminate.") println("Key ${X509Utilities.CORDA_INTERMEDIATE_CA} already exists in keystore, process will now terminate.")
println(oldKey) println(oldKey)
exitProcess(1) exitProcess(1)
@ -225,9 +231,9 @@ fun generateCAKeyPair(keystorePath: Path, rootStorePath: Path, rootKeystorePass:
CordaX500Name(commonName = "Corda Intermediate CA", organisation = "R3 Ltd", organisationUnit = "Corda", locality = "London", country = "GB", state = null), intermediateKey.public) CordaX500Name(commonName = "Corda Intermediate CA", organisation = "R3 Ltd", organisationUnit = "Corda", locality = "London", country = "GB", state = null), intermediateKey.public)
keyStore.addOrReplaceKey(X509Utilities.CORDA_INTERMEDIATE_CA, intermediateKey.private, keyStore.addOrReplaceKey(X509Utilities.CORDA_INTERMEDIATE_CA, intermediateKey.private,
caPrivateKeyPassword.toCharArray(), arrayOf(intermediateCert, rootKeyAndCert.certificate)) caPrivateKeyPassword.toCharArray(), arrayOf(intermediateCert, rootKeyAndCert.certificate))
keyStore.save(keystorePath, keystorePassword) keyStore.save(keystoreFile, keystorePassword)
println("Intermediate CA keypair and certificate stored in $keystorePath.") println("Intermediate CA keypair and certificate stored in $keystoreFile.")
println(loadKeyStore(keystorePath, keystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey) println(loadKeyStore(keystoreFile, keystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey)
} }