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:
```
network-management/capsule/build/libs/doorman-<VERSION>.jar
network-management/capsule/build/libs/doorman-<version>.jar
```
## HSM signing server
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:
```
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.
@ -28,12 +28,13 @@ To run the HSM signing server:
```
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:
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
### Local signing
@ -143,8 +144,9 @@ networkMapConfig {
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.
Note: We will be distributing a trust store instead of the pem file in future updates.
A trust store file containing the root trust certificate will be produced in the location `distribute-nodes / truststore.jks`
(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
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
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
The network parameter should contain the name and public key of the newly created notaries.
Example network parameter file:
### 4. Add notary identities to the network parameters
The network parameters should contain the name and public key of the newly created notaries.
Example network parameters file:
notaries : [{
name: "O=Notary A, L=Port Louis, C=MU, OU=Org Unit, CN=Service Name"
@ -173,11 +175,11 @@ networkMapConfig {
maxMessageSize = 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
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.
```
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()
// TODO Remove this as we already have InternalUtils.cert
fun X509CertificateHolder.toX509Certificate(): X509Certificate = X509CertificateFactory().generateCertificate(encoded.inputStream())
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?,
// TODO Should be part of a localSigning sub-config
val rootPrivateKeyPassword: String?
) {
companion object {
// TODO: Do we really need these defaults?
@ -79,7 +78,6 @@ fun parseParameters(vararg args: String): NetworkManagementServerParameters {
.describedAs("filepath")
accepts("update-network-parameters", "Update network parameters filepath. Currently only network parameters initialisation is supported.")
.withRequiredArg()
.describedAs("The new network map")
.describedAs("filepath")
accepts("mode", "Set the mode of this application")
.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.signer.NetworkMapSigner
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.JiraCsrHandler
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 net.corda.core.crypto.Crypto
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.cert
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
@ -169,52 +169,58 @@ internal fun readPassword(fmt: String): String {
}
// Keygen utilities.
// TODO: Move keygen methods to Utilities.kt
fun generateRootKeyPair(rootStorePath: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?) {
fun generateRootKeyPair(rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?) {
println("Generating Root CA keypair and certificate.")
// Get password from console if not in config.
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore Password: ")
// Ensure folder exists.
rootStorePath.parent.createDirectories()
val rootStore = loadOrCreateKeyStore(rootStorePath, rootKeystorePassword)
rootStoreFile.parent.createDirectories()
val rootStore = loadOrCreateKeyStore(rootStoreFile, rootKeystorePassword)
val rootPrivateKeyPassword = rootPrivateKeyPass ?: readPassword("Root Private Key Password: ")
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(oldKey)
exitProcess(1)
}
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.save(rootStorePath, rootKeystorePassword)
rootStore.save(rootStoreFile, rootKeystorePassword)
// TODO: remove this once we create truststore for nodes.
X509Utilities.saveCertificateAsPEMFile(selfSignCert.toX509Certificate(), rootStorePath.parent / "rootcert.pem")
val nodeTrustStoreFile = (rootStoreFile.parent / "distribute-nodes").createDirectories() / "truststore.jks"
// 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(loadKeyStore(rootStorePath, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey)
println("Root CA keypair and certificate stored in ${rootStoreFile.toAbsolutePath()}.")
println(loadKeyStore(rootStoreFile, rootKeystorePassword).getCertificate(X509Utilities.CORDA_ROOT_CA).publicKey)
}
fun generateCAKeyPair(keystorePath: Path, rootStorePath: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) {
println("Generating Intermediate CA keypair and certificate using root keystore $rootStorePath.")
fun generateCAKeyPair(keystoreFile: Path, rootStoreFile: Path, rootKeystorePass: String?, rootPrivateKeyPass: String?, keystorePass: String?, caPrivateKeyPass: String?) {
println("Generating Intermediate CA keypair and certificate using root keystore $rootStoreFile.")
// Get password from console if not in config.
val rootKeystorePassword = rootKeystorePass ?: readPassword("Root Keystore 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 keystorePassword = keystorePass ?: readPassword("Keystore Password: ")
val caPrivateKeyPassword = caPrivateKeyPass ?: readPassword("CA Private Key Password: ")
// Ensure folder exists.
keystorePath.parent.createDirectories()
val keyStore = loadOrCreateKeyStore(keystorePath, keystorePassword)
keystoreFile.parent.createDirectories()
val keyStore = loadOrCreateKeyStore(keystoreFile, keystorePassword)
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(oldKey)
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)
keyStore.addOrReplaceKey(X509Utilities.CORDA_INTERMEDIATE_CA, intermediateKey.private,
caPrivateKeyPassword.toCharArray(), arrayOf(intermediateCert, rootKeyAndCert.certificate))
keyStore.save(keystorePath, keystorePassword)
println("Intermediate CA keypair and certificate stored in $keystorePath.")
println(loadKeyStore(keystorePath, keystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey)
keyStore.save(keystoreFile, keystorePassword)
println("Intermediate CA keypair and certificate stored in $keystoreFile.")
println(loadKeyStore(keystoreFile, keystorePassword).getCertificate(X509Utilities.CORDA_INTERMEDIATE_CA).publicKey)
}