rocketmq
rocketmq copied to clipboard
acl module support namespace
At present, ACL module does not support namespace. The way to achieve it is as follows:
- "namesppace%ak" is globally unique
- the acl config is modified as follows:
globalWhiteRemoteAddresses:
- 10.10.103.*
- 192.168.0.*
accounts:
- accessKey: namespace1%RocketMQ
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
topicPerms:
- namespace1%topicA=DENY
- namespace1%topicB=PUB|SUB
- namespace1%topicC=SUB
groupPerms:
- namespace1%groupA=DENY
- namespace1%groupB=PUB|SUB
- namespace1%groupC=SUB
- accessKey: rocketmq2
secretKey: 12345678
whiteRemoteAddress: 192.168.1.*
admin: true
Based on the above, the code that needs to be modified is as follows:
- To use this feature, clients needs to use RPCHook to inject accesskey、secretkey and namespace
- To support this feature, the code in acl module needs to be modified as follows: (1) SessionCredentials adds an attributes called namespce (2) Before client sends request, client calls doBeforeRequest method at first, so we can add an operation which is adding namespace in the extended attributes in the request in doBeforeRequest method (3) After broker receieves the request, it will parse the PlainAccessResource object from the request, at this moment we can parse the namespace,and then set the accesskey
- ACL mqadmin commands also need to be modified, updateAclConfig and deleteAccessConfig should add a optional parameter called namespace to support namespace
This design requires updating rocketmq-client, which might bring cost for users to update rocketmq-client. I've some suggestions:
-
accessKey
should be defined as a globally unique string, so that complexity is reduced and users with older versions of rocketmq-client may adopt this feature. Some uniqueness check ofaccessKey
should be added in ACL mqadmin command to keepaccessKey
globally unique with best effort. -
One
accessKey
can only be granted permissions to access resources in the same namespace. -
Separate presentation with storage of namespace in ACL module.
{namespace}%{resource}
is just a presentation way of resources in a namespace. For the definition ofaccount
data structure, a new field should be added to store namespace. When checking permissions, resources defined in ACL account are converted as{namespace}%{resource}
.
In that way, the ACL config file would like this:
globalWhiteRemoteAddresses:
- 10.10.103.*
- 192.168.0.*
accounts:
- accessKey: RocketMQ # accessKey is globally unique
secretKey: 12345678
namespace: namespace1 # add namespace field in acount
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
# All topics below are in namespace1
topicPerms:
- topicA=DENY
- topicB=PUB|SUB
- topicC=SUB
# All groups below are in namespace1
groupPerms:
- groupA=DENY
- groupB=PUB|SUB
- groupC=SUB
- accessKey: rocketmq2 # rocketmq2 is in a 'default' namespace
secretKey: 12345678
whiteRemoteAddress: 192.168.1.*
admin: true
This design requires updating rocketmq-client, which might bring cost for users to update rocketmq-client. I've some suggestions:
accessKey
should be defined as a globally unique string, so that complexity is reduced and users with older versions of rocketmq-client may adopt this feature. Some uniqueness check ofaccessKey
should be added in ACL mqadmin command to keepaccessKey
globally unique with best effort.- One
accessKey
can only be granted permissions to access resources in the same namespace.- Separate presentation with storage of namespace in ACL module.
{namespace}%{resource}
is just a presentation way of resources in a namespace. For the definition ofaccount
data structure, a new field should be added to store namespace. When checking permissions, resources defined in ACL account are converted as{namespace}%{resource}
.In that way, the ACL config file would like this:
globalWhiteRemoteAddresses: - 10.10.103.* - 192.168.0.* accounts: - accessKey: RocketMQ # accessKey is globally unique secretKey: 12345678 namespace: namespace1 # add namespace field in acount whiteRemoteAddress: admin: false defaultTopicPerm: DENY defaultGroupPerm: SUB # All topics below are in namespace1 topicPerms: - topicA=DENY - topicB=PUB|SUB - topicC=SUB # All groups below are in namespace1 groupPerms: - groupA=DENY - groupB=PUB|SUB - groupC=SUB - accessKey: rocketmq2 # rocketmq2 is in a 'default' namespace secretKey: 12345678 whiteRemoteAddress: 192.168.1.* admin: true
@caigy It is true that there is a little consideration to the client upgrades. So I adjust the design. The details are as follows: 1.Clients don't need to be upgraded, they can use this feature as follows:
public class ProducerAclWithNamespace {
public static final String NAMESPACE = "n";
public static final String PRODUCER_GROUP = "producerGroup";
public static final String DEFAULT_NAMESRVADDR = "127.0.0.1:9876";
public static final int MESSAGE_COUNT = 100;
public static final String TOPIC = "topicB";
public static final String TAG = "tagTest";
private static final String ACL_ACCESS_KEY = "RocketMQ";
private static final String ACL_SECRET_KEY = "12345678";
public static void main(String[] args) throws Exception {
DefaultMQProducer producer = new DefaultMQProducer(NAMESPACE, PRODUCER_GROUP, getAclRPCHook());
producer.setNamesrvAddr(DEFAULT_NAMESRVADDR);
producer.start();
for (int i = 0; i < MESSAGE_COUNT; i++) {
Message message = new Message(TOPIC, TAG, "Hello world".getBytes());
try {
SendResult result = producer.send(message);
System.out.printf("Topic:%s send success, misId is:%s%n", message.getTopic(), result.getMsgId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
static RPCHook getAclRPCHook() {
return new AclClientRPCHook(new SessionCredentials(ACL_ACCESS_KEY,ACL_SECRET_KEY));
}
}
public class ConsumerAclWithNamespace {
public static final String NAMESPACE = "n";
public static final String CONSUMER_GROUP = "groupB";
public static final String DEFAULT_NAMESRVADDR = "127.0.0.1:9876";
public static final String TOPIC = "topicB";
private static final String ACL_ACCESS_KEY = "RocketMQ";
private static final String ACL_SECRET_KEY = "12345678";
public static void main(String[] args) throws Exception {
DefaultMQPushConsumer defaultMQPushConsumer = new DefaultMQPushConsumer(NAMESPACE, CONSUMER_GROUP, getAclRPCHook());
defaultMQPushConsumer.setNamesrvAddr(DEFAULT_NAMESRVADDR);
defaultMQPushConsumer.subscribe(TOPIC, "*");
defaultMQPushConsumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
msgs.forEach(msg -> System.out.printf("Msg topic is:%s, MsgId is:%s, reconsumeTimes is:%s%n", msg.getTopic(), msg.getMsgId(), msg.getReconsumeTimes()));
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
});
defaultMQPushConsumer.start();
}
static RPCHook getAclRPCHook() {
return new AclClientRPCHook(new SessionCredentials(ACL_ACCESS_KEY,ACL_SECRET_KEY));
}
}
2."namesppace%ak" is globally unique and the config of acl is modified as follows:
globalWhiteRemoteAddresses:
- 10.10.103.*
- 192.168.0.*
accounts:
- accessKey: namespace1%RocketMQ
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
topicPerms:
- namespace1%topicA=DENY
- namespace1%topicB=PUB|SUB
- namespace1%topicC=SUB
groupPerms:
- namespace1%groupA=DENY
- namespace1%groupB=PUB|SUB
- namespace1%groupC=SUB
- accessKey: rocketmq2
secretKey: 12345678
whiteRemoteAddress: 192.168.1.*
admin: true
3.To support this feature, the code in acl module needs to be modified as follows When broker parse the request from client, the broker needs to get the namespace from the request. When namespace is not null, broker can set the accesskey 4.ACL mqadmin commands also need to be modified, updateAclConfig and deleteAccessConfig should add a optional parameter called namespace to support namespace
A Question: is a pair of ak/sk allowed to access topics from two or more name space? do we need to consider this scenario?
A Question: is a pair of ak/sk allowed to access topics from two or more name space? do we need to consider this scenario?
@ShannonDing I don't think a pair of ak/sk from one namespace should be allowed to access topics from other namespace.
AK/SK属于权限类,可以认为是一个用户,NameSpace属于资源类,两个应该是不同的维度。 从这个角度,一个用户是允许访问两个NameSpace下的topic的。这种权限结构我觉得才比较合理。
accounts:
- accessKey: RocketMQ # accessKey is globally unique
secretKey: 12345678
whiteRemoteAddress:
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: SUB
resourcePerm:
- resource:topicA
type:TOPIC
namespace:xxxxx
perm:PUB
- resource:GroupA
type:GROUP
namespace:xxxxx
perm:PUB|SUB
- resource:topicA
type:TOPIC
namespace:yyyyyy
perm:PUB
A Question: is a pair of ak/sk allowed to access topics from two or more name space? do we need to consider this scenario?
@ShannonDing I don't think a pair of ak/sk from one namespace should be allowed to access topics from other namespace.
对于不同用户来说,特别是云上用户,授权访问资源是很常见的场景。 我认为, 1.要么规定一个用户可以访问哪些资源,2.要么规定某个资源可以被哪些用户访问。我们现在的ACL的配置其实还是第一种情况,增加了namespace,只是对资源做了分组,而不是对用户本身做了变化,因此不应该打破原来的这个逻辑。
This issue is stale because it has been open for 365 days with no activity. It will be closed in 3 days if no further activity occurs.
This issue was closed because it has been inactive for 3 days since being marked as stale.