Search code examples
springconfigurationjmsmessage-queueactivemq-artemis

ActiveMQ Artemis wildcard security settings not behaving as expected


While trying to set up a nice and automatic way to configure ActiveMQ Artemis users I stumbled on the wildcard routing that can be used within the security-settings block.

Leveraging this would make inter application communication easy. Sending something from appA to appB could always be done by using a fixed queue pattern: appA.appB.requestSomething would indicate communication from appA to appB containing requestSomething. Is would be trivial to create a queue with requestSomethingElse etc.

Inverse would also be possible, just flip around the pattern: appB.appA.responseSomething etc.

Given the following security-settings block:

    <security-setting match="appA.#">
        <permission type="createDurableQueue" roles="appA"/>
        <permission type="deleteDurableQueue" roles="appA"/>
        <permission type="createAddress" roles="appA"/>
        <permission type="deleteAddress" roles="appA"/>
        <permission type="consume" roles="appA"/>
        <permission type="browse" roles="appA"/>
        <permission type="send" roles="appA"/>
        <permission type="manage" roles="appA"/>
    </security-setting>
    <security-setting match="*.appA.#">
        <permission type="consume" roles="appA"/>
        <permission type="browse" roles="appA"/>
    </security-setting>
    <security-setting match="appB.#">
        <permission type="createDurableQueue" roles="appB"/>
        <permission type="deleteDurableQueue" roles="appB"/>
        <permission type="createAddress" roles="appB"/>
        <permission type="deleteAddress" roles="appB"/>
        <permission type="consume" roles="appB"/>
        <permission type="browse" roles="appB"/>
        <permission type="send" roles="appB"/>
        <permission type="manage" roles="appB"/>
    </security-setting>
    <security-setting match="*.appB.#">
        <permission type="consume" roles="appB"/>
        <permission type="browse" roles="appB"/>
    </security-setting>

and configuring a producer with appA sending to appA.appB.request the following exception is thrown: Cause: AMQ229213: User: appA does not have permission='CREATE_DURABLE_QUEUE' for queue appA.appB.request on address appA.appB.request.

Did the security-settings block describing the read permissions for appB overrule all previous described settings?

Is this undocumented behavior? Did I misunderstand how this mechanism should work? Looked like a great way to configure communication between different applications..


Solution

  • What you're seeing is, in fact, the expected behavior. When the client application attempts to send a message to appA.appB.request then broker looks up appA.appB.request in the internal security-settings repo and finds this match:

        <security-setting match="*.appB.#">
            <permission type="consume" roles="appB"/>
            <permission type="browse" roles="appB"/>
        </security-setting>
    

    This only allows users with the appB role to consume from or browse queues on matching addresses. Since your user has appA the authorization is denied.

    Keep in mind, as the documentation notes:

    Note that settings are not inherited from the former block. All the settings will be taken from the more specific matching block..

    By not inheriting permissions, it allows you to effectively deny permissions in more specific security-setting blocks by simply not specifying them. Otherwise it would not be possible to deny permissions in sub-groups of addresses.