authenticationrabbitmq

Attribute RabbitMQ messages based on producer username


I am developing a log collector where different applications send tracing messages to a predefined RabbitMQ queue.

Every producer authorizes itself connecting to rabbitmq server. Is there a way to distinguish producers at the consumer level using the authorisation information provided during sending the message?

I would like to add the producer's username to the message header. So the consumer could read it out. Is there a way to achieve this within RabbitMQ?

Update: all the folks who leave a negative vote on the question. Could you give me a hint, what is wrong with it?


Solution

  • RabbitMQ supports a special message property "user-id".

    In Java one can set it like this:

    Channel channel = connection.createChannel();
    
    AMQP.BasicProperties props = new AMQP.BasicProperties.Builder()
            .userId("user42")
            .contentType("text/plain")
            .build();
    
    String message = "Hello World!";
    channel.basicPublish("", QUEUE_NAME, props, message.getBytes());
    

    If the property is set, RabbitMQ validates the user and throws an exception, if the provided user-id doesn't match (case-sensitive) the username used for sending the message.

    Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - user_id property set to 'user42' but authenticated user was 'admin', class-id=60, method-id=40)
    

    The receiver can read the information and authorize the producer this way.

    DeliverCallback deliverCallback = (consumerTag, delivery) -> {
        String messageIn = new String(delivery.getBody());
        String userId = delivery.getProperties().getUserId();
    
        System.out.println(" [x] Received '" + messageIn + "' from " + userId);
    };
    
    channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
    

    OAuth authentication

    If using OAuth authentication, the username seams to be a claim which is used as a scope. For example, you can configures oid as a scope claim for an Azure Entra ID Token in your rabbitmq.conf file:

    auth_oauth2.additional_scopes_key = oid
    

    In this case the username expected in the user-id property will be the Object ID of your service principal. It is a UUID like 30087a5b-0cc3-44ac-9e3f-868dbb0b5b8e.