mirror of
https://github.com/corda/corda.git
synced 2025-02-04 02:01:13 +00:00
Move all the configuration for running doorman in its configuration f… (#104)
* Move all the configuration for running doorman in its configuration files
This commit is contained in:
parent
fffcdb47da
commit
233f1fb8e2
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@ -46,6 +46,8 @@
|
||||
<module name="finance_integrationTest" target="1.8" />
|
||||
<module name="finance_main" target="1.8" />
|
||||
<module name="finance_test" target="1.8" />
|
||||
<module name="gradle-plugins-cordform-common_main" target="1.8" />
|
||||
<module name="gradle-plugins-cordform-common_test" target="1.8" />
|
||||
<module name="graphs_main" target="1.8" />
|
||||
<module name="graphs_test" target="1.8" />
|
||||
<module name="intellij-plugin_main" target="1.8" />
|
||||
@ -88,8 +90,12 @@
|
||||
<module name="notary-demo_test" target="1.8" />
|
||||
<module name="perftestcordapp_main" target="1.8" />
|
||||
<module name="perftestcordapp_test" target="1.8" />
|
||||
<module name="publish-utils_main" target="1.8" />
|
||||
<module name="publish-utils_test" target="1.8" />
|
||||
<module name="quasar-hook_main" target="1.8" />
|
||||
<module name="quasar-hook_test" target="1.8" />
|
||||
<module name="quasar-utils_main" target="1.8" />
|
||||
<module name="quasar-utils_test" target="1.8" />
|
||||
<module name="rpc_integrationTest" target="1.8" />
|
||||
<module name="rpc_main" target="1.8" />
|
||||
<module name="rpc_smokeTest" target="1.8" />
|
||||
|
@ -15,6 +15,50 @@ This is an example of what a Doorman configuration file might look like:
|
||||
Invoke Doorman with ``-?`` for a full list of supported command-line arguments.
|
||||
|
||||
|
||||
Configuration parameters
|
||||
------------------------
|
||||
Allowed parameters are:
|
||||
|
||||
:keystorePassword: the keystore password
|
||||
|
||||
:caPrivateKeyPassword: the ca private key password
|
||||
|
||||
:rootKeystorePassword: Password for the root store
|
||||
|
||||
:rootPrivateKeyPassword: Password for the root private key
|
||||
|
||||
:host: host on which doorman runs
|
||||
|
||||
:port: port on which doorman runs
|
||||
|
||||
:mode: must be one of: DOORMAN (default), CA_KEYGEN, ROOT_KEYGEN.
|
||||
|
||||
:approveAll: Whether to approve all request (defaults to false), this is for debug only.
|
||||
|
||||
:databaseProperties: database properties
|
||||
|
||||
:dataSourceProperties: datasoruce properties
|
||||
|
||||
:jiraConfig: The Jira configuration
|
||||
|
||||
:address: The URL to use to connect to Jira
|
||||
|
||||
:projectCode: The project code on Jira
|
||||
|
||||
:username: Username for Jira
|
||||
|
||||
:password: Password for Jira
|
||||
|
||||
:doneTransitionCode: Jira status to put approved tickets in
|
||||
|
||||
:keystorePath: Path for the keystore
|
||||
|
||||
:rootStorePath: Path for the root keystore
|
||||
|
||||
:approveInterval: How often to process Jira approved requests in seconds
|
||||
|
||||
:signInterval: How often to sign the network map in seconds
|
||||
|
||||
Bootstrapping the network parameters
|
||||
------------------------------------
|
||||
When Doorman is running it will serve the current network parameters. The first time Doorman is
|
||||
|
@ -1,3 +1,4 @@
|
||||
basedir = "."
|
||||
host = localhost
|
||||
port = 0
|
||||
keystorePath = ${basedir}"/certificates/caKeystore.jks"
|
||||
|
@ -1,10 +1,14 @@
|
||||
package com.r3.corda.networkmanage.doorman
|
||||
|
||||
import com.r3.corda.networkmanage.common.utils.ShowHelpException
|
||||
import com.r3.corda.networkmanage.common.utils.toConfigWithOptions
|
||||
import com.r3.corda.networkmanage.doorman.DoormanParameters.Companion.DEFAULT_APPROVE_INTERVAL
|
||||
import com.r3.corda.networkmanage.doorman.DoormanParameters.Companion.DEFAULT_SIGN_INTERVAL
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigParseOptions
|
||||
import joptsimple.OptionParser
|
||||
import net.corda.core.internal.isRegularFile
|
||||
import net.corda.core.internal.exists
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.nodeapi.config.parseAs
|
||||
@ -13,24 +17,22 @@ import java.nio.file.Paths
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
|
||||
data class DoormanParameters(val basedir: Path,
|
||||
val keystorePassword: String?,
|
||||
data class DoormanParameters(val keystorePassword: String?,
|
||||
val caPrivateKeyPassword: String?,
|
||||
val rootKeystorePassword: String?,
|
||||
val rootPrivateKeyPassword: String?,
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val dataSourceProperties: Properties,
|
||||
val mode: Mode,
|
||||
val mode: Mode = Mode.DOORMAN,
|
||||
val approveAll: Boolean = false,
|
||||
val databaseProperties: Properties? = null,
|
||||
val jiraConfig: JiraConfig? = null,
|
||||
val keystorePath: Path? = null, // basedir / "certificates" / "caKeystore.jks",
|
||||
val rootStorePath: Path? = null, // basedir / "certificates" / "rootCAKeystore.jks"
|
||||
val keystorePath: Path? = null,
|
||||
val rootStorePath: Path? = null,
|
||||
// TODO Change these to Duration in the future
|
||||
val approveInterval: Long = DEFAULT_APPROVE_INTERVAL,
|
||||
val signInterval: Long = DEFAULT_SIGN_INTERVAL,
|
||||
val initialNetworkParameters: Path
|
||||
val signInterval: Long = DEFAULT_SIGN_INTERVAL
|
||||
) {
|
||||
enum class Mode {
|
||||
DOORMAN, CA_KEYGEN, ROOT_KEYGEN
|
||||
@ -50,30 +52,48 @@ data class DoormanParameters(val basedir: Path,
|
||||
}
|
||||
}
|
||||
|
||||
fun parseParameters(vararg args: String): DoormanParameters {
|
||||
val argConfig = args.toConfigWithOptions {
|
||||
accepts("basedir", "Overriding configuration filepath, default to current directory.").withRequiredArg().defaultsTo(".").describedAs("filepath")
|
||||
accepts("configFile", "Overriding configuration file, default to <<current directory>>/node.conf.").withRequiredArg().describedAs("filepath")
|
||||
accepts("mode", "Execution mode. Allowed values: ${DoormanParameters.Mode.values().toList()}").withRequiredArg().defaultsTo(DoormanParameters.Mode.DOORMAN.name)
|
||||
accepts("keystorePath", "CA keystore filepath").withRequiredArg().describedAs("filepath")
|
||||
accepts("rootStorePath", "Root CA keystore filepath").withRequiredArg().describedAs("filepath")
|
||||
accepts("keystorePassword", "CA keystore password.").withRequiredArg().describedAs("password")
|
||||
accepts("caPrivateKeyPassword", "CA private key password.").withRequiredArg().describedAs("password")
|
||||
accepts("rootKeystorePassword", "Root CA keystore password.").withRequiredArg().describedAs("password")
|
||||
accepts("rootPrivateKeyPassword", "Root private key password.").withRequiredArg().describedAs("password")
|
||||
accepts("host", "Doorman web service host override").withRequiredArg().describedAs("hostname")
|
||||
accepts("port", "Doorman web service port override").withRequiredArg().ofType(Int::class.java).describedAs("port number")
|
||||
accepts("approveInterval", "Time interval (in seconds) in which CSRs are approved (default: ${DEFAULT_APPROVE_INTERVAL})").withRequiredArg().ofType(Long::class.java).defaultsTo(DEFAULT_APPROVE_INTERVAL)
|
||||
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)
|
||||
accepts("initialNetworkParameters", "initial network parameters filepath").withRequiredArg().describedAs("The initial network map").describedAs("filepath")
|
||||
data class CommandLineOptions(val configFile: Path,
|
||||
val initialNetworkParameters: Path) {
|
||||
init {
|
||||
check(configFile.isRegularFile()) { "Config file $configFile does not exist" }
|
||||
check(initialNetworkParameters.isRegularFile()) { "Initial network parameters file $initialNetworkParameters does not exist" }
|
||||
}
|
||||
}
|
||||
|
||||
val configFile = if (argConfig.hasPath("configFile")) {
|
||||
Paths.get(argConfig.getString("configFile"))
|
||||
} else {
|
||||
Paths.get(argConfig.getString("basedir")) / "node.conf"
|
||||
/**
|
||||
* Parses the doorman command line options.
|
||||
*/
|
||||
fun parseCommandLine(vararg args: String): CommandLineOptions {
|
||||
val optionParser = OptionParser()
|
||||
val configFileArg = optionParser
|
||||
.accepts("config-file", "The path to the config file")
|
||||
.withRequiredArg()
|
||||
.describedAs("filepath")
|
||||
val initialNetworkParametersArg = optionParser
|
||||
.accepts("initial-network-parameters", "initial network parameters filepath")
|
||||
.withRequiredArg()
|
||||
.describedAs("The initial network map")
|
||||
.describedAs("filepath")
|
||||
val helpOption = optionParser.acceptsAll(listOf("h", "?", "help"), "show help").forHelp();
|
||||
|
||||
val optionSet = optionParser.parse(*args)
|
||||
// Print help and exit on help option.
|
||||
if (optionSet.has(helpOption)) {
|
||||
throw ShowHelpException(optionParser)
|
||||
}
|
||||
return argConfig.withFallback(ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true)))
|
||||
val configFile = Paths.get(optionSet.valueOf(configFileArg)).toAbsolutePath()
|
||||
val initialNetworkParameters = Paths.get(optionSet.valueOf(initialNetworkParametersArg)).toAbsolutePath()
|
||||
|
||||
return CommandLineOptions(configFile, initialNetworkParameters)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a configuration file, which contains all the configuration except the initial values for the network
|
||||
* parameters.
|
||||
*/
|
||||
fun parseParameters(configFile: Path): DoormanParameters {
|
||||
return ConfigFactory
|
||||
.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true))
|
||||
.resolve()
|
||||
.parseAs()
|
||||
}
|
||||
|
@ -245,8 +245,8 @@ private class ApproveAllCertificateRequestStorage(private val delegate: Certific
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
try {
|
||||
// TODO : Remove config overrides and solely use config file after testnet is finalized.
|
||||
parseParameters(*args).run {
|
||||
val commandLineOptions = parseCommandLine(*args)
|
||||
parseParameters(commandLineOptions.configFile).run {
|
||||
when (mode) {
|
||||
DoormanParameters.Mode.ROOT_KEYGEN -> generateRootKeyPair(
|
||||
rootStorePath ?: throw IllegalArgumentException("The 'rootStorePath' parameter must be specified when generating keys!"),
|
||||
@ -263,7 +263,7 @@ fun main(args: Array<String>) {
|
||||
val database = configureDatabase(dataSourceProperties, databaseProperties, { throw UnsupportedOperationException() }, SchemaService())
|
||||
val signer = buildLocalSigner(this)
|
||||
|
||||
val networkParameters = parseNetworkParametersFrom(initialNetworkParameters)
|
||||
val networkParameters = parseNetworkParametersFrom(commandLineOptions.initialNetworkParameters)
|
||||
startDoorman(NetworkHostAndPort(host, port), database, approveAll, networkParameters, signer, approveInterval, signInterval, jiraConfig)
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +1,52 @@
|
||||
package com.r3.corda.networkmanage.doorman
|
||||
|
||||
import com.r3.corda.networkmanage.TestBase
|
||||
import com.r3.corda.networkmanage.common.utils.ShowHelpException
|
||||
import com.typesafe.config.ConfigException
|
||||
import net.corda.core.utilities.seconds
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.nio.file.Paths
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
class DoormanParametersTest : TestBase() {
|
||||
private val testDummyPath = ".${File.separator}testDummyPath.jks"
|
||||
class DoormanParametersTest {
|
||||
private val validInitialNetworkConfigPath = File(javaClass.getResource("/initial-network-parameters.conf").toURI()).absolutePath
|
||||
private val validConfigPath = File(javaClass.getResource("/doorman.conf").toURI()).absolutePath
|
||||
private val invalidConfigPath = File(javaClass.getResource("/doorman_fail.conf").toURI()).absolutePath
|
||||
|
||||
private val requiredArgs = arrayOf("--configFile", validConfigPath, "--initialNetworkParameters", validInitialNetworkConfigPath)
|
||||
private val validArgs = arrayOf("--config-file", validConfigPath, "--initial-network-parameters", validInitialNetworkConfigPath)
|
||||
|
||||
@Test
|
||||
fun `parse mode flag arg correctly`() {
|
||||
assertEquals(DoormanParameters.Mode.CA_KEYGEN, callParseParametersWithRequiredArgs("--mode", "CA_KEYGEN").mode)
|
||||
assertEquals(DoormanParameters.Mode.ROOT_KEYGEN, callParseParametersWithRequiredArgs("--mode", "ROOT_KEYGEN").mode)
|
||||
assertEquals(DoormanParameters.Mode.DOORMAN, callParseParametersWithRequiredArgs("--mode", "DOORMAN").mode)
|
||||
fun `should fail when initial network parameters file is missing`() {
|
||||
val message = assertFailsWith<IllegalStateException> {
|
||||
parseCommandLine("--config-file", validConfigPath, "--initial-network-parameters", "not-here")
|
||||
}.message
|
||||
assertThat(message).contains("Initial network parameters file ")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `command line arg should override config file`() {
|
||||
val params = callParseParametersWithRequiredArgs("--keystorePath", testDummyPath, "--port", "1000")
|
||||
assertEquals(testDummyPath, params.keystorePath.toString())
|
||||
assertEquals(1000, params.port)
|
||||
fun `should fail when config file is missing`() {
|
||||
val message = assertFailsWith<IllegalStateException> {
|
||||
parseCommandLine("--config-file", "not-existing-file", "--initial-network-parameters", validInitialNetworkConfigPath)
|
||||
}.message
|
||||
assertThat(message).contains("Config file ")
|
||||
}
|
||||
|
||||
val params2 = callParseParametersWithRequiredArgs()
|
||||
assertEquals(Paths.get("/opt/doorman/certificates/caKeystore.jks"), params2.keystorePath)
|
||||
assertEquals(8080, params2.port)
|
||||
@Test
|
||||
fun `should throw ShowHelpException when -? is on the command line`() {
|
||||
assertFailsWith<ShowHelpException> {
|
||||
parseCommandLine("-?")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should fail when config missing`() {
|
||||
// dataSourceProperties is missing from node_fail.conf and it should fail during parsing, and shouldn't use default from reference.conf.
|
||||
assertFailsWith<ConfigException.Missing> {
|
||||
parseParameters("--configFile", invalidConfigPath)
|
||||
parseParameters(parseCommandLine("--config-file", invalidConfigPath, "--initial-network-parameters", validInitialNetworkConfigPath).configFile)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should parse jira config correctly`() {
|
||||
val parameter = callParseParametersWithRequiredArgs()
|
||||
val parameter = parseCommandLineAndGetParameters()
|
||||
assertEquals("https://doorman-jira-host.com/", parameter.jiraConfig?.address)
|
||||
assertEquals("TD", parameter.jiraConfig?.projectCode)
|
||||
assertEquals("username", parameter.jiraConfig?.username)
|
||||
@ -53,7 +54,7 @@ class DoormanParametersTest : TestBase() {
|
||||
assertEquals(41, parameter.jiraConfig?.doneTransitionCode)
|
||||
}
|
||||
|
||||
private fun callParseParametersWithRequiredArgs(vararg additionalArgs: String): DoormanParameters {
|
||||
return parseParameters(*(requiredArgs + additionalArgs))
|
||||
private fun parseCommandLineAndGetParameters(): DoormanParameters {
|
||||
return parseParameters(parseCommandLine(*validArgs).configFile)
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
basedir="."
|
||||
keystorePath = "/opt/doorman/certificates/caKeystore.jks"
|
||||
keyStorePassword = "password"
|
||||
caPrivateKeyPassword = "password"
|
||||
|
Loading…
x
Reference in New Issue
Block a user