-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Pipe: Implemented tree auth check for source + write-back-sink #16531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
* fix * fix * fix * fix * fix * fix * fix * fix * refactor * fix * fix * partial * grass * Update PipeConfigTreePrivilegeParseVisitor.java * Feature/client hide password (#16468) * session hide password * fix start-cli.sh * fix start-cli.bat * client hide password * fix client warning * echo cmd line * fix * Update PipeConfigTreePrivilegeParseVisitor.java * partial * partial * fix * fix * partial --------- Co-authored-by: Hongzhi Gao <[email protected]>
…to fix-audit-logger
* fix * fix * fix * fix * fix * fix * fix * fix * refactor * fix * fix * partial * grass * Update PipeConfigTreePrivilegeParseVisitor.java * Feature/client hide password (#16468) * session hide password * fix start-cli.sh * fix start-cli.bat * client hide password * fix client warning * echo cmd line * fix * Update PipeConfigTreePrivilegeParseVisitor.java * partial * partial * fix * fix * partial --------- Co-authored-by: Hongzhi Gao <[email protected]>
…to fix-audit-logger
# Conflicts: # integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/auto/basic/IoTDBTreePatternFormatIT.java # integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipeInclusionIT.java # iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/PipeConfigTreePatternParseVisitor.java # iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorInfo.java # iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java # iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/manager/pipe/source/PipeConfigTreePatternParseVisitorTest.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/agent/task/connection/PipeEventCollector.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/parser/TsFileInsertionEventParser.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/parser/TsFileInsertionEventParserProvider.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/parser/query/TsFileInsertionEventQueryParser.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/parser/scan/TsFileInsertionEventScanParser.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/parser/table/TsFileInsertionEventTableParser.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/visitor/PipeTableStatementDataTypeConvertExecutionVisitor.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/converter/LoadTableStatementDataTypeConvertExecutionVisitor.java # iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/datastructure/pattern/IoTDBTreePattern.java
# Conflicts: # iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/pipe/source/PipeConfigTreePatternParseVisitor.java # iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/agent/task/connection/PipeEventCollector.java # iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/pipe/datastructure/pattern/IoTDBTreePattern.java
...test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipePermissionIT.java
Outdated
Show resolved
Hide resolved
| // A user shall only see its own pipe | ||
| try (final SyncConfigNodeIServiceClient client = | ||
| (SyncConfigNodeIServiceClient) senderEnv.getLeaderConfigNodeConnection()) { | ||
| Assert.assertEquals( | ||
| 1, client.showPipe(new TShowPipeReq().setUserName("thulab")).pipeInfoList.size()); | ||
| } catch (Exception e) { | ||
| fail(e.getMessage()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can show another user's pipe simply by setting the request's username?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but if the config client can be initialized outside of IoTDB, a user can do everything without permission, because the permissions are checked on DataNode. So users shall not have the chance to directly "set" the request's username
| if (!Boolean.TRUE.equals(isTableDatabasePlan)) { | ||
| final Optional<ConfigPhysicalPlan> result = treePrivilegeParseVisitor.process(plan, userName); | ||
| if (result.isPresent()) { | ||
| return Optional.of( | ||
| new PipeConfigRegionWritePlanEvent(result.get(), event.isGeneratedByPipe())); | ||
| } | ||
| } | ||
|
|
||
| final Optional<ConfigPhysicalPlan> result = | ||
| TABLE_PRIVILEGE_PARSE_VISITOR.process(plan, userName); | ||
| if (result.isPresent()) { | ||
| return Optional.of( | ||
| new PipeConfigRegionWritePlanEvent(result.get(), event.isGeneratedByPipe())); | ||
| if (!Boolean.FALSE.equals(isTableDatabasePlan)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reverse the conditions to remove unnecessary !.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cannot be done because other than table database, the planNodes are processed by both of the visitor but will only be filtered by one and pass directly through another. The ! is to tell 'null + FALSE' and 'TRUE + NULL'
| public boolean canShowSchemaTemplate(final String templateName, final String userName) { | ||
| try { | ||
| return ConfigNode.getInstance() | ||
| .getConfigManager() | ||
| .getPermissionManager() | ||
| .checkUserPrivileges(userName, new PrivilegeUnion(PrivilegeType.SYSTEM)) | ||
| .getStatus() | ||
| .getCode() | ||
| == TSStatusCode.SUCCESS_STATUS.getStatusCode() | ||
| || ConfigNode.getInstance() | ||
| .getConfigManager() | ||
| .getClusterSchemaManager() | ||
| .getPathsSetTemplate(templateName, ALL_MATCH_SCOPE) | ||
| .getPathList() | ||
| .stream() | ||
| .anyMatch( | ||
| path -> { | ||
| try { | ||
| return ConfigNode.getInstance() | ||
| .getConfigManager() | ||
| .getPermissionManager() | ||
| .checkUserPrivileges( | ||
| userName, | ||
| new PrivilegeUnion( | ||
| Collections.singletonList( | ||
| new PartialPath(path) | ||
| .concatNode(MULTI_LEVEL_PATH_WILDCARD)), | ||
| PrivilegeType.READ_SCHEMA)) | ||
| .getStatus() | ||
| .getCode() | ||
| == TSStatusCode.SUCCESS_STATUS.getStatusCode(); | ||
| } catch (final IllegalPathException e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| }); | ||
| } catch (final Exception e) { | ||
| LOGGER.warn( | ||
| "Un-parse-able path name encountered during template privilege trimming, please check", | ||
| e); | ||
| return false; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test to cover this?
...ava/org/apache/iotdb/confignode/manager/pipe/source/PipeConfigTreePrivilegeParseVisitor.java
Show resolved
Hide resolved
| final Set<IDeviceID> devices = getDeviceSet(); | ||
| if (Objects.nonNull(devices)) { | ||
| final List<MeasurementPath> measurementList = new ArrayList<>(); | ||
| for (final IDeviceID device : devices) { | ||
| measurementList.add(new MeasurementPath(device, IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)); | ||
| } | ||
| final TSStatus status = | ||
| AuthorityChecker.getAccessControl() | ||
| .checkSeriesPrivilege4Pipe( | ||
| new UserEntity(Long.parseLong(userId), userName, cliHostname), | ||
| measurementList, | ||
| PrivilegeType.READ_DATA); | ||
| if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != status.getCode()) { | ||
| if (skipIfNoPrivileges) { | ||
| shouldParse4Privilege = true; | ||
| } else { | ||
| throw new AccessDeniedException(status.getMessage()); | ||
| } | ||
| } | ||
| } else { | ||
| shouldParse4Privilege = true; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the file only contains root.db1.d1.s1 (on which the user has privileges), but the user does not have privileges on root.db1.s2, and skipIfNoPrivileges = false, then the file will not be transferred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course, "skipIf == false" means the pipe will stop for any data/schema without privilege.
...e/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java
Outdated
Show resolved
Hide resolved
| TABLE_PRIVILEGE_PARSE_VISITOR.process( | ||
| ((PipeSchemaRegionWritePlanEvent) event).getPlanNode(), userEntity); | ||
| treePrivilegeParseVisitor | ||
| .process(((PipeSchemaRegionWritePlanEvent) event).getPlanNode(), userEntity) | ||
| .flatMap(planNode -> TABLE_PRIVILEGE_PARSE_VISITOR.process(planNode, userEntity)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same node is processed by both treeVisitor and tableVisitor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is OK because one kind of node will only be parsed by one visitor. In the other one it just "pass by"
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
Outdated
Show resolved
Hide resolved
...mons/src/main/java/org/apache/iotdb/commons/pipe/datastructure/pattern/IoTDBTreePattern.java
Show resolved
Hide resolved
|



Description
As the title said.
This PR has:
for an unfamiliar reader.
for code coverage.
Key changed/added classes (or packages if there are too many classes) in this PR