rocketMq开启访问权限控制的目的是为了提高系统的安全性和保密性。要保证系统的安全性和保密性,那么就需要从身份认证和访问控制两个方向出发。身份认证是对系统的用户进行有效性、真实性验证;访问控制是在身份认证的基础上,根据不同用户的操作请求加以限制。身份认证关心的是“你是谁,你是否拥有你所声明的身份”这个问题;而访问控制则关心“你能做什么,不能做什么”的问题。rocketMq在4.4.0版本时引入了ACL机制,用于访问权限控制。
ACL是access control list的简称,俗称访问控制列表。用户通过ACL对rocketmq进行访问控制,可以将用户访问权限控制到Topic资源级别,并对请求类型进一步验证。用户在使用RocketMQ权限控制时,可以在Client客户端通过 RPCHook注入AccessKey和SecretKey签名;broker将对应的权限控制属性(包括Topic访问权限、IP白名单和AccessKey和SecretKey签名等)设置在distribution/conf/plain_acl.yml的配置文件中。client客户端对AccessKey所拥有的权限进行校验,校验不过,抛出AclException异常。
用户:用户是访问控制的基础要素,也不难理解,RocketMQ ACL 必然也会引入用户的概 念,即支持用户名、密码;
资源:需要保护的对象,在 RocketMQ 中,消息发送涉及的 Topic、消息消费涉及的 消费组,应该进行保护,故可以抽象成资源;
权限:针对资源,能进行的操作;
角色:RocketMQ 中,只定义两种是否是管理员
另外,RocketMQ ACL还支持按照客户端 IP 进行白名单设置。
globalWhiteRemoteAddresses:
- 10.10.103.*
- 192.168.0.*
accounts:
- accessKey: RocketMQ
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
topicPerms:
- topicA=DENY
- topicB=PUB|SUB
- topicC=SUB
groupPerms:
# the group should convert to retry topic
- groupA=DENY
- groupB=PUB|SUB
- groupC=SUB
- accessKey: rocketmq2
secretKey: 12345678
whiteRemoteAddress: 192.168.1.*
# if it is admin, it could access all resources
admin: true
全局白名单,其类型为数组,即支持多个配置。其支持的配置格式如下:
• 空
表示不设置白名单,该条规则默认返回false。
• *
表示全部匹配,该条规则直接返回true,将会阻断其他规则的判断,请慎重使用。
• 192.168.0.{100,101}
多地址配置模式,ip地址的最后一组,使用{},大括号中多个ip地址,用英文逗号(,)隔开。
• 192.168.1.100,192.168.2.100
直接使用,分隔,配置多个ip地址。
• 192.168…或192.168.100-200.10-20
每个IP段使用 “*” 或"-"表示范围。
配置用户信息,该类型为数组类型。拥有accessKey、secretKey、whiteRemoteAddress、admin、defaultTopicPerm、defaultGroupPerm、topicPerms、groupPerms子元素。
• accessKey:登录用户名,长度必须大于6个字符。
• secretKey:登录密码。长度必须大于6个字符。
用户级别的IP地址白名单。其类型为一个字符串,其配置规则与globalWhiteRemoteAddresses,但只能配置一条规则。
boolean类型,设置是否是admin。如下权限只有admin=true时才有权限执行。
• UPDATE_AND_CREATE_TOPIC
更新或创建主题。
• UPDATE_BROKER_CONFIG
更新Broker配置。
• DELETE_TOPIC_IN_BROKER
删除主题。
• UPDATE_AND_CREATE_SUBSCRIPTIONGROUP
更新或创建订阅组信息。
• DELETE_SUBSCRIPTIONGROUP
删除订阅组信息。
默认topic权限。该值默认为DENY(拒绝)。
默认消费组权限,该值默认为DENY(拒绝),建议值为SUB。
设置topic的权限。其类型为数组,其可选择值在下节介绍。
设置消费组的权限。其类型为数组,其可选择值在下节介绍。可以为每一消费组配置不一样的权限。
• DENY
拒绝。
• PUB
拥有发送权限。
• SUB
拥有订阅权限。
Broker端对客户端的RequestCommand请求进行解析,拿到需要鉴权的属性字段。 主要包括: (1)AccessKey:类似于用户名,代指用户主体,权限数据与之对应;(2)Signature:客户根据 SecretKey 签名得到的串,服务端再用SecretKey进行签名验证;
首先,需要在broker.conf文件中,增加参数aclEnable=true。并拷贝distribution/conf/plain_acl.yml文件到${ROCKETMQ_HOME}/conf目录。
broker.conf的配置文件如下:
brokerClusterName = DefaultCluster
brokerName = broker-b
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
listenPort=10915
storePathRootDir=E:/SH2019/tmp/rocketmq_home/rocketmq4.5MB/store
storePathCommitLog=E:/SH2019/tmp/rocketmq_home/rocketmq4.5MB/store/commitlog
namesrvAddr=127.0.0.1:9876
autoCreateTopicEnable=false
aclEnable=true
globalWhiteRemoteAddresses:
accounts:
- accessKey: RocketMQ
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
topicPerms:
- TopicTest=PUB
groupPerms:
# the group should convert to retry topic
- oms_consumer_group=DENY
- accessKey: admin
secretKey: 12345678
whiteRemoteAddress:
# if it is admin, it could access all resources
admin: true
从上面的配置可知,用户RocketMQ只能发送TopicTest的消息,其他topic无权限发送;拒绝oms_consumer_group消费组的消息消费,其他消费组默认可消费。
public class AclProducer {
public static void main(String[] args) throws MQClientException, InterruptedException {
DefaultMQProducer producer = new DefaultMQProducer("please_rename_unique_group_name", getAclRPCHook());
producer.setNamesrvAddr("127.0.0.1:9876");
producer.start();
for (int i = 0; i < 1; i++) {
try {
Message msg = new Message("TopicTest3" ,"TagA" , ("Hello RocketMQ " + i).getBytes(RemotingHelper.DEFAULT_CHARSET));
SendResult sendResult = producer.send(msg);
System.out.printf("%s%n", sendResult);
} catch (Exception e) {
e.printStackTrace();
Thread.sleep(1000);
}
}
producer.shutdown();
}
static RPCHook getAclRPCHook() {
return new AclClientRPCHook(new SessionCredentials("RocketMQ","12345678"));
}
}
由于broker已经开启acl鉴权,RocketMQ用户只允许发送topic为TopicTest的消息,所以必将抛出AclException异常。
• 如果ACL与高可用部署(Master/Slave架构)同时启用,那么需要在Broker Master节点的distribution/conf/plain_acl.yml配置文件中 设置全局白名单信息,即为将Slave节点的ip地址设置至Master节点plain_acl.yml配置文件的全局白名单中。
• 如果ACL与高可用部署(多副本Dledger架构)同时启用,由于出现节点宕机时,Dledger Group组内会自动选主,那么就需要将Dledger Group组 内所有Broker节点的plain_acl.yml配置文件的白名单设置所有Broker节点的ip地址。
特别注意在[4.5.0]版本中即使使用上面所述的白名单也无法解决开启ACL的问题,解决该问题的PR链接