Clarify exceptions thrown from loading a key store

Clarify exceptions thrown from loading a key store as a general cleanup. Also tightens the
exceptions caught when loading key stores from AbstractNode, so in case of an unexpected error
we don't silently drop the exception.
This commit is contained in:
Ross Nicoll 2017-03-30 15:56:36 +01:00
parent 51c7f6ca30
commit 30dd29752c
4 changed files with 22 additions and 2 deletions

View File

@ -27,6 +27,7 @@ import java.io.ByteArrayInputStream
import java.io.FileReader
import java.io.FileWriter
import java.io.InputStream
import java.io.IOException
import java.math.BigInteger
import java.net.InetAddress
import java.nio.file.Path
@ -151,7 +152,10 @@ object X509Utilities {
* @param storePassword password to open the store. This does not have to be the same password as any keys stored,
* but for SSL purposes this is recommended.
* @return returns the KeyStore opened
* @throws IOException if there was an error reading the key store from the file.
* @throws KeyStoreException if the password is incorrect or the key store is damaged.
*/
@Throws(KeyStoreException::class, IOException::class)
fun loadKeyStore(keyStoreFilePath: Path, storePassword: String): KeyStore {
val pass = storePassword.toCharArray()
val keyStore = KeyStore.getInstance(KEYSTORE_TYPE)
@ -165,7 +169,10 @@ object X509Utilities {
* @param storePassword password to open the store. This does not have to be the same password as any keys stored,
* but for SSL purposes this is recommended.
* @return returns the KeyStore opened
* @throws IOException if there was an error reading the key store from the stream.
* @throws KeyStoreException if the password is incorrect or the key store is damaged.
*/
@Throws(KeyStoreException::class, IOException::class)
fun loadKeyStore(input: InputStream, storePassword: String): KeyStore {
val pass = storePassword.toCharArray()
val keyStore = KeyStore.getInstance(KEYSTORE_TYPE)

View File

@ -53,9 +53,11 @@ import net.corda.node.utilities.databaseTransaction
import org.apache.activemq.artemis.utils.ReusableLatch
import org.jetbrains.exposed.sql.Database
import org.slf4j.Logger
import java.io.IOException
import java.nio.file.FileAlreadyExistsException
import java.nio.file.Path
import java.security.KeyPair
import java.security.KeyStoreException
import java.time.Clock
import java.util.*
import java.util.concurrent.ConcurrentHashMap
@ -312,9 +314,12 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
private fun hasSSLCertificates(): Boolean {
val keyStore = try {
// This will throw exception if key file not found or keystore password is incorrect.
// This will throw IOException if key file not found or KeyStoreException if keystore password is incorrect.
X509Utilities.loadKeyStore(configuration.keyStoreFile, configuration.keyStorePassword)
} catch (e: Exception) {
} catch (e: IOException) {
null
} catch (e: KeyStoreException) {
log.warn("Certificate key store found but key store password does not match configuration.")
null
}
return keyStore?.containsAlias(X509Utilities.CORDA_CLIENT_CA) ?: false

View File

@ -50,6 +50,7 @@ import rx.Subscription
import java.io.IOException
import java.math.BigInteger
import java.security.KeyStore
import java.security.KeyStoreException
import java.security.Principal
import java.util.*
import java.util.concurrent.Executor
@ -113,6 +114,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
* The server will make sure the bridge exists on network map changes, see method [updateBridgesOnNetworkChange]
* We assume network map will be updated accordingly when the client node register with the network map server.
*/
@Throws(IOException::class, KeyStoreException::class)
fun start() = mutex.locked {
if (!running) {
configureAndStartServer()
@ -130,6 +132,9 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
running = false
}
// TODO: Maybe wrap [IOException] on a key store load error so that it's clearly splitting key store loading from
// Artemis IO errors
@Throws(IOException::class, KeyStoreException::class)
private fun configureAndStartServer() {
val config = createArtemisConfig()
val securityManager = createArtemisSecurityManager()
@ -225,6 +230,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
deleteNonDurableQueue, manage, browse)
}
@Throws(IOException::class, KeyStoreException::class)
private fun createArtemisSecurityManager(): ActiveMQJAASSecurityManager {
val ourCertificate = X509Utilities
.loadCertificateFromKeyStore(config.keyStoreFile, config.keyStorePassword, CORDA_CLIENT_CA)

View File

@ -88,6 +88,8 @@ class ArtemisMessagingTests {
fun cleanUp() {
messagingClient?.stop()
messagingServer?.stop()
messagingClient = null
messagingServer = null
dataSource.close()
LogHelper.reset(PersistentUniquenessProvider::class)
}