mirror of
https://github.com/corda/corda.git
synced 2025-01-15 17:30:02 +00:00
Introducing the InputReader interface (#102)
* Introducing the InputReader interface * Addressing review comments * Addressing review comments
This commit is contained in:
parent
c56ea4088f
commit
fffcdb47da
@ -125,7 +125,7 @@ dependencies {
|
|||||||
testCompile "com.nhaarman:mockito-kotlin:0.6.1"
|
testCompile "com.nhaarman:mockito-kotlin:0.6.1"
|
||||||
testRuntime "net.corda:corda-rpc:$corda_dependency_version"
|
testRuntime "net.corda:corda-rpc:$corda_dependency_version"
|
||||||
testCompile "com.spotify:docker-client:8.9.1"
|
testCompile "com.spotify:docker-client:8.9.1"
|
||||||
integrationTestCompile "net.corda:corda-test-utils:$corda_dependency_version"
|
integrationTestCompile "net.corda:corda-test-common:$corda_dependency_version"
|
||||||
integrationTestRuntime "net.corda:corda-rpc:$corda_dependency_version"
|
integrationTestRuntime "net.corda:corda-rpc:$corda_dependency_version"
|
||||||
|
|
||||||
compile('com.atlassian.jira:jira-rest-java-client-core:4.0.0') {
|
compile('com.atlassian.jira:jira-rest-java-client-core:4.0.0') {
|
||||||
|
@ -5,12 +5,12 @@ import com.nhaarman.mockito_kotlin.mock
|
|||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import com.r3.corda.networkmanage.HsmSimulator
|
import com.r3.corda.networkmanage.HsmSimulator
|
||||||
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
||||||
|
import com.r3.corda.networkmanage.hsm.authentication.InputReader
|
||||||
import com.r3.corda.networkmanage.hsm.authentication.createProvider
|
import com.r3.corda.networkmanage.hsm.authentication.createProvider
|
||||||
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.Console
|
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class HsmTest {
|
class HsmTest {
|
||||||
@ -19,11 +19,11 @@ class HsmTest {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val hsmSimulator: HsmSimulator = HsmSimulator()
|
val hsmSimulator: HsmSimulator = HsmSimulator()
|
||||||
|
|
||||||
private var console: Console? = null
|
private lateinit var inputReader: InputReader
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
console = mock()
|
inputReader = mock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -35,9 +35,9 @@ class HsmTest {
|
|||||||
keySpecifier = 1,
|
keySpecifier = 1,
|
||||||
keyGroup = "*"
|
keyGroup = "*"
|
||||||
)
|
)
|
||||||
whenever(console?.readLine()).thenReturn(hsmSimulator.cryptoUserCredentials().username)
|
whenever(inputReader.readLine()).thenReturn(hsmSimulator.cryptoUserCredentials().username)
|
||||||
whenever(console?.readPassword(any())).thenReturn(hsmSimulator.cryptoUserCredentials().password.toCharArray())
|
whenever(inputReader.readPassword(any())).thenReturn(hsmSimulator.cryptoUserCredentials().password)
|
||||||
val authenticator = Authenticator(parameters.createProvider(), console = console)
|
val authenticator = Authenticator(parameters.createProvider(), inputReader = inputReader)
|
||||||
var executed = false
|
var executed = false
|
||||||
|
|
||||||
// when
|
// when
|
||||||
|
@ -4,7 +4,6 @@ import CryptoServerJCE.CryptoServerProvider
|
|||||||
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.Console
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.reflect.full.memberProperties
|
import kotlin.reflect.full.memberProperties
|
||||||
|
|
||||||
@ -17,7 +16,7 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
private val authKeyFilePath: Path? = null,
|
private val authKeyFilePath: Path? = null,
|
||||||
private val authKeyFilePass: String? = null,
|
private val authKeyFilePass: String? = null,
|
||||||
private val authStrengthThreshold: Int = 2,
|
private val authStrengthThreshold: Int = 2,
|
||||||
val console: Console? = System.console()) {
|
inputReader: InputReader = ConsoleInputReader()) : InputReader by inputReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interactively (using console) authenticates a user against the HSM. Once authentication is successful the
|
* Interactively (using console) authenticates a user against the HSM. Once authentication is successful the
|
||||||
@ -32,7 +31,7 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
loop@ while (true) {
|
loop@ while (true) {
|
||||||
val user = if (autoUsername.isNullOrEmpty()) {
|
val user = if (autoUsername.isNullOrEmpty()) {
|
||||||
print("Enter User Name (or Q to quit): ")
|
print("Enter User Name (or Q to quit): ")
|
||||||
val input = readConsoleLine(console)
|
val input = readLine()
|
||||||
if (input != null && "q" == input.toLowerCase()) {
|
if (input != null && "q" == input.toLowerCase()) {
|
||||||
authenticated.clear()
|
authenticated.clear()
|
||||||
break
|
break
|
||||||
@ -47,7 +46,7 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
AuthMode.KEY_FILE -> {
|
AuthMode.KEY_FILE -> {
|
||||||
println("Authenticating using preconfigured key file")
|
println("Authenticating using preconfigured key file")
|
||||||
val password = if (authKeyFilePass == null) {
|
val password = if (authKeyFilePass == null) {
|
||||||
val input = readPassword("Enter key file password (or Q to quit): ", console)
|
val input = readPassword("Enter key file password (or Q to quit): ")
|
||||||
if ("q" == input.toLowerCase()) {
|
if ("q" == input.toLowerCase()) {
|
||||||
authenticated.clear()
|
authenticated.clear()
|
||||||
break@loop
|
break@loop
|
||||||
@ -60,7 +59,7 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
provider.loginSign(user, authKeyFilePath.toString(), password)
|
provider.loginSign(user, authKeyFilePath.toString(), password)
|
||||||
}
|
}
|
||||||
AuthMode.PASSWORD -> {
|
AuthMode.PASSWORD -> {
|
||||||
val password = readPassword("Enter password (or Q to quit): ", console)
|
val password = readPassword("Enter password (or Q to quit): ")
|
||||||
if ("q" == password.toLowerCase()) {
|
if ("q" == password.toLowerCase()) {
|
||||||
authenticated.clear()
|
authenticated.clear()
|
||||||
break@loop
|
break@loop
|
||||||
@ -126,22 +125,3 @@ fun Parameters.createProvider(): CryptoServerProvider {
|
|||||||
cfg.close()
|
cfg.close()
|
||||||
return provider
|
return provider
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */
|
|
||||||
internal fun readPassword(fmt: String, console: Console? = System.console()): String {
|
|
||||||
return if (console != null) {
|
|
||||||
String(console.readPassword(fmt))
|
|
||||||
} else {
|
|
||||||
print(fmt)
|
|
||||||
readLine()!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read console line */
|
|
||||||
internal fun readConsoleLine(console: Console?): String? {
|
|
||||||
return if (console == null) {
|
|
||||||
readLine()
|
|
||||||
} else {
|
|
||||||
console.readLine()
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.r3.corda.networkmanage.hsm.authentication
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User input reader interface
|
||||||
|
*/
|
||||||
|
interface InputReader {
|
||||||
|
/**
|
||||||
|
* Reads a single line from user's input.
|
||||||
|
*/
|
||||||
|
fun readLine(): String?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a single line from user's input. The characters from the input are masked while being entered.
|
||||||
|
* @param format message string displayed before user's input
|
||||||
|
*/
|
||||||
|
fun readPassword(format: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConsoleInputReader : InputReader {
|
||||||
|
private val console = System.console()
|
||||||
|
|
||||||
|
/** Read password from console, do a readLine instead if console is null (e.g. when debugging in IDE). */
|
||||||
|
override fun readPassword(format: String): String {
|
||||||
|
return if (console != null) {
|
||||||
|
String(console.readPassword(format))
|
||||||
|
} else {
|
||||||
|
print(format)
|
||||||
|
kotlin.io.readLine() ?: throw IllegalArgumentException("Password required")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Read console line */
|
||||||
|
override fun readLine(): String? {
|
||||||
|
return if (console == null) {
|
||||||
|
kotlin.io.readLine()
|
||||||
|
} else {
|
||||||
|
console.readLine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.r3.corda.networkmanage.hsm.signer
|
package com.r3.corda.networkmanage.hsm.signer
|
||||||
|
|
||||||
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
||||||
import com.r3.corda.networkmanage.hsm.authentication.readPassword
|
|
||||||
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
|
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
|
||||||
import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateRequestStorage
|
import com.r3.corda.networkmanage.hsm.persistence.SignedCertificateRequestStorage
|
||||||
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.buildCertPath
|
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.buildCertPath
|
||||||
@ -36,7 +35,7 @@ class HsmCsrSigner(private val storage: SignedCertificateRequestStorage,
|
|||||||
// This should be changed once we allow for more certificates in the chain. Preferably we should use
|
// 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).
|
// keyStore.getCertificateChain(String) and assume entire chain is stored in the HSM (depending on the support).
|
||||||
val caParentCertificate = keyStore.getCertificate(caParentCertificateName)
|
val caParentCertificate = keyStore.getCertificate(caParentCertificateName)
|
||||||
val caPrivateKeyPass = caPrivateKeyPass ?: readPassword("CA Private Key Password: ", authenticator.console)
|
val caPrivateKeyPass = caPrivateKeyPass ?: authenticator.readPassword("CA Private Key Password: ")
|
||||||
val caCertAndKey = retrieveCertificateAndKeys(caCertificateName, caPrivateKeyPass, keyStore)
|
val caCertAndKey = retrieveCertificateAndKeys(caCertificateName, caPrivateKeyPass, keyStore)
|
||||||
toSign.forEach {
|
toSign.forEach {
|
||||||
it.certPath = buildCertPath(createClientCertificate(caCertAndKey, it.request, validDays, provider), caParentCertificate)
|
it.certPath = buildCertPath(createClientCertificate(caCertAndKey, it.request, validDays, provider), caParentCertificate)
|
||||||
|
@ -5,20 +5,19 @@ import com.nhaarman.mockito_kotlin.*
|
|||||||
import com.r3.corda.networkmanage.TestBase
|
import com.r3.corda.networkmanage.TestBase
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.Console
|
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class AuthenticatorTest : TestBase() {
|
class AuthenticatorTest : TestBase() {
|
||||||
|
|
||||||
private lateinit var provider: CryptoServerProvider
|
private lateinit var provider: CryptoServerProvider
|
||||||
private lateinit var console: Console
|
private lateinit var inputReader: InputReader
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
provider = mock()
|
provider = mock()
|
||||||
whenever(provider.cryptoServer).thenReturn(mock())
|
whenever(provider.cryptoServer).thenReturn(mock())
|
||||||
console = mock()
|
inputReader = mock()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -28,7 +27,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
var executed = false
|
var executed = false
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Authenticator(provider = provider, console = console).connectAndAuthenticate { _, _ -> executed = true }
|
Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true }
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertFalse(executed)
|
assertFalse(executed)
|
||||||
@ -47,7 +46,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
var executed = false
|
var executed = false
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Authenticator(provider = provider, console = console).connectAndAuthenticate { _, _ -> executed = true }
|
Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true }
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider).loginPassword(username, password)
|
verify(provider).loginPassword(username, password)
|
||||||
@ -64,7 +63,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
var executed = false
|
var executed = false
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Authenticator(provider = provider, console = console, mode = AuthMode.CARD_READER).connectAndAuthenticate { _, _ -> executed = true }
|
Authenticator(provider = provider, inputReader = inputReader, mode = AuthMode.CARD_READER).connectAndAuthenticate { _, _ -> executed = true }
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider).loginSign(username, ":cs2:cyb:USB0", null)
|
verify(provider).loginSign(username, ":cs2:cyb:USB0", null)
|
||||||
@ -83,7 +82,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
var executed = false
|
var executed = false
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Authenticator(provider = provider, console = console).connectAndAuthenticate { _, _ -> executed = true }
|
Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true }
|
||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider, times(3)).loginPassword(username, password)
|
verify(provider, times(3)).loginPassword(username, password)
|
||||||
@ -99,11 +98,11 @@ class AuthenticatorTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun givenUserConsoleInputOnReadPassword(input: String) {
|
private fun givenUserConsoleInputOnReadPassword(input: String) {
|
||||||
whenever(console.readPassword(any<String>())).thenReturn(input.toCharArray())
|
whenever(inputReader.readPassword(any<String>())).thenReturn(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun givenUserConsoleInputOnReadLine(input: String) {
|
private fun givenUserConsoleInputOnReadLine(input: String) {
|
||||||
whenever(console.readLine()).thenReturn(input)
|
whenever(inputReader.readLine()).thenReturn(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user