Adding HSM signing service docs (#122)

* Adding HSM signing service docs

* Addressing review comments

* Addressing review comments - round 2

* Addressing review comments - round 3

* Fixing method comment
This commit is contained in:
mkit 2017-11-24 11:32:12 +00:00 committed by GitHub
parent c516a4b028
commit c5e17d90f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 266 additions and 60 deletions

Binary file not shown.

View File

@ -7,12 +7,12 @@ See the Readme in under ``network-management`` for detailed building instruction
Configuration file
------------------
At startup Doorman reads a configuration file, passed with ``--configFile`` on the command line.
At startup doorman reads a configuration file, passed with ``--configFile`` on the command line.
This is an example of what a Doorman configuration file might look like:
This is an example of what a doorman configuration file might look like:
.. literalinclude:: ../../network-management/doorman.conf
Invoke Doorman with ``-?`` for a full list of supported command-line arguments.
Invoke doorman with ``-?`` for a full list of supported command-line arguments.
Configuration parameters
@ -51,7 +51,9 @@ Allowed parameters are:
:doneTransitionCode: Jira status to put approved tickets in
:keystorePath: Path for the keystore
:keystorePath: Path for the keystore. If not set (or null is passed) doorman will NOT perform any signing.
This is required in case of the HSM integration where signing process is offloaded (from doorman) to an external service
that binds with an HSM.
:rootStorePath: Path for the root keystore
@ -61,7 +63,7 @@ Allowed parameters are:
Bootstrapping the network parameters
------------------------------------
When Doorman is running it will serve the current network parameters. The first time Doorman is
When doorman is running it will serve the current network parameters. The first time doorman is
started it will need to know the initial value for the network parameters.
The initial values for the network parameters can be specified with a file, like this:
@ -71,6 +73,21 @@ And the location of that file can be specified with: ``--initialNetworkParameter
Note that when reading from file:
1. ``epoch`` will always be set to 1,
2. ``modifiedTime`` will be the Doorman startup time
2. ``modifiedTime`` will be the doorman startup time
``epoch`` will increase by one every time the network parameters are updated.
Bootstrapping the network map
-----------------------------
The network map is periodically refreshed, with frequency driven by the 'signInterval' parameter when local signing is in use.
In case of an external signing service it depends on that service configuration. Due to the design decisions dictated by the security concerns
around the external signing service, doorman is not allowed to connect directly with the signing sevice. Instead, the external service is
expected to access the doorman database in order to obtain signature requiring data.
Therefore, doorman takes a passive role considering all signing process related aspects.
Network map refresh happens only if there is a change to the current one (i.e. most recently created version of the network map).
See the :doc:`signing-service` for a more detailed description of the service.
When dealing with a fresh deployment (i.e. no previous data is present in the doorman database),
it may take some time until the network map is available. This is caused by the aforementioned decoupling of the signing
process from doorman itself.

View File

@ -0,0 +1,76 @@
Running the signing service
===========================
The signing service is a bridge between the networking service and the HSM infrastructure. It is responsible for retrieving
pending requests for signatures and managing the process of securing these signatures from an HSM infrastructure.
The signing service has a console-based user interface (designed for the manual signing process of the certificate signing requests),
which upon successful startup should display different options to the user.
At the same time, it connects to the database (which is expected to be shared with Doorman)
and periodically polls it and if needed automatically signs the following: network map and certificate revocation list.
See the :doc:`signing-service` for a more detailed description of the service.
Configuration file
------------------
At startup the signing service reads a configuration file, passed with ``--configFile`` on the command line.
This is an example of what a signing service configuration file might look like:
.. literalinclude:: ../../network-management/hsm.conf
Invoke the signing service with ``-?`` for a full list of supported command-line arguments.
Configuration parameters
------------------------
Allowed parameters are:
:device: HSM connection string. It is of the following format 3001@127.0.0.1, where 3001 is the port number.
Default value: "3001@127.0.0.1"
:keyGroup: HSM key group. This parameter is vendor specific (see Utimaco docs).
:keySpecifier: HSM key specifier. This parameter is vendor specific (see Utimaco docs). Default value: 1
:rootPrivateKeyPassword: Private key password for the root certificate.
:rootCertificateName: Root certificate name. Default value: "cordarootca"
:csrPrivateKeyPassword: Private key password for the intermediate certificate used to sign certficate signing requests.
:csrCertificateName: Certificate signing requests intermediate certificate name. Default value: "cordaintermediateca"
:databaseProperties: Database properties.
:dataSourceProperties: Data source properties. It should describe (or point to) the Doorman database.
:networkMapCertificateName: Network map intermediate certificate name. Default value: "cordaintermediateca_nm"
:networkMapPrivateKeyPassword: Private key password for the intermediate certificate used to sign the network map.
:validDays: Number of days issued signatures are valid for.
:signAuthThreshold: Minimum authentication strength threshold required for certificate signing requests.
Default value: 2
:keyGenAuthThreshold: Minimum authentication strength threshold required for key generation.
Default value: 2
:authMode: Authentication mode, used when validating a user for certificate signing request signature.
Allowed values are:
"PASSWORD" (default) - type-in password authentication
CARD_READER - smart card reader authentication
KEY_FILE - key file authentication
:authKeyFilePath: Authentication key file. It is used when the 'authMode' is set to "KEY_FILE"
or for the automated signing process - e.g. network map, certificate revocation list. Default value: null
:authKeyFilePassword: Authentication key file password. It is used when the 'authMode' is set to "KEY_FILE"
or for the automated signing process - e.g. network map, certificate revocation list. Default value: null
:signInterval: Interval (in seconds) in which all automated signing happens. Default value: 600 seconds
Expected behaviour and output upon the service start-up
-------------------------------------------------------
A commandline-based interface (with different menu options) is presented to a user.

View File

@ -0,0 +1,77 @@
HSM Signing Service
===================
The HSM Signing Service is designed to act as a bridge between the networking service and the HSM infrastructure.
Due to possible security concerns, the signing service is meant to be hosted on private premises and not in a cloud environment.
That does not apply to the networking service, which may be hosted by a cloud provider. Such a design allows for, and in fact
was driven by the requirement of, permitting only outgoing connections between the two deployments (i.e. private and cloud).
Having this deployment design in mind, the signing service initiates connection to the networking service database and
retrieves all the data that has to be signed.
This retrieval happens automatically (based on the pre-configured time interval) in case of Network Map and Certificate Revocation List signing.
The on-demand approach applies only in case of Certificate Signing Requests signatures as they involve human interaction (for authentication credentials input).
For that purpose, the service provides a commandline-based interface and guides the user throughout the signing process.
The signing service assumes an HSM configuration in place - i.e. all users and certificates should be set-up on the HSM box,
prior to the signing service deployment and usage. Nevertheless, currently, the signing service comes with a simple utility
that allows an authenticated HSM user to generate the root and intermediate certificates. The utility is only a temporary
solution and should NOT be used in case of production deployment. This convenience feature will be removed in a future release.
Following, are the steps for the signing service operation with respect to every kind of object it signs:
Certificate Signing Request Steps
---------------------------------
* The networking service receives a certificate signing request and approves it (more specifically the certificate signing request is approved using an external ticket tracking tool - e.g. Jira).
It is ready to be signed.
* A privileged user chooses (using the commandline interface) that she wants to sign the approved requests.
* A connection to the networking service database is established and all approved requests are fetched and listed to the user.
* After selecting an appropriate option (either signing all approved requests or just some of them) user is prompted for her username (in terms of the HSM setup).
* Next step is to confirm user's identity against the HSM. In this case, the signing service supports two authentication methods: Password or Card Reader.
* If the user's identity is confirmed (using one of the above methods) and her privileges are strong enough, then the signing process commences using the configured intermediate certificate.
* After that, the networking service database is updated with the signed certificates.
* In case of insufficient user privileges, the service will prompt for another user to be authenticated.
Visualised steps available as :download:`pdf <resources/hsm_csr_signing_flow.pdf>`
Certificate Revocation List Steps
---------------------------------
* The networking service receives a certificate revocation request and approves it (more specifically the certificate signing request is approved using an external ticket tracking tool - e.g. Jira).
It is ready to be included into the certificate revocation list.
* Periodically (the time interval is pre-configured at the deployment time), the signing service fetches all approved certificate revocation requests. If the list is empty, then nothing happens and means that the current Certificate Revocation List remains unchanged.
* If there is at least one approved certificate revocation request, it means that a new certificate revocation list needs to be created and signed.
* In such a case, the service fetches all (already) revoked certificate revocation requests
* It builds a new certificate revocation list that combines already revoked requests and approved ones.
* The list is signed on HSM with an intermediate certificate whose name (together with the auto-user credentials) was pre-configured at the signing service deployment time
* The signed list is serialised and stored in the networking service database ready to be served. Also, all approved requests become revoked now.
Signing Network Map
-------------------
* The networking service receives a new (or updated) node info.
* Periodically (the time interval is pre-configured at the deployment time), the signing service fetches from the database current network map, all node info objects with valid certificates and current network parameters.
* A new network map object is created out of the fetched data.
* If the new network map hash does not differ from the current network map hash, then nothing happens and current network map remains unchanged.
* If they are different, then the newly created network map object is serialized using the Corda AMQP serialisation format and signed by the dedicated intermediate certificate stored in HSM.
* Once signed, the new network map data is stored in the networking service database and available for nodes to retrieve when they next poll for the network map.

View File

@ -0,0 +1,25 @@
device = "3001@127.0.0.1"
keyGroup = "DEV.DOORMAN"
keySpecifier = -1
authMode = PASSWORD
rootCertificateName = "corda_root_ca"
rootPrivateKeyPassword = "Password"
csrPrivateKeyPassword = "Password"
csrCertificateName = "intermediate_ca"
networkMapCertificateName = "intermediate_ca"
networkMapPrivateKeyPassword = "Password"
validDays = 3650
signAuthThreshold = 2
keyGenAuthThreshold = 2
authKeyFilePath = "./Administrator.key"
authKeyFilePassword = "Password"
autoUsername = "AUTO_USER"
signInterval = 600
h2port = 0
dataSourceProperties {
"dataSourceClassName" = org.h2.jdbcx.JdbcDataSource
"dataSource.url" = "jdbc:h2:file:"${basedir}"/persistence;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=10000;WRITE_DELAY=0;AUTO_SERVER_PORT="${h2port}
"dataSource.user" = sa
"dataSource.password" = ""
}

View File

@ -24,7 +24,12 @@ import java.util.*
fun main(args: Array<String>) {
run(Parameters(
dataSourceProperties = makeTestDataSourceProperties(),
databaseProperties = makeNotInitialisingTestDatabaseProperties()
databaseProperties = makeNotInitialisingTestDatabaseProperties(),
csrPrivateKeyPassword = "",
networkMapPrivateKeyPassword = "",
rootPrivateKeyPassword = "",
keyGroup = "DEV.DOORMAN",
validDays = 3650
))
}

View File

@ -23,7 +23,11 @@ class HsmTest {
dataSourceProperties = mock(),
device = "${hsmSimulator.port}@${hsmSimulator.host}",
keySpecifier = 1,
keyGroup = "*"
csrPrivateKeyPassword = "",
networkMapPrivateKeyPassword = "",
rootPrivateKeyPassword = "",
keyGroup = "DEV.DOORMAN",
validDays = 3650
)
@Rule

View File

@ -21,7 +21,7 @@ fun PublicKey.hashString() = encoded.sha256().toString()
fun Array<out String>.toConfigWithOptions(registerOptions: OptionParser.() -> Unit): Config {
val parser = OptionParser()
val helpOption = parser.acceptsAll(listOf("h", "?", "help"), "show help").forHelp();
val helpOption = parser.acceptsAll(listOf("h", "?", "help"), "show help").forHelp()
registerOptions(parser)
val optionSet = parser.parse(*this)
// Print help and exit on help option.

View File

@ -17,9 +17,13 @@ import java.nio.file.Paths
import java.time.Duration
import java.util.*
data class DoormanParameters(val keystorePassword: String?,
data class DoormanParameters(// TODO Create a localSigning sub-config and put that there
val keystorePassword: String?,
// TODO Should be part of a localSigning sub-config
val caPrivateKeyPassword: String?,
// TODO Should be part of a localSigning sub-config
val rootKeystorePassword: String?,
// TODO Should be part of a localSigning sub-config
val rootPrivateKeyPassword: String?,
val host: String,
val port: Int,
@ -28,10 +32,13 @@ data class DoormanParameters(val keystorePassword: String?,
val approveAll: Boolean = false,
val databaseProperties: Properties? = null,
val jiraConfig: JiraConfig? = null,
// TODO Should be part of a localSigning sub-config
val keystorePath: Path? = null,
// TODO Should be part of a localSigning sub-config
val rootStorePath: Path? = null,
// TODO Change these to Duration in the future
val approveInterval: Long = DEFAULT_APPROVE_INTERVAL,
// TODO Should be part of a localSigning sub-config
val signInterval: Long = DEFAULT_SIGN_INTERVAL
) {
enum class Mode {

View File

@ -34,31 +34,28 @@ fun run(parameters: Parameters) {
val hsmNetworkMapSigningThread = HsmNetworkMapSigner(
networkMapStorage,
networkMapCertificateName,
networkMapPrivateKeyPass,
keyStorePass,
Authenticator(createProvider(), AuthMode.KEY_FILE, autoUsername, authKeyFilePath, authKeyFilePass, signAuthThreshold)).start()
networkMapPrivateKeyPassword,
Authenticator(createProvider(), AuthMode.KEY_FILE, autoUsername, authKeyFilePath, authKeyFilePassword, signAuthThreshold)).start()
val sign: (List<ApprovedCertificateRequestData>) -> Unit = {
val signer = HsmCsrSigner(
csrStorage,
csrCertificateName,
csrPrivateKeyPass,
csrPrivateKeyPassword,
rootCertificateName,
validDays,
keyStorePass,
Authenticator(createProvider(), authMode, autoUsername, authKeyFilePath, authKeyFilePass, signAuthThreshold))
Authenticator(createProvider(), authMode, autoUsername, authKeyFilePath, authKeyFilePassword, signAuthThreshold))
signer.sign(it)
}
Menu().withExceptionHandler(::processError).addItem("1", "Generate root and intermediate certificates", {
if (confirmedKeyGen()) {
val generator = KeyCertificateGenerator(
Authenticator(createProvider(), authMode, autoUsername, authKeyFilePath, authKeyFilePass, keyGenAuthThreshold),
Authenticator(createProvider(), authMode, autoUsername, authKeyFilePath, authKeyFilePassword, keyGenAuthThreshold),
keySpecifier,
keyGroup)
generator.generateAllCertificates(
keyStorePass,
listOf(CertificateNameAndPass(csrCertificateName, csrPrivateKeyPass), CertificateNameAndPass(networkMapCertificateName, networkMapPrivateKeyPass)),
listOf(CertificateNameAndPass(csrCertificateName, csrPrivateKeyPassword), CertificateNameAndPass(networkMapCertificateName, networkMapPrivateKeyPassword)),
rootCertificateName,
rootPrivateKeyPass,
rootPrivateKeyPassword,
validDays)
}
}).addItem("2", "Sign all approved and unsigned CSRs", {

View File

@ -6,12 +6,10 @@ import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_CSR_CERTIFICATE_NAME
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_DEVICE
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_KEY_GEN_AUTH_THRESHOLD
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_KEY_GROUP
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_KEY_SPECIFIER
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_ROOT_CERTIFICATE_NAME
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_SIGN_AUTH_THRESHOLD
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_SIGN_INTERVAL
import com.r3.corda.networkmanage.hsm.configuration.Parameters.Companion.DEFAULT_VALID_DAYS
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import net.corda.core.internal.div
@ -28,24 +26,23 @@ data class Parameters(val basedir: Path = Paths.get("."),
val dataSourceProperties: Properties,
val databaseProperties: Properties? = null,
val device: String = DEFAULT_DEVICE,
val keyStorePass: String? = null,
// TODO this needs cleaning up after the config-file-only support is implemented
val keyGroup: String = DEFAULT_KEY_GROUP,
val keyGroup: String,
val keySpecifier: Int = DEFAULT_KEY_SPECIFIER,
val rootPrivateKeyPass: String = DEFAULT_ROOT_PRIVATE_KEY,
val csrPrivateKeyPass: String = DEFAULT_CSR_PRIVATE_KEY,
val rootPrivateKeyPassword: String,
val csrPrivateKeyPassword: String,
val csrCertificateName: String = DEFAULT_CSR_CERTIFICATE_NAME,
val networkMapCertificateName: String = DEFAULT_NETWORK_MAP_CERTIFICATE_NAME,
val networkMapPrivateKeyPass: String = DEFAULT_NETWORK_MAP_PRIVATE_KEY_PASS,
val networkMapPrivateKeyPassword: String,
val rootCertificateName: String = DEFAULT_ROOT_CERTIFICATE_NAME,
val validDays: Int = DEFAULT_VALID_DAYS,
val validDays: Int,
val signAuthThreshold: Int = DEFAULT_SIGN_AUTH_THRESHOLD,
val keyGenAuthThreshold: Int = DEFAULT_KEY_GEN_AUTH_THRESHOLD,
val authMode: AuthMode = DEFAULT_AUTH_MODE,
val authKeyFilePath: Path? = DEFAULT_KEY_FILE_PATH,
val authKeyFilePass: String? = DEFAULT_KEY_FILE_PASS,
val authKeyFilePassword: String? = DEFAULT_KEY_FILE_PASSWORD,
val autoUsername: String? = DEFAULT_AUTO_USERNAME,
// TODO Change this to Duration in the future
// TODO Change this to Duration in the future.
val signInterval: Long = DEFAULT_SIGN_INTERVAL) {
companion object {
val DEFAULT_DEVICE = "3001@127.0.0.1"
@ -54,16 +51,11 @@ data class Parameters(val basedir: Path = Paths.get("."),
val DEFAULT_KEY_GEN_AUTH_THRESHOLD = 2
val DEFAULT_CSR_CERTIFICATE_NAME = X509Utilities.CORDA_INTERMEDIATE_CA
val DEFAULT_ROOT_CERTIFICATE_NAME = X509Utilities.CORDA_ROOT_CA
val DEFAULT_VALID_DAYS = 3650
val DEFAULT_KEY_GROUP = "DEV.DOORMAN"
val DEFAULT_KEY_SPECIFIER = 1
val DEFAULT_KEY_FILE_PATH: Path? = null //Paths.get("/Users/michalkit/WinDev1706Eval/Shared/TEST4.key")
val DEFAULT_KEY_FILE_PASS: String? = null
val DEFAULT_KEY_FILE_PASSWORD: String? = null
val DEFAULT_AUTO_USERNAME: String? = null
val DEFAULT_CSR_PRIVATE_KEY = ""
val DEFAULT_ROOT_PRIVATE_KEY = ""
val DEFAULT_NETWORK_MAP_CERTIFICATE_NAME = "cordaintermediateca_nm"
val DEFAULT_NETWORK_MAP_PRIVATE_KEY_PASS = ""
val DEFAULT_SIGN_INTERVAL = 600L // in seconds (10 minutes)
}
}
@ -78,20 +70,19 @@ fun parseParameters(vararg args: String): Parameters {
accepts("basedir", "Overriding configuration filepath, default to current directory.").withRequiredArg().defaultsTo(".").describedAs("filepath")
accepts("configFile", "Overriding configuration file. (default: <<current directory>>/node.conf)").withRequiredArg().describedAs("filepath")
accepts("device", "CryptoServer device address (default: $DEFAULT_DEVICE)").withRequiredArg()
accepts("keyStorePass", "Password for the key store").withRequiredArg().describedAs("password")
accepts("keyGroup", "CryptoServer key group (default: $DEFAULT_KEY_GROUP)").withRequiredArg().defaultsTo(DEFAULT_KEY_GROUP)
accepts("keyGroup", "CryptoServer key group").withRequiredArg()
accepts("keySpecifier", "CryptoServer key specifier (default: $DEFAULT_KEY_SPECIFIER)").withRequiredArg().ofType(Int::class.java).defaultsTo(DEFAULT_KEY_SPECIFIER)
accepts("rootPrivateKeyPass", "Password for the root certificate private key").withRequiredArg().describedAs("password")
accepts("csrPrivateKeyPass", "Password for the CSR signing certificate private key").withRequiredArg().describedAs("password")
accepts("rootPrivateKeyPassword", "Password for the root certificate private key").withRequiredArg().describedAs("password")
accepts("csrPrivateKeyPassword", "Password for the CSR signing certificate private key").withRequiredArg().describedAs("password")
accepts("keyGenAuthThreshold", "Authentication strength threshold for the HSM key generation (default: $DEFAULT_KEY_GEN_AUTH_THRESHOLD)").withRequiredArg().ofType(Int::class.java).defaultsTo(DEFAULT_KEY_GEN_AUTH_THRESHOLD)
accepts("signAuthThreshold", "Authentication strength threshold for the HSM CSR signing (default: $DEFAULT_SIGN_AUTH_THRESHOLD)").withRequiredArg().ofType(Int::class.java).defaultsTo(DEFAULT_SIGN_AUTH_THRESHOLD)
accepts("authMode", "Authentication mode. Allowed values: ${AuthMode.values()} (default: $DEFAULT_AUTH_MODE)").withRequiredArg().defaultsTo(DEFAULT_AUTH_MODE.name)
accepts("authKeyFilePath", "Key file path when authentication is based on a key file (i.e. authMode=${AuthMode.KEY_FILE.name})").withRequiredArg().describedAs("filepath")
accepts("authKeyFilePass", "Key file password when authentication is based on a key file (i.e. authMode=${AuthMode.KEY_FILE.name})").withRequiredArg()
accepts("authKeyFilePassword", "Key file password when authentication is based on a key file (i.e. authMode=${AuthMode.KEY_FILE.name})").withRequiredArg()
accepts("autoUsername", "Username to be used for certificate signing (if not specified it will be prompted for input)").withRequiredArg()
accepts("csrCertificateName", "Name of the certificate to be used by this CA to sign CSR (default: $DEFAULT_CSR_CERTIFICATE_NAME)").withRequiredArg().defaultsTo(DEFAULT_CSR_CERTIFICATE_NAME)
accepts("rootCertificateName", "Name of the root certificate to be used by this CA (default: $DEFAULT_ROOT_CERTIFICATE_NAME)").withRequiredArg().defaultsTo(DEFAULT_ROOT_CERTIFICATE_NAME)
accepts("validDays", "Validity duration in days (default: $DEFAULT_VALID_DAYS)").withRequiredArg().ofType(Int::class.java).defaultsTo(DEFAULT_VALID_DAYS)
accepts("validDays", "Validity duration in days").withRequiredArg().ofType(Int::class.java)
accepts("signInterval", "Time interval (in seconds) in which network map is signed (default: $DEFAULT_SIGN_INTERVAL)").withRequiredArg().ofType(Long::class.java).defaultsTo(DEFAULT_SIGN_INTERVAL)
}

View File

@ -24,20 +24,17 @@ class KeyCertificateGenerator(private val authenticator: Authenticator,
/**
* Generates root and intermediate key and certificates and stores them in the key store given by provider.
* If the keys and certificates already exists they will be overwritten.
* @param keyStorePassword password to the key store
* @param certificateKeyName name of the intermediate key/certificate
* @param privateKeyPassword password for the intermediate private key
* @param intermediateCertificatesCredentials name and password for the intermediate key/certificate
* @param parentCertificateName name of the parent key/certificate
* @param parentPrivateKeyPassword password for the parent private key
* @param validDays days of certificate validity
*/
fun generateAllCertificates(keyStorePassword: String? = null,
intermediateCertificatesCredentials: List<CertificateNameAndPass>,
fun generateAllCertificates(intermediateCertificatesCredentials: List<CertificateNameAndPass>,
parentCertificateName: String,
parentPrivateKeyPassword: String,
validDays: Int) {
authenticator.connectAndAuthenticate { provider, _ ->
val keyStore = getAndInitializeKeyStore(provider, keyStorePassword)
val keyStore = getAndInitializeKeyStore(provider)
generateRootCertificate(provider, keyStore, parentCertificateName, parentPrivateKeyPassword, validDays)
intermediateCertificatesCredentials.forEach {
generateIntermediateCertificate(provider, keyStore, it.certificateName, it.privateKeyPassword, parentCertificateName, parentPrivateKeyPassword, validDays)

View File

@ -16,7 +16,6 @@ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage,
private val caPrivateKeyPass: String?,
private val caParentCertificateName: String,
private val validDays: Int,
private val keyStorePassword: String?,
private val authenticator: Authenticator) : CertificateSigningRequestSigner {
/**
@ -31,7 +30,7 @@ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage,
*/
override fun sign(toSign: List<ApprovedCertificateRequestData>) {
authenticator.connectAndAuthenticate { provider, signers ->
val keyStore = getAndInitializeKeyStore(provider, keyStorePassword)
val keyStore = getAndInitializeKeyStore(provider)
// This should be changed once we allow for more certificates in the chain. Preferably we should use
// keyStore.getCertificateChain(String) and assume entire chain is stored in the HSM (depending on the support).
val caParentCertificate = keyStore.getCertificate(caParentCertificateName)

View File

@ -7,7 +7,7 @@ import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
import com.r3.corda.networkmanage.common.signer.Signer
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
import com.r3.corda.networkmanage.hsm.utils.X509Utilities
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.getAndInitializeKeyStore
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.signData
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.verify
import net.corda.core.utilities.loggerFor
@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit
class HsmNetworkMapSigner(networkMapStorage: NetworkMapStorage,
private val caCertificateKeyName: String,
private val caPrivateKeyPass: String,
private val keyStorePassword: String?,
private val authenticator: Authenticator,
private val signingPeriod: Duration = DEFAULT_SIGNING_PERIOD_MS) : Signer {
@ -63,7 +62,7 @@ class HsmNetworkMapSigner(networkMapStorage: NetworkMapStorage,
override fun sign(data: ByteArray): SignatureAndCertPath? {
var result: SignatureAndCertPath? = null
authenticator.connectAndAuthenticate { provider, _ ->
val keyStore = X509Utilities.getAndInitializeKeyStore(provider, keyStorePassword)
val keyStore = getAndInitializeKeyStore(provider)
val caCertificateChain = keyStore.getCertificateChain(caCertificateKeyName)
val caKey = keyStore.getKey(caCertificateKeyName, caPrivateKeyPass.toCharArray()) as PrivateKey
val signature = signData(data, KeyPair(caCertificateChain.first().publicKey, caKey), provider)

View File

@ -237,14 +237,12 @@ object X509Utilities {
/**
* Creates and initializes a key store from the given crypto server provider.
* It uses the provided key store password to enable key store access.
* @param provider crypto server provider to be used for the key store creation
* @param keyStorePassword key store password to be used for key store access authentication
* @return created key store instance
*/
fun getAndInitializeKeyStore(provider: CryptoServerProvider, keyStorePassword: String?): KeyStore {
fun getAndInitializeKeyStore(provider: CryptoServerProvider): KeyStore {
val keyStore = KeyStore.getInstance("CryptoServer", provider)
keyStore.load(null, keyStorePassword?.toCharArray())
keyStore.load(null, null)
return keyStore
}

View File

@ -2,6 +2,11 @@ device = "3001@127.0.0.1"
keyGroup = "*"
keySpecifier = -1
authMode = PASSWORD
csrPrivateKeyPassword = ""
networkMapPrivateKeyPassword = ""
rootPrivateKeyPassword = ""
keyGroup = "DEV.DOORMAN"
validDays = 3650
h2port = 0
dataSourceProperties {

View File

@ -1,7 +1,12 @@
device = "3001@127.0.0.1"
keyGroup = "*"
keyGroup = "DEV.DOORMAN"
keySpecifier = -1
authMode = PASSWORD
csrPrivateKeyPassword = ""
networkMapPrivateKeyPassword = ""
rootPrivateKeyPassword = ""
keyGroup = "DEV.DOORMAN"
validDays = 3650
h2port = 0
dataSourceProperties {

View File

@ -1,4 +1,8 @@
device = "3001@127.0.0.1"
keyGroup = "*"
keyGroup = "DEV.DOORMAN"
keySpecifier = -1
authMode = PASSWORD
authMode = PASSWORD
csrPrivateKeyPassword = ""
networkMapPrivateKeyPassword = ""
rootPrivateKeyPassword = ""
keyGroup = "DEV.DOORMAN"