mirror of
https://github.com/corda/corda.git
synced 2025-01-27 22:59:54 +00:00
Adding HSM permissions related tests (#448)
* Adding HSM permission tests * Addressing review comments
This commit is contained in:
parent
3baa15960f
commit
73fbff6c4f
@ -39,7 +39,24 @@ class HsmSimulator(private val serverAddress: String = DEFAULT_SERVER_ADDRESS,
|
||||
|
||||
private companion object {
|
||||
val DEFAULT_SERVER_ADDRESS = "corda.azurecr.io"
|
||||
val DEFAULT_IMAGE_REPO_TAG = "corda.azurecr.io/network-management/hsm-simulator"
|
||||
/*
|
||||
* Currently we have following images:
|
||||
* 1) corda.azurecr.io/network-management/hsm-simulator - having only one user configured:
|
||||
* - INTEGRATION_TEST (password: INTEGRATION_TEST) with the CXI_GROUP="*"
|
||||
* 2)corda.azurecr.io/network-management/hsm-simulator-with-groups - having following users configured:
|
||||
* - INTEGRATION_TEST (password: INTEGRATION_TEST) with the CXI_GROUP=*
|
||||
* - INTEGRATION_TEST_SUPER (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT
|
||||
* - INTEGRATION_TEST_ROOT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.ROOT
|
||||
* - INTEGRATION_TEST_OPS (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS
|
||||
* - INTEGRATION_TEST_SUPER_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.*
|
||||
* - INTEGRATION_TEST_ROOT_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.ROOT.*
|
||||
* - INTEGRATION_TEST_OPS_ (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.*
|
||||
* - INTEGRATION_TEST_OPS_CERT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.CERT
|
||||
* - INTEGRATION_TEST_OPS_NETMAP (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.NETMAP
|
||||
* - INTEGRATION_TEST_OPS_CERT (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.CERT.*
|
||||
* - INTEGRATION_TEST_OPS_NETMAP (password: INTEGRATION_TEST) with the CXI_GROUP=TEST.CORDACONNECT.OPS.NETMAP.*
|
||||
*/
|
||||
val DEFAULT_IMAGE_REPO_TAG = "corda.azurecr.io/network-management/hsm-simulator-with-groups"
|
||||
val DEFAULT_IMAGE_VERSION = "latest"
|
||||
val DEFAULT_PULL_IMAGE = true
|
||||
|
||||
|
@ -21,18 +21,44 @@ import java.util.*
|
||||
|
||||
abstract class HsmBaseTest {
|
||||
companion object {
|
||||
const val ROOT_CERT_KEY_GROUP = "DEV.CORDACONNECT.ROOT"
|
||||
const val NETWORK_MAP_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.NETMAP"
|
||||
const val DOORMAN_CERT_KEY_GROUP = "DEV.CORDACONNECT.OPS.CERT"
|
||||
const val ROOT_CERT_SUBJECT = "CN=Corda Root CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US"
|
||||
const val NETWORK_MAP_CERT_SUBJECT = "CN=Corda Network Map, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US"
|
||||
const val DOORMAN_CERT_SUBJECT = "CN=Corda Doorman CA, O=R3 HoldCo LLC, OU=Corda, L=New York, C=US"
|
||||
val HSM_USER_CONFIGS = listOf(UserAuthenticationParameters(
|
||||
username = "INTEGRATION_TEST",
|
||||
authMode = AuthMode.PASSWORD,
|
||||
authToken = "INTEGRATION_TEST",
|
||||
keyFilePassword = null))
|
||||
const val ROOT_KEYSTORE_PASSWORD: String = "trustpass"
|
||||
const val ROOT_CERT_KEY_GROUP = "TEST.CORDACONNECT.ROOT"
|
||||
const val NETWORK_MAP_CERT_KEY_GROUP = "TEST.CORDACONNECT.OPS.NETMAP"
|
||||
const val DOORMAN_CERT_KEY_GROUP = "TEST.CORDACONNECT.OPS.CERT"
|
||||
const val ROOT_CERT_SUBJECT = "CN=Corda Root CA, O=R3 Ltd, OU=Corda, L=London, C=GB"
|
||||
const val NETWORK_MAP_CERT_SUBJECT = "CN=Corda Network Map, O=R3 Ltd, OU=Corda, L=London, C=GB"
|
||||
const val DOORMAN_CERT_SUBJECT = "CN=Corda Doorman CA, O=R3 Ltd, OU=Corda, L=London, C=GB"
|
||||
const val TRUSTSTORE_PASSWORD: String = "trustpass"
|
||||
const val HSM_USERNAME = "INTEGRATION_TEST"
|
||||
const val HSM_PASSWORD = "INTEGRATION_TEST"
|
||||
const val HSM_USERNAME_SUPER = "INTEGRATION_TEST_SUPER"
|
||||
const val HSM_USERNAME_OPS = "INTEGRATION_TEST_OPS"
|
||||
const val HSM_USERNAME_ROOT = "INTEGRATION_TEST_ROOT"
|
||||
const val HSM_USERNAME_SUPER_ = "INTEGRATION_TEST_SUPER_"
|
||||
const val HSM_USERNAME_OPS_ = "INTEGRATION_TEST_OPS_"
|
||||
const val HSM_USERNAME_ROOT_ = "INTEGRATION_TEST_ROOT_"
|
||||
const val HSM_USERNAME_OPS_CERT = "INTEGRATION_TEST_OPS_CERT"
|
||||
const val HSM_USERNAME_OPS_NETMAP = "INTEGRATION_TEST_OPS_NETMAP"
|
||||
const val HSM_USERNAME_OPS_CERT_ = "INTEGRATION_TEST_OPS_CERT_"
|
||||
const val HSM_USERNAME_OPS_NETMAP_ = "INTEGRATION_TEST_OPS_NETMAP_"
|
||||
val HSM_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME)
|
||||
val HSM_SUPER_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_SUPER)
|
||||
val HSM_ROOT_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_ROOT)
|
||||
val HSM_OPS_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS)
|
||||
val HSM_SUPER__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_SUPER_)
|
||||
val HSM_ROOT__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_ROOT_)
|
||||
val HSM_OPS__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_)
|
||||
val HSM_OPS_CERT_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_CERT)
|
||||
val HSM_OPS_NETMAP_USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_NETMAP)
|
||||
val HSM_OPS_CERT__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_CERT_)
|
||||
val HSM_OPS_NETMAP__USER_CONFIGS = createHsmUserConfigs(HSM_USERNAME_OPS_NETMAP_)
|
||||
|
||||
private fun createHsmUserConfigs(username: String): List<UserAuthenticationParameters> {
|
||||
return listOf(UserAuthenticationParameters(
|
||||
username = username,
|
||||
authMode = AuthMode.PASSWORD,
|
||||
authToken = "INTEGRATION_TEST",
|
||||
keyFilePassword = null))
|
||||
}
|
||||
}
|
||||
|
||||
protected lateinit var rootKeyStoreFile: Path
|
||||
@ -53,13 +79,14 @@ abstract class HsmBaseTest {
|
||||
dbName = random63BitValue().toString()
|
||||
}
|
||||
|
||||
private fun createGeneratorParameters(certConfig: CertificateConfiguration): GeneratorParameters {
|
||||
private fun createGeneratorParameters(certConfig: CertificateConfiguration,
|
||||
userConfigs: List<UserAuthenticationParameters>): GeneratorParameters {
|
||||
return GeneratorParameters(
|
||||
hsmHost = hsmSimulator.host,
|
||||
hsmPort = hsmSimulator.port,
|
||||
trustStoreDirectory = rootKeyStoreFile.parent,
|
||||
trustStorePassword = ROOT_KEYSTORE_PASSWORD,
|
||||
userConfigs = HSM_USER_CONFIGS,
|
||||
trustStorePassword = TRUSTSTORE_PASSWORD,
|
||||
userConfigs = userConfigs,
|
||||
certConfig = certConfig
|
||||
)
|
||||
}
|
||||
@ -67,7 +94,8 @@ abstract class HsmBaseTest {
|
||||
protected fun createGeneratorParameters(keyGroup: String,
|
||||
rootKeyGroup: String?,
|
||||
certificateType: CertificateType,
|
||||
subject: String): GeneratorParameters {
|
||||
subject: String,
|
||||
hsmUserConfigs: List<UserAuthenticationParameters> = HSM_USER_CONFIGS): GeneratorParameters {
|
||||
return createGeneratorParameters(CertificateConfiguration(
|
||||
keySpecifier = 1,
|
||||
keyGroup = keyGroup,
|
||||
@ -82,7 +110,7 @@ abstract class HsmBaseTest {
|
||||
keyOverride = 0,
|
||||
crlIssuer = null,
|
||||
crlDistributionUrl = null
|
||||
))
|
||||
), hsmUserConfigs)
|
||||
}
|
||||
|
||||
protected fun createHsmSigningServiceConfig(): Parameters {
|
||||
@ -91,7 +119,7 @@ abstract class HsmBaseTest {
|
||||
device = "${hsmSimulator.port}@${hsmSimulator.host}",
|
||||
keySpecifier = 1,
|
||||
rootKeyStoreFile = rootKeyStoreFile,
|
||||
rootKeyStorePassword = ROOT_KEYSTORE_PASSWORD,
|
||||
rootKeyStorePassword = TRUSTSTORE_PASSWORD,
|
||||
doormanKeyGroup = DOORMAN_CERT_KEY_GROUP,
|
||||
networkMapKeyGroup = NETWORK_MAP_CERT_KEY_GROUP,
|
||||
validDays = 3650,
|
||||
@ -99,10 +127,11 @@ abstract class HsmBaseTest {
|
||||
)
|
||||
}
|
||||
|
||||
protected fun givenHsmUserAuthenticationInput(): InputReader {
|
||||
protected fun givenHsmUserAuthenticationInput(username: String = HSM_USERNAME,
|
||||
password: String = HSM_PASSWORD): InputReader {
|
||||
val inputReader = mock<InputReader>()
|
||||
whenever(inputReader.readLine()).thenReturn(hsmSimulator.cryptoUserCredentials().username)
|
||||
whenever(inputReader.readPassword(any())).thenReturn(hsmSimulator.cryptoUserCredentials().password)
|
||||
whenever(inputReader.readLine()).thenReturn(username)
|
||||
whenever(inputReader.readPassword(any())).thenReturn(password)
|
||||
return inputReader
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,158 @@
|
||||
package com.r3.corda.networkmanage.hsm
|
||||
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.r3.corda.networkmanage.common.HsmBaseTest
|
||||
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
||||
import com.r3.corda.networkmanage.hsm.authentication.createProvider
|
||||
import com.r3.corda.networkmanage.hsm.generator.UserAuthenticationParameters
|
||||
import com.r3.corda.networkmanage.hsm.generator.run
|
||||
import com.r3.corda.networkmanage.hsm.persistence.ApprovedCertificateRequestData
|
||||
import com.r3.corda.networkmanage.hsm.signer.HsmCsrSigner
|
||||
import net.corda.core.crypto.Crypto.generateKeyPair
|
||||
import net.corda.core.identity.CordaX500Name.Companion.parse
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.createCertificateSigningRequest
|
||||
import org.junit.Test
|
||||
import java.security.GeneralSecurityException
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class HsmPermissionTest : HsmBaseTest() {
|
||||
|
||||
/**
|
||||
* This test case scenario reflects the issue observed on 02.02.2018, when permissions user CXI_GROUP permissions
|
||||
* were wrongly configured on the PROD HSM box.
|
||||
*
|
||||
* Key groups are as follows:
|
||||
* "TEST.CORDACONNECT.ROOT"
|
||||
* "TEST.CORDACONNECT.OPS.NETMAP"
|
||||
* "TEST.CORDACONNECT.OPS.CERT"
|
||||
*
|
||||
* User CXI_GROUP configurations are as follows:
|
||||
* Root cert creator: TEST.CORDACONNECT.*
|
||||
* Doorman cert creator: TEST.CORDACONNECT.*
|
||||
* Networkmap cert creator: TEST.CORDACONNECT.*
|
||||
*
|
||||
* CSR signing user CXI_GROUP is as follows:
|
||||
* TEST.CORDACONNECT.OPS.CERT.*
|
||||
*/
|
||||
@Test
|
||||
fun `HSM signing service cannot sign CSR data when HSM user CXI_GROUP permissions are wrongly configured`() {
|
||||
// given certs created
|
||||
givenCertificatesCreated(HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS)
|
||||
// given authenticated user
|
||||
val userInput = givenHsmUserAuthenticationInput(HSM_USERNAME_OPS_CERT_)
|
||||
|
||||
// given HSM CSR signer
|
||||
val hsmSigningServiceConfig = createHsmSigningServiceConfig()
|
||||
val signer = HsmCsrSigner(
|
||||
mock(),
|
||||
hsmSigningServiceConfig.loadRootKeyStore(),
|
||||
"",
|
||||
null,
|
||||
3650,
|
||||
Authenticator(
|
||||
provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.doormanKeyGroup),
|
||||
inputReader = userInput)
|
||||
)
|
||||
|
||||
// give random data to sign
|
||||
val toSign = ApprovedCertificateRequestData(
|
||||
"test",
|
||||
createCertificateSigningRequest(
|
||||
parse("O=R3Cev,L=London,C=GB").x500Principal,
|
||||
"my@mail.com",
|
||||
generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME)))
|
||||
|
||||
// then
|
||||
// The GeneralSecurityException is thrown by the JCE layer.
|
||||
// This exception is caused by the CryptoServerException with code B0680001 - permission denied.
|
||||
assertFailsWith(GeneralSecurityException::class) {
|
||||
signer.sign(listOf(toSign))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This test case scenario reflects the fix for the issue observed on 02.02.2018, when permissions user CXI_GROUP permissions
|
||||
* were wrongly configured on the PROD HSM box.
|
||||
*
|
||||
* Key groups are as follows:
|
||||
* "TEST.CORDACONNECT.ROOT"
|
||||
* "TEST.CORDACONNECT.OPS.NETMAP"
|
||||
* "TEST.CORDACONNECT.OPS.CERT"
|
||||
*
|
||||
* User CXI_GROUP configurations are as follows:
|
||||
* Root cert creator: TEST.CORDACONNECT.*
|
||||
* Doorman cert creator: TEST.CORDACONNECT.*
|
||||
* Networkmap cert creator: TEST.CORDACONNECT.*
|
||||
*
|
||||
* CSR signing user CXI_GROUP is as follows:
|
||||
* TEST.CORDACONNECT.OPS.CERT
|
||||
*/
|
||||
@Test
|
||||
fun `HSM signing service signs CSR data when HSM user CXI_GROUP permissions are correctly configured`() {
|
||||
// given certs created
|
||||
givenCertificatesCreated(HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS, HSM_SUPER__USER_CONFIGS)
|
||||
// given authenticated user
|
||||
val userInput = givenHsmUserAuthenticationInput(HSM_USERNAME_OPS_CERT)
|
||||
|
||||
// given HSM CSR signer
|
||||
val hsmSigningServiceConfig = createHsmSigningServiceConfig()
|
||||
val signer = HsmCsrSigner(
|
||||
mock(),
|
||||
hsmSigningServiceConfig.loadRootKeyStore(),
|
||||
"trustpass",
|
||||
null,
|
||||
3650,
|
||||
Authenticator(
|
||||
provider = hsmSigningServiceConfig.createProvider(hsmSigningServiceConfig.doormanKeyGroup),
|
||||
inputReader = userInput)
|
||||
)
|
||||
|
||||
// give random data to sign
|
||||
val toSign = ApprovedCertificateRequestData(
|
||||
"test",
|
||||
createCertificateSigningRequest(
|
||||
parse("O=R3Cev,L=London,C=GB").x500Principal,
|
||||
"my@mail.com",
|
||||
generateKeyPair(DEFAULT_TLS_SIGNATURE_SCHEME)))
|
||||
|
||||
// when
|
||||
signer.sign(listOf(toSign))
|
||||
|
||||
// then
|
||||
assertNotNull(toSign.certPath)
|
||||
val certificates = toSign.certPath!!.certificates
|
||||
assertEquals(3, certificates.size)
|
||||
}
|
||||
|
||||
private fun givenCertificatesCreated(rootCertUserConfigs: List<UserAuthenticationParameters>,
|
||||
doormanCertUserConfigs: List<UserAuthenticationParameters>,
|
||||
netMapCertUserConfigs: List<UserAuthenticationParameters>) {
|
||||
// when root cert is created
|
||||
run(createGeneratorParameters(
|
||||
keyGroup = HsmBaseTest.ROOT_CERT_KEY_GROUP,
|
||||
rootKeyGroup = null,
|
||||
certificateType = CertificateType.ROOT_CA,
|
||||
subject = HsmBaseTest.ROOT_CERT_SUBJECT,
|
||||
hsmUserConfigs = rootCertUserConfigs))
|
||||
// when network map cert is created
|
||||
run(createGeneratorParameters(
|
||||
keyGroup = HsmBaseTest.NETWORK_MAP_CERT_KEY_GROUP,
|
||||
rootKeyGroup = HsmBaseTest.ROOT_CERT_KEY_GROUP,
|
||||
certificateType = CertificateType.NETWORK_MAP,
|
||||
subject = HsmBaseTest.NETWORK_MAP_CERT_SUBJECT,
|
||||
hsmUserConfigs = netMapCertUserConfigs
|
||||
))
|
||||
// when doorman cert is created
|
||||
run(createGeneratorParameters(
|
||||
keyGroup = HsmBaseTest.DOORMAN_CERT_KEY_GROUP,
|
||||
rootKeyGroup = HsmBaseTest.ROOT_CERT_KEY_GROUP,
|
||||
certificateType = CertificateType.INTERMEDIATE_CA,
|
||||
subject = HsmBaseTest.DOORMAN_CERT_SUBJECT,
|
||||
hsmUserConfigs = doormanCertUserConfigs
|
||||
))
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ class HsmSigningServiceTest : HsmBaseTest() {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
loadOrCreateKeyStore(rootKeyStoreFile, ROOT_KEYSTORE_PASSWORD)
|
||||
loadOrCreateKeyStore(rootKeyStoreFile, TRUSTSTORE_PASSWORD)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
x
Reference in New Issue
Block a user