Tweaking hibernate to support Azure and H2 dbs (#60)

This commit is contained in:
mkit 2017-10-19 10:29:35 +01:00 committed by GitHub
parent 40b1eca0aa
commit 5deb708bb3
12 changed files with 29 additions and 32 deletions

View File

@ -1,7 +1,7 @@
ext {
// We use Corda release artifact dependencies instead of project dependencies to make sure each doorman releases are
// align with the corresponding Corda release.
corda_dependency_version = '1.0.0'
corda_dependency_version = '2.0-20171017.135310-6'
}
version "$corda_dependency_version"

View File

@ -33,10 +33,10 @@ class DoormanIntegrationTest {
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey,
CordaX500Name(commonName = "Integration Test Corda Node Intermediate CA", locality = "London", country = "GB", organisation = "R3 Ltd"), intermediateCAKey.public)
val database = configureDatabase(makeTestDataSourceProperties(), null, { DoormanSchemaService() }, createIdentityService = {
val database = configureDatabase(makeTestDataSourceProperties(), null, {
// Identity service not needed doorman, corda persistence is not very generic.
throw UnsupportedOperationException()
})
}, DoormanSchemaService())
val signer = Signer(intermediateCAKey, arrayOf(intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()))
//Start doorman server

View File

@ -237,7 +237,7 @@ fun main(args: Array<String>) {
keystorePassword,
caPrivateKeyPassword)
DoormanParameters.Mode.DOORMAN -> {
val database = configureDatabase(dataSourceProperties, databaseProperties, { DoormanSchemaService() }, { throw UnsupportedOperationException() })
val database = configureDatabase(dataSourceProperties, databaseProperties, { throw UnsupportedOperationException() }, DoormanSchemaService())
val signer = buildLocalSigner(this)
startDoorman(NetworkHostAndPort(host, port), database, approveAll, signer, jiraConfig)
}

View File

@ -10,14 +10,16 @@ import net.corda.node.utilities.DatabaseTransaction
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import java.security.cert.CertPath
import java.sql.Connection
import java.time.Instant
import javax.persistence.LockModeType
import javax.persistence.criteria.CriteriaBuilder
import javax.persistence.criteria.Path
import javax.persistence.criteria.Predicate
class DBCertificateRequestStorage(private val database: CordaPersistence) : CertificationRequestStorage {
override fun putCertificatePath(requestId: String, certificates: CertPath, signedBy: List<String>) {
return database.transaction {
return database.transaction(Connection.TRANSACTION_SERIALIZABLE) {
val request = singleRequestWhere { builder, path ->
val requestIdEq = builder.equal(path.get<String>(CertificateSigningRequest::requestId.name), requestId)
val statusEq = builder.equal(path.get<String>(CertificateSigningRequest::status.name), Approved)
@ -37,7 +39,7 @@ class DBCertificateRequestStorage(private val database: CordaPersistence) : Cert
override fun saveRequest(rawRequest: PKCS10CertificationRequest): String {
val request = JcaPKCS10CertificationRequest(rawRequest)
val requestId = SecureHash.randomSHA256().toString()
database.transaction {
database.transaction(Connection.TRANSACTION_SERIALIZABLE) {
// TODO ensure public key not duplicated.
val (legalName, rejectReason) = try {
// This will fail with IllegalArgumentException if subject name is malformed.
@ -73,7 +75,7 @@ class DBCertificateRequestStorage(private val database: CordaPersistence) : Cert
override fun approveRequest(requestId: String, approvedBy: String): Boolean {
var approved = false
database.transaction {
database.transaction(Connection.TRANSACTION_SERIALIZABLE) {
val request = singleRequestWhere { builder, path ->
builder.and(builder.equal(path.get<String>(CertificateSigningRequest::requestId.name), requestId),
builder.equal(path.get<String>(CertificateSigningRequest::status.name), New))
@ -90,7 +92,7 @@ class DBCertificateRequestStorage(private val database: CordaPersistence) : Cert
}
override fun rejectRequest(requestId: String, rejectedBy: String, rejectReason: String) {
database.transaction {
database.transaction(Connection.TRANSACTION_SERIALIZABLE) {
val request = singleRequestWhere { builder, path ->
builder.equal(path.get<String>(CertificateSigningRequest::requestId.name), requestId)
}
@ -130,6 +132,6 @@ class DBCertificateRequestStorage(private val database: CordaPersistence) : Cert
val query = criteriaQuery.from(CertificateSigningRequest::class.java).run {
criteriaQuery.where(predicate(builder, this))
}
return session.createQuery(query).uniqueResultOptional().orElse(null)
return session.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_WRITE).uniqueResultOptional().orElse(null)
}
}

View File

@ -18,9 +18,4 @@ class DoormanSchemaService : SchemaService {
override fun generateMappedObject(state: ContractState, schema: MappedSchema): PersistentState = throw UnsupportedOperationException()
override fun registerCustomSchemas(customSchemas: Set<MappedSchema>) {
schemaOptions = schemaOptions.plus(customSchemas.map { mappedSchema ->
Pair(mappedSchema, SchemaService.SchemaOptions())
})
}
}

View File

@ -29,7 +29,7 @@ class DBCertificateRequestStorageTest {
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { DoormanSchemaService() }, createIdentityService = { throw UnsupportedOperationException() })
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, DoormanSchemaService())
storage = DBCertificateRequestStorage(persistence)
}

View File

@ -58,7 +58,7 @@ class PersistenceNodeInfoStorageTest {
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { DoormanSchemaService() }, createIdentityService = { throw UnsupportedOperationException() })
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, DoormanSchemaService())
nodeInfoStorage = PersistenceNodeInfoStorage(persistence)
requestStorage = DBCertificateRequestStorage(persistence)
}

View File

@ -1,7 +1,7 @@
ext {
// We use Corda release artifact dependencies instead of project dependencies to make sure each doorman releases are
// align with the corresponding Corda release.
corda_dependency_version = '0.16-20170913.101300-6'
corda_dependency_version = '2.0-20171017.135310-6'
}
version "$corda_dependency_version"

View File

@ -1,6 +1,5 @@
package com.r3.corda.signing
import net.corda.node.utilities.configureDatabase
import com.r3.corda.signing.authentication.Authenticator
import com.r3.corda.signing.authentication.createProvider
import com.r3.corda.signing.configuration.Parameters
@ -12,6 +11,7 @@ import com.r3.corda.signing.persistence.ApprovedCertificateRequestData
import com.r3.corda.signing.persistence.DBCertificateRequestStorage
import com.r3.corda.signing.persistence.SigningServerSchemaService
import com.r3.corda.signing.utils.mapCryptoServerException
import net.corda.node.utilities.configureDatabase
fun main(args: Array<String>) {
run(parseParameters(*args))
@ -21,10 +21,10 @@ fun run(parameters: Parameters) {
parameters.run {
// Create DB connection.
checkNotNull(dataSourceProperties)
val database = configureDatabase(dataSourceProperties, databaseProperties, { SigningServerSchemaService() }, createIdentityService = {
val database = configureDatabase(dataSourceProperties, databaseProperties, {
// Identity service not needed
throw UnsupportedOperationException()
})
}, SigningServerSchemaService())
val storage = DBCertificateRequestStorage(database)
val provider = createProvider()

View File

@ -3,8 +3,7 @@ package com.r3.corda.signing.persistence
import net.corda.node.utilities.CordaPersistence
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import java.security.cert.CertPath
import java.security.cert.Certificate
import java.security.cert.CertificateFactory
import java.sql.Connection
import java.time.Instant
import javax.persistence.*
import javax.persistence.criteria.CriteriaBuilder
@ -53,7 +52,7 @@ class DBCertificateRequestStorage(private val database: CordaPersistence) : Cert
override fun sign(requests: List<ApprovedCertificateRequestData>, signers: List<String>) {
requests.forEach {
database.transaction {
database.transaction(Connection.TRANSACTION_SERIALIZABLE) {
val request = singleRequestWhere { builder, path ->
builder.and(
builder.equal(path.get<String>(CertificateSigningRequest::requestId.name), it.requestId),

View File

@ -3,6 +3,7 @@ package com.r3.corda.signing.utils
import CryptoServerJCE.CryptoServerProvider
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.toX509CertHolder
import net.corda.core.internal.x500Name
import net.corda.node.utilities.CertificateAndKeyPair
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.X509Utilities
@ -108,7 +109,7 @@ object X509Utilities {
fun retrieveCertificateAndKeys(certificateKeyName: String, privateKeyPassword: String, keyStore: KeyStore): CertificateAndKeyPair {
val privateKey = keyStore.getKey(certificateKeyName, privateKeyPassword.toCharArray()) as PrivateKey
val publicKey = keyStore.getCertificate(certificateKeyName).publicKey
val certificate = keyStore.getX509Certificate(certificateKeyName)
val certificate = keyStore.getX509Certificate(certificateKeyName).toX509CertHolder()
return CertificateAndKeyPair(certificate, getCleanEcdsaKeyPair(publicKey, privateKey))
}
@ -176,13 +177,13 @@ object X509Utilities {
provider: Provider): Certificate {
val jcaRequest = JcaPKCS10CertificationRequest(request)
// This can be adjusted more to our future needs.
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, CordaX500Name.build(jcaRequest.subject).copy(commonName = null).x500Name))), arrayOf())
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = null).x500Name))), arrayOf())
val issuerCertificate = caCertAndKey.certificate
val issuerKeyPair = caCertAndKey.keyPair
val certificateType = CertificateType.CLIENT_CA
val validityWindow = getCertificateValidityWindow(0, validDays, issuerCertificate.notBefore, issuerCertificate.notAfter)
val serial = BigInteger.valueOf(random63BitValue(provider))
val subject = CordaX500Name.build(jcaRequest.subject).copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name
val subject = CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(jcaRequest.publicKey.encoded))
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
val builder = JcaX509v3CertificateBuilder(issuerCertificate.subject, serial, validityWindow.first, validityWindow.second, subject, jcaRequest.publicKey)

View File

@ -1,5 +1,8 @@
package com.r3.corda.signing.persistence
import com.r3.corda.signing.persistence.DBCertificateRequestStorage.CertificateSigningRequest
import com.r3.corda.signing.persistence.DBCertificateRequestStorage.Status
import com.r3.corda.signing.utils.X509Utilities.buildCertPath
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.identity.CordaX500Name
@ -7,8 +10,6 @@ import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.X509Utilities
import net.corda.node.utilities.configureDatabase
import com.r3.corda.signing.persistence.DBCertificateRequestStorage.CertificateSigningRequest
import com.r3.corda.signing.persistence.DBCertificateRequestStorage.Status
import org.bouncycastle.asn1.x509.GeneralName
import org.bouncycastle.asn1.x509.GeneralSubtree
import org.bouncycastle.asn1.x509.NameConstraints
@ -27,17 +28,16 @@ import javax.persistence.criteria.Path
import javax.persistence.criteria.Predicate
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import com.r3.corda.signing.utils.X509Utilities.buildCertPath
class DBCertificateRequestStorageTest {
private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val intermediateCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Intermediate CA", organisation = "R3 Ltd", locality = "London", country = "GB").x500Name, intermediateCAKey)
private val intermediateCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Intermediate CA", organisation = "R3 Ltd", locality = "London", country = "GB"), intermediateCAKey)
private lateinit var storage: DBCertificateRequestStorage
private lateinit var persistence: CordaPersistence
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { SigningServerSchemaService() }, createIdentityService = { throw UnsupportedOperationException() })
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, SigningServerSchemaService())
storage = DBCertificateRequestStorage(persistence)
}
@ -131,7 +131,7 @@ class DBCertificateRequestStorageTest {
val requestId = SecureHash.randomSHA256().toString()
persistence.transaction {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val x500Name = CordaX500Name(organisation = legalName, locality = "London", country = "GB").x500Name
val x500Name = CordaX500Name(organisation = legalName, locality = "London", country = "GB")
session.save(CertificateSigningRequest(
requestId = requestId,
status = status,