ENT-1661 Doorman crashes ungracefully when started with incorrect or … (#747)

* ENT-1661 Doorman crashes ungracefully when started with incorrect or no program arguments. Should display a meaningful message instead.
This commit is contained in:
Patrick Kuo 2018-04-19 21:22:04 +01:00 committed by GitHub
parent b3a4e3907f
commit 57291c435c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 141 additions and 180 deletions

View File

@ -68,6 +68,8 @@ publish {
dependencies {
compile project(':node')
// TODO: remove this when ArgsParser is moved into corda.
compile project(':network-management')
testCompile 'junit:junit:4.12'
testCompile "org.assertj:assertj-core:${assertj_version}"
}

View File

@ -1,87 +1,74 @@
package com.r3.corda.networkmanage.registration
import com.r3.corda.networkmanage.common.utils.ArgsParser
import com.r3.corda.networkmanage.registration.ToolOption.KeyCopierOption
import com.r3.corda.networkmanage.registration.ToolOption.RegistrationOption
import joptsimple.OptionParser
import joptsimple.OptionSet
import joptsimple.OptionSpecBuilder
import joptsimple.util.PathConverter
import joptsimple.util.PathProperties
import net.corda.core.crypto.Crypto
import java.nio.file.Path
import kotlin.system.exitProcess
fun main(args: Array<String>) {
Crypto.registerProviders() // Required to register Providers first thing on boot.
val options = try {
parseOptions(*args)
} catch (e: ShowHelpException) {
e.errorMessage?.let(::println)
e.parser.printHelpOn(System.out)
exitProcess(0)
}
val options = ToolArgsParser().parseOrExit(*args, printHelpOn = System.out)
when (options) {
is RegistrationOption -> options.runRegistration()
is KeyCopierOption -> options.copyKeystore()
}
}
fun parseOptions(vararg args: String): ToolOption {
val optionParser = OptionParser()
val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
class ToolArgsParser : ArgsParser<ToolOption>() {
private val importKeyStoreArg = optionParser.accepts("importkeystore")
val importKeyStoreArg = optionParser.accepts("importkeystore")
val configFileArg = optionParser
private val configFileArg = optionParser
.accepts("config-file", "Path to the registration config file")
.availableUnless(importKeyStoreArg)
.requiredUnless(importKeyStoreArg)
.withRequiredArg()
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
// key copy tool args
val destKeystorePathArg = optionParser.accepts("destkeystore", "Path to the destination keystore which the private key should be copied to")
private val destKeystorePathArg = optionParser.accepts("destkeystore", "Path to the destination keystore which the private key should be copied to")
.requireOnlyIf(importKeyStoreArg)
.withRequiredArg()
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
val srcKeystorePathArg = optionParser.accepts("srckeystore", "Path to the source keystore containing the private key")
private val srcKeystorePathArg = optionParser.accepts("srckeystore", "Path to the source keystore containing the private key")
.requireOnlyIf(importKeyStoreArg)
.withRequiredArg()
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
val destPasswordArg = optionParser.accepts("deststorepass", "Source keystore password. Read in from the console if not specified.")
private val destPasswordArg = optionParser.accepts("deststorepass", "Source keystore password. Read in from the console if not specified.")
.availableIf(importKeyStoreArg)
.withRequiredArg()
val srcPasswordArg = optionParser.accepts("srcstorepass", "Destination keystore password. Read in from the console if not specified.")
private val srcPasswordArg = optionParser.accepts("srcstorepass", "Destination keystore password. Read in from the console if not specified.")
.availableIf(importKeyStoreArg)
.withRequiredArg()
val destAliasArg = optionParser.accepts("destalias", "The alias under which the private key will be stored in the destination key store. If not provided then [srcalias] is used.")
private val destAliasArg = optionParser.accepts("destalias", "The alias under which the private key will be stored in the destination key store. If not provided then [srcalias] is used.")
.availableIf(importKeyStoreArg)
.withRequiredArg()
val srcAliasArg = optionParser.accepts("srcalias", "The alias under which the private key resides in the source key store")
private val srcAliasArg = optionParser.accepts("srcalias", "The alias under which the private key resides in the source key store")
.requireOnlyIf(importKeyStoreArg)
.withRequiredArg()
val optionSet = optionParser.parse(*args)
if (optionSet.has(helpOption)) {
throw ShowHelpException(optionParser)
}
val isCopyKey = optionSet.has(importKeyStoreArg)
return if (isCopyKey) {
val srcKeystorePath = optionSet.valueOf(srcKeystorePathArg)
val targetKeystorePath = optionSet.valueOf(destKeystorePathArg)
val srcPassword = optionSet.valueOf(srcPasswordArg)
val destPassword = optionSet.valueOf(destPasswordArg)
val srcAlias = optionSet.valueOf(srcAliasArg)
val destAlias = optionSet.valueOf(destAliasArg)
KeyCopierOption(srcKeystorePath, targetKeystorePath, srcPassword, destPassword, srcAlias, destAlias)
} else {
val configFile = optionSet.valueOf(configFileArg)
RegistrationOption(configFile)
override fun parse(optionSet: OptionSet): ToolOption {
val isCopyKey = optionSet.has(importKeyStoreArg)
return if (isCopyKey) {
val srcKeystorePath = optionSet.valueOf(srcKeystorePathArg)
val targetKeystorePath = optionSet.valueOf(destKeystorePathArg)
val srcPassword = optionSet.valueOf(srcPasswordArg)
val destPassword = optionSet.valueOf(destPasswordArg)
val srcAlias = optionSet.valueOf(srcAliasArg)
val destAlias = optionSet.valueOf(destAliasArg)
KeyCopierOption(srcKeystorePath, targetKeystorePath, srcPassword, destPassword, srcAlias, destAlias)
} else {
val configFile = optionSet.valueOf(configFileArg)
RegistrationOption(configFile)
}
}
}
@ -97,8 +84,6 @@ sealed class ToolOption {
val destinationAlias: String?) : ToolOption()
}
class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception()
fun readPassword(fmt: String): String {
return if (System.console() != null) {
String(System.console().readPassword(fmt))

View File

@ -27,7 +27,7 @@ class OptionParserTest {
@Test
fun `parse registration args correctly`() {
val options = parseOptions("--config-file", "${tempDir / "test.file"}") as ToolOption.RegistrationOption
val options = ToolArgsParser().parseOrExit("--config-file", "${tempDir / "test.file"}") as ToolOption.RegistrationOption
assertThat(options.configFile).isEqualTo(tempDir / "test.file")
}
@ -40,7 +40,7 @@ class OptionParserTest {
"--destkeystore", "${tempDir / "target.jks"}",
"--deststorepass", "password2",
"--srcalias", "testalias")
assertThatThrownBy { parseOptions(*keyCopyArgs, "--config-file", "test.file") }
assertThatThrownBy { ToolArgsParser().parseOrExit(*keyCopyArgs, "--config-file", "test.file", printHelpOn = null) }
.isInstanceOf(OptionException::class.java)
.hasMessageContaining("Option(s) [config-file] are unavailable given other options on the command line")
}
@ -48,7 +48,7 @@ class OptionParserTest {
@Test
fun `key copy args should be unavailable in registration mode`() {
assertThatThrownBy {
parseOptions("--config-file", "${tempDir / "test.file"}", "--srckeystore", "${tempDir / "source.jks"}")
ToolArgsParser().parseOrExit("--config-file", "${tempDir / "test.file"}", "--srckeystore", "${tempDir / "source.jks"}", printHelpOn = null)
}.isInstanceOf(OptionException::class.java)
.hasMessageContaining("Option(s) [srckeystore] are unavailable given other options on the command line")
}
@ -63,7 +63,7 @@ class OptionParserTest {
"--deststorepass", "password2",
"--srcalias", "testalias",
"--destalias", "testalias2")
assertThat(parseOptions(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption(
assertThat(ToolArgsParser().parseOrExit(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption(
sourceFile = tempDir / "source.jks",
destinationFile = tempDir / "target.jks",
sourcePassword = "password1",
@ -80,7 +80,7 @@ class OptionParserTest {
"--srckeystore", "${tempDir / "source.jks"}",
"--destkeystore", "${tempDir / "target.jks"}",
"--srcalias", "testalias")
assertThat(parseOptions(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption(
assertThat(ToolArgsParser().parseOrExit(*keyCopyArgs)).isEqualTo(ToolOption.KeyCopierOption(
sourceFile = tempDir / "source.jks",
destinationFile = tempDir / "target.jks",
sourcePassword = null,

View File

@ -0,0 +1,23 @@
package com.r3.corda.networkmanage.common.configuration
import com.r3.corda.networkmanage.common.utils.ArgsParser
import joptsimple.OptionSet
import joptsimple.util.PathConverter
import joptsimple.util.PathProperties
import java.nio.file.Path
/**
* Parses key generator command line options.
*/
class ConfigFilePathArgsParser : ArgsParser<Path>() {
private val configFileArg = optionParser
.accepts("config-file", "The path to the config file")
.withRequiredArg()
.required()
.describedAs("filepath")
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
override fun parse(optionSet: OptionSet): Path {
return optionSet.valueOf(configFileArg).toAbsolutePath()
}
}

View File

@ -1,28 +0,0 @@
package com.r3.corda.networkmanage.common.configuration
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import joptsimple.OptionParser
import joptsimple.util.PathConverter
import joptsimple.util.PathProperties
import java.nio.file.Path
/**
* Parses key generator command line options.
*/
fun parseCommandLine(vararg args: String): Path {
val optionParser = OptionParser()
val configFileArg = optionParser
.accepts("config-file", "The path to the config file")
.withRequiredArg()
.required()
.describedAs("filepath")
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
val optionSet = optionParser.parse(*args)
// Print help and exit on help option or if there are missing options.
if (optionSet.has(helpOption) || !optionSet.has(configFileArg)) {
throw ShowHelpException(optionParser)
}
return optionSet.valueOf(configFileArg).toAbsolutePath()
}

View File

@ -0,0 +1,37 @@
package com.r3.corda.networkmanage.common.utils
import joptsimple.OptionException
import joptsimple.OptionParser
import joptsimple.OptionSet
import java.io.PrintStream
import kotlin.system.exitProcess
// TODO: This class could be useful for the rest of the codebase.
abstract class ArgsParser<out T : Any> {
protected val optionParser = OptionParser()
private val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
/**
If [printHelpOn] output stream is not null, this method will print help message and exit process
when encountered any error during args parsing, or when help flag is set.
*/
fun parseOrExit(vararg args: String, printHelpOn: PrintStream? = System.out): T {
val optionSet = try {
optionParser.parse(*args)
} catch (e: OptionException) {
printHelpOn?.let {
it.println(e.message ?: "Unable to parse arguments.")
optionParser.printHelpOn(it)
exitProcess(-1)
}
throw e
}
if (optionSet.has(helpOption)) {
printHelpOn?.let(optionParser::printHelpOn)
exitProcess(0)
}
return parse(optionSet)
}
protected abstract fun parse(optionSet: OptionSet): T
}

View File

@ -13,9 +13,7 @@ package com.r3.corda.networkmanage.common.utils
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import com.typesafe.config.ConfigRenderOptions
import joptsimple.OptionParser
import net.corda.core.CordaOID
import net.corda.core.crypto.sha256
import net.corda.core.internal.CertRole
import net.corda.core.serialization.internal.SerializationEnvironmentImpl
import net.corda.core.serialization.internal.nodeSerializationEnv
@ -34,7 +32,6 @@ import org.slf4j.LoggerFactory
import java.nio.file.Path
import java.security.KeyPair
import java.security.PrivateKey
import java.security.PublicKey
import java.security.cert.CertPath
import java.security.cert.X509Certificate
@ -52,8 +49,6 @@ inline fun <reified T : Any> parseConfig(file: Path): T {
return config.parseAs(strict = false)
}
class ShowHelpException(val parser: OptionParser, val errorMessage: String? = null) : Exception()
fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream())
fun X509KeyStore.getCertPathAndKey(alias: String, privateKeyPassword: String): CertPathAndKey {

View File

@ -38,8 +38,7 @@ fun parseParameters(configFile: Path?): GeneratorConfiguration {
return if (configFile == null) {
GeneratorConfiguration()
} else {
ConfigFactory
.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true))
ConfigFactory.parseFile(configFile.toFile(), ConfigParseOptions.defaults().setAllowMissing(true))
.resolve()
.parseAs()
}

View File

@ -10,7 +10,7 @@
package com.r3.corda.networkmanage.dev
import com.r3.corda.networkmanage.common.configuration.parseCommandLine
import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser
import com.r3.corda.networkmanage.doorman.CORDA_X500_BASE
import net.corda.core.crypto.Crypto
import net.corda.core.internal.createDirectories
@ -34,7 +34,7 @@ private val logger = LogManager.getLogger("com.r3.corda.networkmanage.dev.Main")
* Look for the 'certificates' directory.
*/
fun main(args: Array<String>) {
run(parseParameters(parseCommandLine(*args)))
run(parseParameters(ConfigFilePathArgsParser().parseOrExit(*args)))
}
fun run(configuration: GeneratorConfiguration) {

View File

@ -1,10 +1,10 @@
package com.r3.corda.networkmanage.doorman
import com.google.common.primitives.Booleans
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.utils.ArgsParser
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import joptsimple.OptionParser
import joptsimple.OptionSet
import joptsimple.util.EnumConverter
import joptsimple.util.PathConverter
import joptsimple.util.PathProperties
@ -14,9 +14,7 @@ import net.corda.nodeapi.internal.config.parseAs
import java.nio.file.Path
import java.time.Instant
class DoormanArgsParser {
private val optionParser = OptionParser()
private val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
class DoormanArgsParser : ArgsParser<DoormanCmdLineOptions>() {
private val configFileArg = optionParser
.accepts("config-file", "The path to the config file")
.withRequiredArg()
@ -37,11 +35,7 @@ class DoormanArgsParser {
.accepts("trust-store-password", "Password for the generated network root trust store. Only applicable when operating in ${Mode.ROOT_KEYGEN} mode.")
.withRequiredArg()
fun parse(vararg args: String): DoormanCmdLineOptions {
val optionSet = optionParser.parse(*args)
if (optionSet.has(helpOption)) {
throw ShowHelpException(optionParser)
}
override fun parse(optionSet: OptionSet): DoormanCmdLineOptions {
val configFile = optionSet.valueOf(configFileArg)
val mode = optionSet.valueOf(modeArg)
val setNetworkParametersFile = optionSet.valueOf(setNetworkParametersArg)

View File

@ -31,13 +31,7 @@ fun main(args: Array<String>) {
}
initialiseSerialization()
val cmdLineOptions = try {
DoormanArgsParser().parse(*args)
} catch (e: ShowHelpException) {
e.errorMessage?.let(::println)
e.parser.printHelpOn(System.out)
exitProcess(0)
}
val cmdLineOptions = DoormanArgsParser().parseOrExit(*args)
val config = parseConfig<NetworkManagementServerConfig>(cmdLineOptions.configFile)

View File

@ -12,7 +12,6 @@ package com.r3.corda.networkmanage.hsm
import com.jcabi.manifests.Manifests
import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.utils.initialiseSerialization
import com.r3.corda.networkmanage.common.utils.parseConfig
import com.r3.corda.networkmanage.hsm.configuration.ManualMode
@ -25,7 +24,6 @@ import org.apache.logging.log4j.LogManager
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.Security
import javax.crypto.Cipher
import kotlin.system.exitProcess
private val logger = LogManager.getLogger("com.r3.corda.networkmanage.hsm.Main")
@ -34,13 +32,7 @@ fun main(args: Array<String>) {
println("Signing Service Version: ${Manifests.read("Signing-Service-Version")}")
}
val cmdLineOptions = try {
SigningServiceArgsParser().parse(*args)
} catch (e: ShowHelpException) {
e.errorMessage?.let(::println)
e.parser.printHelpOn(System.out)
exitProcess(0)
}
val cmdLineOptions = SigningServiceArgsParser().parseOrExit(*args)
val config = parseConfig<SigningServiceConfig>(cmdLineOptions.configFile)

View File

@ -11,20 +11,15 @@
package com.r3.corda.networkmanage.hsm.configuration
import com.google.common.primitives.Booleans
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.utils.ArgsParser
import com.r3.corda.networkmanage.hsm.authentication.AuthMode
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import com.typesafe.config.ConfigRenderOptions
import joptsimple.OptionParser
import joptsimple.OptionSet
import joptsimple.util.PathConverter
import joptsimple.util.PathProperties
import net.corda.core.internal.div
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.persistence.DatabaseConfig
import java.net.InetAddress
import java.net.URL
import java.nio.file.Path
import java.nio.file.Paths
@ -61,7 +56,7 @@ data class DoormanCertificateConfig(val crlDistributionPoint: URL,
val crlServerSocketAddress: NetworkHostAndPort,
val crlUpdatePeriod: Long,
val mode: ManualMode,
val keyGroup:String,
val keyGroup: String,
val validDays: Int,
val rootKeyStoreFile: Path,
val rootKeyStorePassword: String,
@ -84,9 +79,7 @@ data class AuthParametersConfig(val mode: AuthMode,
val keyFilePath: Path? = null,
val threshold: Int)
class SigningServiceArgsParser {
private val optionParser = OptionParser()
private val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
class SigningServiceArgsParser : ArgsParser<SigningServiceCmdLineOptions>() {
private val baseDirArg = optionParser
.accepts("basedir", "Overriding configuration filepath, default to current directory.")
.withRequiredArg()
@ -97,11 +90,7 @@ class SigningServiceArgsParser {
.withRequiredArg()
.withValuesConvertedBy(PathConverter(PathProperties.FILE_EXISTING))
fun parse(vararg args: String): SigningServiceCmdLineOptions {
val optionSet = optionParser.parse(*args)
if (optionSet.has(helpOption)) {
throw ShowHelpException(optionParser)
}
override fun parse(optionSet: OptionSet): SigningServiceCmdLineOptions {
val baseDir = optionSet.valueOf(baseDirArg)
val configFile = optionSet.valueOf(configFileArg) ?: baseDir / "signing_service.conf"
return SigningServiceCmdLineOptions(baseDir, configFile)

View File

@ -10,7 +10,7 @@
package com.r3.corda.networkmanage.hsm.generator
import com.r3.corda.networkmanage.common.configuration.parseCommandLine
import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser
import com.r3.corda.networkmanage.hsm.authentication.CryptoServerProviderConfig
import com.r3.corda.networkmanage.hsm.utils.mapCryptoServerException
import net.corda.nodeapi.internal.crypto.CertificateType.ROOT_CA
@ -19,7 +19,7 @@ import org.apache.logging.log4j.LogManager
private val logger = LogManager.getLogger("com.r3.corda.networkmanage.hsm.generator.Main")
fun main(args: Array<String>) {
run(parseParameters(parseCommandLine(*args)))
run(parseParameters(ConfigFilePathArgsParser().parseOrExit(*args)))
}
fun run(parameters: GeneratorParameters) {

View File

@ -0,0 +1,16 @@
package com.r3.corda.networkmanage.tools.crr.submission
import com.r3.corda.networkmanage.common.utils.ArgsParser
import joptsimple.OptionSet
import java.net.URL
class CRRToolArgsParser : ArgsParser<URL>() {
private val submissionUrlArg = optionParser
.accepts("submission-url", "CRR submission endpoint.")
.withRequiredArg()
.required()
override fun parse(optionSet: OptionSet): URL {
return URL(optionSet.valueOf(submissionUrlArg))
}
}

View File

@ -1,21 +0,0 @@
package com.r3.corda.networkmanage.tools.crr.submission
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import joptsimple.OptionParser
import java.net.URL
fun parseSubmissionUrl(vararg args: String): URL {
val optionParser = OptionParser()
val submissionUrlArg = optionParser
.accepts("submission-url", "CRR submission endpoint.")
.withRequiredArg()
.required()
val helpOption = optionParser.acceptsAll(listOf("h", "help"), "show help").forHelp()
val optionSet = optionParser.parse(*args)
// Print help and exit on help option or if there are missing options.
if (optionSet.has(helpOption) || !optionSet.has(submissionUrlArg)) {
throw ShowHelpException(optionParser)
}
return URL(optionSet.valueOf(submissionUrlArg))
}

View File

@ -17,7 +17,7 @@ private val logger = LogManager.getLogger("com.r3.corda.networkmanage.common.too
fun main(args: Array<String>) {
initialiseSerialization()
try {
submit(parseSubmissionUrl(*args))
submit(CRRToolArgsParser().parseOrExit(*args))
} catch (e: Exception) {
logger.error("Error when submitting a certificate revocation request.", e)
throw e

View File

@ -10,7 +10,7 @@
package com.r3.corda.networkmanage.dev
import com.r3.corda.networkmanage.common.configuration.parseCommandLine
import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser
import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_FILE
import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS
import net.corda.nodeapi.internal.DEV_CA_TRUST_STORE_FILE
@ -31,7 +31,7 @@ class GeneratorConfigurationTest {
@Test
fun `config file is parsed correctly`() {
val config = parseParameters(parseCommandLine("--config-file", configPath))
val config = parseParameters(ConfigFilePathArgsParser().parseOrExit("--config-file", configPath))
assertEquals(GeneratorConfiguration.DEFAULT_DIRECTORY, config.directory)
assertEquals(DEV_CA_KEY_STORE_FILE, config.keyStoreFileName)
assertEquals(DEV_CA_KEY_STORE_PASS, config.keyStorePass)

View File

@ -10,7 +10,6 @@
package com.r3.corda.networkmanage.doorman
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import joptsimple.OptionException
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.junit.Test
@ -26,39 +25,32 @@ class DoormanArgsParserTest {
@Test
fun `should fail when network parameters file is missing`() {
assertThatThrownBy {
argsParser.parse("--config-file", validConfigPath, "--set-network-parameters", "not-here")
argsParser.parseOrExit("--config-file", validConfigPath, "--set-network-parameters", "not-here")
}.hasMessageContaining("not-here")
}
@Test
fun `should fail when config file is missing`() {
assertThatThrownBy {
argsParser.parse("--config-file", "not-existing-file")
argsParser.parseOrExit("--config-file", "not-existing-file")
}.hasMessageContaining("not-existing-file")
}
@Test
fun `should throw ShowHelpException when help option is passed on the command line`() {
assertFailsWith<ShowHelpException> {
argsParser.parse("-h")
}
}
@Test
fun `should parse trust store password correctly`() {
val parameter = argsParser.parse("--config-file", validConfigPath, "--mode", "ROOT_KEYGEN", "--trust-store-password", "testPassword")
val parameter = argsParser.parseOrExit("--config-file", validConfigPath, "--mode", "ROOT_KEYGEN", "--trust-store-password", "testPassword")
assertEquals("testPassword", parameter.trustStorePassword)
assertFailsWith<OptionException> {
argsParser.parse("--trust-store-password")
argsParser.parseOrExit("--trust-store-password", printHelpOn = null)
}
// Should fail if password is provided in mode other then root keygen.
assertFailsWith<IllegalArgumentException> {
argsParser.parse("--config-file", validConfigPath, "--trust-store-password", "testPassword")
argsParser.parseOrExit("--config-file", validConfigPath, "--trust-store-password", "testPassword")
}
// trust store password is optional.
assertNull(argsParser.parse("--config-file", validConfigPath).trustStorePassword)
assertNull(argsParser.parseOrExit("--config-file", validConfigPath).trustStorePassword)
}
}

View File

@ -26,7 +26,7 @@ class SigningServiceArgsParserTest : TestBase() {
@Test
fun `doorman-based config file is parsed correctly`() {
val cmdLineOptions = argsParser.parse("--config-file", doormanConfigPath)
val cmdLineOptions = argsParser.parseOrExit("--config-file", doormanConfigPath)
val config = parseConfig<SigningServiceConfig>(cmdLineOptions.configFile)
assertEquals("3001@192.168.0.1", config.device)
val doormanCertParameters = config.doorman!!
@ -37,7 +37,7 @@ class SigningServiceArgsParserTest : TestBase() {
@Test
fun `networkmap-based config file is parsed correctly`() {
val cmdLineOptions = argsParser.parse("--config-file", networkMapConfigPath)
val cmdLineOptions = argsParser.parseOrExit("--config-file", networkMapConfigPath)
val config = parseConfig<SigningServiceConfig>(cmdLineOptions.configFile)
assertEquals("3001@192.168.0.1", config.device)
val networkMapConfig = config.networkMap!!
@ -51,7 +51,7 @@ class SigningServiceArgsParserTest : TestBase() {
@Test
fun `should fail when config file is missing`() {
assertThatThrownBy {
argsParser.parse("--config-file", "not-existing-file")
argsParser.parseOrExit("--config-file", "not-existing-file")
}.hasMessageContaining("not-existing-file")
}
}

View File

@ -10,8 +10,7 @@
package com.r3.corda.networkmanage.hsm.generator
import com.r3.corda.networkmanage.common.configuration.parseCommandLine
import com.r3.corda.networkmanage.common.utils.ShowHelpException
import com.r3.corda.networkmanage.common.configuration.ConfigFilePathArgsParser
import com.typesafe.config.ConfigException
import joptsimple.OptionException
import net.corda.nodeapi.internal.crypto.CertificateType
@ -31,22 +30,15 @@ class GeneratorParametersTest {
@Test
fun `should fail when config file is missing`() {
val message = assertFailsWith<OptionException> {
parseCommandLine("--config-file", "not-existing-file")
ConfigFilePathArgsParser().parseOrExit("--config-file", "not-existing-file")
}.message
Assertions.assertThat(message).contains("not-existing-file")
}
@Test
fun `should throw ShowHelpException when help option is passed on the command line`() {
assertFailsWith<ShowHelpException> {
parseCommandLine("-h")
}
}
@Test
fun `should fail when config is invalid`() {
assertFailsWith<ConfigException.Missing> {
parseParameters(parseCommandLine("--config-file", invalidConfigPath))
parseParameters(ConfigFilePathArgsParser().parseOrExit("--config-file", invalidConfigPath))
}
}
@ -71,6 +63,6 @@ class GeneratorParametersTest {
}
private fun parseCommandLineAndGetParameters(): GeneratorParameters {
return parseParameters(parseCommandLine(*validArgs))
return parseParameters(ConfigFilePathArgsParser().parseOrExit(*validArgs))
}
}