2
votes

Is there a way to authorize destinations with Apache Apollo MQ?

What I would like is to make it so that 1) users may write only to a shared topic but restrict read to an server/admin. This topic is to send messages to a server. 2) Users may read from their own private topic but no one but the server/admin may write to it.

For Example:

Topic               User rights                     Server/Admin rights
/public             Write only                      Read only
/user/foo           ONLY the user foo may read      Write only
/user/bar           ONLY the user bar may read      Write only
/user/<username>    ONLY the <username> may read    Write only

Now for the interesting part. This must work with dynamic topics. The user's name is NOT known ahead of time.

I had this working with Apache ActiveMQ using a custom BrokerFilter but am not sure how to do with with Apollo.

Thanks for any help.

1

1 Answers

1
votes

After a lot of head scratching I figured it out.

In apollo.xml:

<broker xmlns="http://activemq.apache.org/schema/activemq/apollo" security_factory="com.me.MyAuthorizationPlugin">

In com.me.MyAuthorizationPlugin:

package com.me

import org.fusesource.hawtdispatch.DispatchQueue.QueueType

import org.apache.activemq.apollo.broker.security._
import org.apache.activemq.apollo.broker.{ Queue, Broker, VirtualHost }
import java.lang.Boolean

class MyAuthorizationPlugin extends SecurityFactory {

    def install(broker: Broker) {
        DefaultSecurityFactory.install(broker)
    }

    def install(virtual_host: VirtualHost) {
        DefaultSecurityFactory.install(virtual_host)
        val default_authorizer = virtual_host.authorizer
        virtual_host.authorizer = new Authorizer() {
            def can(ctx: SecurityContext, action: String, resource: SecuredResource): Boolean = {

                println("Resource: " + resource.id + " User: " + ctx.user)
                resource.resource_kind match {
                    case SecuredResource.TopicKind =>
                        val id = resource.id
                        println("Topic Resource: " + id + " User: " + ctx.user)
                        var result : Boolean = id.startsWith("user." + ctx.user) || id.startsWith("MDN." + ctx.user + ".")
                        println("Result: " + result)
                        return result
                    case _ =>
                        return default_authorizer.can(ctx, action, resource)
                }
            }
        }
    }
}

The following URLs seemed VERY useful and indeed nearly a perfect match:

Now I only need to clean up my nasty scala and put it in Git.

I am thinking of doing two tests:

  1. Speed of EXACTLY what I need
  2. A Regex pattern matcher with username / clientID replacements and +/*/?/etc This pattern will be pulled from the config file.

If they are nearly identical I may see about adding it to Apollo by contacting commiters.