mirror of
https://github.com/corda/corda.git
synced 2025-06-21 00:23:09 +00:00
Merge remote-tracking branch 'open/master' into tudor-merge-21-05-18
# Conflicts: # .idea/compiler.xml # client/rpc/src/main/kotlin/net/corda/client/rpc/CordaRPCClient.kt # client/rpc/src/main/kotlin/net/corda/client/rpc/internal/CordaRPCClientUtils.kt # docs/source/generating-a-node.rst # finance/src/main/kotlin/net/corda/finance/contracts/asset/CommodityContract.kt # node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisMessagingClient.kt # node/src/integration-test/kotlin/net/corda/node/amqp/AMQPBridgeTest.kt # node/src/integration-test/kotlin/net/corda/node/amqp/ProtonWrapperTests.kt # node/src/integration-test/kotlin/net/corda/node/services/rpc/RpcSslTest.kt # node/src/main/kotlin/net/corda/node/internal/Node.kt # node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt # node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt # node/src/main/kotlin/net/corda/node/services/config/SslOptions.kt # node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt # node/src/main/kotlin/net/corda/node/services/rpc/NodeLoginModule.kt # tools/shell/src/integration-test/kotlin/net/corda/tools/shell/InteractiveShellIntegrationTest.kt
This commit is contained in:
@ -13,23 +13,28 @@ package net.corda.tools.shell
|
||||
import com.google.common.io.Files
|
||||
import com.jcraft.jsch.ChannelExec
|
||||
import com.jcraft.jsch.JSch
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.services.Permissions
|
||||
import net.corda.node.services.Permissions.Companion.all
|
||||
import net.corda.testing.common.internal.withCertificates
|
||||
import net.corda.testing.common.internal.withKeyStores
|
||||
import net.corda.node.services.config.shell.toShellConfig
|
||||
import net.corda.nodeapi.BrokerRpcSslOptions
|
||||
import net.corda.core.messaging.ClientRpcSslOptions
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.driver.internal.NodeHandleInternal
|
||||
import net.corda.testing.driver.internal.RandomFree
|
||||
import net.corda.testing.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
import net.corda.testing.internal.toDatabaseSchemaName
|
||||
import net.corda.testing.internal.createKeyPairAndSelfSignedCertificate
|
||||
import net.corda.testing.internal.saveToKeyStore
|
||||
import net.corda.testing.internal.saveToTrustStore
|
||||
import net.corda.testing.internal.useSslRpcOverrides
|
||||
import net.corda.testing.node.User
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException
|
||||
@ -39,7 +44,9 @@ import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.bouncycastle.util.io.Streams
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Ignore
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class InteractiveShellIntegrationTest : IntegrationTest() {
|
||||
@ -50,6 +57,10 @@ class InteractiveShellIntegrationTest : IntegrationTest() {
|
||||
.map { it.toDatabaseSchemaName() }.toTypedArray())
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
val tempFolder = TemporaryFolder()
|
||||
|
||||
@Test
|
||||
fun `shell should not log in with invalid credentials`() {
|
||||
val user = User("u", "p", setOf())
|
||||
@ -67,7 +78,7 @@ class InteractiveShellIntegrationTest : IntegrationTest() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `shell should log in with valid crentials`() {
|
||||
fun `shell should log in with valid credentials`() {
|
||||
val user = User("u", "p", setOf())
|
||||
driver {
|
||||
val nodeFuture = startNode(providedName = ALICE_NAME, rpcUsers = listOf(user), startInSameProcess = true)
|
||||
@ -85,72 +96,65 @@ class InteractiveShellIntegrationTest : IntegrationTest() {
|
||||
@Test
|
||||
fun `shell should log in with ssl`() {
|
||||
val user = User("mark", "dadada", setOf(all()))
|
||||
withCertificates { server, client, createSelfSigned, createSignedBy ->
|
||||
val rootCertificate = createSelfSigned(CordaX500Name("SystemUsers/Node", "IT", "R3 London", "London", "London", "GB"))
|
||||
val markCertificate = createSignedBy(CordaX500Name("shell", "IT", "R3 London", "London", "London", "GB"), rootCertificate)
|
||||
var successful = false
|
||||
|
||||
// truststore needs to contain root CA for how the driver works...
|
||||
server.keyStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["shell"] = markCertificate
|
||||
val (keyPair, cert) = createKeyPairAndSelfSignedCertificate()
|
||||
val keyStorePath = saveToKeyStore(tempFolder.root.toPath() / "keystore.jks", keyPair, cert)
|
||||
val brokerSslOptions = BrokerRpcSslOptions(keyStorePath, "password")
|
||||
|
||||
client.keyStore["shell"] = markCertificate
|
||||
client.trustStore["cordaclienttls"] = rootCertificate
|
||||
val trustStorePath = saveToTrustStore(tempFolder.root.toPath() / "truststore.jks", cert)
|
||||
val clientSslOptions = ClientRpcSslOptions(trustStorePath, "password")
|
||||
|
||||
withKeyStores(server, client) { nodeSslOptions, clientSslOptions ->
|
||||
var successful = false
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = nodeSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = brokerSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
|
||||
val sslConfiguration = ShellSslOptions(clientSslOptions.sslKeystore, clientSslOptions.keyStorePassword,
|
||||
clientSslOptions.trustStoreFile, clientSslOptions.trustStorePassword, clientSslOptions.crlCheckSoftFail)
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = sslConfiguration)
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = clientSslOptions)
|
||||
|
||||
InteractiveShell.startShell(conf)
|
||||
InteractiveShell.startShell(conf)
|
||||
|
||||
InteractiveShell.nodeInfo()
|
||||
successful = true
|
||||
}
|
||||
}
|
||||
assertThat(successful).isTrue()
|
||||
InteractiveShell.nodeInfo()
|
||||
successful = true
|
||||
}
|
||||
}
|
||||
assertThat(successful).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `shell shoud not log in with invalid truststore`() {
|
||||
val user = User("mark", "dadada", setOf("ALL"))
|
||||
val (keyPair, cert) = createKeyPairAndSelfSignedCertificate()
|
||||
val keyStorePath = saveToKeyStore(tempFolder.root.toPath() / "keystore.jks", keyPair, cert)
|
||||
val brokerSslOptions = BrokerRpcSslOptions(keyStorePath, "password")
|
||||
|
||||
val (_, cert1) = createKeyPairAndSelfSignedCertificate()
|
||||
val trustStorePath = saveToTrustStore(tempFolder.root.toPath() / "truststore.jks", cert1)
|
||||
val clientSslOptions = ClientRpcSslOptions(trustStorePath, "password")
|
||||
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = brokerSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = clientSslOptions)
|
||||
|
||||
InteractiveShell.startShell(conf)
|
||||
|
||||
assertThatThrownBy { InteractiveShell.nodeInfo() }.isInstanceOf(ActiveMQNotConnectedException::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `shell shoud not log in without ssl keystore`() {
|
||||
val user = User("mark", "dadada", setOf("ALL"))
|
||||
withCertificates { server, client, createSelfSigned, createSignedBy ->
|
||||
val rootCertificate = createSelfSigned(CordaX500Name("SystemUsers/Node", "IT", "R3 London", "London", "London", "GB"))
|
||||
val markCertificate = createSignedBy(CordaX500Name("shell", "IT", "R3 London", "London", "London", "GB"), rootCertificate)
|
||||
|
||||
// truststore needs to contain root CA for how the driver works...
|
||||
server.keyStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["shell"] = markCertificate
|
||||
|
||||
//client key store doesn't have "mark" certificate
|
||||
client.trustStore["cordaclienttls"] = rootCertificate
|
||||
|
||||
withKeyStores(server, client) { nodeSslOptions, clientSslOptions ->
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = nodeSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
|
||||
val sslConfiguration = ShellSslOptions(clientSslOptions.sslKeystore, clientSslOptions.keyStorePassword,
|
||||
clientSslOptions.trustStoreFile, clientSslOptions.trustStorePassword, clientSslOptions.crlCheckSoftFail)
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = sslConfiguration)
|
||||
|
||||
InteractiveShell.startShell(conf)
|
||||
|
||||
assertThatThrownBy { InteractiveShell.nodeInfo() }.isInstanceOf(ActiveMQNotConnectedException::class.java)
|
||||
}
|
||||
}
|
||||
fun `internal shell user should not be able to connect if node started with devMode=false`() {
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode().getOrThrow().use { node ->
|
||||
val conf = (node as NodeHandleInternal).configuration.toShellConfig()
|
||||
InteractiveShell.startShellInternal(conf)
|
||||
assertThatThrownBy { InteractiveShell.nodeInfo() }.isInstanceOf(ActiveMQSecurityException::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -204,62 +208,54 @@ class InteractiveShellIntegrationTest : IntegrationTest() {
|
||||
val user = User("mark", "dadada", setOf(Permissions.startFlow<SSHServerTest.FlowICanRun>(),
|
||||
Permissions.invokeRpc(CordaRPCOps::registeredFlows),
|
||||
Permissions.invokeRpc(CordaRPCOps::nodeInfo)/*all()*/))
|
||||
withCertificates { server, client, createSelfSigned, createSignedBy ->
|
||||
val rootCertificate = createSelfSigned(CordaX500Name("SystemUsers/Node", "IT", "R3 London", "London", "London", "GB"))
|
||||
val markCertificate = createSignedBy(CordaX500Name("shell", "IT", "R3 London", "London", "London", "GB"), rootCertificate)
|
||||
|
||||
// truststore needs to contain root CA for how the driver works...
|
||||
server.keyStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["cordaclienttls"] = rootCertificate
|
||||
server.trustStore["shell"] = markCertificate
|
||||
val (keyPair, cert) = createKeyPairAndSelfSignedCertificate()
|
||||
val keyStorePath = saveToKeyStore(tempFolder.root.toPath() / "keystore.jks", keyPair, cert)
|
||||
val brokerSslOptions = BrokerRpcSslOptions(keyStorePath, "password")
|
||||
val trustStorePath = saveToTrustStore(tempFolder.root.toPath() / "truststore.jks", cert)
|
||||
val clientSslOptions = ClientRpcSslOptions(trustStorePath, "password")
|
||||
|
||||
client.keyStore["shell"] = markCertificate
|
||||
client.trustStore["cordaclienttls"] = rootCertificate
|
||||
var successful = false
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = brokerSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
|
||||
withKeyStores(server, client) { nodeSslOptions, clientSslOptions ->
|
||||
var successful = false
|
||||
driver(DriverParameters(isDebug = true, startNodesInProcess = true, portAllocation = RandomFree)) {
|
||||
startNode(rpcUsers = listOf(user), customOverrides = nodeSslOptions.useSslRpcOverrides()).getOrThrow().use { node ->
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = clientSslOptions,
|
||||
sshdPort = 2223)
|
||||
|
||||
val sslConfiguration = ShellSslOptions(clientSslOptions.sslKeystore, clientSslOptions.keyStorePassword,
|
||||
clientSslOptions.trustStoreFile, clientSslOptions.trustStorePassword, clientSslOptions.crlCheckSoftFail)
|
||||
val conf = ShellConfiguration(commandsDirectory = Files.createTempDir().toPath(),
|
||||
user = user.username, password = user.password,
|
||||
hostAndPort = node.rpcAddress,
|
||||
ssl = sslConfiguration,
|
||||
sshdPort = 2223)
|
||||
InteractiveShell.startShell(conf)
|
||||
InteractiveShell.nodeInfo()
|
||||
|
||||
InteractiveShell.startShell(conf)
|
||||
InteractiveShell.nodeInfo()
|
||||
val session = JSch().getSession("mark", "localhost", 2223)
|
||||
session.setConfig("StrictHostKeyChecking", "no")
|
||||
session.setPassword("dadada")
|
||||
session.connect()
|
||||
|
||||
val session = JSch().getSession("mark", "localhost", 2223)
|
||||
session.setConfig("StrictHostKeyChecking", "no")
|
||||
session.setPassword("dadada")
|
||||
session.connect()
|
||||
assertTrue(session.isConnected)
|
||||
|
||||
assertTrue(session.isConnected)
|
||||
val channel = session.openChannel("exec") as ChannelExec
|
||||
channel.setCommand("start FlowICanRun")
|
||||
channel.connect(5000)
|
||||
|
||||
val channel = session.openChannel("exec") as ChannelExec
|
||||
channel.setCommand("start FlowICanRun")
|
||||
channel.connect(5000)
|
||||
assertTrue(channel.isConnected)
|
||||
|
||||
assertTrue(channel.isConnected)
|
||||
val response = String(Streams.readAll(channel.inputStream))
|
||||
|
||||
val response = String(Streams.readAll(channel.inputStream))
|
||||
val linesWithDoneCount = response.lines().filter { line -> line.contains("Done") }
|
||||
|
||||
val linesWithDoneCount = response.lines().filter { line -> line.contains("Done") }
|
||||
channel.disconnect()
|
||||
session.disconnect() // TODO Simon make sure to close them
|
||||
|
||||
channel.disconnect()
|
||||
session.disconnect() // TODO Simon make sure to close them
|
||||
// There are ANSI control characters involved, so we want to avoid direct byte to byte matching.
|
||||
assertThat(linesWithDoneCount).hasSize(1)
|
||||
|
||||
// There are ANSI control characters involved, so we want to avoid direct byte to byte matching.
|
||||
assertThat(linesWithDoneCount).hasSize(1)
|
||||
|
||||
successful = true
|
||||
}
|
||||
}
|
||||
assertThat(successful).isTrue()
|
||||
successful = true
|
||||
}
|
||||
|
||||
assertThat(successful).isTrue()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -19,6 +19,7 @@ import net.corda.client.jackson.StringToMethodCallParser
|
||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||
import net.corda.client.rpc.CordaRPCConnection
|
||||
import net.corda.client.rpc.PermissionException
|
||||
import net.corda.client.rpc.internal.createCordaRPCClientWithInternalSslAndClassLoader
|
||||
import net.corda.client.rpc.internal.createCordaRPCClientWithSslAndClassLoader
|
||||
import net.corda.core.CordaException
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
@ -90,7 +91,6 @@ object InteractiveShell {
|
||||
* internals.
|
||||
*/
|
||||
fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null) {
|
||||
shellConfiguration = configuration
|
||||
rpcOps = { username: String, credentials: String ->
|
||||
val client = createCordaRPCClientWithSslAndClassLoader(hostAndPort = configuration.hostAndPort,
|
||||
configuration = object : CordaRPCClientConfiguration {
|
||||
@ -101,6 +101,29 @@ object InteractiveShell {
|
||||
this.connection = client.start(username, credentials)
|
||||
connection.proxy
|
||||
}
|
||||
_startShell(configuration, classLoader)
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an interactive shell connected to the local terminal. This shell gives administrator access to the node
|
||||
* internals.
|
||||
*/
|
||||
fun startShellInternal(configuration: ShellConfiguration, classLoader: ClassLoader? = null) {
|
||||
rpcOps = { username: String, credentials: String ->
|
||||
val client = createCordaRPCClientWithInternalSslAndClassLoader(hostAndPort = configuration.hostAndPort,
|
||||
configuration = object : CordaRPCClientConfiguration {
|
||||
override val maxReconnectAttempts = 1
|
||||
},
|
||||
sslConfiguration = configuration.nodeSslConfig,
|
||||
classLoader = classLoader)
|
||||
this.connection = client.start(username, credentials)
|
||||
connection.proxy
|
||||
}
|
||||
_startShell(configuration, classLoader)
|
||||
}
|
||||
|
||||
private fun _startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null) {
|
||||
shellConfiguration = configuration
|
||||
InteractiveShell.classLoader = classLoader
|
||||
val runSshDaemon = configuration.sshdPort != null
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
package net.corda.tools.shell
|
||||
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.messaging.ClientRpcSslOptions
|
||||
import net.corda.nodeapi.internal.config.SSLConfiguration
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
data class ShellConfiguration(
|
||||
val commandsDirectory: Path,
|
||||
@ -11,7 +11,8 @@ data class ShellConfiguration(
|
||||
var user: String = "",
|
||||
var password: String = "",
|
||||
val hostAndPort: NetworkHostAndPort,
|
||||
val ssl: ShellSslOptions? = null,
|
||||
val ssl: ClientRpcSslOptions? = null,
|
||||
val nodeSslConfig: SSLConfiguration? = null,
|
||||
val sshdPort: Int? = null,
|
||||
val sshHostKeyDirectory: Path? = null,
|
||||
val noLocalShell: Boolean = false) {
|
||||
@ -22,13 +23,3 @@ data class ShellConfiguration(
|
||||
const val SSHD_HOSTKEY_DIR = "ssh"
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: sslKeystore -> it's a path not the keystore itself.
|
||||
//TODO: trustStoreFile -> it's a path not the file itself.
|
||||
data class ShellSslOptions(override val sslKeystore: Path,
|
||||
override val keyStorePassword: String,
|
||||
override val trustStoreFile: Path,
|
||||
override val trustStorePassword: String,
|
||||
override val crlCheckSoftFail: Boolean) : SSLConfiguration {
|
||||
override val certificatesDirectory: Path get() = Paths.get("")
|
||||
}
|
@ -16,6 +16,7 @@ import joptsimple.OptionParser
|
||||
import joptsimple.util.EnumConverter
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.messaging.ClientRpcSslOptions
|
||||
import net.corda.nodeapi.internal.config.parseAs
|
||||
import net.corda.tools.shell.ShellConfiguration.Companion.COMMANDS_DIR
|
||||
import org.slf4j.event.Level
|
||||
@ -62,15 +63,6 @@ class CommandLineOptionParser {
|
||||
private val helpArg = optionParser
|
||||
.accepts("help")
|
||||
.forHelp()
|
||||
private val keyStorePasswordArg = optionParser
|
||||
.accepts("keystore-password", "The password to unlock the KeyStore file.")
|
||||
.withOptionalArg()
|
||||
private val keyStoreDirArg = optionParser
|
||||
.accepts("keystore-file", "The path to the KeyStore file.")
|
||||
.withOptionalArg()
|
||||
private val keyStoreTypeArg = optionParser
|
||||
.accepts("keystore-type", "The type of the KeyStore (e.g. JKS).")
|
||||
.withOptionalArg()
|
||||
private val trustStorePasswordArg = optionParser
|
||||
.accepts("truststore-password", "The password to unlock the TrustStore file.")
|
||||
.withOptionalArg()
|
||||
@ -95,11 +87,8 @@ class CommandLineOptionParser {
|
||||
loggingLevel = optionSet.valueOf(loggerLevel),
|
||||
sshdPort = optionSet.valueOf(sshdPortArg),
|
||||
sshdHostKeyDirectory = (optionSet.valueOf(sshdHostKeyDirectoryArg))?.let { Paths.get(it).normalize().toAbsolutePath() },
|
||||
keyStorePassword = optionSet.valueOf(keyStorePasswordArg),
|
||||
trustStorePassword = optionSet.valueOf(trustStorePasswordArg),
|
||||
keyStoreFile = (optionSet.valueOf(keyStoreDirArg))?.let { Paths.get(it).normalize().toAbsolutePath() },
|
||||
trustStoreFile = (optionSet.valueOf(trustStoreDirArg))?.let { Paths.get(it).normalize().toAbsolutePath() },
|
||||
keyStoreType = optionSet.valueOf(keyStoreTypeArg),
|
||||
trustStoreType = optionSet.valueOf(trustStoreTypeArg))
|
||||
}
|
||||
|
||||
@ -117,11 +106,8 @@ data class CommandLineOptions(val configFile: String?,
|
||||
val loggingLevel: Level,
|
||||
val sshdPort: String?,
|
||||
val sshdHostKeyDirectory: Path?,
|
||||
val keyStorePassword: String?,
|
||||
val trustStorePassword: String?,
|
||||
val keyStoreFile: Path?,
|
||||
val trustStoreFile: Path?,
|
||||
val keyStoreType: String?,
|
||||
val trustStoreType: String?) {
|
||||
|
||||
private fun toConfigFile(): Config {
|
||||
@ -133,9 +119,6 @@ data class CommandLineOptions(val configFile: String?,
|
||||
password?.apply { cmdOpts["node.password"] = this }
|
||||
host?.apply { cmdOpts["node.addresses.rpc.host"] = this }
|
||||
port?.apply { cmdOpts["node.addresses.rpc.port"] = this }
|
||||
keyStoreFile?.apply { cmdOpts["ssl.keystore.path"] = this.toString() }
|
||||
keyStorePassword?.apply { cmdOpts["ssl.keystore.password"] = this }
|
||||
keyStoreType?.apply { cmdOpts["ssl.keystore.type"] = this }
|
||||
trustStoreFile?.apply { cmdOpts["ssl.truststore.path"] = this.toString() }
|
||||
trustStorePassword?.apply { cmdOpts["ssl.truststore.password"] = this }
|
||||
trustStoreType?.apply { cmdOpts["ssl.truststore.type"] = this }
|
||||
@ -197,12 +180,11 @@ private class ShellConfigurationFile {
|
||||
|
||||
data class KeyStore(
|
||||
val path: String,
|
||||
val type: String,
|
||||
val type: String = "JKS",
|
||||
val password: String
|
||||
)
|
||||
|
||||
data class Ssl(
|
||||
val keystore: KeyStore,
|
||||
val truststore: KeyStore
|
||||
)
|
||||
|
||||
@ -215,12 +197,9 @@ private class ShellConfigurationFile {
|
||||
|
||||
val sslOptions =
|
||||
ssl?.let {
|
||||
ShellSslOptions(
|
||||
sslKeystore = Paths.get(it.keystore.path),
|
||||
keyStorePassword = it.keystore.password,
|
||||
trustStoreFile = Paths.get(it.truststore.path),
|
||||
trustStorePassword = it.truststore.password,
|
||||
crlCheckSoftFail = true)
|
||||
ClientRpcSslOptions(
|
||||
trustStorePath = Paths.get(it.truststore.path),
|
||||
trustStorePassword = it.truststore.password)
|
||||
}
|
||||
|
||||
return ShellConfiguration(
|
||||
|
@ -12,6 +12,7 @@ package net.corda.tools.shell
|
||||
|
||||
import net.corda.core.internal.toPath
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.messaging.ClientRpcSslOptions
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
import org.slf4j.event.Level
|
||||
@ -34,12 +35,9 @@ class StandaloneShellArgsParserTest {
|
||||
"--sshd-port", "2223",
|
||||
"--sshd-hostkey-directory", "/x/y/ssh",
|
||||
"--help",
|
||||
"--keystore-password", "pass1",
|
||||
"--truststore-password", "pass2",
|
||||
"--keystore-file", "/x/y/keystore.jks",
|
||||
"--truststore-file", "/x/y/truststore.jks",
|
||||
"--truststore-type", "dummy",
|
||||
"--keystore-type", "JKS")
|
||||
"--truststore-type", "dummy")
|
||||
|
||||
val expectedOptions = CommandLineOptions(
|
||||
configFile = "/x/y/z/config.conf",
|
||||
@ -53,12 +51,9 @@ class StandaloneShellArgsParserTest {
|
||||
loggingLevel = Level.DEBUG,
|
||||
sshdPort = "2223",
|
||||
sshdHostKeyDirectory = Paths.get("/x/y/ssh").normalize().toAbsolutePath(),
|
||||
keyStorePassword = "pass1",
|
||||
trustStorePassword = "pass2",
|
||||
keyStoreFile = Paths.get("/x/y/keystore.jks").normalize().toAbsolutePath(),
|
||||
trustStoreFile = Paths.get("/x/y/truststore.jks").normalize().toAbsolutePath(),
|
||||
trustStoreType = "dummy",
|
||||
keyStoreType = "JKS")
|
||||
trustStoreType = "dummy")
|
||||
|
||||
val options = CommandLineOptionParser().parse(*args)
|
||||
|
||||
@ -80,12 +75,9 @@ class StandaloneShellArgsParserTest {
|
||||
loggingLevel = Level.INFO,
|
||||
sshdPort = null,
|
||||
sshdHostKeyDirectory = null,
|
||||
keyStorePassword = null,
|
||||
trustStorePassword = null,
|
||||
keyStoreFile = null,
|
||||
trustStoreFile = null,
|
||||
trustStoreType = null,
|
||||
keyStoreType = null)
|
||||
trustStoreType = null)
|
||||
|
||||
val options = CommandLineOptionParser().parse(*args)
|
||||
|
||||
@ -106,19 +98,14 @@ class StandaloneShellArgsParserTest {
|
||||
loggingLevel = Level.DEBUG,
|
||||
sshdPort = "2223",
|
||||
sshdHostKeyDirectory = Paths.get("/x/y/ssh"),
|
||||
keyStorePassword = "pass1",
|
||||
trustStorePassword = "pass2",
|
||||
keyStoreFile = Paths.get("/x/y/keystore.jks"),
|
||||
trustStoreFile = Paths.get("/x/y/truststore.jks"),
|
||||
keyStoreType = "dummy",
|
||||
trustStoreType = "dummy"
|
||||
)
|
||||
|
||||
val expectedSsl = ShellSslOptions(sslKeystore = Paths.get("/x/y/keystore.jks"),
|
||||
keyStorePassword = "pass1",
|
||||
trustStoreFile = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2",
|
||||
crlCheckSoftFail = true)
|
||||
val expectedSsl = ClientRpcSslOptions(
|
||||
trustStorePath = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2")
|
||||
val expectedConfig = ShellConfiguration(
|
||||
commandsDirectory = Paths.get("/x/y/commands"),
|
||||
cordappsDirectory = Paths.get("/x/y/cordapps"),
|
||||
@ -149,25 +136,19 @@ class StandaloneShellArgsParserTest {
|
||||
loggingLevel = Level.DEBUG,
|
||||
sshdPort = null,
|
||||
sshdHostKeyDirectory = null,
|
||||
keyStorePassword = null,
|
||||
trustStorePassword = null,
|
||||
keyStoreFile = null,
|
||||
trustStoreFile = null,
|
||||
keyStoreType = null,
|
||||
trustStoreType = null)
|
||||
|
||||
val expectedSsl = ShellSslOptions(sslKeystore = Paths.get("/x/y/keystore.jks"),
|
||||
keyStorePassword = "pass1",
|
||||
trustStoreFile = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2",
|
||||
crlCheckSoftFail = true)
|
||||
val expectedConfig = ShellConfiguration(
|
||||
commandsDirectory = Paths.get("/x/y/commands"),
|
||||
cordappsDirectory = Paths.get("/x/y/cordapps"),
|
||||
user = "demo",
|
||||
password = "abcd1234",
|
||||
hostAndPort = NetworkHostAndPort("alocalhost", 1234),
|
||||
ssl = expectedSsl,
|
||||
ssl = ClientRpcSslOptions(
|
||||
trustStorePath = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2"),
|
||||
sshdPort = 2223)
|
||||
|
||||
val config = options.toConfig()
|
||||
@ -189,18 +170,13 @@ class StandaloneShellArgsParserTest {
|
||||
loggingLevel = Level.DEBUG,
|
||||
sshdPort = null,
|
||||
sshdHostKeyDirectory = null,
|
||||
keyStorePassword = null,
|
||||
trustStorePassword = null,
|
||||
keyStoreFile = Paths.get("/x/y/cmd.jks"),
|
||||
trustStoreFile = null,
|
||||
keyStoreType = null,
|
||||
trustStoreType = null)
|
||||
|
||||
val expectedSsl = ShellSslOptions(sslKeystore = Paths.get("/x/y/cmd.jks"),
|
||||
keyStorePassword = "pass1",
|
||||
trustStoreFile = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2",
|
||||
crlCheckSoftFail = true)
|
||||
val expectedSsl = ClientRpcSslOptions(
|
||||
trustStorePath = Paths.get("/x/y/truststore.jks"),
|
||||
trustStorePassword = "pass2")
|
||||
val expectedConfig = ShellConfiguration(
|
||||
commandsDirectory = Paths.get("/x/y/commands"),
|
||||
cordappsDirectory = Paths.get("/x/y/cordapps"),
|
||||
|
@ -21,11 +21,6 @@ extensions {
|
||||
}
|
||||
}
|
||||
ssl {
|
||||
keystore {
|
||||
path : "/x/y/keystore.jks"
|
||||
type : "JKS"
|
||||
password : "pass1"
|
||||
}
|
||||
truststore {
|
||||
path : "/x/y/truststore.jks"
|
||||
type : "JKS"
|
||||
|
Reference in New Issue
Block a user