Code Monkey home page Code Monkey logo

Comments (6)

timcharper avatar timcharper commented on August 22, 2024 2

@borice this is great! Any chance you'd be willing to put this in to a PR with some additions to the README for how to use?

from op-rabbit.

DStranger avatar DStranger commented on August 22, 2024

Hi @borice,

connection {
    virtual-host = "/"
    hosts = ["127.0.0.1"]
    username = "guest"
    password = "guest"
    port = 5672
    ssl = true
  }

from op-rabbit.

borice avatar borice commented on August 22, 2024

Thank you @DStranger, however I was looking for a different answer.
How do I specify the TLS certificates to be used for the connection?
I would like to set up an encrypted connection for the messaging subsystem whereby all the messages between client and server are encrypted, and the client's certificate is verified.
Also, I believe the port should be 5671 for TLS connections, no?
Thank you.

EDIT: for example, I want to be able to use
ssl_options.verify=verify_peer and ssl_options.fail_if_no_peer_cert=true in the server configuration, and be able to connect to it via op_rabbit.

from op-rabbit.

DStranger avatar DStranger commented on August 22, 2024

Hi @borice! Sorry, I didn't really give your question too much thought.
This is how TLS configuration is done with the java client, but I think this is not currently possible in op-rabbit.

from op-rabbit.

borice avatar borice commented on August 22, 2024

Hi again.

I managed to get SSL working the way I want. Here's how I did it (can be refactored better, but here it goes as PoC):

I added a new ssl-config section to the oprabbit.connection configuration:

    connection {
        virtual-host = "/"
        hosts = ["REDACTED"]
        username = "REDACTED"
        password = "REDACTED"
        port = 5671
        connection-timeout = 3s
        ssl = true

        ssl-config {
            ssl: "TLSv1.2"

            keyManager.store {
                type: "PKCS12"
                path: "client_key.p12"
                password: "REDACTED"
            }

            trustManager.store {
                type: "JKS"
                path: "rabbitstore.jks"
                password: "REDACTED"
            }
        }
    }

and then, in code:

    implicit val actorSystem: ActorSystem = ActorSystem("rabbitmq")
    val connectionConfig = RabbitConfig.connectionConfig
    val connectionParams = ConnectionParams.fromConfig(connectionConfig)

    val sslContext =
      if (connectionParams.ssl) Some(getSslContext(connectionConfig.getConfig("ssl-config")))
      else None

    val factory = new ConnectionFactory()
    val firstHost = connectionParams.hosts.head
    factory.setHost(firstHost.getHost)
    factory.setPort(firstHost.getPort)
    factory.setUsername(connectionParams.username)
    factory.setPassword(connectionParams.password)
    factory.setVirtualHost(connectionParams.virtualHost)
    factory.setClientProperties(connectionParams.clientProperties.asJava)
    factory.setConnectionTimeout(connectionParams.connectionTimeout)
    factory.setExceptionHandler(connectionParams.exceptionHandler)
    factory.setRequestedChannelMax(connectionParams.requestedChannelMax)
    factory.setRequestedFrameMax(connectionParams.requestedFrameMax)
    factory.setRequestedHeartbeat(connectionParams.requestedHeartbeat)
    factory.setSaslConfig(connectionParams.saslConfig)
    connectionParams.sharedExecutor foreach factory.setSharedExecutor
    factory.setShutdownTimeout(connectionParams.shutdownTimeout)
    factory.setSocketFactory(connectionParams.socketFactory)
    sslContext foreach factory.useSslProtocol

    val connectionActorProps = ConnectionActor.props(factory)
    val connectionActor = actorSystem.actorOf(connectionActorProps, RabbitControl.CONNECTION_ACTOR_NAME)

    val rabbitControlProps = Props(classOf[RabbitControl], connectionActor)
    val rabbitControl = actorSystem.actorOf(rabbitControlProps)

    // now you can use rabbitControl as normal

with supporting methods:

  def getSslContext(config: Config): SSLContext = {
    val keyStoreConfig = config.getConfig("keyManager.store")
    val keyManagerFactory = getKeyManagerFactory(keyStoreConfig)

    val trustStoreConfig = config.getConfig("trustManager.store")
    val trustManagerFactory = getTrustManagerFactory(trustStoreConfig)

    val ssl = if (config.hasPath("ssl")) config.getString("ssl") else "TLSv1.2"
    val sslContext = SSLContext.getInstance(ssl)
    sslContext.init(keyManagerFactory.getKeyManagers, trustManagerFactory.getTrustManagers, null)

    sslContext
  }

  def getKeyManagerFactory(config: Config): KeyManagerFactory = {
    val ksType = if (config.hasPath("type")) config.getString("type") else "PKCS12"
    val ksPath = config.getString("path")
    val ksPassword = if (config.hasPath("password")) Some(config.getString("password").toCharArray) else None

    val ks = KeyStore.getInstance(ksType)
    using(new FileInputStream(ksPath))(ks.load(_, ksPassword.orNull))

    val kmf = KeyManagerFactory.getInstance("SunX509")
    kmf.init(ks, ksPassword.orNull)

    kmf
  }

  def getTrustManagerFactory(config: Config): TrustManagerFactory = {
    val ksType = if (config.hasPath("type")) config.getString("type") else "PKCS12"
    val ksPath = config.getString("path")
    val ksPassword = if (config.hasPath("password")) Some(config.getString("password").toCharArray) else None

    val ks = KeyStore.getInstance(ksType)
    using(new FileInputStream(ksPath))(ks.load(_, ksPassword.orNull))

    val tmf = TrustManagerFactory.getInstance("SunX509")
    tmf.init(ks)

    tmf
  }

  def using[A, B <: {def close() : Unit}](closeable: B)(f: B => A): A =
    try {
      f(closeable)
    }
    finally {
      closeable.close()
    }

Hope this helps someone else.

from op-rabbit.

timcharper avatar timcharper commented on August 22, 2024

Also, any reason to not just configure and use the JVM's default keystore?

from op-rabbit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.