[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GitHub] activemq-artemis issue #2113: [ARTEMIS-1890] Any-word wildcard fix

Github user jostbg commented on the issue:

    @clebertsuconic We are using Artemis as a fast event/message bus for AMQP communication between (micro-)services developed and operated by different organizational units.
    Each service has it's own LDAP managed login credentials. We allow all services with LDAP Ids below certain organizational units (base DNs) to access the broker.
    Thus we do not manually grant access to the broker on a per-service/per-application basis.
    The functional requirement we are faced with is that a service shall be able to send multicast messages while maintaining control over which other services are able to read those messages.
    Since there is no finite set of services that are accessing the broker and services shall be able to specify adressees on a per-message base we cannot work with pre-configured ACL-secured addresses/queues. 
    In ActiveMQ 5.x we could maybe setup something involving a `MessageAuthorizationPolicy.isAllowedToConsume` but this feature is [not yet available](https://issues.apache.org/jira/browse/ARTEMIS-1884) in Artemis.
    So we came up with a system that involves topic based wildcard routing, auto-created addresses/queues and a custom Artemis plugin that performs ACLs checks on address/queue access.
    It works as follows: 
    A service is allowed to send multicast messages to other services by publishing to addresses following the naming convention `topics.<someTopicName>.for.<serviceId1>.<serviceId2>...` where `serviceId1`, `serviceId2` etc are the LDAP authenticated usernames of the services that are allowed to read the message. 
    Each service that can access the broker has the right to subscribe to addresses following the naming convention `topics.<someTopicName>.for.#.<myAuthenticatedUsername>.#` to receive messages addressed to it where `myAuthenticatedUsername` is it's own LDAP id.
    This means, if a `serviceA` wants to send information about a newly created contract to `serviceB` and `serviceC` it publishes a message to the address `topics.contracts.for.serviceB.serviceC`. `serviceB` subscribes to `topics.contracts.for.#.serviceB.#` to receive all contracts related messages addressed to it. If `serviceB` then wants to send invoice information to `serviceA` and `serviceB` it would publishes a message to `topics.invoices.for.serviceA.serviceC`.
    The only missing piece for us atm is that `#` must always be interpreted as `zero-or-more` words as stated in the documentation otherwise services will not be able to receive messages in all cases.
    For performance/resources reasons and simplicity of scaling/operations/maintenance we do not want to introduce another more sophisticated external routing component like camel as the setup I described fulfills our requirements.