Caideyipi commented on code in PR #18418:
URL: https://github.com/apache/iotdb/pull/18418#discussion_r3734760719
##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/subscription/agent/SubscriptionTopicAgent.java:
##########
@@ -369,6 +375,105 @@ public TSStatus checkTopicOwners(
return RpcUtils.SUCCESS_STATUS;
}
+ /**
+ * Check that the authenticated session can read all data covered by the
requested topics.
+ * ConsumerConfig is client-controlled and therefore must not be used as the
authorization
+ * identity.
+ */
+ public TSStatus checkTopicReadPermissions(
+ final String username,
+ final ConsumerConfig consumerConfig,
+ final Iterable<String> topicNames) {
+ if (Objects.isNull(username)) {
+ return RpcUtils.getStatus(TSStatusCode.NO_PERMISSION);
+ }
+
+ acquireReadLock();
+ try {
+ for (final String topicName : topicNames) {
+ final TopicMeta topicMeta =
+ topicMetaKeeper.getTopicMeta(topicName,
isTableModel(consumerConfig));
+ if (Objects.isNull(topicMeta)) {
+ continue;
+ }
+
+ final TSStatus status =
+ topicMeta.getConfig().isTableTopic()
+ ? checkTableTopicReadPermission(username, topicMeta)
+ : checkTreeTopicReadPermission(username, topicMeta);
+ if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ return status;
+ }
+ }
+ return RpcUtils.SUCCESS_STATUS;
+ } finally {
+ releaseReadLock();
+ }
+ }
+
+ private TSStatus checkTreeTopicReadPermission(final String username, final
TopicMeta topicMeta) {
+ final TopicConfig topicConfig = topicMeta.getConfig();
+ final TreePattern treePattern =
+ topicConfig.getAttribute().containsKey(TopicConstant.PATTERN_KEY)
+ ? new
PrefixTreePattern(topicConfig.getAttribute().get(TopicConstant.PATTERN_KEY))
+ : new IoTDBTreePattern(
+ topicConfig.getStringOrDefault(
+ TopicConstant.PATH_KEY, TopicConstant.PATH_DEFAULT_VALUE));
+ for (final PartialPath path : treePattern.getBaseInclusionPaths()) {
+ if (!AuthorityChecker.checkFullPathOrPatternPermission(
+ username, path, PrivilegeType.READ_DATA)) {
+ return AuthorityChecker.getTSStatus(false, path,
PrivilegeType.READ_DATA);
+ }
+ }
+ return RpcUtils.SUCCESS_STATUS;
+ }
+
+ private TSStatus checkTableTopicReadPermission(final String username, final
TopicMeta topicMeta) {
+ if (AuthorityChecker.SUPER_USER.equals(username)) {
+ return RpcUtils.SUCCESS_STATUS;
+ }
+ final TopicConfig topicConfig = topicMeta.getConfig();
+ final String database =
+ topicConfig.getStringOrDefault(
+ TopicConstant.DATABASE_KEY, TopicConstant.DATABASE_DEFAULT_VALUE);
+ final String table =
+ topicConfig.getStringOrDefault(TopicConstant.TABLE_KEY,
TopicConstant.TABLE_DEFAULT_VALUE);
+
+ // A database-level SELECT grant covers all tables in one database. For a
topic whose
+ // database/table is a regular expression, only an any-scope SELECT grant
is broad enough to
+ // cover every object matched by the topic.
+ final boolean databasePattern = isRegexPattern(database);
+ final boolean tablePattern = isRegexPattern(table);
+ final boolean allowed =
+ (databasePattern
+ ? AuthorityChecker.checkDBPermission(
+ username, AuthorityChecker.ANY_SCOPE, PrivilegeType.SELECT)
+ : AuthorityChecker.checkDBPermission(username, database,
PrivilegeType.SELECT)
+ || (!tablePattern
+ && AuthorityChecker.checkTablePermission(
+ username, database, table, PrivilegeType.SELECT)));
+ return allowed
+ ? RpcUtils.SUCCESS_STATUS
+ : AuthorityChecker.getTSStatus(false, PrivilegeType.SELECT, database,
table);
+ }
+
+ private static boolean isRegexPattern(final String value) {
+ return value.indexOf('.') >= 0
+ || value.indexOf('*') >= 0
+ || value.indexOf('+') >= 0
+ || value.indexOf('?') >= 0
+ || value.indexOf('[') >= 0
+ || value.indexOf(']') >= 0
+ || value.indexOf('(') >= 0
+ || value.indexOf(')') >= 0
+ || value.indexOf('{') >= 0
+ || value.indexOf('}') >= 0
+ || value.indexOf('|') >= 0
+ || value.indexOf('^') >= 0
+ || value.indexOf('$') >= 0
+ || value.indexOf('\\') >= 0;
+ }
Review Comment:
The database and table attributes in a table topic are regex patterns by
contract (the same values are compiled by TablePattern). Therefore a
metacharacter means the topic may cover multiple objects, and the conservative
any-scope SELECT check is intentional. A literal name containing regex
metacharacters must be escaped in the topic pattern; it is not interpreted as
an unescaped literal table name.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]