From 7d6cb9b2d97b88386e36e8f29aaec234d4747b1a Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Fri, 13 Nov 2020 14:12:03 -0300 Subject: [PATCH 01/13] add new RpcClient Base --- src/main/resources/application.conf | 2 +- .../chains/testnet-internal-genesis.json | 2 +- .../faucet/jsonrpc/FaucetBuilder.scala | 6 +- .../faucet/jsonrpc/FaucetRpcService.scala | 19 ++-- .../faucet/jsonrpc/WalletRpcClient.scala | 28 +++++ .../jsonrpc}/CommonJsonCodecs.scala | 2 +- .../jsonrpc/jsonrpc/RpcBaseClient.scala | 101 ++++++++++++++++++ .../mallet/interpreter/Commands.scala | 2 +- .../ethereum/mallet/service/RpcClient.scala | 2 +- .../faucet/FaucetRpcServiceSpec.scala | 12 +-- src/universal/conf/faucet.conf | 4 +- 11 files changed, 153 insertions(+), 27 deletions(-) create mode 100644 src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala rename src/main/scala/io/iohk/ethereum/{mallet/service => jsonrpc/jsonrpc}/CommonJsonCodecs.scala (96%) create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 2ab2269787..9df573badd 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -259,7 +259,7 @@ mantis { } blockchains { - network = "etc" + network = "testnet-internal" etc {include "chains/etc-chain.conf"} diff --git a/src/main/resources/chains/testnet-internal-genesis.json b/src/main/resources/chains/testnet-internal-genesis.json index f5708d5e61..b710af8ed9 100644 --- a/src/main/resources/chains/testnet-internal-genesis.json +++ b/src/main/resources/chains/testnet-internal-genesis.json @@ -10,7 +10,7 @@ "coinbase": "0x0000000000000000000000000000000000000000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "alloc": { - "d7a681378321f472adffb9fdded2712f677e0ba9": {"balance": + "d1c7b7daf09ee87ff68f2a1e27319ad006ebca93": {"balance": "1606938044258990275541962092341162602522202993782792835301376"} } } diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index b6604cd944..528fa08d65 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -8,7 +8,6 @@ import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer import io.iohk.ethereum.keystore.KeyStoreImpl -import io.iohk.ethereum.mallet.service.RpcClient import io.iohk.ethereum.utils.{ConfigUtils, KeyStoreConfig, Logger} import scala.util.Try @@ -28,8 +27,9 @@ trait FaucetRpcServiceBuilder { self: FaucetConfigBuilder with FaucetControllerBuilder with ActorSystemBuilder => val keyStore = new KeyStoreImpl(KeyStoreConfig.customKeyStoreConfig(faucetConfig.keyStoreDir), new SecureRandom()) - val rpcClient = new RpcClient(faucetConfig.rpcAddress) - val faucetRpcService = new FaucetRpcService(rpcClient, keyStore, faucetConfig) + + val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, None) //TODO: maybeSslContext??? + val faucetRpcService = new FaucetRpcService(walletRpcClient, keyStore, faucetConfig) } trait FaucetJsonRpcHealthCheckBuilder { diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala index 97d8299732..2aa5b5e075 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala @@ -1,19 +1,19 @@ package io.iohk.ethereum.faucet.jsonrpc import akka.util.ByteString +import cats.data.EitherT import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.faucet.FaucetConfig import io.iohk.ethereum.faucet.FaucetStatus.FaucetUnavailable import io.iohk.ethereum.faucet.jsonrpc.FaucetDomain.{SendFundsRequest, SendFundsResponse, StatusRequest, StatusResponse} import io.iohk.ethereum.jsonrpc.{JsonRpcError, ServiceResponse} import io.iohk.ethereum.keystore.KeyStore -import io.iohk.ethereum.mallet.service.RpcClient import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc import io.iohk.ethereum.rlp import io.iohk.ethereum.utils.{ByteStringUtils, Logger} import monix.eval.Task -class FaucetRpcService(rpcClient: RpcClient, keyStore: KeyStore, config: FaucetConfig) extends Logger { +class FaucetRpcService(walletRpcClient: WalletRpcClient, keyStore: KeyStore, config: FaucetConfig) extends Logger { private val wallet = keyStore.unlockAccount(config.walletAddress, config.walletPassword) match { case Right(w) => @@ -24,20 +24,17 @@ class FaucetRpcService(rpcClient: RpcClient, keyStore: KeyStore, config: FaucetC } def sendFunds(sendFundsRequest: SendFundsRequest): ServiceResponse[SendFundsResponse] = { - val res = for { - nonce <- rpcClient.getNonce(wallet.address) - txId <- rpcClient.sendTransaction(prepareTx(sendFundsRequest.address, nonce)) - } yield txId - - res match { + (for { + nonce <- EitherT(walletRpcClient.getNonce(wallet.address)) + txId <- EitherT(walletRpcClient.sendTransaction(prepareTx(sendFundsRequest.address, nonce))) + } yield txId).value map { case Right(txId) => val txIdHex = s"0x${ByteStringUtils.hash2string(txId)}" log.info(s"Sending ${config.txValue} ETC to ${sendFundsRequest.address} in tx: $txIdHex.") - Task.now(Right(SendFundsResponse(txId))) - + Right(SendFundsResponse(txId)) case Left(err) => log.error(s"An error occurred while using faucet: $err") - Task.now(Left(JsonRpcError.InternalError)) + Left(JsonRpcError.InternalError) } } diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala new file mode 100644 index 0000000000..85c0281524 --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala @@ -0,0 +1,28 @@ +package io.iohk.ethereum.faucet.jsonrpc + +import akka.actor.ActorSystem +import akka.http.scaladsl.model.Uri +import io.circe.syntax._ +import akka.util.ByteString +import io.iohk.ethereum.domain.Address +import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient +import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient.RpcError +import io.iohk.ethereum.utils.Logger +import javax.net.ssl.SSLContext +import monix.eval.Task + +import scala.concurrent.ExecutionContext + +class WalletRpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit + system: ActorSystem, + ec: ExecutionContext +) extends RpcBaseClient(node, maybeSslContext) + with Logger { + import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ + + def getNonce(address: Address): Task[Either[RpcError, BigInt]] = + doRequest[BigInt]("eth_getTransactionCount", List(address.asJson, "latest".asJson)) + + def sendTransaction(rawTx: ByteString): Task[Either[RpcError, ByteString]] = + doRequest[ByteString]("eth_sendRawTransaction", List(rawTx.asJson)) +} diff --git a/src/main/scala/io/iohk/ethereum/mallet/service/CommonJsonCodecs.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala similarity index 96% rename from src/main/scala/io/iohk/ethereum/mallet/service/CommonJsonCodecs.scala rename to src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala index 5c2336abee..1bc6d3b110 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/service/CommonJsonCodecs.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.mallet.service +package io.iohk.ethereum.jsonrpc.jsonrpc import akka.util.ByteString import io.circe._ diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala new file mode 100644 index 0000000000..cd6d5f5857 --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala @@ -0,0 +1,101 @@ +package io.iohk.ethereum.jsonrpc.jsonrpc + +import java.io.{PrintWriter, StringWriter} +import java.util.UUID + +import akka.actor.ActorSystem +import akka.http.scaladsl.model._ +import akka.http.scaladsl.unmarshalling.Unmarshal +import akka.http.scaladsl.{ConnectionContext, Http} +import io.circe.generic.auto._ +import io.circe.parser.parse +import io.circe.syntax._ +import io.circe.{Decoder, Json} +import io.iohk.ethereum.jsonrpc.JsonRpcError +import io.iohk.ethereum.utils.Logger +import javax.net.ssl.SSLContext +import monix.eval.Task + +import scala.concurrent.duration._ +import scala.concurrent.{Await, ExecutionContext} + +abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit + system: ActorSystem, + ec: ExecutionContext +) extends Logger { + + import RpcBaseClient._ + + lazy val connectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) + + def shutdown(): Unit = { + Await.ready(system.terminate(), 5.seconds) + } + + protected def doRequest[T: Decoder](method: String, args: Seq[Json]): RpcResponse[T] = { + doJsonRequest(method, args).map(_.flatMap(getResult[T])) + } + + protected def doJsonRequest( + method: String, + args: Seq[Json] + ): RpcResponse[Json] = { + val request = prepareJsonRequest(method, args) + log.info(s"Making RPC call with request: $request") + makeRpcCall(request.asJson) + } + + private def getResult[T: Decoder](jsonResponse: Json): Either[RpcError, T] = { + jsonResponse.hcursor.downField("error").as[JsonRpcError] match { + case Right(error) => + Left(RpcClientError(s"Node returned an error: ${error.message} (${error.code})")) + case Left(_) => + jsonResponse.hcursor.downField("result").as[T].left.map(f => RpcClientError(f.message)) + } + } + + private def makeRpcCall(jsonRequest: Json): Task[Either[RpcError, Json]] = { + val entity = HttpEntity(ContentTypes.`application/json`, jsonRequest.noSpaces) + val request = HttpRequest(method = HttpMethods.POST, uri = node, entity = entity) + + Task + .deferFuture(for { + resp <- Http().singleRequest(request, connectionContext) + data <- Unmarshal(resp.entity).to[String] + } yield parse(data).left.map(e => RpcClientError(e.message))) + .onErrorHandle { ex: Throwable => + Left(RpcClientError(s"RPC request failed: ${exceptionToString(ex)}")) + } + } + + private def prepareJsonRequest(method: String, args: Seq[Json]): Json = { + Map( + "jsonrpc" -> "2.0".asJson, + "method" -> method.asJson, + "params" -> args.asJson, + "id" -> s"${UUID.randomUUID()}".asJson + ).asJson + } + + private def exceptionToString(ex: Throwable): String = { + val sw = new StringWriter() + sw.append(ex.getMessage + "\n") + ex.printStackTrace(new PrintWriter(sw)) + sw.toString + } + +} + +object RpcBaseClient { + type RpcResponse[T] = Task[Either[RpcError, T]] + + type Secrets = Map[String, Json] + + sealed trait RpcError { + def msg: String + } + + case class ParserError(msg: String) extends RpcError + + case class RpcClientError(msg: String) extends RpcError +} diff --git a/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala b/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala index 3dd09c5310..e0d99a8e76 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala @@ -6,7 +6,7 @@ import io.circe.syntax._ import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.mallet.common.{StringUtil, Util} import io.iohk.ethereum.mallet.interpreter.Parameter._ -import io.iohk.ethereum.mallet.service.CommonJsonCodecs._ +import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ import io.iohk.ethereum.mallet.service.State import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc import io.iohk.ethereum.rlp diff --git a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala index fcc41035d2..8c054cf96e 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala @@ -41,7 +41,7 @@ object RpcClient { * Note: the URI schema determines whether HTTP or HTTPS is used */ class RpcClient(node: Uri)(implicit system: ActorSystem, ec: ExecutionContext) { - import CommonJsonCodecs._ + import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ //TODO: CL option private val httpTimeout = 5.seconds diff --git a/src/test/scala/io/iohk/ethereum/faucet/FaucetRpcServiceSpec.scala b/src/test/scala/io/iohk/ethereum/faucet/FaucetRpcServiceSpec.scala index 60f50c343e..1c567a043c 100644 --- a/src/test/scala/io/iohk/ethereum/faucet/FaucetRpcServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/faucet/FaucetRpcServiceSpec.scala @@ -7,11 +7,11 @@ import akka.util.ByteString import io.iohk.ethereum.crypto._ import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.faucet.jsonrpc.FaucetDomain.{SendFundsRequest, SendFundsResponse} -import io.iohk.ethereum.faucet.jsonrpc.FaucetRpcService +import io.iohk.ethereum.faucet.jsonrpc.{FaucetRpcService, WalletRpcClient} import io.iohk.ethereum.keystore.{KeyStore, Wallet} -import io.iohk.ethereum.mallet.service.RpcClient import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc import io.iohk.ethereum.{crypto, rlp} +import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.bouncycastle.util.encoders.Hex import org.scalamock.scalatest.MockFactory @@ -36,7 +36,7 @@ class FaucetRpcServiceSpec val config: FaucetConfig = FaucetConfig(wallet.address, "", 10, 20, 1, "", "", 10.seconds) - val mockRpcClient = mock[RpcClient] + val mockWalletRpcClient = mock[WalletRpcClient] val mockKeyStore = mock[KeyStore] val receivingAddress = Address("0x99") @@ -52,10 +52,10 @@ class FaucetRpcServiceSpec val retTxId = ByteString(Hex.decode("112233")) (mockKeyStore.unlockAccount _).expects(config.walletAddress, config.walletPassword).returning(Right(wallet)) - (mockRpcClient.getNonce _).expects(config.walletAddress).returning(Right(currentNonce)) - (mockRpcClient.sendTransaction _).expects(ByteString(expectedTx)).returning(Right(retTxId)) + (mockWalletRpcClient.getNonce _).expects(config.walletAddress).returning(Task(Right(currentNonce))) + (mockWalletRpcClient.sendTransaction _).expects(ByteString(expectedTx)).returning(Task(Right(retTxId))) - val faucetRpcService = new FaucetRpcService(mockRpcClient, mockKeyStore, config) + val faucetRpcService = new FaucetRpcService(mockWalletRpcClient, mockKeyStore, config) val res = faucetRpcService.sendFunds(SendFundsRequest(Address("0x99"))).runSyncUnsafe() diff --git a/src/universal/conf/faucet.conf b/src/universal/conf/faucet.conf index 73e44cbd64..9c7ba76184 100644 --- a/src/universal/conf/faucet.conf +++ b/src/universal/conf/faucet.conf @@ -4,10 +4,10 @@ faucet { datadir = ${user.home}"/.mantis-faucet" # Wallet address used to send transactions from - wallet-address = "0x00" + wallet-address = "0xd1c7b7daf09ee87ff68f2a1e27319ad006ebca93" # Password to unlock faucet wallet - wallet-password = "" + wallet-password = "12345678" # Path to directory where wallet key is stored keystore-dir = ${faucet.datadir}"/keystore" From 9141528fb2937578a69e157a5a1b03f702756a08 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Sun, 15 Nov 2020 12:12:10 -0300 Subject: [PATCH 02/13] add security in rpc client --- .../io/iohk/ethereum/crypto/EcKeyGen.scala | 3 +- .../faucet/jsonrpc/FaucetBuilder.scala | 10 +- .../ethereum/jsonrpc/security/SSLConfig.scala | 27 +++++ .../jsonrpc/security/SSLContextBuilder.scala | 20 ++++ .../jsonrpc/security/SSLContextFactory.scala | 101 ++++++++++++++++++ .../security/SecureRandomBuilder.scala | 27 +++++ .../server/http/JsonRpcHttpServer.scala | 15 +-- .../server/http/JsonRpcHttpsServer.scala | 42 +++----- .../network/discovery/Secp256k1SigAlg.scala | 10 +- .../ethereum/nodebuilder/NodeBuilder.scala | 6 +- 10 files changed, 212 insertions(+), 49 deletions(-) create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala diff --git a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala index a0f54d0101..8e22e1ee90 100644 --- a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala +++ b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala @@ -1,6 +1,7 @@ package io.iohk.ethereum.crypto -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder + /** * A simple tool to generate and ECDSA key pair. The key pair will be printed in the format: diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index 528fa08d65..bb1c2019c8 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -7,10 +7,9 @@ import io.iohk.ethereum.faucet.FaucetConfigBuilder import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.keystore.KeyStoreImpl -import io.iohk.ethereum.utils.{ConfigUtils, KeyStoreConfig, Logger} - -import scala.util.Try +import io.iohk.ethereum.utils.{KeyStoreConfig, Logger} trait ActorSystemBuilder { def systemName: String @@ -60,14 +59,15 @@ trait FaucetJsonRpcControllerBuilder { val faucetJsonRpcController = new FaucetJsonRpcController(faucetRpcService, jsonRpcConfig) } -trait SecureRandomBuilder { +//TODO: add this config in faucet +/*trait SecureRandomBuilder { self: FaucetConfigBuilder => lazy val secureRandom: SecureRandom = ConfigUtils .getOptionalValue(rawMantisConfig, "secure-random-algo", config => config.getString("secure-random-algo")) .flatMap(name => Try { SecureRandom.getInstance(name) }.toOption) .getOrElse(new SecureRandom()) -} +}*/ trait FaucetJsonRpcHttpServerBuilder { self: ActorSystemBuilder diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala new file mode 100644 index 0000000000..26d420a40f --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala @@ -0,0 +1,27 @@ +package io.iohk.ethereum.jsonrpc.security + +import com.typesafe.config.Config + +import scala.util.Try + +case class SSLConfig( + certificateKeyStorePath: Option[String], + certificateKeyStoreType: Option[String], + certificatePasswordFile: Option[String] +) + +object SSLConfig { + def apply(config: Config): SSLConfig = { + SSLConfig( + certificateKeyStorePath = Try( + config.getString("certificate-keystore-path") + ).toOption, + certificateKeyStoreType = Try( + config.getString("certificate-keystore-type") + ).toOption, + certificatePasswordFile = Try( + config.getString("certificate-password-file") + ).toOption) + } + +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala new file mode 100644 index 0000000000..5c4165488b --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala @@ -0,0 +1,20 @@ +package io.iohk.ethereum.jsonrpc.security +//import com.typesafe.config.Config +//import com.typesafe.config.ConfigFactory +//import javax.net.ssl.SSLContext + + +case class SSLError(reason: String) //TODO: throwable exception + +/*trait SSLConfigBuilder { + lazy val networkConfig: Config = ConfigFactory.load().getConfig("mantis.network") + lazy val sslConfig: Option[SSLConfig] = SSLConfig(networkConfig) +} + +class SSLContextBuilder { self: SSLConfigBuilder with SecureRandomBuilder => + lazy val sslContext: Either[SSLError, SSLContext] = + sslConfig + .toRight(SSLError("No SSL config present")) + .flatMap(SSLContextFactory.createSSLContext(_, secureRandom)) + +}*/ diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala new file mode 100644 index 0000000000..51124f018d --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala @@ -0,0 +1,101 @@ +package io.iohk.ethereum.jsonrpc.security + +import java.io.{File, FileInputStream} +import java.security.{KeyStore, SecureRandom} + +import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory} + +import scala.io.Source +import scala.util.{Failure, Success, Try} + +object SSLContextFactory { + + def createSSLContext(sSLConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { + validateCertificateFiles( + sSLConfig.certificateKeyStorePath, + sSLConfig.certificateKeyStoreType, + sSLConfig.certificatePasswordFile + ).flatMap { case (keystorePath, keystoreType, passwordFile) => + val passwordReader = Source.fromFile(passwordFile) + try { + val password = passwordReader.getLines().mkString + obtainSSLContext(secureRandom, keystorePath, keystoreType, password) + } finally { + passwordReader.close() + } + } + } + + /** + * Validates that the keystore certificate file and password file were configured and that the files exists + * + * @param maybeKeystorePath, with the path to the certificate keystore if it was configured + * @param maybePasswordFile, with the path to the password file if it was configured + * @return the certificate path and password file or the error detected + */ + private def validateCertificateFiles( + maybeKeystorePath: Option[String], + maybeKeystoreType: Option[String], + maybePasswordFile: Option[String] + ): Either[SSLError, (String, String, String)] = + (maybeKeystorePath, maybeKeystoreType, maybePasswordFile) match { + case (Some(keystorePath), Some(keystoreType), Some(passwordFile)) => + val keystoreDirMissing = !new File(keystorePath).isFile + val passwordFileMissing = !new File(passwordFile).isFile + if (keystoreDirMissing && passwordFileMissing) + Left(SSLError("Certificate keystore path and password file configured but files are missing")) + else if (keystoreDirMissing) + Left(SSLError("Certificate keystore path configured but file is missing")) + else if (passwordFileMissing) + Left(SSLError("Certificate password file configured but file is missing")) + else + Right((keystorePath, keystoreType, passwordFile)) + case _ => + Left( + SSLError("HTTPS requires: certificate-keystore-path, certificate-keystore-type and certificate-password-file to be configured") + ) + } + + /** + * Constructs the SSL context given a certificate + * + * @param certificateKeyStorePath, path to the keystore where the certificate is stored + * @param password for accessing the keystore with the certificate + * @return the SSL context with the obtained certificate or an error if any happened + */ + private def obtainSSLContext( + secureRandom: SecureRandom, + certificateKeyStorePath: String, + certificateKeyStoreType: String, + password: String + ): Either[SSLError, SSLContext] = { + val passwordCharArray: Array[Char] = password.toCharArray + + val maybeKeyStore: Either[SSLError, KeyStore] = Try(KeyStore.getInstance(certificateKeyStoreType)).toOption + .toRight(SSLError(s"Certificate keystore invalid type set: $certificateKeyStoreType")) + val keyStoreInitResult: Either[SSLError, KeyStore] = maybeKeyStore.flatMap { keyStore => + val keyStoreFileCreationResult = Option(new FileInputStream(certificateKeyStorePath)) + .toRight(SSLError("Certificate keystore file creation failed")) + keyStoreFileCreationResult.flatMap { keyStoreFile => + Try(keyStore.load(keyStoreFile, passwordCharArray)) match { + case Success(_) => Right(keyStore) + case Failure(err) => Left(SSLError(err.getMessage)) + } + } + } + + keyStoreInitResult.map { ks => + val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") + keyManagerFactory.init(ks, passwordCharArray) + + val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") + tmf.init(ks) + + val sslContext: SSLContext = SSLContext.getInstance("TLS") + sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, secureRandom) + sslContext + } + + } + +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala new file mode 100644 index 0000000000..1305a9454a --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala @@ -0,0 +1,27 @@ +package io.iohk.ethereum.jsonrpc.security + +import java.security.SecureRandom + +import io.iohk.ethereum.utils.{Config, Logger} + +import scala.util.{Failure, Success, Try} + +trait SecureRandomBuilder extends Logger { + + //TODO: work with this config... + lazy val secureRandom: SecureRandom = + Config.secureRandomAlgo + .flatMap(name => + Try(SecureRandom.getInstance(name)) match { + case Failure(exception) => + log.error( + s"Couldn't create SecureRandom instance using algorithm $name. Falling-back to default one", + exception + ) + None + case Success(value) => + Some(value) + } + ) + .getOrElse(new SecureRandom()) +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala index f6faada726..492f1c7b20 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala @@ -12,6 +12,7 @@ import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings import de.heikoseeberger.akkahttpjson4s.Json4sSupport import io.iohk.ethereum.jsonrpc._ +import io.iohk.ethereum.jsonrpc.security.SSLConfig import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.utils.{ConfigUtils, Logger} @@ -19,8 +20,6 @@ import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.json4s.{DefaultFormats, JInt, native} -import scala.util.Try - trait JsonRpcHttpServer extends Json4sSupport { val jsonRpcController: JsonRpcBaseController val jsonRpcHealthChecker: JsonRpcHealthChecker @@ -114,9 +113,10 @@ object JsonRpcHttpServer extends Logger { val enabled: Boolean val interface: String val port: Int - val certificateKeyStorePath: Option[String] - val certificateKeyStoreType: Option[String] - val certificatePasswordFile: Option[String] + //val certificateKeyStorePath: Option[String] + //val certificateKeyStoreType: Option[String] + //val certificatePasswordFile: Option[String] + val sSLConfig: SSLConfig val corsAllowedOrigins: HttpOriginMatcher } @@ -134,7 +134,8 @@ object JsonRpcHttpServer extends Logger { override val corsAllowedOrigins = ConfigUtils.parseCorsAllowedOrigins(rpcHttpConfig, "cors-allowed-origins") - override val certificateKeyStorePath: Option[String] = Try( + override val sSLConfig: SSLConfig = SSLConfig(rpcHttpConfig) + /*override val certificateKeyStorePath: Option[String] = Try( rpcHttpConfig.getString("certificate-keystore-path") ).toOption override val certificateKeyStoreType: Option[String] = Try( @@ -142,7 +143,7 @@ object JsonRpcHttpServer extends Logger { ).toOption override val certificatePasswordFile: Option[String] = Try( rpcHttpConfig.getString("certificate-password-file") - ).toOption + ).toOption*/ } } } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala index 1777c9389d..70ac42bd43 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala @@ -1,21 +1,18 @@ package io.iohk.ethereum.jsonrpc.server.http +import java.security.SecureRandom + import akka.actor.ActorSystem import akka.http.scaladsl.{ConnectionContext, Http} import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import io.iohk.ethereum.jsonrpc.JsonRpcHealthChecker +import io.iohk.ethereum.jsonrpc.security.SSLContextFactory +import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig -import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpsServer.HttpsSetupResult import io.iohk.ethereum.utils.Logger -import java.io.{File, FileInputStream} -import java.security.{KeyStore, SecureRandom} - -import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController -import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory} import scala.concurrent.ExecutionContext.Implicits.global -import scala.io.Source -import scala.util.{Failure, Success, Try} +import scala.util.{Failure, Success} class JsonRpcHttpsServer( val jsonRpcController: JsonRpcBaseController, @@ -27,7 +24,8 @@ class JsonRpcHttpsServer( with Logger { def run(): Unit = { - val maybeSslContext = validateCertificateFiles( + val maybeSslContext = SSLContextFactory.createSSLContext(config.sSLConfig, secureRandom) + /*val maybeSslContext = validateCertificateFiles( config.certificateKeyStorePath, config.certificateKeyStoreType, config.certificatePasswordFile @@ -39,7 +37,7 @@ class JsonRpcHttpsServer( } finally { passwordReader.close() } - } + }*/ val maybeHttpsContext = maybeSslContext.map(sslContext => ConnectionContext.httpsServer(sslContext)) @@ -55,14 +53,8 @@ class JsonRpcHttpsServer( } } - /** - * Constructs the SSL context given a certificate - * - * @param certificateKeyStorePath, path to the keystore where the certificate is stored - * @param password for accessing the keystore with the certificate - * @return the SSL context with the obtained certificate or an error if any happened - */ - private def obtainSSLContext( + + /*private def obtainSSLContext( certificateKeyStorePath: String, certificateKeyStoreType: String, password: String @@ -96,13 +88,7 @@ class JsonRpcHttpsServer( } - /** - * Validates that the keystore certificate file and password file were configured and that the files exists - * - * @param maybeKeystorePath, with the path to the certificate keystore if it was configured - * @param maybePasswordFile, with the path to the password file if it was configured - * @return the certificate path and password file or the error detected - */ + private def validateCertificateFiles( maybeKeystorePath: Option[String], maybeKeystoreType: Option[String], @@ -124,11 +110,11 @@ class JsonRpcHttpsServer( Left( "HTTPS requires: certificate-keystore-path, certificate-keystore-type and certificate-password-file to be configured" ) - } + }*/ override def corsAllowedOrigins: HttpOriginMatcher = config.corsAllowedOrigins } -object JsonRpcHttpsServer { +/*object JsonRpcHttpsServer { type HttpsSetupResult[T] = Either[String, T] -} +}*/ diff --git a/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala b/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala index a7edcce53e..09864a3fc9 100644 --- a/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala +++ b/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala @@ -3,13 +3,13 @@ package io.iohk.ethereum.network.discovery import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto.ECDSASignature -import io.iohk.scalanet.discovery.crypto.{SigAlg, PublicKey, PrivateKey, Signature} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.scalanet.discovery.crypto.{PrivateKey, PublicKey, SigAlg, Signature} +import org.bouncycastle.crypto.AsymmetricCipherKeyPair +import org.bouncycastle.crypto.params.ECPublicKeyParameters import scodec.bits.BitVector import scodec.{Attempt, Err} -import scodec.bits.BitVector -import org.bouncycastle.crypto.params.ECPublicKeyParameters -import org.bouncycastle.crypto.AsymmetricCipherKeyPair + import scala.collection.concurrent.TrieMap class Secp256k1SigAlg extends SigAlg with SecureRandomBuilder { diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index f4b56eab83..49ef2546e0 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -1,6 +1,5 @@ package io.iohk.ethereum.nodebuilder -import java.security.SecureRandom import java.time.Clock import java.util.concurrent.atomic.AtomicReference @@ -20,6 +19,7 @@ import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer import io.iohk.ethereum.jsonrpc.server.ipc.JsonRpcIpcServer +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.keystore.{KeyStore, KeyStoreImpl} import io.iohk.ethereum.ledger.Ledger.VMImpl import io.iohk.ethereum.ledger._ @@ -595,7 +595,7 @@ trait GenesisDataLoaderBuilder { lazy val genesisDataLoader = new GenesisDataLoader(blockchain, blockchainConfig) } -trait SecureRandomBuilder extends Logger { +/*trait SecureRandomBuilder extends Logger { lazy val secureRandom: SecureRandom = Config.secureRandomAlgo .flatMap(name => @@ -608,7 +608,7 @@ trait SecureRandomBuilder extends Logger { } ) .getOrElse(new SecureRandom()) -} +}*/ /** Provides the basic functionality of a Node, except the consensus algorithm. * The latter is loaded dynamically based on configuration. From e4a6271129a59cbefa9a91ccd9cf776ce2fdcc60 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Mon, 16 Nov 2020 17:44:43 -0300 Subject: [PATCH 03/13] change ssl config --- .../vm/PrecompiledContractsSpecEvm.scala | 2 +- .../ethereum/sync/util/CommonFakePeer.scala | 12 +-- .../txExecTest/util/DumpChainApp.scala | 3 +- .../faucet/jsonrpc/FaucetBuilder.scala | 29 +++---- .../jsonrpc/jsonrpc/RpcBaseClient.scala | 5 +- .../jsonrpc/security/SSLContextBuilder.scala | 22 ++--- .../security/SecureRandomBuilder.scala | 12 ++- .../server/http/JsonRpcHttpServer.scala | 8 +- .../server/http/JsonRpcHttpsServer.scala | 86 ++----------------- .../ethereum/nodebuilder/NodeBuilder.scala | 33 +++---- .../scala/io/iohk/ethereum/BlockHelpers.scala | 2 +- .../sync/regular/RegularSyncFixtures.scala | 2 +- .../validators/BlockValidatorSpec.scala | 2 +- ...ockWithCheckpointHeaderValidatorSpec.scala | 3 +- .../ethereum/crypto/ECDSASignatureSpec.scala | 2 +- .../iohk/ethereum/crypto/ECIESCoderSpec.scala | 2 +- .../db/storage/BlockBodiesStorageSpec.scala | 2 +- .../domain/SignedTransactionSpec.scala | 2 +- .../jsonrpc/CheckpointingJRCSpec.scala | 3 +- .../ethereum/jsonrpc/FilterManagerSpec.scala | 2 +- .../ethereum/jsonrpc/NetServiceSpec.scala | 2 +- .../server/http/JsonRpcHttpServerSpec.scala | 5 +- .../ethereum/keystore/EncryptedKeySpec.scala | 2 +- .../ethereum/keystore/KeyStoreImplSpec.scala | 2 +- .../ethereum/ledger/LedgerTestSetup.scala | 2 +- .../AsymmetricCipherKeyPairLoaderSpec.scala | 2 +- .../ethereum/network/AuthHandshakerSpec.scala | 2 +- .../network/AuthInitiateMessageSpec.scala | 2 +- .../discovery/PeerDiscoveryManagerSpec.scala | 6 +- .../handshaker/EtcHandshakerSpec.scala | 3 +- .../ethereum/network/p2p/PeerActorSpec.scala | 2 +- .../network/p2p/SecureChannelSetup.scala | 2 +- .../network/p2p/messages/NewBlockSpec.scala | 2 +- .../rlpx/RLPxConnectionHandlerSpec.scala | 2 +- .../PendingTransactionsManagerSpec.scala | 2 +- .../vm/PrecompiledContractsSpec.scala | 2 +- 36 files changed, 95 insertions(+), 179 deletions(-) diff --git a/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala b/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala index 2cf08a893c..a13897423e 100644 --- a/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala +++ b/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala @@ -4,7 +4,7 @@ import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto._ import io.iohk.ethereum.domain.SignedTransaction.{FirstByteOfAddress, LastByteOfAddress} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.vm.utils.EvmTestEnv import org.bouncycastle.crypto.params.ECPublicKeyParameters import org.scalatest.funsuite.AnyFunSuite diff --git a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala index 0d7adfdb9d..979818ed57 100644 --- a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala +++ b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala @@ -14,6 +14,7 @@ import io.iohk.ethereum.db.dataSource.{RocksDbConfig, RocksDbDataSource} import io.iohk.ethereum.db.storage.pruning.{ArchivePruning, PruningMode} import io.iohk.ethereum.db.storage.{AppStateStorage, Namespaces} import io.iohk.ethereum.domain.{Block, Blockchain, BlockchainImpl, ChainWeight} +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger.InMemoryWorldStateProxy import io.iohk.ethereum.mpt.MerklePatriciaTrie import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo @@ -25,15 +26,8 @@ import io.iohk.ethereum.network.p2p.EthereumMessageDecoder import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import io.iohk.ethereum.network.rlpx.AuthHandshaker import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration -import io.iohk.ethereum.network.{ - EtcPeerManagerActor, - ForkResolver, - KnownNodesManager, - PeerEventBusActor, - PeerManagerActor, - ServerActor -} -import io.iohk.ethereum.nodebuilder.{PruningConfigBuilder, SecureRandomBuilder} +import io.iohk.ethereum.network.{EtcPeerManagerActor, ForkResolver, KnownNodesManager, PeerEventBusActor, PeerManagerActor, ServerActor} +import io.iohk.ethereum.nodebuilder.PruningConfigBuilder import io.iohk.ethereum.sync.util.SyncCommonItSpec._ import io.iohk.ethereum.sync.util.SyncCommonItSpecUtils._ import io.iohk.ethereum.utils.ServerStatus.Listening diff --git a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala index 396d779fe8..6a58ab590a 100644 --- a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala +++ b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala @@ -18,7 +18,8 @@ import io.iohk.ethereum.network.handshaker.{EtcHandshaker, EtcHandshakerConfigur import io.iohk.ethereum.network.p2p.EthereumMessageDecoder import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerEventBusActor, PeerManagerActor} -import io.iohk.ethereum.nodebuilder.{AuthHandshakerBuilder, NodeKeyBuilder, SecureRandomBuilder} +import io.iohk.ethereum.nodebuilder.{AuthHandshakerBuilder, NodeKeyBuilder} +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} import java.util.concurrent.atomic.AtomicReference diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index bb1c2019c8..4dbb1059bf 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -1,13 +1,11 @@ package io.iohk.ethereum.faucet.jsonrpc -import java.security.SecureRandom - import akka.actor.ActorSystem import io.iohk.ethereum.faucet.FaucetConfigBuilder +import io.iohk.ethereum.jsonrpc.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.keystore.KeyStoreImpl import io.iohk.ethereum.utils.{KeyStoreConfig, Logger} @@ -23,9 +21,13 @@ trait FaucetControllerBuilder { } trait FaucetRpcServiceBuilder { - self: FaucetConfigBuilder with FaucetControllerBuilder with ActorSystemBuilder => + self: FaucetConfigBuilder with FaucetControllerBuilder with ActorSystemBuilder with SecureRandomBuilder => - val keyStore = new KeyStoreImpl(KeyStoreConfig.customKeyStoreConfig(faucetConfig.keyStoreDir), new SecureRandom()) + val keyStore = + new KeyStoreImpl( + KeyStoreConfig.customKeyStoreConfig(faucetConfig.keyStoreDir), + secureRandom + ) //TODO: ask secureRandom?? val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, None) //TODO: maybeSslContext??? val faucetRpcService = new FaucetRpcService(walletRpcClient, keyStore, faucetConfig) @@ -59,28 +61,20 @@ trait FaucetJsonRpcControllerBuilder { val faucetJsonRpcController = new FaucetJsonRpcController(faucetRpcService, jsonRpcConfig) } -//TODO: add this config in faucet -/*trait SecureRandomBuilder { - self: FaucetConfigBuilder => - lazy val secureRandom: SecureRandom = - ConfigUtils - .getOptionalValue(rawMantisConfig, "secure-random-algo", config => config.getString("secure-random-algo")) - .flatMap(name => Try { SecureRandom.getInstance(name) }.toOption) - .getOrElse(new SecureRandom()) -}*/ - trait FaucetJsonRpcHttpServerBuilder { self: ActorSystemBuilder with JsonRpcConfigBuilder with SecureRandomBuilder with FaucetJsonRpcHealthCheckBuilder - with FaucetJsonRpcControllerBuilder => + with FaucetJsonRpcControllerBuilder + with SSLContextBuilder => val faucetJsonRpcHttpServer = JsonRpcHttpServer( faucetJsonRpcController, faucetJsonRpcHealthCheck, jsonRpcConfig.httpServerConfig, - secureRandom + secureRandom, + () => sslContext ) } @@ -94,6 +88,7 @@ class FaucetServer with FaucetRpcServiceBuilder with FaucetJsonRpcHealthCheckBuilder with FaucetJsonRpcControllerBuilder + with SSLContextBuilder with FaucetJsonRpcHttpServerBuilder with Logger { diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala index cd6d5f5857..9ff76b7d12 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala @@ -6,7 +6,7 @@ import java.util.UUID import akka.actor.ActorSystem import akka.http.scaladsl.model._ import akka.http.scaladsl.unmarshalling.Unmarshal -import akka.http.scaladsl.{ConnectionContext, Http} +import akka.http.scaladsl.{ConnectionContext, Http, HttpsConnectionContext} import io.circe.generic.auto._ import io.circe.parser.parse import io.circe.syntax._ @@ -26,7 +26,8 @@ abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(imp import RpcBaseClient._ - lazy val connectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) + //TODO.... + lazy val connectionContext: HttpsConnectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) def shutdown(): Unit = { Await.ready(system.terminate(), 5.seconds) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala index 5c4165488b..787256bdf7 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala @@ -1,20 +1,14 @@ package io.iohk.ethereum.jsonrpc.security -//import com.typesafe.config.Config -//import com.typesafe.config.ConfigFactory -//import javax.net.ssl.SSLContext - +import com.typesafe.config.ConfigFactory +import javax.net.ssl.SSLContext case class SSLError(reason: String) //TODO: throwable exception -/*trait SSLConfigBuilder { - lazy val networkConfig: Config = ConfigFactory.load().getConfig("mantis.network") - lazy val sslConfig: Option[SSLConfig] = SSLConfig(networkConfig) -} +trait SSLContextBuilder { self: SecureRandomBuilder => -class SSLContextBuilder { self: SSLConfigBuilder with SecureRandomBuilder => - lazy val sslContext: Either[SSLError, SSLContext] = - sslConfig - .toRight(SSLError("No SSL config present")) - .flatMap(SSLContextFactory.createSSLContext(_, secureRandom)) + private lazy val rpcHttpConfig = ConfigFactory.load().getConfig("mantis.network.rpc.http") + private lazy val sSLConfig: SSLConfig = SSLConfig(rpcHttpConfig) -}*/ + lazy val sslContext: Either[SSLError, SSLContext] = SSLContextFactory.createSSLContext(sSLConfig, secureRandom) + +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala index 1305a9454a..f7021186b3 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala @@ -2,15 +2,21 @@ package io.iohk.ethereum.jsonrpc.security import java.security.SecureRandom -import io.iohk.ethereum.utils.{Config, Logger} +import com.typesafe.config.{Config, ConfigFactory} +import io.iohk.ethereum.utils.Logger import scala.util.{Failure, Success, Try} trait SecureRandomBuilder extends Logger { - //TODO: work with this config... + private lazy val rawMantisConfig: Config = ConfigFactory.load().getConfig("mantis") + + private val secureRandomAlgo: Option[String] = + if (rawMantisConfig.hasPath("secure-random-algo")) Some(rawMantisConfig.getString("secure-random-algo")) + else None + lazy val secureRandom: SecureRandom = - Config.secureRandomAlgo + secureRandomAlgo .flatMap(name => Try(SecureRandom.getInstance(name)) match { case Failure(exception) => diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala index 492f1c7b20..d1147b0ad7 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala @@ -12,10 +12,11 @@ import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings import de.heikoseeberger.akkahttpjson4s.Json4sSupport import io.iohk.ethereum.jsonrpc._ -import io.iohk.ethereum.jsonrpc.security.SSLConfig +import io.iohk.ethereum.jsonrpc.security.{SSLConfig, SSLError} import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.utils.{ConfigUtils, Logger} +import javax.net.ssl.SSLContext import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.json4s.{DefaultFormats, JInt, native} @@ -99,12 +100,13 @@ object JsonRpcHttpServer extends Logger { jsonRpcController: JsonRpcBaseController, jsonRpcHealthchecker: JsonRpcHealthChecker, config: JsonRpcHttpServerConfig, - secureRandom: SecureRandom + secureRandom: SecureRandom, + fSslContext: () => Either[SSLError, SSLContext] )(implicit actorSystem: ActorSystem): Either[String, JsonRpcHttpServer] = config.mode match { case "http" => Right(new BasicJsonRpcHttpServer(jsonRpcController, jsonRpcHealthchecker, config)(actorSystem)) case "https" => - Right(new JsonRpcHttpsServer(jsonRpcController, jsonRpcHealthchecker, config, secureRandom)(actorSystem)) + Right(new JsonRpcHttpsServer(jsonRpcController, jsonRpcHealthchecker, config, secureRandom, fSslContext)(actorSystem)) case _ => Left(s"Cannot start JSON RPC server: Invalid mode ${config.mode} selected") } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala index 70ac42bd43..182217e444 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala @@ -6,10 +6,11 @@ import akka.actor.ActorSystem import akka.http.scaladsl.{ConnectionContext, Http} import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import io.iohk.ethereum.jsonrpc.JsonRpcHealthChecker -import io.iohk.ethereum.jsonrpc.security.SSLContextFactory +import io.iohk.ethereum.jsonrpc.security.SSLError import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig import io.iohk.ethereum.utils.Logger +import javax.net.ssl.SSLContext import scala.concurrent.ExecutionContext.Implicits.global import scala.util.{Failure, Success} @@ -18,28 +19,14 @@ class JsonRpcHttpsServer( val jsonRpcController: JsonRpcBaseController, val jsonRpcHealthChecker: JsonRpcHealthChecker, config: JsonRpcHttpServerConfig, - secureRandom: SecureRandom + secureRandom: SecureRandom, + fSslContext: () => Either[SSLError, SSLContext] )(implicit val actorSystem: ActorSystem) extends JsonRpcHttpServer with Logger { def run(): Unit = { - val maybeSslContext = SSLContextFactory.createSSLContext(config.sSLConfig, secureRandom) - /*val maybeSslContext = validateCertificateFiles( - config.certificateKeyStorePath, - config.certificateKeyStoreType, - config.certificatePasswordFile - ).flatMap { case (keystorePath, keystoreType, passwordFile) => - val passwordReader = Source.fromFile(passwordFile) - try { - val password = passwordReader.getLines().mkString - obtainSSLContext(keystorePath, keystoreType, password) - } finally { - passwordReader.close() - } - }*/ - - val maybeHttpsContext = maybeSslContext.map(sslContext => ConnectionContext.httpsServer(sslContext)) + val maybeHttpsContext = fSslContext().map(sslContext => ConnectionContext.httpsServer(sslContext)) maybeHttpsContext match { case Right(httpsContext) => @@ -53,68 +40,5 @@ class JsonRpcHttpsServer( } } - - /*private def obtainSSLContext( - certificateKeyStorePath: String, - certificateKeyStoreType: String, - password: String - ): HttpsSetupResult[SSLContext] = { - val passwordCharArray: Array[Char] = password.toCharArray - - val maybeKeyStore: HttpsSetupResult[KeyStore] = Try(KeyStore.getInstance(certificateKeyStoreType)).toOption - .toRight(s"Certificate keystore invalid type set: $certificateKeyStoreType") - val keyStoreInitResult: HttpsSetupResult[KeyStore] = maybeKeyStore.flatMap { keyStore => - val keyStoreFileCreationResult = Option(new FileInputStream(certificateKeyStorePath)) - .toRight("Certificate keystore file creation failed") - keyStoreFileCreationResult.flatMap { keyStoreFile => - Try(keyStore.load(keyStoreFile, passwordCharArray)) match { - case Success(_) => Right(keyStore) - case Failure(err) => Left(err.getMessage) - } - } - } - - keyStoreInitResult.map { ks => - val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") - keyManagerFactory.init(ks, passwordCharArray) - - val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") - tmf.init(ks) - - val sslContext: SSLContext = SSLContext.getInstance("TLS") - sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, secureRandom) - sslContext - } - - } - - - private def validateCertificateFiles( - maybeKeystorePath: Option[String], - maybeKeystoreType: Option[String], - maybePasswordFile: Option[String] - ): HttpsSetupResult[(String, String, String)] = - (maybeKeystorePath, maybeKeystoreType, maybePasswordFile) match { - case (Some(keystorePath), Some(keystoreType), Some(passwordFile)) => - val keystoreDirMissing = !new File(keystorePath).isFile - val passwordFileMissing = !new File(passwordFile).isFile - if (keystoreDirMissing && passwordFileMissing) - Left("Certificate keystore path and password file configured but files are missing") - else if (keystoreDirMissing) - Left("Certificate keystore path configured but file is missing") - else if (passwordFileMissing) - Left("Certificate password file configured but file is missing") - else - Right((keystorePath, keystoreType, passwordFile)) - case _ => - Left( - "HTTPS requires: certificate-keystore-path, certificate-keystore-type and certificate-password-file to be configured" - ) - }*/ - override def corsAllowedOrigins: HttpOriginMatcher = config.corsAllowedOrigins } - -/*object JsonRpcHttpsServer { - type HttpsSetupResult[T] = Either[String, T] -}*/ diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index 49ef2546e0..5c78374f65 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -15,11 +15,11 @@ import io.iohk.ethereum.db.storage.pruning.PruningMode import io.iohk.ethereum.domain._ import io.iohk.ethereum.jsonrpc.NetService.NetServiceConfig import io.iohk.ethereum.jsonrpc._ +import io.iohk.ethereum.jsonrpc.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer import io.iohk.ethereum.jsonrpc.server.ipc.JsonRpcIpcServer -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.keystore.{KeyStore, KeyStoreImpl} import io.iohk.ethereum.ledger.Ledger.VMImpl import io.iohk.ethereum.ledger._ @@ -467,10 +467,17 @@ trait JSONRpcHttpServerBuilder { with JSONRpcControllerBuilder with JSONRpcHealthcheckerBuilder with SecureRandomBuilder - with JSONRpcConfigBuilder => + with JSONRpcConfigBuilder + with SSLContextBuilder => lazy val maybeJsonRpcHttpServer = - JsonRpcHttpServer(jsonRpcController, jsonRpcHealthChecker, jsonRpcConfig.httpServerConfig, secureRandom) + JsonRpcHttpServer( + jsonRpcController, + jsonRpcHealthChecker, + jsonRpcConfig.httpServerConfig, + secureRandom, + () => sslContext + ) } trait JSONRpcIpcServerBuilder { @@ -595,21 +602,6 @@ trait GenesisDataLoaderBuilder { lazy val genesisDataLoader = new GenesisDataLoader(blockchain, blockchainConfig) } -/*trait SecureRandomBuilder extends Logger { - lazy val secureRandom: SecureRandom = - Config.secureRandomAlgo - .flatMap(name => - Try(SecureRandom.getInstance(name)) match { - case Failure(exception) => - log.warn(s"Couldn't create SecureRandom instance using algorithm ${name}. Falling-back to default one") - None - case Success(value) => - Some(value) - } - ) - .getOrElse(new SecureRandom()) -}*/ - /** Provides the basic functionality of a Node, except the consensus algorithm. * The latter is loaded dynamically based on configuration. * @@ -617,7 +609,8 @@ trait GenesisDataLoaderBuilder { * [[io.iohk.ethereum.consensus.ConsensusConfigBuilder ConsensusConfigBuilder]] */ trait Node - extends NodeKeyBuilder + extends SecureRandomBuilder + with NodeKeyBuilder with ActorSystemBuilder with StorageBuilder with BlockchainBuilder @@ -639,6 +632,7 @@ trait Node with JSONRpcConfigBuilder with JSONRpcHealthcheckerBuilder with JSONRpcControllerBuilder + with SSLContextBuilder with JSONRpcHttpServerBuilder with JSONRpcIpcServerBuilder with ShutdownHookBuilder @@ -654,7 +648,6 @@ trait Node with FilterManagerBuilder with FilterConfigBuilder with TxPoolConfigBuilder - with SecureRandomBuilder with AuthHandshakerBuilder with PruningConfigBuilder with PeerDiscoveryManagerBuilder diff --git a/src/test/scala/io/iohk/ethereum/BlockHelpers.scala b/src/test/scala/io/iohk/ethereum/BlockHelpers.scala index 6eef1ac638..1ea621c329 100644 --- a/src/test/scala/io/iohk/ethereum/BlockHelpers.scala +++ b/src/test/scala/io/iohk/ethereum/BlockHelpers.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum import akka.util.ByteString import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.domain.{Address, Block, BlockBody, SignedTransaction, Transaction} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.bouncycastle.crypto.AsymmetricCipherKeyPair import mouse.all._ diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala index a2d98014eb..4f3a9b7698 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala @@ -15,6 +15,7 @@ import io.iohk.ethereum.blockchain.sync._ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator import io.iohk.ethereum.domain.BlockHeaderImplicits._ import io.iohk.ethereum.domain._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger._ import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer @@ -24,7 +25,6 @@ import io.iohk.ethereum.network.p2p.messages.CommonMessages.{NewBlock, Status} import io.iohk.ethereum.network.p2p.messages.PV62._ import io.iohk.ethereum.network.p2p.messages.PV63.{GetNodeData, NodeData} import io.iohk.ethereum.network.{Peer, PeerId} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.Config.SyncConfig import monix.eval.Task import monix.reactive.Observable diff --git a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala index e5e3e4fffd..dbd07329c3 100644 --- a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala @@ -7,8 +7,8 @@ import io.iohk.ethereum.consensus.validators.std.StdBlockValidator import io.iohk.ethereum.consensus.validators.std.StdBlockValidator._ import io.iohk.ethereum.crypto import io.iohk.ethereum.domain._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import org.bouncycastle.util.encoders.Hex import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala index 1ccb266d78..9c2bb37f83 100644 --- a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala @@ -9,8 +9,9 @@ import io.iohk.ethereum.crypto.ECDSASignature import io.iohk.ethereum.crypto.ECDSASignatureImplicits.ECDSASignatureOrdering import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields.HefPostEcip1097 import io.iohk.ethereum.domain._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter -import io.iohk.ethereum.nodebuilder.{BlockchainConfigBuilder, SecureRandomBuilder} +import io.iohk.ethereum.nodebuilder.BlockchainConfigBuilder import io.iohk.ethereum.utils.{BlockchainConfig, ByteStringUtils} import io.iohk.ethereum.{Fixtures, ObjectGenerators, crypto} import org.scalamock.scalatest.MockFactory diff --git a/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala b/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala index 30e2eeb04c..4280d91c79 100644 --- a/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala +++ b/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala @@ -1,7 +1,7 @@ package io.iohk.ethereum.crypto import akka.util.ByteString -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalacheck.Arbitrary import org.scalacheck.Arbitrary.arbitrary import org.bouncycastle.crypto.params.ECPublicKeyParameters diff --git a/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala b/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala index 18ab9da5c7..1392b2b63e 100644 --- a/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala +++ b/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.crypto import java.math.BigInteger -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.bouncycastle.crypto.generators.ECKeyPairGenerator import org.bouncycastle.crypto.params.ECKeyGenerationParameters import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala index f5b6caaa19..3c0529f0f1 100644 --- a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala +++ b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala @@ -2,9 +2,9 @@ package io.iohk.ethereum.db.storage import io.iohk.ethereum.ObjectGenerators import io.iohk.ethereum.db.dataSource.EphemDataSource +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network.p2p.messages.CommonMessages import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import org.bouncycastle.util.encoders.Hex import org.scalacheck.Gen import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks diff --git a/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala b/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala index 9f307d48f7..74f8e2e6fc 100644 --- a/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala +++ b/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum.domain import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.domain.SignedTransaction.FirstByteOfAddress -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.vm.Generators import org.scalacheck.Arbitrary import org.bouncycastle.crypto.params.ECPublicKeyParameters diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala index edfbd73495..adcfa6ccd0 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala @@ -5,7 +5,8 @@ import io.iohk.ethereum.crypto.ECDSASignature import io.iohk.ethereum.jsonrpc.CheckpointingService._ import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams -import io.iohk.ethereum.nodebuilder.{ApisBuilder, SecureRandomBuilder} +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.nodebuilder.ApisBuilder import io.iohk.ethereum.utils.{ByteStringUtils, Config} import io.iohk.ethereum.{Fixtures, NormalPatience, crypto} import monix.eval.Task diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala index 6f31476782..6d596376fc 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala @@ -15,8 +15,8 @@ import io.iohk.ethereum.consensus.blocks.{BlockGenerator, PendingBlock} import io.iohk.ethereum.{NormalPatience, Timeouts, WithActorSystemShutDown} import io.iohk.ethereum.crypto.{ECDSASignature, generateKeyPair} import io.iohk.ethereum.jsonrpc.FilterManager.LogFilterLogs +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.transactions.PendingTransactionsManager import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction import io.iohk.ethereum.utils.{FilterConfig, TxPoolConfig} diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala index 4ecec066e2..dedb5a58bc 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala @@ -6,8 +6,8 @@ import java.util.concurrent.atomic.AtomicReference import akka.actor.ActorSystem import akka.testkit.TestProbe import io.iohk.ethereum.jsonrpc.NetService._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network.{Peer, PeerActor, PeerManagerActor} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.{NodeStatus, ServerStatus} import io.iohk.ethereum.{NormalPatience, crypto} import monix.execution.Scheduler.Implicits.global diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala index 52470d2578..32a9f9f60f 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala @@ -6,6 +6,7 @@ import akka.http.scaladsl.server.Route import akka.http.scaladsl.testkit.ScalatestRouteTest import akka.util.ByteString import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher +import io.iohk.ethereum.jsonrpc.security.SSLConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig import io.iohk.ethereum.jsonrpc.{JsonRpcController, JsonRpcHealthChecker, JsonRpcResponse} import monix.eval.Task @@ -98,9 +99,7 @@ class JsonRpcHttpServerSpec extends AnyFlatSpec with Matchers with ScalatestRout override val enabled: Boolean = true override val interface: String = "" override val port: Int = 123 - override val certificateKeyStorePath = None - override val certificateKeyStoreType = None - override val certificatePasswordFile = None + override val sSLConfig: SSLConfig = SSLConfig(???) //TODO override val corsAllowedOrigins = HttpOriginMatcher.* } diff --git a/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala b/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala index 96517cd2a3..778c91060d 100644 --- a/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala +++ b/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.keystore import io.iohk.ethereum.crypto import io.iohk.ethereum.domain.Address -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala b/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala index 606e0263f2..9529f8c24e 100644 --- a/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala +++ b/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala @@ -6,7 +6,7 @@ import java.nio.file.{FileSystemException, FileSystems, Files, Path} import akka.util.ByteString import io.iohk.ethereum.domain.Address import io.iohk.ethereum.keystore.KeyStore.{DecryptionFailed, IOError, KeyNotFound, PassPhraseTooShort} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.utils.{Config, KeyStoreConfig} import org.apache.commons.io.FileUtils import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala b/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala index 99057e7f91..5996a8ebfc 100644 --- a/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala +++ b/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala @@ -13,9 +13,9 @@ import io.iohk.ethereum.consensus.validators.{BlockHeaderValidator, Validators} import io.iohk.ethereum.consensus.{GetBlockHeaderByHash, GetNBlocksBack, TestConsensus} import io.iohk.ethereum.crypto.{generateKeyPair, kec256} import io.iohk.ethereum.domain._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BlockExecutionError.ValidationAfterExecError import io.iohk.ethereum.ledger.Ledger.{PC, PR, VMImpl} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.Config.SyncConfig import io.iohk.ethereum.utils.{BlockchainConfig, Config, DaoForkConfig} import io.iohk.ethereum.vm.{ProgramError, ProgramResult} diff --git a/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala b/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala index 9bd526dd82..346ed397bc 100644 --- a/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala @@ -3,8 +3,8 @@ package io.iohk.ethereum.network import java.io.File import java.nio.file.Files +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.crypto.params.{ECPrivateKeyParameters, ECPublicKeyParameters} import org.scalatest.flatspec.AnyFlatSpec diff --git a/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala b/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala index 4eed6c0590..8f46d0c7f7 100644 --- a/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala @@ -5,8 +5,8 @@ import java.net.URI import akka.util.ByteString import io.iohk.ethereum.crypto._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network.rlpx.{AuthHandshakeSuccess, AuthHandshaker, AuthResponseMessage, Secrets} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import org.bouncycastle.crypto.params.{ECPrivateKeyParameters, ECPublicKeyParameters} import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala b/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala index 3421558210..0ae6c731e5 100644 --- a/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala @@ -2,8 +2,8 @@ package io.iohk.ethereum.network import akka.util.ByteString import io.iohk.ethereum.crypto._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network.rlpx.{AuthHandshaker, AuthInitiateMessage} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.ByteUtils import org.bouncycastle.crypto.generators.ECKeyPairGenerator import org.bouncycastle.crypto.params.{ECKeyGenerationParameters, ECPublicKeyParameters} diff --git a/src/test/scala/io/iohk/ethereum/network/discovery/PeerDiscoveryManagerSpec.scala b/src/test/scala/io/iohk/ethereum/network/discovery/PeerDiscoveryManagerSpec.scala index 248b09b2c4..cabd2ea8ca 100644 --- a/src/test/scala/io/iohk/ethereum/network/discovery/PeerDiscoveryManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/discovery/PeerDiscoveryManagerSpec.scala @@ -2,6 +2,7 @@ package io.iohk.ethereum.network.discovery import java.net.{InetAddress, InetSocketAddress} import java.time.{Clock, Instant, ZoneId} + import akka.actor.ActorSystem import akka.testkit.{TestActorRef, TestProbe} import akka.util.ByteString @@ -10,12 +11,15 @@ import io.iohk.ethereum.NormalPatience import io.iohk.ethereum.blockchain.sync.EphemBlockchainTestSetup import io.iohk.ethereum.network.discovery.DiscoveryListener._ import io.iohk.ethereum.network.discovery.PeerDiscoveryManager.{DiscoveryNodeInfo, PingInfo} -import io.iohk.ethereum.nodebuilder.{NodeKeyBuilder, SecureRandomBuilder} +import io.iohk.ethereum.nodebuilder.NodeKeyBuilder import io.iohk.ethereum.rlp.RLPEncoder import io.iohk.ethereum.utils.{Config, NodeStatus, ServerStatus} import java.util.concurrent.atomic.AtomicReference + +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalamock.scalatest.MockFactory import org.scalatest.concurrent.ScalaFutures + import scala.util.Success import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala index 5391008516..6dd085fcd1 100644 --- a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala @@ -17,9 +17,10 @@ import io.iohk.ethereum.network.p2p.messages.PV62.{BlockHeaders, GetBlockHeaders import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Hello.HelloEnc import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Capability, Disconnect, Hello} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils._ import java.util.concurrent.atomic.AtomicReference + +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala index 6e5c6466f6..d572aa46a4 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala @@ -28,7 +28,7 @@ import io.iohk.ethereum.network.p2p.messages.WireProtocol._ import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerActor, PeerEventBusActor, _} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} import io.iohk.ethereum.{Fixtures, Mocks, Timeouts, WithActorSystemShutDown, crypto} import org.bouncycastle.crypto.AsymmetricCipherKeyPair diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala b/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala index 6a69c3aa6b..4fbf2b9dc3 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala @@ -5,9 +5,9 @@ import java.net.URI import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto._ +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network._ import io.iohk.ethereum.network.rlpx.{AuthHandshakeSuccess, AuthHandshaker, Secrets} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.crypto.params.ECPublicKeyParameters import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala index d5446826d3..2713bb3cf8 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala @@ -6,7 +6,7 @@ import io.iohk.ethereum.domain.{Block, BlockBody, BlockHeader, ChainWeight} import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import org.bouncycastle.util.encoders.Hex import NewBlock._ -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import org.scalatest.funsuite.AnyFunSuite diff --git a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala index 3506a2299d..a3ff5310a7 100644 --- a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala @@ -12,7 +12,7 @@ import io.iohk.ethereum.network.p2p.{MessageDecoder, MessageSerializable} import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Ping import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalamock.scalatest.MockFactory import scala.concurrent.duration.FiniteDuration diff --git a/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala b/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala index b9cbaae7ad..5e3df44dcc 100644 --- a/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala @@ -7,6 +7,7 @@ import akka.pattern.ask import akka.testkit.TestProbe import akka.util.ByteString import io.iohk.ethereum.domain.{Address, SignedTransaction, SignedTransactionWithSender, Transaction} +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import io.iohk.ethereum.network.PeerActor.Status.Handshaked import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent import io.iohk.ethereum.network.PeerManagerActor.Peers @@ -15,7 +16,6 @@ import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions import io.iohk.ethereum.network.{EtcPeerManagerActor, Peer, PeerId, PeerManagerActor} import io.iohk.ethereum.transactions.PendingTransactionsManager._ import io.iohk.ethereum.{NormalPatience, Timeouts, crypto} -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.transactions.SignedTransactionsFilterActor.ProperSignedTransactions import io.iohk.ethereum.utils.TxPoolConfig import org.scalatest.concurrent.ScalaFutures diff --git a/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala b/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala index 0b829bfd4f..cc34d38c53 100644 --- a/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala +++ b/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala @@ -5,10 +5,10 @@ import io.iohk.ethereum.crypto._ import io.iohk.ethereum.domain.{Account, Address, UInt256} import io.iohk.ethereum.Fixtures.{Blocks => BlockFixtures} import MockWorldState._ -import io.iohk.ethereum.nodebuilder.SecureRandomBuilder import io.iohk.ethereum.utils.ByteUtils import org.bouncycastle.util.encoders.Hex import Fixtures.blockchainConfig +import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers From b95c6ec8b74c482df095c25714d044a267619ed8 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Tue, 17 Nov 2020 12:41:07 -0300 Subject: [PATCH 04/13] change certificate config --- src/main/resources/application.conf | 9 ++- .../io/iohk/ethereum/crypto/EcKeyGen.scala | 1 - .../faucet/jsonrpc/FaucetBuilder.scala | 8 ++- .../jsonrpc/jsonrpc/RpcBaseClient.scala | 3 +- .../ethereum/jsonrpc/security/SSLConfig.scala | 34 +++++----- .../jsonrpc/security/SSLContextBuilder.scala | 16 ++++- .../jsonrpc/security/SSLContextFactory.scala | 63 +++++++++---------- .../server/http/JsonRpcHttpServer.scala | 23 ++----- .../server/http/JsonRpcHttpsServer.scala | 4 +- .../conf/rpc-test-private.conf | 4 +- .../server/http/JsonRpcHttpServerSpec.scala | 2 - src/universal/conf/faucet.conf | 9 ++- 12 files changed, 91 insertions(+), 85 deletions(-) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 9df573badd..0d3c13d438 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -159,17 +159,20 @@ mantis { # Listening port of JSON-RPC HTTP(S) endpoint port = 8546 + certificate = null + #certificate { # Path to the keystore storing the certificates (used only for https) # null value indicates HTTPS is not being used - certificate-keystore-path = null + # keystore-path = null # Type of certificate keystore being used # null value indicates HTTPS is not being used - certificate-keystore-type = null + # keystore-type = null # File with the password used for accessing the certificate keystore (used only for https) # null value indicates HTTPS is not being used - certificate-password-file = null + # password-file = null + #} # Domains allowed to query RPC endpoint. Use "*" to enable requests from # any domain. diff --git a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala index 8e22e1ee90..e384779211 100644 --- a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala +++ b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala @@ -2,7 +2,6 @@ package io.iohk.ethereum.crypto import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder - /** * A simple tool to generate and ECDSA key pair. The key pair will be printed in the format: * priv-key-hex (32 bytes) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index 4dbb1059bf..a842b7cda8 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -21,7 +21,11 @@ trait FaucetControllerBuilder { } trait FaucetRpcServiceBuilder { - self: FaucetConfigBuilder with FaucetControllerBuilder with ActorSystemBuilder with SecureRandomBuilder => + self: FaucetConfigBuilder + with FaucetControllerBuilder + with ActorSystemBuilder + with SecureRandomBuilder + with SSLContextBuilder => val keyStore = new KeyStoreImpl( @@ -29,7 +33,7 @@ trait FaucetRpcServiceBuilder { secureRandom ) //TODO: ask secureRandom?? - val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, None) //TODO: maybeSslContext??? + val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, sslContext.toOption) val faucetRpcService = new FaucetRpcService(walletRpcClient, keyStore, faucetConfig) } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala index 9ff76b7d12..e27e9e1555 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala @@ -27,7 +27,8 @@ abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(imp import RpcBaseClient._ //TODO.... - lazy val connectionContext: HttpsConnectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) + lazy val connectionContext: HttpsConnectionContext = + maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) def shutdown(): Unit = { Await.ready(system.terminate(), 5.seconds) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala index 26d420a40f..60ae35c5b5 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala @@ -2,26 +2,28 @@ package io.iohk.ethereum.jsonrpc.security import com.typesafe.config.Config -import scala.util.Try - case class SSLConfig( - certificateKeyStorePath: Option[String], - certificateKeyStoreType: Option[String], - certificatePasswordFile: Option[String] + keyStorePath: String, + keyStoreType: String, + passwordFile: String ) object SSLConfig { - def apply(config: Config): SSLConfig = { - SSLConfig( - certificateKeyStorePath = Try( - config.getString("certificate-keystore-path") - ).toOption, - certificateKeyStoreType = Try( - config.getString("certificate-keystore-type") - ).toOption, - certificatePasswordFile = Try( - config.getString("certificate-password-file") - ).toOption) + + val key = "certificate" + + def apply(config: Config): Option[SSLConfig] = { + if (config.getIsNull(key)) + None + else { + Some( + SSLConfig( + keyStorePath = config.getString("keystore-path"), + keyStoreType = config.getString("keystore-type"), + passwordFile = config.getString("password-file") + ) + ) + } } } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala index 787256bdf7..bc899f6d30 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala @@ -2,13 +2,23 @@ package io.iohk.ethereum.jsonrpc.security import com.typesafe.config.ConfigFactory import javax.net.ssl.SSLContext -case class SSLError(reason: String) //TODO: throwable exception +case class SSLError(reason: String) trait SSLContextBuilder { self: SecureRandomBuilder => private lazy val rpcHttpConfig = ConfigFactory.load().getConfig("mantis.network.rpc.http") - private lazy val sSLConfig: SSLConfig = SSLConfig(rpcHttpConfig) + private lazy val sslConfig: Option[SSLConfig] = SSLConfig(rpcHttpConfig) - lazy val sslContext: Either[SSLError, SSLContext] = SSLContextFactory.createSSLContext(sSLConfig, secureRandom) + lazy val sslContext: Either[SSLError, SSLContext] = + sslConfig + .toRight(SSLError("No SSL config present")) + .flatMap(SSLContextFactory.createSSLContext(_, secureRandom)) match { + case Right(sslConfig) => + log.debug("Loaded ssl config successful") + Right(sslConfig) + case Left(error) => + log.error(s"Loaded ssl config failure - $error") + Left(error) + } } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala index 51124f018d..1c30b92cfe 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala @@ -12,9 +12,9 @@ object SSLContextFactory { def createSSLContext(sSLConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { validateCertificateFiles( - sSLConfig.certificateKeyStorePath, - sSLConfig.certificateKeyStoreType, - sSLConfig.certificatePasswordFile + sSLConfig.keyStorePath, + sSLConfig.keyStoreType, + sSLConfig.passwordFile ).flatMap { case (keystorePath, keystoreType, passwordFile) => val passwordReader = Source.fromFile(passwordFile) try { @@ -29,52 +29,49 @@ object SSLContextFactory { /** * Validates that the keystore certificate file and password file were configured and that the files exists * - * @param maybeKeystorePath, with the path to the certificate keystore if it was configured - * @param maybePasswordFile, with the path to the password file if it was configured + * @param keystorePath with the path to the certificate keystore if it was configured + * @param keystoreType for accessing the keystore with the certificate + * @param passwordFile with the path to the password file if it was configured * @return the certificate path and password file or the error detected */ private def validateCertificateFiles( - maybeKeystorePath: Option[String], - maybeKeystoreType: Option[String], - maybePasswordFile: Option[String] - ): Either[SSLError, (String, String, String)] = - (maybeKeystorePath, maybeKeystoreType, maybePasswordFile) match { - case (Some(keystorePath), Some(keystoreType), Some(passwordFile)) => - val keystoreDirMissing = !new File(keystorePath).isFile - val passwordFileMissing = !new File(passwordFile).isFile - if (keystoreDirMissing && passwordFileMissing) - Left(SSLError("Certificate keystore path and password file configured but files are missing")) - else if (keystoreDirMissing) - Left(SSLError("Certificate keystore path configured but file is missing")) - else if (passwordFileMissing) - Left(SSLError("Certificate password file configured but file is missing")) - else - Right((keystorePath, keystoreType, passwordFile)) - case _ => - Left( - SSLError("HTTPS requires: certificate-keystore-path, certificate-keystore-type and certificate-password-file to be configured") - ) - } + keystorePath: String, + keystoreType: String, + passwordFile: String + ): Either[SSLError, (String, String, String)] = { + val keystoreDirMissing = !new File(keystorePath).isFile + val passwordFileMissing = !new File(passwordFile).isFile + if (keystoreDirMissing && passwordFileMissing) + Left(SSLError("Certificate keystore path and password file configured but files are missing")) + else if (keystoreDirMissing) + Left(SSLError("Certificate keystore path configured but file is missing")) + else if (passwordFileMissing) + Left(SSLError("Certificate password file configured but file is missing")) + else + Right((keystorePath, keystoreType, passwordFile)) + } /** * Constructs the SSL context given a certificate * - * @param certificateKeyStorePath, path to the keystore where the certificate is stored - * @param password for accessing the keystore with the certificate + * @param secureRandom + * @param keyStorePath path to the keystore where the certificate is stored + * @param keyStoreType for accessing the keystore with the certificate + * @param password * @return the SSL context with the obtained certificate or an error if any happened */ private def obtainSSLContext( secureRandom: SecureRandom, - certificateKeyStorePath: String, - certificateKeyStoreType: String, + keyStorePath: String, + keyStoreType: String, password: String ): Either[SSLError, SSLContext] = { val passwordCharArray: Array[Char] = password.toCharArray - val maybeKeyStore: Either[SSLError, KeyStore] = Try(KeyStore.getInstance(certificateKeyStoreType)).toOption - .toRight(SSLError(s"Certificate keystore invalid type set: $certificateKeyStoreType")) + val maybeKeyStore: Either[SSLError, KeyStore] = Try(KeyStore.getInstance(keyStoreType)).toOption + .toRight(SSLError(s"Certificate keystore invalid type set: $keyStoreType")) val keyStoreInitResult: Either[SSLError, KeyStore] = maybeKeyStore.flatMap { keyStore => - val keyStoreFileCreationResult = Option(new FileInputStream(certificateKeyStorePath)) + val keyStoreFileCreationResult = Option(new FileInputStream(keyStorePath)) .toRight(SSLError("Certificate keystore file creation failed")) keyStoreFileCreationResult.flatMap { keyStoreFile => Try(keyStore.load(keyStoreFile, passwordCharArray)) match { diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala index d1147b0ad7..9190bc70ce 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala @@ -12,7 +12,7 @@ import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings import de.heikoseeberger.akkahttpjson4s.Json4sSupport import io.iohk.ethereum.jsonrpc._ -import io.iohk.ethereum.jsonrpc.security.{SSLConfig, SSLError} +import io.iohk.ethereum.jsonrpc.security.SSLError import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.utils.{ConfigUtils, Logger} @@ -106,7 +106,11 @@ object JsonRpcHttpServer extends Logger { config.mode match { case "http" => Right(new BasicJsonRpcHttpServer(jsonRpcController, jsonRpcHealthchecker, config)(actorSystem)) case "https" => - Right(new JsonRpcHttpsServer(jsonRpcController, jsonRpcHealthchecker, config, secureRandom, fSslContext)(actorSystem)) + Right( + new JsonRpcHttpsServer(jsonRpcController, jsonRpcHealthchecker, config, secureRandom, fSslContext)( + actorSystem + ) + ) case _ => Left(s"Cannot start JSON RPC server: Invalid mode ${config.mode} selected") } @@ -115,10 +119,6 @@ object JsonRpcHttpServer extends Logger { val enabled: Boolean val interface: String val port: Int - //val certificateKeyStorePath: Option[String] - //val certificateKeyStoreType: Option[String] - //val certificatePasswordFile: Option[String] - val sSLConfig: SSLConfig val corsAllowedOrigins: HttpOriginMatcher } @@ -135,17 +135,6 @@ object JsonRpcHttpServer extends Logger { override val port: Int = rpcHttpConfig.getInt("port") override val corsAllowedOrigins = ConfigUtils.parseCorsAllowedOrigins(rpcHttpConfig, "cors-allowed-origins") - - override val sSLConfig: SSLConfig = SSLConfig(rpcHttpConfig) - /*override val certificateKeyStorePath: Option[String] = Try( - rpcHttpConfig.getString("certificate-keystore-path") - ).toOption - override val certificateKeyStoreType: Option[String] = Try( - rpcHttpConfig.getString("certificate-keystore-type") - ).toOption - override val certificatePasswordFile: Option[String] = Try( - rpcHttpConfig.getString("certificate-password-file") - ).toOption*/ } } } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala index 182217e444..498a8e44e3 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala @@ -36,7 +36,9 @@ class JsonRpcHttpsServer( case Success(serverBinding) => log.info(s"JSON RPC HTTPS server listening on ${serverBinding.localAddress}") case Failure(ex) => log.error("Cannot start JSON HTTPS RPC server", ex) } - case Left(error) => log.error(s"Cannot start JSON HTTPS RPC server due to: $error") + case Left(error) => + log.error(s"Cannot start JSON HTTPS RPC server due to: $error") + throw new RuntimeException(error.reason) } } diff --git a/src/rpcTest/resources/privateNetConfig/conf/rpc-test-private.conf b/src/rpcTest/resources/privateNetConfig/conf/rpc-test-private.conf index da984edd30..fc9f4b795f 100644 --- a/src/rpcTest/resources/privateNetConfig/conf/rpc-test-private.conf +++ b/src/rpcTest/resources/privateNetConfig/conf/rpc-test-private.conf @@ -48,9 +48,7 @@ mantis { interface = "localhost" port = 8546 - certificate-keystore-path = null - certificate-keystore-type = null - certificate-password-file = null + certificate = null cors-allowed-origins = "*" } diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala index 32a9f9f60f..911646b4ab 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServerSpec.scala @@ -6,7 +6,6 @@ import akka.http.scaladsl.server.Route import akka.http.scaladsl.testkit.ScalatestRouteTest import akka.util.ByteString import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher -import io.iohk.ethereum.jsonrpc.security.SSLConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig import io.iohk.ethereum.jsonrpc.{JsonRpcController, JsonRpcHealthChecker, JsonRpcResponse} import monix.eval.Task @@ -99,7 +98,6 @@ class JsonRpcHttpServerSpec extends AnyFlatSpec with Matchers with ScalatestRout override val enabled: Boolean = true override val interface: String = "" override val port: Int = 123 - override val sSLConfig: SSLConfig = SSLConfig(???) //TODO override val corsAllowedOrigins = HttpOriginMatcher.* } diff --git a/src/universal/conf/faucet.conf b/src/universal/conf/faucet.conf index 9c7ba76184..adce6a64b4 100644 --- a/src/universal/conf/faucet.conf +++ b/src/universal/conf/faucet.conf @@ -62,17 +62,20 @@ mantis { # Listening port of JSON-RPC HTTP(S) endpoint port = 8099 + certificate = null + #certificate { # Path to the keystore storing the certificates (used only for https) # null value indicates HTTPS is not being used - certificate-keystore-path = null + # keystore-path = null # Type of certificate keystore being used # null value indicates HTTPS is not being used - certificate-keystore-type = null + # keystore-type = null # File with the password used for accessing the certificate keystore (used only for https) # null value indicates HTTPS is not being used - certificate-password-file = null + # password-file = null + #} # Domains allowed to query RPC endpoint. Use "*" to enable requests from # any domain. From f7d0e8b6643c1df99beb22f4f2ccd5e438748c0b Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Wed, 18 Nov 2020 13:50:24 -0300 Subject: [PATCH 05/13] change ssl config --- .../scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala index 60ae35c5b5..f11d3a2f86 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala @@ -18,9 +18,9 @@ object SSLConfig { else { Some( SSLConfig( - keyStorePath = config.getString("keystore-path"), - keyStoreType = config.getString("keystore-type"), - passwordFile = config.getString("password-file") + keyStorePath = config.getString("certificate.keystore-path"), + keyStoreType = config.getString("certificate.keystore-type"), + passwordFile = config.getString("certificate.password-file") ) ) } From a2c0f21fff9c665a5e94ca3227d698ce2153a336 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Thu, 19 Nov 2020 12:25:00 -0300 Subject: [PATCH 06/13] change package from json rpc client --- .../faucet/jsonrpc/WalletRpcClient.scala | 6 ++--- .../faucet/jsonrpc/WalletService.scala | 24 +++++++++---------- .../CommonJsonCodecs.scala | 2 +- .../{jsonrpc => client}/RpcBaseClient.scala | 2 +- .../mallet/interpreter/Commands.scala | 2 +- .../ethereum/mallet/service/RpcClient.scala | 2 +- .../ethereum/nodebuilder/NodeBuilder.scala | 1 - .../ethereum/faucet/FaucetHandlerSpec.scala | 9 ++++--- .../faucet/jsonrpc/WalletServiceSpec.scala | 10 ++++---- 9 files changed, 28 insertions(+), 30 deletions(-) rename src/main/scala/io/iohk/ethereum/jsonrpc/{jsonrpc => client}/CommonJsonCodecs.scala (96%) rename src/main/scala/io/iohk/ethereum/jsonrpc/{jsonrpc => client}/RpcBaseClient.scala (98%) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala index 85c0281524..51f2fa0c49 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala @@ -5,8 +5,8 @@ import akka.http.scaladsl.model.Uri import io.circe.syntax._ import akka.util.ByteString import io.iohk.ethereum.domain.Address -import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient -import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient.RpcError +import io.iohk.ethereum.jsonrpc.client.RpcBaseClient +import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.RpcError import io.iohk.ethereum.utils.Logger import javax.net.ssl.SSLContext import monix.eval.Task @@ -18,7 +18,7 @@ class WalletRpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit ec: ExecutionContext ) extends RpcBaseClient(node, maybeSslContext) with Logger { - import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ + import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ def getNonce(address: Address): Task[Either[RpcError, BigInt]] = doRequest[BigInt]("eth_getTransactionCount", List(address.asJson, "latest".asJson)) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala index 2e312b535c..92cdb05bbb 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala @@ -4,7 +4,7 @@ import akka.util.ByteString import cats.data.EitherT import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.faucet.FaucetConfig -import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient.RpcError +import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.RpcError import io.iohk.ethereum.keystore.KeyStore.KeyStoreError import io.iohk.ethereum.keystore.{KeyStore, Wallet} import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc @@ -16,17 +16,17 @@ class WalletService(walletRpcClient: WalletRpcClient, keyStore: KeyStore, config def sendFunds(wallet: Wallet, addressTo: Address): Task[Either[RpcError, ByteString]] = { (for { - nonce <- EitherT(walletRpcClient.getNonce(wallet.address)) - txId <- EitherT(walletRpcClient.sendTransaction(prepareTx(wallet, addressTo, nonce))) - } yield txId).value map { - case Right(txId) => - val txIdHex = s"0x${ByteStringUtils.hash2string(txId)}" - log.info(s"Sending ${config.txValue} ETH to $addressTo in tx: $txIdHex.") - Right(txId) - case Left(error) => - log.error(s"An error occurred while using faucet", error) - Left(error) - } + nonce <- EitherT(walletRpcClient.getNonce(wallet.address)) + txId <- EitherT(walletRpcClient.sendTransaction(prepareTx(wallet, addressTo, nonce))) + } yield txId).value map { + case Right(txId) => + val txIdHex = s"0x${ByteStringUtils.hash2string(txId)}" + log.info(s"Sending ${config.txValue} ETH to $addressTo in tx: $txIdHex.") + Right(txId) + case Left(error) => + log.error(s"An error occurred while using faucet", error) + Left(error) + } } private def prepareTx(wallet: Wallet, targetAddress: Address, nonce: BigInt): ByteString = { diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/CommonJsonCodecs.scala similarity index 96% rename from src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala rename to src/main/scala/io/iohk/ethereum/jsonrpc/client/CommonJsonCodecs.scala index 1bc6d3b110..0904aeeb9b 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/CommonJsonCodecs.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/CommonJsonCodecs.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.jsonrpc +package io.iohk.ethereum.jsonrpc.client import akka.util.ByteString import io.circe._ diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala similarity index 98% rename from src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala rename to src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala index e27e9e1555..453449efd4 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/jsonrpc/RpcBaseClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.jsonrpc +package io.iohk.ethereum.jsonrpc.client import java.io.{PrintWriter, StringWriter} import java.util.UUID diff --git a/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala b/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala index e0d99a8e76..8bc091d5c6 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/interpreter/Commands.scala @@ -6,7 +6,7 @@ import io.circe.syntax._ import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.mallet.common.{StringUtil, Util} import io.iohk.ethereum.mallet.interpreter.Parameter._ -import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ +import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ import io.iohk.ethereum.mallet.service.State import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc import io.iohk.ethereum.rlp diff --git a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala index 8c054cf96e..923622106c 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala @@ -41,7 +41,7 @@ object RpcClient { * Note: the URI schema determines whether HTTP or HTTPS is used */ class RpcClient(node: Uri)(implicit system: ActorSystem, ec: ExecutionContext) { - import io.iohk.ethereum.jsonrpc.jsonrpc.CommonJsonCodecs._ + import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ //TODO: CL option private val httpTimeout = 5.seconds diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index 78e7dc5899..81bf2cc868 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -1,6 +1,5 @@ package io.iohk.ethereum.nodebuilder - import akka.actor.{ActorRef, ActorSystem} import io.iohk.ethereum.blockchain.data.GenesisDataLoader import io.iohk.ethereum.blockchain.sync.{BlockchainHostActor, SyncController} diff --git a/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala b/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala index 8e6d3f7e6a..69cbeb5616 100644 --- a/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala @@ -10,10 +10,9 @@ import io.iohk.ethereum.crypto.{generateKeyPair, keyPairToByteStrings} import io.iohk.ethereum.domain.Address import io.iohk.ethereum.faucet.FaucetHandler.{FaucetHandlerMsg, FaucetHandlerResponse} import io.iohk.ethereum.faucet.jsonrpc.WalletService -import io.iohk.ethereum.jsonrpc.jsonrpc.RpcBaseClient.RpcError +import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.{ParserError, RpcClientError} import io.iohk.ethereum.keystore.KeyStore.DecryptionFailed import io.iohk.ethereum.keystore.Wallet -import io.iohk.ethereum.mallet.common.{ParserError, RpcClientError} import io.iohk.ethereum.{NormalPatience, WithActorSystemShutDown, crypto} import monix.eval.Task import org.bouncycastle.util.encoders.Hex @@ -86,7 +85,7 @@ class FaucetHandlerSpec .returning(Task.pure(Left(errorMessage))) sender.send(faucetHandler, FaucetHandlerMsg.SendFunds(paymentAddress)) - sender.expectMsg(FaucetHandlerResponse.WalletRpcClientError(errorMessage)) + sender.expectMsg(FaucetHandlerResponse.WalletRpcClientError(errorMessage.msg)) } } @@ -95,10 +94,10 @@ class FaucetHandlerSpec val errorMessage = ParserError("error parser") (walletService.sendFunds _) .expects(wallet, paymentAddress) - .returning(Task.pure(Left(errorMessage)))) + .returning(Task.pure(Left(errorMessage))) sender.send(faucetHandler, FaucetHandlerMsg.SendFunds(paymentAddress)) - sender.expectMsg(FaucetHandlerResponse.WalletRpcClientError(errorMessage)) + sender.expectMsg(FaucetHandlerResponse.WalletRpcClientError(errorMessage.msg)) } } } diff --git a/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala b/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala index b27bf209cd..f3681ba6b4 100644 --- a/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala @@ -9,9 +9,9 @@ import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.faucet.{FaucetConfig, SupervisorConfig} import io.iohk.ethereum.keystore.KeyStore.DecryptionFailed import io.iohk.ethereum.keystore.{KeyStore, Wallet} -import io.iohk.ethereum.mallet.service.RpcClient import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc import io.iohk.ethereum.{crypto, rlp} +import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.bouncycastle.util.encoders.Hex import org.scalamock.scalatest.MockFactory @@ -37,8 +37,8 @@ class WalletServiceSpec extends AnyFlatSpec with Matchers with MockFactory with val retTxId = ByteString(Hex.decode("112233")) - (mockRpcClient.getNonce _).expects(config.walletAddress).returning(Right(currentNonce)) - (mockRpcClient.sendTransaction _).expects(ByteString(expectedTx)).returning(Right(retTxId)) + (walletRpcClient.getNonce _).expects(config.walletAddress).returning(Task.pure(Right(currentNonce))) + (walletRpcClient.sendTransaction _).expects(ByteString(expectedTx)).returning(Task.pure(Right(retTxId))) val res = walletService.sendFunds(wallet, Address("0x99")).runSyncUnsafe() @@ -69,7 +69,7 @@ class WalletServiceSpec extends AnyFlatSpec with Matchers with MockFactory with val (prvKey, pubKey) = keyPairToByteStrings(walletKeyPair) val wallet = Wallet(Address(crypto.kec256(pubKey)), prvKey) - val mockRpcClient = mock[RpcClient] + val walletRpcClient = mock[WalletRpcClient] val mockKeyStore = mock[KeyStore] val config: FaucetConfig = FaucetConfig( @@ -87,7 +87,7 @@ class WalletServiceSpec extends AnyFlatSpec with Matchers with MockFactory with shutdownTimeout = 15.seconds ) - val walletService = new WalletService(mockRpcClient, mockKeyStore, config) + val walletService = new WalletService(walletRpcClient, mockKeyStore, config) } } From 6fb247088c2d678a1de6e558c5de99b54aa213da Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Sat, 21 Nov 2020 12:54:28 -0300 Subject: [PATCH 07/13] add new test --- ...lder.scala => FaucetHandlerSelector.scala} | 4 +- .../faucet/jsonrpc/FaucetRpcService.scala | 6 +- .../jsonrpc/client/RpcBaseClient.scala | 1 - .../ethereum/jsonrpc/security/FileUtils.scala | 61 +++++ .../ethereum/jsonrpc/security/SSLConfig.scala | 6 +- .../jsonrpc/security/SSLContextBuilder.scala | 2 +- .../jsonrpc/security/SSLContextFactory.scala | 51 ++-- .../faucet/jsonrpc/WalletServiceSpec.scala | 4 +- .../security/SSLContextFactorySpec.scala | 224 ++++++++++++++++++ 9 files changed, 322 insertions(+), 37 deletions(-) rename src/main/scala/io/iohk/ethereum/faucet/jsonrpc/{FaucetHandlerBuilder.scala => FaucetHandlerSelector.scala} (87%) create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala create mode 100644 src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerSelector.scala similarity index 87% rename from src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerBuilder.scala rename to src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerSelector.scala index d95c26855a..b9fd9259b8 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetHandlerSelector.scala @@ -6,7 +6,7 @@ import akka.util.Timeout import io.iohk.ethereum.faucet.{FaucetConfigBuilder, FaucetHandler, FaucetSupervisor} import monix.eval.Task -trait FaucetHandlerBuilder { +trait FaucetHandlerSelector { self: FaucetConfigBuilder with RetrySupport => val handlerPath = s"user/${FaucetSupervisor.name}/${FaucetHandler.name}" @@ -15,7 +15,7 @@ trait FaucetHandlerBuilder { lazy val handlerTimeout: Timeout = Timeout(faucetConfig.handlerTimeout) - def faucetHandler()(implicit system: ActorSystem): Task[ActorRef] = { + def selectFaucetHandler()(implicit system: ActorSystem): Task[ActorRef] = { Task.deferFuture( retry(() => system.actorSelection(handlerPath).resolveOne(handlerTimeout.duration), attempts, delay)( system.dispatcher, diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala index 6d79431841..3e1f1f0030 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetRpcService.scala @@ -14,20 +14,20 @@ import io.iohk.ethereum.utils.Logger class FaucetRpcService(config: FaucetConfig)(implicit system: ActorSystem) extends FaucetConfigBuilder with RetrySupport - with FaucetHandlerBuilder + with FaucetHandlerSelector with Logger { implicit lazy val actorTimeout: Timeout = Timeout(config.responseTimeout) def sendFunds(sendFundsRequest: SendFundsRequest): ServiceResponse[SendFundsResponse] = - faucetHandler().flatMap(handler => + selectFaucetHandler().flatMap(handler => handler .askFor[Any](FaucetHandlerMsg.SendFunds(sendFundsRequest.address)) .map(handleSendFundsResponse orElse handleErrors) ) def status(statusRequest: StatusRequest): ServiceResponse[StatusResponse] = - faucetHandler() + selectFaucetHandler() .flatMap(handler => handler.askFor[Any](FaucetHandlerMsg.Status)) .map(handleStatusResponse orElse handleErrors) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala index 453449efd4..5a7bfb8056 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala @@ -26,7 +26,6 @@ abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(imp import RpcBaseClient._ - //TODO.... lazy val connectionContext: HttpsConnectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala new file mode 100644 index 0000000000..6829c6b4fb --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala @@ -0,0 +1,61 @@ +package io.iohk.ethereum.jsonrpc.security + +import java.io.{File, FileInputStream} +import java.security.KeyStore + +import io.iohk.ethereum.utils.Logger +import javax.net.ssl.{KeyManager, KeyManagerFactory, TrustManager, TrustManagerFactory} + +import scala.io.{BufferedSource, Source} +import scala.util.Try + +trait FileUtils extends Logger { + + def exist(pathName: String): Boolean = new File(pathName).isFile + + def createFileInputStream(pathName: String): Either[Throwable, FileInputStream] = + Try(new FileInputStream(pathName)).toEither match { + case Right(fileInputStream) => + Option(fileInputStream).map(Right(_)).getOrElse { + log.error("empty fileInputStream") + Left(new RuntimeException("empty fileInputStream")) + } + case Left(error) => + log.error("create file input stream failed", error) + Left(error) + } + + //TODO: remove... + def getPasswordReader(passwordFile: String): BufferedSource = Source.fromFile(passwordFile) + + def loadKeyStore( + keyStoreFile: FileInputStream, + passwordCharArray: Array[Char], + keyStore: KeyStore + ): Either[Throwable, Unit] = + Try(keyStore.load(keyStoreFile, passwordCharArray)).toEither + + def getKeyManager(keyStore: KeyStore, passwordCharArray: Array[Char]): Either[Throwable, Array[KeyManager]] = + Try { + val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") + keyManagerFactory.init(keyStore, passwordCharArray) + keyManagerFactory.getKeyManagers + }.toEither match { + case Right(keyManager) => Right(keyManager) + case Left(error) => + log.error("") //TODO.. + Left(error) + } + + def getTrustManager(keyStore: KeyStore): Either[Throwable, Array[TrustManager]] = Try { + val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") + tmf.init(keyStore) + tmf.getTrustManagers + }.toEither match { + case Right(trustManager) => Right(trustManager) + case Left(error) => + log.error("") //TODO.. + Left(error) + } + +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala index f11d3a2f86..c751c25591 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala @@ -18,9 +18,9 @@ object SSLConfig { else { Some( SSLConfig( - keyStorePath = config.getString("certificate.keystore-path"), - keyStoreType = config.getString("certificate.keystore-type"), - passwordFile = config.getString("certificate.password-file") + keyStorePath = config.getString(s"$key.keystore-path"), + keyStoreType = config.getString(s"$key.keystore-type"), + passwordFile = config.getString(s"$key.password-file") ) ) } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala index bc899f6d30..eb3cf5bbdd 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala @@ -12,7 +12,7 @@ trait SSLContextBuilder { self: SecureRandomBuilder => lazy val sslContext: Either[SSLError, SSLContext] = sslConfig .toRight(SSLError("No SSL config present")) - .flatMap(SSLContextFactory.createSSLContext(_, secureRandom)) match { + .flatMap(SSLContextFactory().createSSLContext(_, secureRandom)) match { case Right(sslConfig) => log.debug("Loaded ssl config successful") Right(sslConfig) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala index 1c30b92cfe..3a7c0276eb 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala @@ -1,14 +1,13 @@ package io.iohk.ethereum.jsonrpc.security -import java.io.{File, FileInputStream} +import java.io.FileInputStream import java.security.{KeyStore, SecureRandom} -import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory} +import javax.net.ssl.SSLContext -import scala.io.Source -import scala.util.{Failure, Success, Try} +import scala.util.Try -object SSLContextFactory { +case class SSLContextFactory() extends FileUtils { def createSSLContext(sSLConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { validateCertificateFiles( @@ -16,7 +15,7 @@ object SSLContextFactory { sSLConfig.keyStoreType, sSLConfig.passwordFile ).flatMap { case (keystorePath, keystoreType, passwordFile) => - val passwordReader = Source.fromFile(passwordFile) + val passwordReader = getPasswordReader(passwordFile) try { val password = passwordReader.getLines().mkString obtainSSLContext(secureRandom, keystorePath, keystoreType, password) @@ -39,8 +38,8 @@ object SSLContextFactory { keystoreType: String, passwordFile: String ): Either[SSLError, (String, String, String)] = { - val keystoreDirMissing = !new File(keystorePath).isFile - val passwordFileMissing = !new File(passwordFile).isFile + val keystoreDirMissing = !exist(keystorePath) + val passwordFileMissing = !exist(passwordFile) if (keystoreDirMissing && passwordFileMissing) Left(SSLError("Certificate keystore path and password file configured but files are missing")) else if (keystoreDirMissing) @@ -71,28 +70,32 @@ object SSLContextFactory { val maybeKeyStore: Either[SSLError, KeyStore] = Try(KeyStore.getInstance(keyStoreType)).toOption .toRight(SSLError(s"Certificate keystore invalid type set: $keyStoreType")) val keyStoreInitResult: Either[SSLError, KeyStore] = maybeKeyStore.flatMap { keyStore => - val keyStoreFileCreationResult = Option(new FileInputStream(keyStorePath)) - .toRight(SSLError("Certificate keystore file creation failed")) + val keyStoreFileCreationResult: Either[SSLError, FileInputStream] = + createFileInputStream(keyStorePath).toOption.toRight(SSLError("Certificate keystore file creation failed")) keyStoreFileCreationResult.flatMap { keyStoreFile => - Try(keyStore.load(keyStoreFile, passwordCharArray)) match { - case Success(_) => Right(keyStore) - case Failure(err) => Left(SSLError(err.getMessage)) + loadKeyStore(keyStoreFile, passwordCharArray, keyStore) match { + case Right(_) => + Right(keyStore) + case Left(err) => + Left(SSLError(err.getMessage)) } } } - keyStoreInitResult.map { ks => - val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") - keyManagerFactory.init(ks, passwordCharArray) - - val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") - tmf.init(ks) - - val sslContext: SSLContext = SSLContext.getInstance("TLS") - sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, secureRandom) - sslContext + keyStoreInitResult.flatMap { ks => + (for { + km <- getKeyManager(ks, passwordCharArray) + tm <- getTrustManager(ks) + } yield (km, tm)) match { + case Right((km, tm)) => + val sslContext: SSLContext = SSLContext.getInstance("TLS") + sslContext.init(km, tm, secureRandom) + Right(sslContext) + case Left(error) => + log.error("Invalid Certificate keystore", error) + Left(SSLError("Invalid Certificate keystore")) + } } - } } diff --git a/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala b/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala index f3681ba6b4..8d6fc57578 100644 --- a/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/faucet/jsonrpc/WalletServiceSpec.scala @@ -2,7 +2,6 @@ package io.iohk.ethereum.faucet.jsonrpc import java.security.SecureRandom -import akka.http.scaladsl.testkit.ScalatestRouteTest import akka.util.ByteString import io.iohk.ethereum.crypto._ import io.iohk.ethereum.domain.{Address, Transaction} @@ -15,13 +14,12 @@ import monix.eval.Task import monix.execution.Scheduler.Implicits.global import org.bouncycastle.util.encoders.Hex import org.scalamock.scalatest.MockFactory -import org.scalatest.concurrent.ScalaFutures import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ -class WalletServiceSpec extends AnyFlatSpec with Matchers with MockFactory with ScalatestRouteTest with ScalaFutures { +class WalletServiceSpec extends AnyFlatSpec with Matchers with MockFactory { "Wallet Service" should "send a transaction" in new TestSetup { diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala new file mode 100644 index 0000000000..6782dda86d --- /dev/null +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala @@ -0,0 +1,224 @@ +package io.iohk.ethereum.jsonrpc.security + +import java.io.{ByteArrayInputStream, File, FileInputStream, FileOutputStream} +import java.security.{KeyStore, SecureRandom} + +import javax.net.ssl.{KeyManager, TrustManager} +import org.scalamock.scalatest.MockFactory +import org.scalatest.BeforeAndAfterAll +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +import scala.io.BufferedSource + +class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory with BeforeAndAfterAll { + + val fileName: String = "temp.txt" + var file: File = _ + + override def beforeAll { + new FileOutputStream(fileName, false).getFD + file = new File(fileName) + } + + override def afterAll { + file.delete() + } + + val keyStorePath = "mantisCA.p12" + val keyStoreType = "pkcs12" + val passwordFile = "password" + + it should "createSSLContext" in new TestSetup( + List(keyStorePath, passwordFile), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) match { + case Right(ssl) => + ssl.getProtocol shouldBe "TLS" + case Left(error) => fail(error.reason) + } + } + + it should "return a Error because keystore path and password are missing" in new TestSetup( + Nil, + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Certificate keystore path and password file configured but files are missing")) + } + + it should "return a Error because keystore path is missing" in new TestSetup( + List(passwordFile), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Certificate keystore path configured but file is missing")) + } + + it should "return a Error because password file is missing" in new TestSetup( + List(keyStorePath), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Certificate password file configured but file is missing")) + } + + it should "return a Error because invalid KeyStore Type" in new TestSetup( + List(keyStorePath, passwordFile), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val invalidKeyStoreType = "invalidkeyStoreType" + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = invalidKeyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError(s"Certificate keystore invalid type set: $invalidKeyStoreType")) + } + + it should "return a Error because keystore file creation failed" in new TestSetup( + List(keyStorePath, passwordFile), + () => Left(new RuntimeException("Certificate keystore file creation failed")), + () => Right(()), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Certificate keystore file creation failed")) + } + + it should "return a Error because failed to load keystore" in new TestSetup( + List(keyStorePath, passwordFile), + () => Right(new FileInputStream(file)), + () => Left(new RuntimeException("Failed to load keyStore")), + () => Right(Array.empty), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Failed to load keyStore")) + } + + it should "return a Error because KeyManager failure" in new TestSetup( + List(keyStorePath, passwordFile), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Left(new RuntimeException("Failed to get KeyManager")), + () => Right(Array.empty) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Invalid Certificate keystore")) + } + + it should "return a Error because TrustManager failure" in new TestSetup( + List(keyStorePath, passwordFile), + () => Right(new FileInputStream(file)), + () => Right(()), + () => Right(Array.empty), + () => Left(new RuntimeException("Failed to get TrustManager")) + ) { + + val sslConfig = SSLConfig( + keyStorePath = keyStorePath, + keyStoreType = keyStoreType, + passwordFile = passwordFile + ) + val response = sSLContextFactory.createSSLContext(sslConfig, new SecureRandom()) + response shouldBe Left(SSLError("Invalid Certificate keystore")) + } + + class TestSetup( + existingFiles: List[String], + fCreateFileInputStream: () => Either[Throwable, FileInputStream], + fLoadKeyStore: () => Either[Throwable, Unit], + fGetKeyManager: () => Either[Throwable, Array[KeyManager]], + fGetTrustManager: () => Either[Throwable, Array[TrustManager]] + ) { + + val sSLContextFactory = new SSLContextFactory { + + override def exist(pathName: String): Boolean = existingFiles.contains(pathName) + + override def createFileInputStream(pathName: String): Either[Throwable, FileInputStream] = + fCreateFileInputStream() + + override def getPasswordReader(passwordFile: String): BufferedSource = new BufferedSource( + new ByteArrayInputStream("password".getBytes) + ) + + override def loadKeyStore( + keyStoreFile: FileInputStream, + passwordCharArray: Array[Char], + keyStore: KeyStore + ): Either[Throwable, Unit] = + fLoadKeyStore() + + override def getKeyManager( + keyStore: KeyStore, + passwordCharArray: Array[Char] + ): Either[Throwable, Array[KeyManager]] = fGetKeyManager() + + override def getTrustManager(keyStore: KeyStore): Either[Throwable, Array[TrustManager]] = + fGetTrustManager() + } + } +} From 0fbeac3d1e6687542140e1ed37f5da739463ec53 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Tue, 24 Nov 2020 13:34:02 -0300 Subject: [PATCH 08/13] improvement in ssl context --- .../ethereum/jsonrpc/security/FileUtils.scala | 35 +-------------- .../jsonrpc/security/KeyStoreUtils.scala | 44 +++++++++++++++++++ .../jsonrpc/security/SSLContextFactory.scala | 38 ++++++++-------- .../security/SSLContextFactorySpec.scala | 2 +- 4 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala index 6829c6b4fb..f96f78fd54 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala @@ -1,10 +1,8 @@ package io.iohk.ethereum.jsonrpc.security import java.io.{File, FileInputStream} -import java.security.KeyStore import io.iohk.ethereum.utils.Logger -import javax.net.ssl.{KeyManager, KeyManagerFactory, TrustManager, TrustManagerFactory} import scala.io.{BufferedSource, Source} import scala.util.Try @@ -25,37 +23,6 @@ trait FileUtils extends Logger { Left(error) } - //TODO: remove... - def getPasswordReader(passwordFile: String): BufferedSource = Source.fromFile(passwordFile) - - def loadKeyStore( - keyStoreFile: FileInputStream, - passwordCharArray: Array[Char], - keyStore: KeyStore - ): Either[Throwable, Unit] = - Try(keyStore.load(keyStoreFile, passwordCharArray)).toEither - - def getKeyManager(keyStore: KeyStore, passwordCharArray: Array[Char]): Either[Throwable, Array[KeyManager]] = - Try { - val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") - keyManagerFactory.init(keyStore, passwordCharArray) - keyManagerFactory.getKeyManagers - }.toEither match { - case Right(keyManager) => Right(keyManager) - case Left(error) => - log.error("") //TODO.. - Left(error) - } - - def getTrustManager(keyStore: KeyStore): Either[Throwable, Array[TrustManager]] = Try { - val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") - tmf.init(keyStore) - tmf.getTrustManagers - }.toEither match { - case Right(trustManager) => Right(trustManager) - case Left(error) => - log.error("") //TODO.. - Left(error) - } + def getReader(file: String): BufferedSource = Source.fromFile(file) } diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala new file mode 100644 index 0000000000..653a74273d --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala @@ -0,0 +1,44 @@ +package io.iohk.ethereum.jsonrpc.security + +import java.io.FileInputStream +import java.security.KeyStore + +import io.iohk.ethereum.utils.Logger +import javax.net.ssl.{KeyManager, KeyManagerFactory, TrustManager, TrustManagerFactory} + +import scala.util.Try + +trait KeyStoreUtils extends Logger { + + lazy val algorithm: String = "SunX509" + + def loadKeyStore( + keyStoreFile: FileInputStream, + passwordCharArray: Array[Char], + keyStore: KeyStore + ): Either[Throwable, Unit] = + Try(keyStore.load(keyStoreFile, passwordCharArray)).toEither + + def getKeyManager(keyStore: KeyStore, passwordCharArray: Array[Char]): Either[Throwable, Array[KeyManager]] = + Try { + val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance(algorithm) + keyManagerFactory.init(keyStore, passwordCharArray) + keyManagerFactory.getKeyManagers + }.toEither match { + case Right(keyManager) => Right(keyManager) + case Left(error) => + log.error("getKeyManagers failure", error) + Left(error) + } + + def getTrustManager(keyStore: KeyStore): Either[Throwable, Array[TrustManager]] = Try { + val tmf: TrustManagerFactory = TrustManagerFactory.getInstance(algorithm) + tmf.init(keyStore) + tmf.getTrustManagers + }.toEither match { + case Right(trustManager) => Right(trustManager) + case Left(error) => + log.error("getTrustManagers failure, error") + Left(error) + } +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala index 3a7c0276eb..932aeebe7d 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala @@ -7,21 +7,25 @@ import javax.net.ssl.SSLContext import scala.util.Try -case class SSLContextFactory() extends FileUtils { +case class SSLContextFactory() extends FileUtils with KeyStoreUtils { - def createSSLContext(sSLConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { - validateCertificateFiles( - sSLConfig.keyStorePath, - sSLConfig.keyStoreType, - sSLConfig.passwordFile - ).flatMap { case (keystorePath, keystoreType, passwordFile) => - val passwordReader = getPasswordReader(passwordFile) - try { - val password = passwordReader.getLines().mkString - obtainSSLContext(secureRandom, keystorePath, keystoreType, password) - } finally { - passwordReader.close() - } + def createSSLContext(sslConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { + for { + _ <- validateCertificateFiles( + sslConfig.keyStorePath, + sslConfig.passwordFile + ) + sslContext <- getSSLContext(sslConfig, secureRandom) + } yield sslContext + } + + private def getSSLContext(sslConfig: SSLConfig, secureRandom: SecureRandom): Either[SSLError, SSLContext] = { + val passwordReader = getReader(sslConfig.passwordFile) + try { + val password = passwordReader.getLines().mkString + obtainSSLContext(secureRandom, sslConfig.keyStorePath, sslConfig.keyStoreType, password) + } finally { + passwordReader.close() } } @@ -29,15 +33,13 @@ case class SSLContextFactory() extends FileUtils { * Validates that the keystore certificate file and password file were configured and that the files exists * * @param keystorePath with the path to the certificate keystore if it was configured - * @param keystoreType for accessing the keystore with the certificate * @param passwordFile with the path to the password file if it was configured * @return the certificate path and password file or the error detected */ private def validateCertificateFiles( keystorePath: String, - keystoreType: String, passwordFile: String - ): Either[SSLError, (String, String, String)] = { + ): Either[SSLError, Unit] = { val keystoreDirMissing = !exist(keystorePath) val passwordFileMissing = !exist(passwordFile) if (keystoreDirMissing && passwordFileMissing) @@ -47,7 +49,7 @@ case class SSLContextFactory() extends FileUtils { else if (passwordFileMissing) Left(SSLError("Certificate password file configured but file is missing")) else - Right((keystorePath, keystoreType, passwordFile)) + Right(()) } /** diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala index 6782dda86d..406182524b 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala @@ -201,7 +201,7 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w override def createFileInputStream(pathName: String): Either[Throwable, FileInputStream] = fCreateFileInputStream() - override def getPasswordReader(passwordFile: String): BufferedSource = new BufferedSource( + override def getReader(passwordFile: String): BufferedSource = new BufferedSource( new ByteArrayInputStream("password".getBytes) ) From 144adb84532ae61ef5072b8ae8ce2afaa062e162 Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Tue, 24 Nov 2020 14:12:55 -0300 Subject: [PATCH 09/13] add tls default folder --- src/main/resources/application.conf | 10 ++++---- .../chains/testnet-internal-genesis.json | 2 +- src/universal/conf/faucet.conf | 12 +++++----- tls/gen-cert.sh | 22 ++++++++++++++++++ tls/mantisCA.p12 | Bin 0 -> 4133 bytes tls/password | 1 + 6 files changed, 35 insertions(+), 12 deletions(-) create mode 100755 tls/gen-cert.sh create mode 100644 tls/mantisCA.p12 create mode 100644 tls/password diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 3fd9e67665..37c2c8e47f 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -170,7 +170,7 @@ mantis { # Choosing https requires creating a certificate and setting up 'certificate-keystore-path' and # 'certificate-password-file' # See: https://github.com/input-output-hk/mantis/wiki/Creating-self-signed-certificate-for-using-JSON-RPC-with-HTTPS - mode = "http" + mode = "https" # Whether to enable JSON-RPC HTTP(S) endpoint enabled = true @@ -185,15 +185,15 @@ mantis { #certificate { # Path to the keystore storing the certificates (used only for https) # null value indicates HTTPS is not being used - # keystore-path = null + # keystore-path = "tls/mantisCA.p12" # Type of certificate keystore being used # null value indicates HTTPS is not being used - # keystore-type = null + # keystore-type = "pkcs12" # File with the password used for accessing the certificate keystore (used only for https) # null value indicates HTTPS is not being used - # password-file = null + # password-file = "tls/password" #} # Domains allowed to query RPC endpoint. Use "*" to enable requests from @@ -284,7 +284,7 @@ mantis { } blockchains { - network = "testnet-internal" + network = "etc" etc {include "chains/etc-chain.conf"} diff --git a/src/main/resources/chains/testnet-internal-genesis.json b/src/main/resources/chains/testnet-internal-genesis.json index b710af8ed9..f5708d5e61 100644 --- a/src/main/resources/chains/testnet-internal-genesis.json +++ b/src/main/resources/chains/testnet-internal-genesis.json @@ -10,7 +10,7 @@ "coinbase": "0x0000000000000000000000000000000000000000", "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "alloc": { - "d1c7b7daf09ee87ff68f2a1e27319ad006ebca93": {"balance": + "d7a681378321f472adffb9fdded2712f677e0ba9": {"balance": "1606938044258990275541962092341162602522202993782792835301376"} } } diff --git a/src/universal/conf/faucet.conf b/src/universal/conf/faucet.conf index 79433ffc8c..05d1099f97 100644 --- a/src/universal/conf/faucet.conf +++ b/src/universal/conf/faucet.conf @@ -4,10 +4,10 @@ faucet { datadir = ${user.home}"/.mantis-faucet" # Wallet address used to send transactions from - wallet-address = "0xd1c7b7daf09ee87ff68f2a1e27319ad006ebca93" + wallet-address = "0x00" # Password to unlock faucet wallet - wallet-password = "12345678" + wallet-password = "" # Path to directory where wallet key is stored keystore-dir = ${faucet.datadir}"/keystore" @@ -69,7 +69,7 @@ mantis { # Choosing https requires creating a certificate and setting up 'certificate-keystore-path' and # 'certificate-password-file' # See: https://github.com/input-output-hk/mantis/wiki/Creating-self-signed-certificate-for-using-JSON-RPC-with-HTTPS - mode = "http" + mode = "https" # Whether to enable JSON-RPC HTTP(S) endpoint enabled = true @@ -84,15 +84,15 @@ mantis { #certificate { # Path to the keystore storing the certificates (used only for https) # null value indicates HTTPS is not being used - # keystore-path = null + # keystore-path = "tls/mantisCA.p12" # Type of certificate keystore being used # null value indicates HTTPS is not being used - # keystore-type = null + # keystore-type = "pkcs12" # File with the password used for accessing the certificate keystore (used only for https) # null value indicates HTTPS is not being used - # password-file = null + # password-file = "tls/password" #} # Domains allowed to query RPC endpoint. Use "*" to enable requests from diff --git a/tls/gen-cert.sh b/tls/gen-cert.sh new file mode 100755 index 0000000000..3c9a54ecd2 --- /dev/null +++ b/tls/gen-cert.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +echo `dirname $0` +cd `dirname $0` + +export PW=`pwgen -Bs 10 1` +echo $PW > ./password + +rm ./mantisCA.p12 + +keytool -genkeypair \ + -keystore mantisCA.p12 \ + -storetype PKCS12 \ + -dname "CN=127.0.0.1" \ + -ext "san=ip:127.0.0.1,dns:localhost" \ + -keypass:env PW \ + -storepass:env PW \ + -keyalg RSA \ + -keysize 4096 \ + -validity 9999 \ + -ext KeyUsage:critical="keyCertSign" \ + -ext BasicConstraints:critical="ca:true" diff --git a/tls/mantisCA.p12 b/tls/mantisCA.p12 new file mode 100644 index 0000000000000000000000000000000000000000..fa57879aa96d1185a53223720985df5bbb834909 GIT binary patch literal 4133 zcmY+GXD}R&)`#s{tM|_8B~cQ)L|r9%XZ1*QQKPKhi6tvRR_|>IqPOVL38MEd{6!E} z2_Zzu&HK*#-aGfhnKSeJ&N<)C%mYPHaRCANP!#0~m{<_4f&N7fAOv7hl%pUN<>@84HMTq@)$>4DQ!wDachdvO3AvQP_=P-12OpN*@Mo4bh#%U)vj8t_w z2PIeV8rVKo>{BJ|Nmm6BvjlNw4gzzk*j_3VTBC&3na$n|aFU$Nm$T_zB-K-dD%!a+ zd>|2gdlR1291I#;?`$x44=>>Lf7zz;s?Qn<9){oJsSCBH>svH|e0#E#ap4gL zjD}=>5bCAw-YF~dIVo=ZBMe(#lq-0du5X`{#ZV?-REy!UQgA1`Z-q)$T#Nw%SCqPP zBzB)FWzv*L?bMA-G+|tyf=n|iuKNivX2d@ahMY@WK5v2lF6rR`KtnTKge>@+SAaKsV!yfYe;5u+Z$tb^~21tRHxj-foCPC z2A=deS|^mNuHJ$S??p{Nr=}KG7*DjWcXzyAr%q#U{e=-%_)z0Fwt2**#<0F z{Pk)1=jmPFi5m*kWU#+5>29S2L?y(e6mpskzO&x^hsV4BfzP#E3k^!12!<#){EdHQ z;5mX*;TR8-%z=(sJ?2RLnHXMv{8Yqpdm}er6l^jweO29V(~)O=B|1&soB6Y16W}M$ zSc(joz<1P?3nln*RV$IxU47VGw|ge^tOhI!o%4!&Z)nnC-JrZb*irSzC9=((<7Wg| zJHcd&O-~VHQ?1@-^$a?C;A@-JH~CSjY6s`6KyEp9BFET}waZi7^U-DK(_=!#m}W!AdL6Ev*<;mzgK`}c^) zS0fSla)e)abM6n9+%c65*Di26<@r8eJQ8yD`2_h>8+pojXUIR=i`J3xvq2Dloac%$ zF>s<*F8g|0uWS~xC>?@fTg7q5Jfw%$AQ&@vJ!W?`X`~|vpLfVfO4CyD%a{Pg;`!BE zS6klkblI72cXg98Ki_*N3-@m2)G;HMgPgN(+7w+j=-7`as z^mz}Ruc2e;EH%518wFj!a^P!Xw)p7pMRQQ^%)TUv&RZFHZt2^AFEh`aYil0-GKQ0S z6RN)b&J~WmJW`qNgT+;1Ig$~=Unbv}?31Q^6ILxEw5SO=ACuv-;C!q|;PhkGwt7a3bs!dWsMURS`ch!ZNu;yNr;` zEjU*%n+cRkqcAws>~E^!)In)&JK|s>iZ^&E@VsPcOM3ba-bBl8KF_;yOKuAdb7L(P z+uT8eO6rmcYvGzfbRNc_kwNX(>zv$A2J_j=ob*Jg z8~UKtCqzsIHL6eEh3!-zAxJgqPRW!C#WKr99&?o_(|tVqZN+`1N9~ zAlh*pT_GM0uK8kMegH43POfXRU)=VM0)ZX~r4m#yRa1R?U8?KzP6JsmUtQB=;y_rw zvMrb@qj#W#m+P67DYDmqQVxhC1Q{pXnX0 zW{Wf*khOEgrN&Adb(HMIY|FeeX*JXddDXUi63*-Pt+&AYBD0k%1;9KM>nztzR^V*X zzFFim<>j}=ijx$CQ~`bqNQBT^jU`cVOe zTNkv>?q4K0|-@pN4De_*fu!+{gbye4h6i9o! z!14N?WV=L#UU{m#bYxv#^gr7Z$_Q~hT z)i<7!8Z4d()IlB!1^$d;VlEv`--y+6dQuhi2=M&Jh;T}CE$c=oP}B(R;${|ej*Pu$ z%C^pys(8{@30cjaK$n@m>iHh7L^oVqBYB3m8_1A-W*B(^{&3d32VZ>i=56DosEkBL z7Unff9?JZ0RU@W@k+GBDx#I=ly})z83xaa}C!&YZfoP0f+#NV!5>N?IF$pm-X-P>a z6h$!i?;%1k7De#sFX{yX@cy>;|0IC_@;mVV_+9<>vf0D5-Uzwnl+cbMPe||(3Df`j z-Afd~OJCY(Dam+zvh8~$MC{-5Hq+SvLMm~T*Ug&k%#5rlwp&(JPLL@LgiZnHxmm?M zsS&X7g=>av8*REUf|aU{>XbIwF@uV!Ct3Dka`m0$(R35%8#`Qkd|UtO*{B|0`eDAeUI+dSDjCpD+%(VeQf6jQsv_VOvLN9^B)I%8}-i#C6 z>(ID+bdc_Q0L9~(&WXn~{19{K84fqMSTd>B$ruPv*hv*b)`wjj#xhro1w>FkhlHHA zF=j|3!$gf~5?-B-_*tIh^4@LQL~vrfWEo=W9aB+}WL@?XtndjXb0Su+&yJe}gX5-5 zc2|#W_MEIdY3E;L^kWT=7HG*5KU#E%6N0~IUSsdbgvMs=k z>6^JZ)RRh%WTf=Iw?i^bl|)jMkEe250uMJ>zMyT_9BY;Ht08{7l9Z|SDd7?wTxhMm0S!rsCbf5pcZ`ZfFC&3t&t;d5 z;4bEOW>(vUmcZ`b%aZ2)Yg_3*Yh5>QzbTe#?M#ioCcuq0Dd>OF70I||k6OO?HeLNb zi~M_3@nqvM=Q_VP+3@3CpJW0+3&MsgXQxogxy1q8PCg~oYZdP|u~z!En3LD4B>jT$ zdvN4#jOm5&VL0z_!oE~MjdKx@W>{)&%FeSV;p0+nMmSG14uf=+Ot~+}B=H9y(B;%a zp@D2QZ~yc|U2`Ld$IC-J^ZbpN9np{1NhbdJC9qGKIwhSw*MolcIZXIGKXy?Qsa}IYT5DakUBdS%tULF65yYzFv=WV+?+bVWr`?Lf*sW$S@>9At|Yz8}6e072N zqh34wT5$yNxy9%ra5NC0xkQto^d!OJ%PeN(>(R4r-6$5UU5%I44Ao+q3FOh#Md{(4C`EIU_yP@hBoPI=U)&z`G_ Date: Tue, 24 Nov 2020 17:42:21 -0300 Subject: [PATCH 10/13] add new tls config from rpc client --- .../vm/PrecompiledContractsSpecEvm.scala | 2 +- .../ethereum/sync/util/CommonFakePeer.scala | 2 +- .../txExecTest/util/DumpChainApp.scala | 2 +- .../io/iohk/ethereum/crypto/EcKeyGen.scala | 2 +- .../faucet/jsonrpc/FaucetBuilder.scala | 9 +++---- .../FaucetSSLContextRpcClientBuilder.scala | 24 +++++++++++++++++++ .../server/http/JsonRpcHttpServer.scala | 2 +- .../server/http/JsonRpcHttpsServer.scala | 2 +- .../network/discovery/Secp256k1SigAlg.scala | 2 +- .../ethereum/nodebuilder/NodeBuilder.scala | 2 +- .../{jsonrpc => }/security/FileUtils.scala | 2 +- .../security/KeyStoreUtils.scala | 2 +- .../{jsonrpc => }/security/SSLConfig.scala | 2 +- .../security/SSLContextBuilder.scala | 2 +- .../security/SSLContextFactory.scala | 2 +- .../security/SecureRandomBuilder.scala | 2 +- .../scala/io/iohk/ethereum/BlockHelpers.scala | 2 +- .../sync/regular/RegularSyncFixtures.scala | 2 +- .../validators/BlockValidatorSpec.scala | 2 +- ...ockWithCheckpointHeaderValidatorSpec.scala | 2 +- .../ethereum/crypto/ECDSASignatureSpec.scala | 2 +- .../iohk/ethereum/crypto/ECIESCoderSpec.scala | 2 +- .../db/storage/BlockBodiesStorageSpec.scala | 2 +- .../domain/SignedTransactionSpec.scala | 2 +- .../jsonrpc/CheckpointingJRCSpec.scala | 2 +- .../ethereum/jsonrpc/FilterManagerSpec.scala | 2 +- .../ethereum/jsonrpc/NetServiceSpec.scala | 2 +- .../ethereum/keystore/EncryptedKeySpec.scala | 2 +- .../ethereum/keystore/KeyStoreImplSpec.scala | 2 +- .../ethereum/ledger/LedgerTestSetup.scala | 2 +- .../AsymmetricCipherKeyPairLoaderSpec.scala | 2 +- .../ethereum/network/AuthHandshakerSpec.scala | 2 +- .../network/AuthInitiateMessageSpec.scala | 2 +- .../handshaker/EtcHandshakerSpec.scala | 2 +- .../ethereum/network/p2p/PeerActorSpec.scala | 2 +- .../network/p2p/SecureChannelSetup.scala | 2 +- .../network/p2p/messages/NewBlockSpec.scala | 2 +- .../rlpx/RLPxConnectionHandlerSpec.scala | 2 +- .../security/SSLContextFactorySpec.scala | 2 +- .../PendingTransactionsManagerSpec.scala | 2 +- .../vm/PrecompiledContractsSpec.scala | 2 +- src/universal/conf/faucet.conf | 17 +++++++++++++ 42 files changed, 85 insertions(+), 43 deletions(-) create mode 100644 src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/FileUtils.scala (94%) rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/KeyStoreUtils.scala (97%) rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/SSLConfig.scala (92%) rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/SSLContextBuilder.scala (94%) rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/SSLContextFactory.scala (98%) rename src/main/scala/io/iohk/ethereum/{jsonrpc => }/security/SecureRandomBuilder.scala (95%) rename src/test/scala/io/iohk/ethereum/{jsonrpc => }/security/SSLContextFactorySpec.scala (99%) diff --git a/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala b/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala index a13897423e..888124c107 100644 --- a/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala +++ b/src/evmTest/scala/io/iohk/ethereum/vm/PrecompiledContractsSpecEvm.scala @@ -4,7 +4,7 @@ import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto._ import io.iohk.ethereum.domain.SignedTransaction.{FirstByteOfAddress, LastByteOfAddress} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.vm.utils.EvmTestEnv import org.bouncycastle.crypto.params.ECPublicKeyParameters import org.scalatest.funsuite.AnyFunSuite diff --git a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala index f0a59b0bf1..22ff21a758 100644 --- a/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala +++ b/src/it/scala/io/iohk/ethereum/sync/util/CommonFakePeer.scala @@ -14,7 +14,7 @@ import io.iohk.ethereum.db.dataSource.{RocksDbConfig, RocksDbDataSource} import io.iohk.ethereum.db.storage.pruning.{ArchivePruning, PruningMode} import io.iohk.ethereum.db.storage.{AppStateStorage, Namespaces} import io.iohk.ethereum.domain.{Block, Blockchain, BlockchainImpl, ChainWeight} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.ledger.InMemoryWorldStateProxy import io.iohk.ethereum.mpt.MerklePatriciaTrie import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo diff --git a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala index 8865c8eccd..5fa7ca8974 100644 --- a/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala +++ b/src/it/scala/io/iohk/ethereum/txExecTest/util/DumpChainApp.scala @@ -19,7 +19,7 @@ import io.iohk.ethereum.network.p2p.EthereumMessageDecoder import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerEventBusActor, PeerManagerActor} import io.iohk.ethereum.nodebuilder.{AuthHandshakerBuilder, NodeKeyBuilder} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} import java.util.concurrent.atomic.AtomicReference diff --git a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala index e384779211..695557efd0 100644 --- a/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala +++ b/src/main/scala/io/iohk/ethereum/crypto/EcKeyGen.scala @@ -1,6 +1,6 @@ package io.iohk.ethereum.crypto -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder /** * A simple tool to generate and ECDSA key pair. The key pair will be printed in the format: diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index 3c132bc883..89581b802f 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.faucet.jsonrpc import akka.actor.ActorSystem import io.iohk.ethereum.faucet.{FaucetConfigBuilder, FaucetSupervisor} -import io.iohk.ethereum.jsonrpc.security.{SSLContextBuilder, SecureRandomBuilder} +import io.iohk.ethereum.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer @@ -28,15 +28,15 @@ trait FaucetRpcServiceBuilder { with ActorSystemBuilder with SecureRandomBuilder with ShutdownHookBuilder - with SSLContextBuilder => + with FaucetSSLContextRpcClientBuilder => val keyStore = new KeyStoreImpl( KeyStoreConfig.customKeyStoreConfig(faucetConfig.keyStoreDir), secureRandom - ) //TODO: ask secureRandom?? + ) - val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, sslContext.toOption) + val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, sslContextRPCClient.toOption) val walletService = new WalletService(walletRpcClient, keyStore, faucetConfig) val faucetSupervisor: FaucetSupervisor = new FaucetSupervisor(walletService, faucetConfig, shutdown)(system) val faucetRpcService = new FaucetRpcService(faucetConfig) @@ -108,6 +108,7 @@ class FaucetServer with JsonRpcConfigBuilder with SecureRandomBuilder with FaucetControllerBuilder + with FaucetSSLContextRpcClientBuilder with FaucetRpcServiceBuilder with FaucetJsonRpcHealthCheckBuilder with FaucetJsonRpcControllerBuilder diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala new file mode 100644 index 0000000000..7915240b42 --- /dev/null +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala @@ -0,0 +1,24 @@ +package io.iohk.ethereum.faucet.jsonrpc + +import com.typesafe.config.ConfigFactory +import io.iohk.ethereum.security.{SSLConfig, SSLContextFactory, SSLError, SecureRandomBuilder} +import javax.net.ssl.SSLContext + +trait FaucetSSLContextRpcClientBuilder { + self: SecureRandomBuilder => + + private lazy val sslConfig: Option[SSLConfig] = SSLConfig(ConfigFactory.load().getConfig("faucet")) + + lazy val sslContextRPCClient: Either[SSLError, SSLContext] = + sslConfig + .toRight(SSLError("No SSL config present")) + .flatMap(SSLContextFactory().createSSLContext(_, secureRandom)) match { + case Right(sslConfig) => + log.debug("Loaded ssl config successful") + Right(sslConfig) + case Left(error) => + log.error(s"Loaded ssl config failure - $error") + Left(error) + } + +} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala index 9190bc70ce..020f077eb7 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpServer.scala @@ -12,7 +12,7 @@ import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings import de.heikoseeberger.akkahttpjson4s.Json4sSupport import io.iohk.ethereum.jsonrpc._ -import io.iohk.ethereum.jsonrpc.security.SSLError +import io.iohk.ethereum.security.SSLError import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.utils.{ConfigUtils, Logger} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala index 498a8e44e3..aae0f4d441 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala @@ -6,7 +6,7 @@ import akka.actor.ActorSystem import akka.http.scaladsl.{ConnectionContext, Http} import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher import io.iohk.ethereum.jsonrpc.JsonRpcHealthChecker -import io.iohk.ethereum.jsonrpc.security.SSLError +import io.iohk.ethereum.security.SSLError import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig import io.iohk.ethereum.utils.Logger diff --git a/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala b/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala index 09864a3fc9..ff4a7e0073 100644 --- a/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala +++ b/src/main/scala/io/iohk/ethereum/network/discovery/Secp256k1SigAlg.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum.network.discovery import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto.ECDSASignature -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.scalanet.discovery.crypto.{PrivateKey, PublicKey, SigAlg, Signature} import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.crypto.params.ECPublicKeyParameters diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index 81bf2cc868..f3e1fd6d07 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -11,7 +11,7 @@ import io.iohk.ethereum.db.storage.pruning.PruningMode import io.iohk.ethereum.domain._ import io.iohk.ethereum.jsonrpc.NetService.NetServiceConfig import io.iohk.ethereum.jsonrpc._ -import io.iohk.ethereum.jsonrpc.security.{SSLContextBuilder, SecureRandomBuilder} +import io.iohk.ethereum.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala b/src/main/scala/io/iohk/ethereum/security/FileUtils.scala similarity index 94% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala rename to src/main/scala/io/iohk/ethereum/security/FileUtils.scala index f96f78fd54..905fc13e24 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/FileUtils.scala +++ b/src/main/scala/io/iohk/ethereum/security/FileUtils.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import java.io.{File, FileInputStream} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala b/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala similarity index 97% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala rename to src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala index 653a74273d..ad8fbace29 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/KeyStoreUtils.scala +++ b/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import java.io.FileInputStream import java.security.KeyStore diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala similarity index 92% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala rename to src/main/scala/io/iohk/ethereum/security/SSLConfig.scala index c751c25591..3cd34df1ba 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLConfig.scala +++ b/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import com.typesafe.config.Config diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala similarity index 94% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala rename to src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala index eb3cf5bbdd..dddb6d4aa6 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import com.typesafe.config.ConfigFactory import javax.net.ssl.SSLContext diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala b/src/main/scala/io/iohk/ethereum/security/SSLContextFactory.scala similarity index 98% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala rename to src/main/scala/io/iohk/ethereum/security/SSLContextFactory.scala index 932aeebe7d..299b448ad9 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactory.scala +++ b/src/main/scala/io/iohk/ethereum/security/SSLContextFactory.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import java.io.FileInputStream import java.security.{KeyStore, SecureRandom} diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala b/src/main/scala/io/iohk/ethereum/security/SecureRandomBuilder.scala similarity index 95% rename from src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala rename to src/main/scala/io/iohk/ethereum/security/SecureRandomBuilder.scala index f7021186b3..0c02c1d19c 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/security/SecureRandomBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/security/SecureRandomBuilder.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import java.security.SecureRandom diff --git a/src/test/scala/io/iohk/ethereum/BlockHelpers.scala b/src/test/scala/io/iohk/ethereum/BlockHelpers.scala index 1ea621c329..05667b39f1 100644 --- a/src/test/scala/io/iohk/ethereum/BlockHelpers.scala +++ b/src/test/scala/io/iohk/ethereum/BlockHelpers.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum import akka.util.ByteString import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.domain.{Address, Block, BlockBody, SignedTransaction, Transaction} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.bouncycastle.crypto.AsymmetricCipherKeyPair import mouse.all._ diff --git a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala index ff6a0c0ca7..dd549d3130 100644 --- a/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala +++ b/src/test/scala/io/iohk/ethereum/blockchain/sync/regular/RegularSyncFixtures.scala @@ -15,7 +15,7 @@ import io.iohk.ethereum.blockchain.sync._ import io.iohk.ethereum.consensus.blocks.CheckpointBlockGenerator import io.iohk.ethereum.domain.BlockHeaderImplicits._ import io.iohk.ethereum.domain._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.ledger._ import io.iohk.ethereum.network.EtcPeerManagerActor.PeerInfo import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent.MessageFromPeer diff --git a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala index dbd07329c3..f1b7926fa9 100644 --- a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockValidatorSpec.scala @@ -7,7 +7,7 @@ import io.iohk.ethereum.consensus.validators.std.StdBlockValidator import io.iohk.ethereum.consensus.validators.std.StdBlockValidator._ import io.iohk.ethereum.crypto import io.iohk.ethereum.domain._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter import org.bouncycastle.util.encoders.Hex import org.scalatest.flatspec.AnyFlatSpec diff --git a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala index 9c2bb37f83..d968ef39e0 100644 --- a/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/consensus/validators/BlockWithCheckpointHeaderValidatorSpec.scala @@ -9,7 +9,7 @@ import io.iohk.ethereum.crypto.ECDSASignature import io.iohk.ethereum.crypto.ECDSASignatureImplicits.ECDSASignatureOrdering import io.iohk.ethereum.domain.BlockHeader.HeaderExtraFields.HefPostEcip1097 import io.iohk.ethereum.domain._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter import io.iohk.ethereum.nodebuilder.BlockchainConfigBuilder import io.iohk.ethereum.utils.{BlockchainConfig, ByteStringUtils} diff --git a/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala b/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala index 4280d91c79..83f1338495 100644 --- a/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala +++ b/src/test/scala/io/iohk/ethereum/crypto/ECDSASignatureSpec.scala @@ -1,7 +1,7 @@ package io.iohk.ethereum.crypto import akka.util.ByteString -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalacheck.Arbitrary import org.scalacheck.Arbitrary.arbitrary import org.bouncycastle.crypto.params.ECPublicKeyParameters diff --git a/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala b/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala index 1392b2b63e..d28341cb1e 100644 --- a/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala +++ b/src/test/scala/io/iohk/ethereum/crypto/ECIESCoderSpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.crypto import java.math.BigInteger -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.bouncycastle.crypto.generators.ECKeyPairGenerator import org.bouncycastle.crypto.params.ECKeyGenerationParameters import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala index 3c0529f0f1..e5f1bef985 100644 --- a/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala +++ b/src/test/scala/io/iohk/ethereum/db/storage/BlockBodiesStorageSpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.db.storage import io.iohk.ethereum.ObjectGenerators import io.iohk.ethereum.db.dataSource.EphemDataSource -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network.p2p.messages.CommonMessages import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala b/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala index 74f8e2e6fc..b70f3e8678 100644 --- a/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala +++ b/src/test/scala/io/iohk/ethereum/domain/SignedTransactionSpec.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum.domain import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto.generateKeyPair import io.iohk.ethereum.domain.SignedTransaction.FirstByteOfAddress -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.vm.Generators import org.scalacheck.Arbitrary import org.bouncycastle.crypto.params.ECPublicKeyParameters diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala index adcfa6ccd0..7ddbd22f8b 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/CheckpointingJRCSpec.scala @@ -5,7 +5,7 @@ import io.iohk.ethereum.crypto.ECDSASignature import io.iohk.ethereum.jsonrpc.CheckpointingService._ import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.JsonRpcError.InvalidParams -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.nodebuilder.ApisBuilder import io.iohk.ethereum.utils.{ByteStringUtils, Config} import io.iohk.ethereum.{Fixtures, NormalPatience, crypto} diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala index 6d596376fc..c44ed7a17c 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/FilterManagerSpec.scala @@ -15,7 +15,7 @@ import io.iohk.ethereum.consensus.blocks.{BlockGenerator, PendingBlock} import io.iohk.ethereum.{NormalPatience, Timeouts, WithActorSystemShutDown} import io.iohk.ethereum.crypto.{ECDSASignature, generateKeyPair} import io.iohk.ethereum.jsonrpc.FilterManager.LogFilterLogs -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.ledger.BloomFilter import io.iohk.ethereum.transactions.PendingTransactionsManager import io.iohk.ethereum.transactions.PendingTransactionsManager.PendingTransaction diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala b/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala index dedb5a58bc..f8c2d8869e 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala +++ b/src/test/scala/io/iohk/ethereum/jsonrpc/NetServiceSpec.scala @@ -6,7 +6,7 @@ import java.util.concurrent.atomic.AtomicReference import akka.actor.ActorSystem import akka.testkit.TestProbe import io.iohk.ethereum.jsonrpc.NetService._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network.{Peer, PeerActor, PeerManagerActor} import io.iohk.ethereum.utils.{NodeStatus, ServerStatus} import io.iohk.ethereum.{NormalPatience, crypto} diff --git a/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala b/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala index 778c91060d..63cf897332 100644 --- a/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala +++ b/src/test/scala/io/iohk/ethereum/keystore/EncryptedKeySpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.keystore import io.iohk.ethereum.crypto import io.iohk.ethereum.domain.Address -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala b/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala index 9529f8c24e..343a5e78e1 100644 --- a/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala +++ b/src/test/scala/io/iohk/ethereum/keystore/KeyStoreImplSpec.scala @@ -6,7 +6,7 @@ import java.nio.file.{FileSystemException, FileSystems, Files, Path} import akka.util.ByteString import io.iohk.ethereum.domain.Address import io.iohk.ethereum.keystore.KeyStore.{DecryptionFailed, IOError, KeyNotFound, PassPhraseTooShort} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.utils.{Config, KeyStoreConfig} import org.apache.commons.io.FileUtils import org.bouncycastle.util.encoders.Hex diff --git a/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala b/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala index 7cdeea8bad..1705442915 100644 --- a/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala +++ b/src/test/scala/io/iohk/ethereum/ledger/LedgerTestSetup.scala @@ -15,7 +15,7 @@ import io.iohk.ethereum.domain._ import io.iohk.ethereum.ledger.BlockExecutionError.ValidationAfterExecError import io.iohk.ethereum.ledger.Ledger.{PC, PR, VMImpl} import io.iohk.ethereum.mpt.MerklePatriciaTrie -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.utils.Config.SyncConfig import io.iohk.ethereum.utils.{BlockchainConfig, Config, DaoForkConfig} import io.iohk.ethereum.vm.{ProgramError, ProgramResult} diff --git a/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala b/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala index 346ed397bc..afd8c86cc4 100644 --- a/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AsymmetricCipherKeyPairLoaderSpec.scala @@ -3,7 +3,7 @@ package io.iohk.ethereum.network import java.io.File import java.nio.file.Files -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network import org.bouncycastle.crypto.AsymmetricCipherKeyPair import org.bouncycastle.crypto.params.{ECPrivateKeyParameters, ECPublicKeyParameters} diff --git a/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala b/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala index 8f46d0c7f7..135cebeee3 100644 --- a/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AuthHandshakerSpec.scala @@ -5,7 +5,7 @@ import java.net.URI import akka.util.ByteString import io.iohk.ethereum.crypto._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network.rlpx.{AuthHandshakeSuccess, AuthHandshaker, AuthResponseMessage, Secrets} import org.bouncycastle.crypto.params.{ECPrivateKeyParameters, ECPublicKeyParameters} import org.bouncycastle.crypto.AsymmetricCipherKeyPair diff --git a/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala b/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala index 0ae6c731e5..803d6ab6bd 100644 --- a/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/AuthInitiateMessageSpec.scala @@ -2,7 +2,7 @@ package io.iohk.ethereum.network import akka.util.ByteString import io.iohk.ethereum.crypto._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network.rlpx.{AuthHandshaker, AuthInitiateMessage} import io.iohk.ethereum.utils.ByteUtils import org.bouncycastle.crypto.generators.ECKeyPairGenerator diff --git a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala index 6dd085fcd1..7b19705b6f 100644 --- a/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/handshaker/EtcHandshakerSpec.scala @@ -20,7 +20,7 @@ import io.iohk.ethereum.network.p2p.messages.WireProtocol.{Capability, Disconnec import io.iohk.ethereum.utils._ import java.util.concurrent.atomic.AtomicReference -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala index d572aa46a4..13f8043ee3 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/PeerActorSpec.scala @@ -28,7 +28,7 @@ import io.iohk.ethereum.network.p2p.messages.WireProtocol._ import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration import io.iohk.ethereum.network.{ForkResolver, PeerActor, PeerEventBusActor, _} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.utils.{BlockchainConfig, Config, NodeStatus, ServerStatus} import io.iohk.ethereum.{Fixtures, Mocks, Timeouts, WithActorSystemShutDown, crypto} import org.bouncycastle.crypto.AsymmetricCipherKeyPair diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala b/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala index 4fbf2b9dc3..55b5e3b3cb 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/SecureChannelSetup.scala @@ -5,7 +5,7 @@ import java.net.URI import akka.util.ByteString import io.iohk.ethereum.crypto import io.iohk.ethereum.crypto._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network._ import io.iohk.ethereum.network.rlpx.{AuthHandshakeSuccess, AuthHandshaker, Secrets} import org.bouncycastle.crypto.AsymmetricCipherKeyPair diff --git a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala index 2713bb3cf8..a10da43a99 100644 --- a/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/p2p/messages/NewBlockSpec.scala @@ -6,7 +6,7 @@ import io.iohk.ethereum.domain.{Block, BlockBody, BlockHeader, ChainWeight} import io.iohk.ethereum.network.p2p.messages.CommonMessages.NewBlock import org.bouncycastle.util.encoders.Hex import NewBlock._ -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import org.scalatest.funsuite.AnyFunSuite diff --git a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala index a3ff5310a7..50dce6c24d 100644 --- a/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/network/rlpx/RLPxConnectionHandlerSpec.scala @@ -12,7 +12,7 @@ import io.iohk.ethereum.network.p2p.{MessageDecoder, MessageSerializable} import io.iohk.ethereum.network.p2p.messages.Versions import io.iohk.ethereum.network.p2p.messages.WireProtocol.Ping import io.iohk.ethereum.network.rlpx.RLPxConnectionHandler.RLPxConfiguration -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalamock.scalatest.MockFactory import scala.concurrent.duration.FiniteDuration diff --git a/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala b/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala similarity index 99% rename from src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala rename to src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala index 406182524b..c505cd1942 100644 --- a/src/test/scala/io/iohk/ethereum/jsonrpc/security/SSLContextFactorySpec.scala +++ b/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala @@ -1,4 +1,4 @@ -package io.iohk.ethereum.jsonrpc.security +package io.iohk.ethereum.security import java.io.{ByteArrayInputStream, File, FileInputStream, FileOutputStream} import java.security.{KeyStore, SecureRandom} diff --git a/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala b/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala index 5e3df44dcc..ce300f2eb1 100644 --- a/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/transactions/PendingTransactionsManagerSpec.scala @@ -7,7 +7,7 @@ import akka.pattern.ask import akka.testkit.TestProbe import akka.util.ByteString import io.iohk.ethereum.domain.{Address, SignedTransaction, SignedTransactionWithSender, Transaction} -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import io.iohk.ethereum.network.PeerActor.Status.Handshaked import io.iohk.ethereum.network.PeerEventBusActor.PeerEvent import io.iohk.ethereum.network.PeerManagerActor.Peers diff --git a/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala b/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala index cc34d38c53..e339f909ea 100644 --- a/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala +++ b/src/test/scala/io/iohk/ethereum/vm/PrecompiledContractsSpec.scala @@ -8,7 +8,7 @@ import MockWorldState._ import io.iohk.ethereum.utils.ByteUtils import org.bouncycastle.util.encoders.Hex import Fixtures.blockchainConfig -import io.iohk.ethereum.jsonrpc.security.SecureRandomBuilder +import io.iohk.ethereum.security.SecureRandomBuilder import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks import org.scalatest.funsuite.AnyFunSuite import org.scalatest.matchers.should.Matchers diff --git a/src/universal/conf/faucet.conf b/src/universal/conf/faucet.conf index 559b18ea17..4b9a2a6fda 100644 --- a/src/universal/conf/faucet.conf +++ b/src/universal/conf/faucet.conf @@ -24,6 +24,22 @@ faucet { # Address of Ethereum node used to send the transaction rpc-address = "http://127.0.0.1:8546/" + # certificate of Ethereum node used to send the transaction when use HTTP(S) + certificate = null + #certificate { + # Path to the keystore storing the certificates (used only for https) + # null value indicates HTTPS is not being used + # keystore-path = "tls/mantisCA.p12" + + # Type of certificate keystore being used + # null value indicates HTTPS is not being used + # keystore-type = "pkcs12" + + # File with the password used for accessing the certificate keystore (used only for https) + # null value indicates HTTPS is not being used + # password-file = "tls/password" + #} + # How often can a single IP address send a request min-request-interval = 1.minute @@ -80,6 +96,7 @@ mantis { # Listening port of JSON-RPC HTTP(S) endpoint port = 8099 + # certificate when use JSON-RPC HTTP(S) certificate = null #certificate { # Path to the keystore storing the certificates (used only for https) From c0f313f20119df4f5a3b63b53fa59cdc567bb89e Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Thu, 26 Nov 2020 17:17:07 -0300 Subject: [PATCH 11/13] fix and add README TLS config --- README.md | 36 ++++++++ .../iohk/ethereum/faucet/FaucetConfig.scala | 2 +- .../faucet/jsonrpc/FaucetBuilder.scala | 12 +-- .../FaucetSSLContextRpcClientBuilder.scala | 24 ----- .../faucet/jsonrpc/WalletRpcClient.scala | 6 +- .../faucet/jsonrpc/WalletService.scala | 2 +- .../{RpcBaseClient.scala => RpcClient.scala} | 10 +-- .../server/http/JsonRpcHttpsServer.scala | 6 +- .../io/iohk/ethereum/mallet/main/Mallet.scala | 4 +- ...{RpcClient.scala => RpcClientMallet.scala} | 11 +-- .../iohk/ethereum/mallet/service/State.scala | 4 +- .../ethereum/nodebuilder/NodeBuilder.scala | 2 +- .../io/iohk/ethereum/security/FileUtils.scala | 2 +- .../ethereum/security/KeyStoreUtils.scala | 4 +- .../io/iohk/ethereum/security/SSLConfig.scala | 7 +- .../ethereum/security/SSLContextBuilder.scala | 7 +- src/test/resources/application.conf | 5 +- .../ethereum/faucet/FaucetHandlerSpec.scala | 2 +- .../security/SSLContextFactorySpec.scala | 90 +++++++++---------- src/universal/conf/faucet.conf | 38 ++++---- 20 files changed, 145 insertions(+), 129 deletions(-) delete mode 100644 src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala rename src/main/scala/io/iohk/ethereum/jsonrpc/client/{RpcBaseClient.scala => RpcClient.scala} (92%) rename src/main/scala/io/iohk/ethereum/mallet/service/{RpcClient.scala => RpcClientMallet.scala} (90%) diff --git a/README.md b/README.md index 2b70d9199c..5c44217d7e 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,42 @@ projectRoot $ docker build -f ./docker/monitoring-client.Dockerfile -t mantis-mo projectRoot $ docker run --network=host mantis-monitoring-client ``` +### TLS setup + +Both the JSON RPC (on the node and faucet) can be additionally protected using TLS. +On the development environment it's already properly configured with a development certificate. + +#### Generating a new certificate + +If a new certificate is required, create a new keystore with a certificate by running `./tls/gen-cert.sh` + +#### Configuring the node + +1. Configure the certificate and password file to be used at `mantis.network.rpc.http.certificate` key on the `application.conf` file: + + keystore-path: path to the keystore storing the certificates (if generated through our script they are by default located in "./tls/mantisCA.p12") + keystore-type: type of certificate keystore being used (if generated through our script use "pkcs12") + password-file: path to the file with the password used for accessing the certificate keystore (if generated through our script they are by default located in "./tls/password") +2. Enable TLS in specific config: + - For JSON RPC: `mantis.network.rpc.http.mode=https` + +#### Configuring the faucet + +1. Configure the certificate and password file to be used at `mantis.network.rpc.http.certificate` key on the `faucet.conf` file: + + keystore-path: path to the keystore storing the certificates (if generated through our script they are by default located in "./tls/mantisCA.p12") + keystore-type: type of certificate keystore being used (if generated through our script use "pkcs12") + password-file: path to the file with the password used for accessing the certificate keystore (if generated through our script they are by default located in "./tls/password") +2. Enable TLS in specific config: + - For JSON RPC: `mantis.network.rpc.http.mode=https` +3. Configure the certificate used from RpcClient to connect with the node. Necessary if the node uses http secure. + This certificate and password file to be used at `faucet.rpc-client.certificate` key on the `faucet.conf` file: + + keystore-path: path to the keystore storing the certificates + keystore-type: type of certificate keystore being used (if generated through our script use "pkcs12") + password-file: path to the file with the password used for accessing the certificate keystore + + ### Feedback Feedback gratefully received through the Ethereum Classic Forum (http://forum.ethereumclassic.org/) diff --git a/src/main/scala/io/iohk/ethereum/faucet/FaucetConfig.scala b/src/main/scala/io/iohk/ethereum/faucet/FaucetConfig.scala index a66c91cf26..ad0030d639 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/FaucetConfig.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/FaucetConfig.scala @@ -36,7 +36,7 @@ object FaucetConfig { txGasPrice = faucetConfig.getLong("tx-gas-price"), txGasLimit = faucetConfig.getLong("tx-gas-limit"), txValue = faucetConfig.getLong("tx-value"), - rpcAddress = faucetConfig.getString("rpc-address"), + rpcAddress = faucetConfig.getString("rpc-client.rpc-address"), keyStoreDir = faucetConfig.getString("keystore-dir"), minRequestInterval = faucetConfig.getDuration("min-request-interval").toMillis.millis, handlerTimeout = faucetConfig.getDuration("handler-timeout").toMillis.millis, diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index 89581b802f..eb8efe12fb 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -2,11 +2,11 @@ package io.iohk.ethereum.faucet.jsonrpc import akka.actor.ActorSystem import io.iohk.ethereum.faucet.{FaucetConfigBuilder, FaucetSupervisor} -import io.iohk.ethereum.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.jsonrpc.server.controllers.ApisBase import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController.JsonRpcConfig import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer import io.iohk.ethereum.keystore.KeyStoreImpl +import io.iohk.ethereum.security.{SSLContextBuilder, SecureRandomBuilder} import io.iohk.ethereum.utils.{KeyStoreConfig, Logger} import scala.concurrent.Await @@ -28,7 +28,7 @@ trait FaucetRpcServiceBuilder { with ActorSystemBuilder with SecureRandomBuilder with ShutdownHookBuilder - with FaucetSSLContextRpcClientBuilder => + with SSLContextBuilder => val keyStore = new KeyStoreImpl( @@ -36,7 +36,8 @@ trait FaucetRpcServiceBuilder { secureRandom ) - val walletRpcClient: WalletRpcClient = new WalletRpcClient(faucetConfig.rpcAddress, sslContextRPCClient.toOption) + val walletRpcClient: WalletRpcClient = + new WalletRpcClient(faucetConfig.rpcAddress, sslContext("faucet.rpc-client").toOption) val walletService = new WalletService(walletRpcClient, keyStore, faucetConfig) val faucetSupervisor: FaucetSupervisor = new FaucetSupervisor(walletService, faucetConfig, shutdown)(system) val faucetRpcService = new FaucetRpcService(faucetConfig) @@ -83,7 +84,7 @@ trait FaucetJsonRpcHttpServerBuilder { faucetJsonRpcHealthCheck, jsonRpcConfig.httpServerConfig, secureRandom, - () => sslContext + () => sslContext("mantis.network.rpc.http") ) } @@ -107,12 +108,11 @@ class FaucetServer with ApisBuilder with JsonRpcConfigBuilder with SecureRandomBuilder + with SSLContextBuilder with FaucetControllerBuilder - with FaucetSSLContextRpcClientBuilder with FaucetRpcServiceBuilder with FaucetJsonRpcHealthCheckBuilder with FaucetJsonRpcControllerBuilder - with SSLContextBuilder with FaucetJsonRpcHttpServerBuilder with ShutdownHookBuilder with Logger { diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala deleted file mode 100644 index 7915240b42..0000000000 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetSSLContextRpcClientBuilder.scala +++ /dev/null @@ -1,24 +0,0 @@ -package io.iohk.ethereum.faucet.jsonrpc - -import com.typesafe.config.ConfigFactory -import io.iohk.ethereum.security.{SSLConfig, SSLContextFactory, SSLError, SecureRandomBuilder} -import javax.net.ssl.SSLContext - -trait FaucetSSLContextRpcClientBuilder { - self: SecureRandomBuilder => - - private lazy val sslConfig: Option[SSLConfig] = SSLConfig(ConfigFactory.load().getConfig("faucet")) - - lazy val sslContextRPCClient: Either[SSLError, SSLContext] = - sslConfig - .toRight(SSLError("No SSL config present")) - .flatMap(SSLContextFactory().createSSLContext(_, secureRandom)) match { - case Right(sslConfig) => - log.debug("Loaded ssl config successful") - Right(sslConfig) - case Left(error) => - log.error(s"Loaded ssl config failure - $error") - Left(error) - } - -} diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala index 51f2fa0c49..0c9a7c2cc6 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala @@ -5,8 +5,8 @@ import akka.http.scaladsl.model.Uri import io.circe.syntax._ import akka.util.ByteString import io.iohk.ethereum.domain.Address -import io.iohk.ethereum.jsonrpc.client.RpcBaseClient -import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.RpcError +import io.iohk.ethereum.jsonrpc.client.RpcClient +import io.iohk.ethereum.jsonrpc.client.RpcClient.RpcError import io.iohk.ethereum.utils.Logger import javax.net.ssl.SSLContext import monix.eval.Task @@ -16,7 +16,7 @@ import scala.concurrent.ExecutionContext class WalletRpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit system: ActorSystem, ec: ExecutionContext -) extends RpcBaseClient(node, maybeSslContext) +) extends RpcClient(node, maybeSslContext) with Logger { import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala index 92cdb05bbb..f83669b8d7 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala @@ -4,7 +4,7 @@ import akka.util.ByteString import cats.data.EitherT import io.iohk.ethereum.domain.{Address, Transaction} import io.iohk.ethereum.faucet.FaucetConfig -import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.RpcError +import io.iohk.ethereum.jsonrpc.client.RpcClient.RpcError import io.iohk.ethereum.keystore.KeyStore.KeyStoreError import io.iohk.ethereum.keystore.{KeyStore, Wallet} import io.iohk.ethereum.network.p2p.messages.CommonMessages.SignedTransactions.SignedTransactionEnc diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala similarity index 92% rename from src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala rename to src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala index 5a7bfb8056..57a285c059 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcBaseClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala @@ -19,12 +19,12 @@ import monix.eval.Task import scala.concurrent.duration._ import scala.concurrent.{Await, ExecutionContext} -abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit +abstract class RpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit system: ActorSystem, ec: ExecutionContext ) extends Logger { - import RpcBaseClient._ + import RpcClient._ lazy val connectionContext: HttpsConnectionContext = maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) @@ -61,8 +61,8 @@ abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(imp Task .deferFuture(for { - resp <- Http().singleRequest(request, connectionContext) - data <- Unmarshal(resp.entity).to[String] + response <- Http().singleRequest(request, connectionContext) + data <- Unmarshal(response.entity).to[String] } yield parse(data).left.map(e => RpcClientError(e.message))) .onErrorHandle { ex: Throwable => Left(RpcClientError(s"RPC request failed: ${exceptionToString(ex)}")) @@ -87,7 +87,7 @@ abstract class RpcBaseClient(node: Uri, maybeSslContext: Option[SSLContext])(imp } -object RpcBaseClient { +object RpcClient { type RpcResponse[T] = Task[Either[RpcError, T]] type Secrets = Map[String, Json] diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala index aae0f4d441..c837e4c184 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/server/http/JsonRpcHttpsServer.scala @@ -20,13 +20,13 @@ class JsonRpcHttpsServer( val jsonRpcHealthChecker: JsonRpcHealthChecker, config: JsonRpcHttpServerConfig, secureRandom: SecureRandom, - fSslContext: () => Either[SSLError, SSLContext] + getSSLContext: () => Either[SSLError, SSLContext] )(implicit val actorSystem: ActorSystem) extends JsonRpcHttpServer with Logger { def run(): Unit = { - val maybeHttpsContext = fSslContext().map(sslContext => ConnectionContext.httpsServer(sslContext)) + val maybeHttpsContext = getSSLContext().map(sslContext => ConnectionContext.httpsServer(sslContext)) maybeHttpsContext match { case Right(httpsContext) => @@ -38,7 +38,7 @@ class JsonRpcHttpsServer( } case Left(error) => log.error(s"Cannot start JSON HTTPS RPC server due to: $error") - throw new RuntimeException(error.reason) + throw new IllegalStateException(error.reason) } } diff --git a/src/main/scala/io/iohk/ethereum/mallet/main/Mallet.scala b/src/main/scala/io/iohk/ethereum/mallet/main/Mallet.scala index 6c3d2d5782..135ae8aced 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/main/Mallet.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/main/Mallet.scala @@ -5,7 +5,7 @@ import java.time.Instant import io.iohk.ethereum.keystore.KeyStoreImpl import io.iohk.ethereum.mallet.interpreter.Interpreter -import io.iohk.ethereum.mallet.service.{RpcClient, State} +import io.iohk.ethereum.mallet.service.{RpcClientMallet, State} import io.iohk.ethereum.utils.KeyStoreConfig import scala.annotation.tailrec @@ -23,7 +23,7 @@ object Mallet extends App { private val initialState = { new State( shell, - RpcClient(clOptions.node), + RpcClientMallet(clOptions.node), new KeyStoreImpl(KeyStoreConfig.customKeyStoreConfig(clOptions.dataDir), new SecureRandom()), clOptions.account, None, diff --git a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClientMallet.scala similarity index 90% rename from src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala rename to src/main/scala/io/iohk/ethereum/mallet/service/RpcClientMallet.scala index 923622106c..10b4d5e4dd 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/service/RpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/service/RpcClientMallet.scala @@ -19,20 +19,21 @@ import scala.concurrent.duration._ import scala.concurrent.{Await, ExecutionContext, Future} import scala.util.{Failure, Success, Try} -object RpcClient { +//TODO: change it class name. Because we have pending remove it. Task: https://jira.iohk.io/browse/ETCM-423 +object RpcClientMallet { /** * This factory method is defining an ActorSystem, ActorMaterializer and ExecutionContext for - * the [[RpcClient]]. To customize these dependencies use [[RpcClient]]'s constructor + * the [[RpcClientMallet]]. To customize these dependencies use [[RpcClientMallet]]'s constructor */ - def apply(node: Uri): RpcClient = { + def apply(node: Uri): RpcClientMallet = { // TODO: CL option to enable akka logging val akkaConfig = ConfigFactory.load("mallet") implicit val system = ActorSystem("mallet_rpc", akkaConfig) implicit val ec = scala.concurrent.ExecutionContext.Implicits.global - new RpcClient(node) + new RpcClientMallet(node) } } @@ -40,7 +41,7 @@ object RpcClient { * Talks to a node over HTTP(S) JSON-RPC * Note: the URI schema determines whether HTTP or HTTPS is used */ -class RpcClient(node: Uri)(implicit system: ActorSystem, ec: ExecutionContext) { +class RpcClientMallet(node: Uri)(implicit system: ActorSystem, ec: ExecutionContext) { import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ //TODO: CL option diff --git a/src/main/scala/io/iohk/ethereum/mallet/service/State.scala b/src/main/scala/io/iohk/ethereum/mallet/service/State.scala index f1843f17b1..d73bb0ec05 100644 --- a/src/main/scala/io/iohk/ethereum/mallet/service/State.scala +++ b/src/main/scala/io/iohk/ethereum/mallet/service/State.scala @@ -9,7 +9,7 @@ import io.iohk.ethereum.keystore.KeyStore /** Immutable representation of application state, which is changed and used by certain commands */ class State( val passwordReader: PasswordReader, - val rpcClient: RpcClient, + val rpcClient: RpcClientMallet, val keyStore: KeyStore, val selectedAccount: Option[Address], val unlockedKey: Option[ByteString], @@ -18,7 +18,7 @@ class State( def copy( passwordReader: PasswordReader = passwordReader, - rpcClient: RpcClient = rpcClient, + rpcClient: RpcClientMallet = rpcClient, keyStore: KeyStore = keyStore, selectedAccount: Option[Address] = selectedAccount, unlockedKey: Option[ByteString] = unlockedKey, diff --git a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala index f3e1fd6d07..5b9d68d9d8 100644 --- a/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/nodebuilder/NodeBuilder.scala @@ -468,7 +468,7 @@ trait JSONRpcHttpServerBuilder { jsonRpcHealthChecker, jsonRpcConfig.httpServerConfig, secureRandom, - () => sslContext + () => sslContext("mantis.network.rpc.http") ) } diff --git a/src/main/scala/io/iohk/ethereum/security/FileUtils.scala b/src/main/scala/io/iohk/ethereum/security/FileUtils.scala index 905fc13e24..243f4e4c53 100644 --- a/src/main/scala/io/iohk/ethereum/security/FileUtils.scala +++ b/src/main/scala/io/iohk/ethereum/security/FileUtils.scala @@ -16,7 +16,7 @@ trait FileUtils extends Logger { case Right(fileInputStream) => Option(fileInputStream).map(Right(_)).getOrElse { log.error("empty fileInputStream") - Left(new RuntimeException("empty fileInputStream")) + Left(new IllegalStateException("empty fileInputStream")) } case Left(error) => log.error("create file input stream failed", error) diff --git a/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala b/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala index ad8fbace29..dd0e0297b6 100644 --- a/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala +++ b/src/main/scala/io/iohk/ethereum/security/KeyStoreUtils.scala @@ -27,7 +27,7 @@ trait KeyStoreUtils extends Logger { }.toEither match { case Right(keyManager) => Right(keyManager) case Left(error) => - log.error("getKeyManagers failure", error) + log.error("getKeyManager failure", error) Left(error) } @@ -38,7 +38,7 @@ trait KeyStoreUtils extends Logger { }.toEither match { case Right(trustManager) => Right(trustManager) case Left(error) => - log.error("getTrustManagers failure, error") + log.error("getTrustManager failure", error) Left(error) } } diff --git a/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala b/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala index 3cd34df1ba..371d253e5d 100644 --- a/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala +++ b/src/main/scala/io/iohk/ethereum/security/SSLConfig.scala @@ -16,11 +16,12 @@ object SSLConfig { if (config.getIsNull(key)) None else { + val certificateConfig = config.getConfig(key) Some( SSLConfig( - keyStorePath = config.getString(s"$key.keystore-path"), - keyStoreType = config.getString(s"$key.keystore-type"), - passwordFile = config.getString(s"$key.password-file") + keyStorePath = certificateConfig.getString("keystore-path"), + keyStoreType = certificateConfig.getString("keystore-type"), + passwordFile = certificateConfig.getString("password-file") ) ) } diff --git a/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala b/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala index dddb6d4aa6..7054da67ea 100644 --- a/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/security/SSLContextBuilder.scala @@ -6,11 +6,8 @@ case class SSLError(reason: String) trait SSLContextBuilder { self: SecureRandomBuilder => - private lazy val rpcHttpConfig = ConfigFactory.load().getConfig("mantis.network.rpc.http") - private lazy val sslConfig: Option[SSLConfig] = SSLConfig(rpcHttpConfig) - - lazy val sslContext: Either[SSLError, SSLContext] = - sslConfig + def sslContext(key: String): Either[SSLError, SSLContext] = + SSLConfig(ConfigFactory.load().getConfig(key)) .toRight(SSLError("No SSL config present")) .flatMap(SSLContextFactory().createSSLContext(_, secureRandom)) match { case Right(sslConfig) => diff --git a/src/test/resources/application.conf b/src/test/resources/application.conf index e95ea3c57f..079c19fc5b 100644 --- a/src/test/resources/application.conf +++ b/src/test/resources/application.conf @@ -151,7 +151,10 @@ faucet { tx-value = 1000000000000000000 - rpc-address = "http://127.0.0.1:8546/" + rpc-client { + rpc-address = "http://127.0.0.1:8546/" + certificate = null + } min-request-interval = 1.minute diff --git a/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala b/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala index 69cbeb5616..077479d944 100644 --- a/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala +++ b/src/test/scala/io/iohk/ethereum/faucet/FaucetHandlerSpec.scala @@ -10,7 +10,7 @@ import io.iohk.ethereum.crypto.{generateKeyPair, keyPairToByteStrings} import io.iohk.ethereum.domain.Address import io.iohk.ethereum.faucet.FaucetHandler.{FaucetHandlerMsg, FaucetHandlerResponse} import io.iohk.ethereum.faucet.jsonrpc.WalletService -import io.iohk.ethereum.jsonrpc.client.RpcBaseClient.{ParserError, RpcClientError} +import io.iohk.ethereum.jsonrpc.client.RpcClient.{ParserError, RpcClientError} import io.iohk.ethereum.keystore.KeyStore.DecryptionFailed import io.iohk.ethereum.keystore.Wallet import io.iohk.ethereum.{NormalPatience, WithActorSystemShutDown, crypto} diff --git a/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala b/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala index c505cd1942..a797c26096 100644 --- a/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala +++ b/src/test/scala/io/iohk/ethereum/security/SSLContextFactorySpec.scala @@ -30,11 +30,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w val passwordFile = "password" it should "createSSLContext" in new TestSetup( - List(keyStorePath, passwordFile), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -50,11 +50,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because keystore path and password are missing" in new TestSetup( - Nil, - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = Nil, + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -67,11 +67,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because keystore path is missing" in new TestSetup( - List(passwordFile), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -84,11 +84,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because password file is missing" in new TestSetup( - List(keyStorePath), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(keyStorePath), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -101,11 +101,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because invalid KeyStore Type" in new TestSetup( - List(keyStorePath, passwordFile), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val invalidKeyStoreType = "invalidkeyStoreType" @@ -119,11 +119,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because keystore file creation failed" in new TestSetup( - List(keyStorePath, passwordFile), - () => Left(new RuntimeException("Certificate keystore file creation failed")), - () => Right(()), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Left(new RuntimeException("Certificate keystore file creation failed")), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -136,11 +136,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because failed to load keystore" in new TestSetup( - List(keyStorePath, passwordFile), - () => Right(new FileInputStream(file)), - () => Left(new RuntimeException("Failed to load keyStore")), - () => Right(Array.empty), - () => Right(Array.empty) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Left(new RuntimeException("Failed to load keyStore")), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -153,11 +153,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because KeyManager failure" in new TestSetup( - List(keyStorePath, passwordFile), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Left(new RuntimeException("Failed to get KeyManager")), - () => Right(Array.empty) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Left(new RuntimeException("Failed to get KeyManager")), + fGetTrustManager = () => Right(Array.empty) ) { val sslConfig = SSLConfig( @@ -170,11 +170,11 @@ class SSLContextFactorySpec extends AnyFlatSpec with Matchers with MockFactory w } it should "return a Error because TrustManager failure" in new TestSetup( - List(keyStorePath, passwordFile), - () => Right(new FileInputStream(file)), - () => Right(()), - () => Right(Array.empty), - () => Left(new RuntimeException("Failed to get TrustManager")) + existingFiles = List(keyStorePath, passwordFile), + fCreateFileInputStream = () => Right(new FileInputStream(file)), + fLoadKeyStore = () => Right(()), + fGetKeyManager = () => Right(Array.empty), + fGetTrustManager = () => Left(new RuntimeException("Failed to get TrustManager")) ) { val sslConfig = SSLConfig( diff --git a/src/universal/conf/faucet.conf b/src/universal/conf/faucet.conf index 4b9a2a6fda..cab8873ac4 100644 --- a/src/universal/conf/faucet.conf +++ b/src/universal/conf/faucet.conf @@ -21,24 +21,26 @@ faucet { # Transaction value tx-value = 1000000000000000000 - # Address of Ethereum node used to send the transaction - rpc-address = "http://127.0.0.1:8546/" - - # certificate of Ethereum node used to send the transaction when use HTTP(S) - certificate = null - #certificate { - # Path to the keystore storing the certificates (used only for https) - # null value indicates HTTPS is not being used - # keystore-path = "tls/mantisCA.p12" - - # Type of certificate keystore being used - # null value indicates HTTPS is not being used - # keystore-type = "pkcs12" - - # File with the password used for accessing the certificate keystore (used only for https) - # null value indicates HTTPS is not being used - # password-file = "tls/password" - #} + rpc-client { + # Address of Ethereum node used to send the transaction + rpc-address = "http://127.0.0.1:8546/" + + # certificate of Ethereum node used to send the transaction when use HTTP(S) + certificate = null + #certificate { + # Path to the keystore storing the certificates (used only for https) + # null value indicates HTTPS is not being used + # keystore-path = "tls/mantisCA.p12" + + # Type of certificate keystore being used + # null value indicates HTTPS is not being used + # keystore-type = "pkcs12" + + # File with the password used for accessing the certificate keystore (used only for https) + # null value indicates HTTPS is not being used + # password-file = "tls/password" + #} + } # How often can a single IP address send a request min-request-interval = 1.minute From ae51850349b1bd027f6fbee9424084978438dcaa Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Fri, 27 Nov 2020 12:47:39 -0300 Subject: [PATCH 12/13] change rpcclient --- .../ethereum/faucet/jsonrpc/FaucetBuilder.scala | 2 +- .../ethereum/faucet/jsonrpc/WalletRpcClient.scala | 5 +++-- .../iohk/ethereum/jsonrpc/client/RpcClient.scala | 15 +++++++-------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala index eb8efe12fb..10857f77d8 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/FaucetBuilder.scala @@ -37,7 +37,7 @@ trait FaucetRpcServiceBuilder { ) val walletRpcClient: WalletRpcClient = - new WalletRpcClient(faucetConfig.rpcAddress, sslContext("faucet.rpc-client").toOption) + new WalletRpcClient(faucetConfig.rpcAddress, () => sslContext("faucet.rpc-client")) val walletService = new WalletService(walletRpcClient, keyStore, faucetConfig) val faucetSupervisor: FaucetSupervisor = new FaucetSupervisor(walletService, faucetConfig, shutdown)(system) val faucetRpcService = new FaucetRpcService(faucetConfig) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala index 0c9a7c2cc6..b896feab81 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala @@ -7,16 +7,17 @@ import akka.util.ByteString import io.iohk.ethereum.domain.Address import io.iohk.ethereum.jsonrpc.client.RpcClient import io.iohk.ethereum.jsonrpc.client.RpcClient.RpcError +import io.iohk.ethereum.security.SSLError import io.iohk.ethereum.utils.Logger import javax.net.ssl.SSLContext import monix.eval.Task import scala.concurrent.ExecutionContext -class WalletRpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit +class WalletRpcClient(node: Uri, fSslContext: () => Either[SSLError, SSLContext])(implicit system: ActorSystem, ec: ExecutionContext -) extends RpcClient(node, maybeSslContext) +) extends RpcClient(node, fSslContext) with Logger { import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala index 57a285c059..1df4841c12 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala @@ -12,25 +12,24 @@ import io.circe.parser.parse import io.circe.syntax._ import io.circe.{Decoder, Json} import io.iohk.ethereum.jsonrpc.JsonRpcError +import io.iohk.ethereum.security.SSLError import io.iohk.ethereum.utils.Logger import javax.net.ssl.SSLContext import monix.eval.Task -import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.ExecutionContext -abstract class RpcClient(node: Uri, maybeSslContext: Option[SSLContext])(implicit +abstract class RpcClient(node: Uri, fSslContext: () => Either[SSLError, SSLContext])(implicit system: ActorSystem, ec: ExecutionContext ) extends Logger { import RpcClient._ - lazy val connectionContext: HttpsConnectionContext = - maybeSslContext.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) - - def shutdown(): Unit = { - Await.ready(system.terminate(), 5.seconds) + lazy val connectionContext: HttpsConnectionContext = if (node.scheme.startsWith("https")) { + fSslContext().toOption.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) + } else { + Http().defaultClientHttpsContext } protected def doRequest[T: Decoder](method: String, args: Seq[Json]): RpcResponse[T] = { From 91b18abcb159a246c94f6fd1f9ddf83f206418cb Mon Sep 17 00:00:00 2001 From: Maximiliano Biandratti Date: Fri, 27 Nov 2020 16:58:00 -0300 Subject: [PATCH 13/13] change name ssl function --- .../io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala | 4 ++-- .../scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala | 2 +- .../scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala index b896feab81..88bc075c2c 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletRpcClient.scala @@ -14,10 +14,10 @@ import monix.eval.Task import scala.concurrent.ExecutionContext -class WalletRpcClient(node: Uri, fSslContext: () => Either[SSLError, SSLContext])(implicit +class WalletRpcClient(node: Uri, getSSLContext: () => Either[SSLError, SSLContext])(implicit system: ActorSystem, ec: ExecutionContext -) extends RpcClient(node, fSslContext) +) extends RpcClient(node, getSSLContext) with Logger { import io.iohk.ethereum.jsonrpc.client.CommonJsonCodecs._ diff --git a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala index f83669b8d7..d6e7de85c3 100644 --- a/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala +++ b/src/main/scala/io/iohk/ethereum/faucet/jsonrpc/WalletService.scala @@ -21,7 +21,7 @@ class WalletService(walletRpcClient: WalletRpcClient, keyStore: KeyStore, config } yield txId).value map { case Right(txId) => val txIdHex = s"0x${ByteStringUtils.hash2string(txId)}" - log.info(s"Sending ${config.txValue} ETH to $addressTo in tx: $txIdHex.") + log.info(s"Sending ${config.txValue} ETC to $addressTo in tx: $txIdHex.") Right(txId) case Left(error) => log.error(s"An error occurred while using faucet", error) diff --git a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala index 1df4841c12..d56c85cfd6 100644 --- a/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala +++ b/src/main/scala/io/iohk/ethereum/jsonrpc/client/RpcClient.scala @@ -19,7 +19,7 @@ import monix.eval.Task import scala.concurrent.ExecutionContext -abstract class RpcClient(node: Uri, fSslContext: () => Either[SSLError, SSLContext])(implicit +abstract class RpcClient(node: Uri, getSSLContext: () => Either[SSLError, SSLContext])(implicit system: ActorSystem, ec: ExecutionContext ) extends Logger { @@ -27,7 +27,7 @@ abstract class RpcClient(node: Uri, fSslContext: () => Either[SSLError, SSLConte import RpcClient._ lazy val connectionContext: HttpsConnectionContext = if (node.scheme.startsWith("https")) { - fSslContext().toOption.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) + getSSLContext().toOption.fold(Http().defaultClientHttpsContext)(ConnectionContext.httpsClient) } else { Http().defaultClientHttpsContext }