Rabbitmq权限控制
'^(amq\.gen.*|amq\.default)$'可以匹配server生成的和默认的exchange,'^$'不匹配任何资源.
转
https://zq99299.github.io/mq-tutorial/rabbitmq-ac/
参数含义:
`-p vhost`:给哪一个 vhost 授权用户访问权限
user:给哪一个用户指定权限
conf: 用于匹配用户在哪些资源上拥有可配置权限的正则表达式;指:队列和交换器的创建及删除之类的操作
write:用于匹配用户在哪些资源上拥有可写权限的正则表达式;指:发布消息
read: 用于匹配用户在哪些资源上拥有可读权限的正则表达式;指:与消息有关的操作,包括读取消息及清空整个队列等
RabbitMQ 為不同帳號設定不同 Queue 權限
同事在新功能的架構設計時想要讓不同 user 在 MQ 存取時可以有權限的概念,但以團隊之前使用的 Kafka 至少就我個人所知是無法達成的,不過這個需求在 RabbitMQ 上就有幾種不同的做法,今天就來紀錄一下相關的 POC 過程與設定方式
基本環境說明
- macOS Big Sur 11.2.2
- docker desktop 3.2.1 (61626)
-
docker images
-
rabbitmq:3.8.14-management
1docker run -d --rm --hostname my-rabbit --name test-rabbit -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=pass.123 rabbitmq:3.8.14-management
-
-
RabbitMQ 基本設定
-
建立 exchange
以
yowkoex
為例1rabbitmqadmin declare exchange name=yowkoex type=topic -u admin -p pass.123 -
建立 queue
以
topic1
,topic2
,topic3
為例123rabbitmqadmin declare queue name=topic1 durable=false -u admin -p pass.123rabbitmqadmin declare queue name=topic2 durable=false -u admin -p pass.123rabbitmqadmin declare queue name=topic3 durable=false -u admin -p pass.123 -
將 queue 跟 exchange 做 binding
123rabbitmqadmin declare binding source="yowkoex" destination_type="queue" destination="topic1" routing_key="topic1" -u admin -p pass.123rabbitmqadmin declare binding source="yowkoex" destination_type="queue" destination="topic2" routing_key="topic2" -u admin -p pass.123rabbitmqadmin declare binding source="yowkoex" destination_type="queue" destination="topic3" routing_key="topic3" -u admin -p pass.123 -
建立 user
yowko1
只能 access topic1;yowko23
只能 access topic2 與 topic312rabbitmqctl add_user yowko1 pass.123rabbitmqctl add_user yowko23 pass.123
-
設定方式
以下三種方式擇一即可
-
使用 ui
- 設定 vhost 權限
- 設定 topic 權限
-
使用 rabbitmqctl
-
設定 vhost 權限
語法:
rabbitmqctl set_permissions [-p {vhost}] {user} {conf} {write} {read}s
12rabbitmqctl set_permissions -p / yowko1 "" "" "topic1"rabbitmqctl set_permissions -p / yowko23 "" "" "^topic(2|3)$" -
設定 topic 權限
語法:
rabbitmqctl set_topic_permissions [-p {vhost}] {user} {exchange} {write} {read}
12rabbitmqctl set_topic_permissions -p / yowko1 yowkoex "" "topic1"rabbitmqctl set_topic_permissions -p / yowko23 yowkoex "" "^topic(2|3)$"
-
-
使用 http rest api
這個部份我沒有實際用過,就不特別紀錄了
實際效果
-
沒有 topic 權限的錯誤
-
錯誤訊息
12345Unhandled exception. RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=403, text='ACCESS_REFUSED - access to queue 'topic1' in vhost '/' refused for user 'yowko23'', classId=60, methodId=20at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)at RabbitMQ.Client.Impl.ModelBase.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)at RabbitMQ.Client.Impl.AutorecoveringModel.BasicConsume(String queue, Boolean autoAck, String consumerTag, Boolean noLocal, Boolean exclusive, IDictionary`2 arguments, IBasicConsumer consumer)at RabbitMQ.Client.IModelExensions.BasicConsume(IModel model, String queue, Boolean autoAck, IBasicConsumer consumer) -
錯誤截圖
-
-
沒有 vhost 權限的錯誤
-
錯誤訊息
12345678910111213Unhandled exception. RabbitMQ.Client.Exceptions.BrokerUnreachableException: None of the specified endpoints were reachable---> RabbitMQ.Client.Exceptions.OperationInterruptedException: The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=530, text='NOT_ALLOWED - access to vhost '/' refused for user 'yuser'', classId=10, methodId=40at RabbitMQ.Client.Impl.SimpleBlockingRpcContinuation.GetReply(TimeSpan timeout)at RabbitMQ.Client.Impl.ModelBase.ConnectionOpen(String virtualHost, String capabilities, Boolean insist)at RabbitMQ.Client.Framing.Impl.Connection.Open(Boolean insist)at RabbitMQ.Client.Framing.Impl.Connection..ctor(IConnectionFactory factory, Boolean insist, IFrameHandler frameHandler, String clientProvidedName)at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IFrameHandler fh)at RabbitMQ.Client.Framing.Impl.AutorecoveringConnection.Init(IEndpointResolver endpoints)at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName)--- End of inner exception stack trace ---at RabbitMQ.Client.ConnectionFactory.CreateConnection(IEndpointResolver endpointResolver, String clientProvidedName)at RabbitMQ.Client.ConnectionFactory.CreateConnection(String clientProvidedName)at RabbitMQ.Client.ConnectionFactory.CreateConnection() -
錯誤截圖
-
心得
透過 user 的權限設定可以將不同 Queue 的讀寫權限分離,但這樣的做法是基於同一個 vhost 的前提下,如果想要更完整地做隔離或是需要 multiple tenants 概念就不是那麼適合,相關的做法待之後筆記再補充了