ruanwenjun commented on code in PR #18585:
URL:
https://github.com/apache/dolphinscheduler/pull/18585#discussion_r4011705649
##########
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/WorkflowDefinitionServiceImpl.java:
##########
@@ -262,6 +264,11 @@ public WorkflowDefinition createWorkflowDefinition(User
loginUser,
List<TaskDefinitionLog> taskDefinitionLogs =
generateTaskDefinitionList(taskDefinitionJson);
List<WorkflowTaskRelationLog> taskRelationList =
generateTaskRelationList(taskRelationJson, taskDefinitionLogs);
+
SensitivePropertyUtils.requireNoPlaceholder(GlobalParameterUtils.deserializeGlobalParameter(globalParams));
+ for (TaskDefinitionLog taskDefinitionLog :
CollectionUtils.emptyIfNull(taskDefinitionLogs)) {
+ taskDefinitionLog.setTaskParams(
+
SensitivePropertyUtils.mergeLocalParams(taskDefinitionLog.getTaskParams(),
null));
Review Comment:
Nit, is this line change the task params? seems don't need this line.
##########
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/utils/SensitivePropertyUtils.java:
##########
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.utils;
+
+import static
org.apache.dolphinscheduler.common.constants.Constants.LOCAL_PARAMS;
+import static
org.apache.dolphinscheduler.plugin.task.api.TaskConstants.LOCAL_PARAMS_LIST;
+
+import org.apache.dolphinscheduler.api.enums.Status;
+import org.apache.dolphinscheduler.api.exceptions.ServiceException;
+import org.apache.dolphinscheduler.common.utils.JSONUtils;
+import org.apache.dolphinscheduler.dao.entity.DagData;
+import org.apache.dolphinscheduler.dao.entity.TaskDefinition;
+import org.apache.dolphinscheduler.dao.entity.TaskInstance;
+import org.apache.dolphinscheduler.dao.entity.WorkflowDefinition;
+import org.apache.dolphinscheduler.dao.entity.WorkflowInstance;
+import org.apache.dolphinscheduler.plugin.task.api.model.Property;
+import org.apache.dolphinscheduler.plugin.task.api.utils.GlobalParameterUtils;
+import
org.apache.dolphinscheduler.plugin.task.api.utils.PropertySensitiveUtils;
+import org.apache.dolphinscheduler.plugin.task.api.utils.VarPoolUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import lombok.experimental.UtilityClass;
+
+import org.springframework.beans.BeanUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * HTTP-layer helpers for {@link Property#isSensitive()}.
+ * Values stay plaintext in DB. Query masks them as {@code ******}.
+ * Create rejects {@code ******}; Update {@link #merge}s it back to the old
value.
+ * Start: {@code ******} is replaced with the definition global plaintext.
+ */
+@UtilityClass
+public class SensitivePropertyUtils {
+
+ /** Create: {@code ******} is never a real value. */
+ public void requireNoPlaceholder(List<Property> properties) {
+ String invalidProp =
PropertySensitiveUtils.findPlaceholderProp(properties);
+ if (invalidProp != null) {
+ throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR,
+ "parameter '" + invalidProp
+ + "' cannot use ****** when creating; please
re-enter the value");
+ }
+ }
+
+ /**
+ * Update: restore DB plaintext for keep-original {@code ******}.
+ * Empty / null is a real empty value. {@code false→true} + {@code ******}
is allowed;
+ * {@code true→false} + {@code ******} is rejected.
+ */
+ public List<Property> merge(List<Property> submittedProperties,
List<Property> existingProperties) {
+ if (CollectionUtils.isEmpty(submittedProperties)) {
+ return submittedProperties;
+ }
+ String invalidProp =
PropertySensitiveUtils.findInvalidSensitivePlaceholderProp(
+ submittedProperties, existingProperties);
+ if (invalidProp != null) {
+ throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR,
+ "parameter '" + invalidProp
+ + "' cannot use ****** when creating, enabling, or
disabling sensitive; please re-enter the value");
+ }
+ return
PropertySensitiveUtils.mergeSensitiveValuePlaceholders(submittedProperties,
existingProperties);
+ }
+
+ /** Start: {@code ******} is replaced with the matching definition global
plaintext. */
+ public List<Property> restoreStartParams(List<Property> startParams,
List<Property> globalParams) {
+ if (CollectionUtils.isEmpty(startParams)) {
+ return startParams;
+ }
+ Map<String, Property> globals =
CollectionUtils.emptyIfNull(globalParams).stream()
+ .filter(Objects::nonNull)
+ .filter(property -> property.getProp() != null)
+ .collect(Collectors.toMap(Property::getProp,
Function.identity(), (left, right) -> right));
+ List<Property> restored = new ArrayList<>();
+ for (Property startParam : startParams) {
+ if (startParam == null) {
+ continue;
+ }
+ if
(!PropertySensitiveUtils.isSensitiveValuePlaceholder(startParam.getValue())) {
+ restored.add(startParam);
+ continue;
+ }
+ Property global = globals.get(startParam.getProp());
+ if (global != null) {
+ restored.add(PropertySensitiveUtils.copy(global));
+ }
+ }
+ return restored;
+ }
+
+ public String mergeLocalParams(String submittedTaskParams, String
existingTaskParams) {
+ return rewriteLocalParams(submittedTaskParams, submitted -> {
+ if (StringUtils.isEmpty(existingTaskParams)) {
+ requireNoPlaceholder(submitted);
+ return submitted;
+ }
+ return merge(submitted, getLocalParams(existingTaskParams));
+ });
+ }
+
+ /**
+ * Copy then mask for HTTP responses. Do not mask Service return values in
place.
+ * Nested {@link DagData} is remasked from the original (BeanUtils is
shallow).
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T mask(T source) {
+ if (source == null) {
+ return null;
+ }
+ if (source instanceof Map) {
+ return (T) maskLocalParamsMap((Map<String, Map<String, Object>>)
source);
+ }
+ T copy = copyBean(source);
+ if (copy instanceof WorkflowInstance) {
+ WorkflowInstance workflowInstance = (WorkflowInstance) copy;
+
workflowInstance.setGlobalParams(maskGlobalParams(workflowInstance.getGlobalParams()));
+
workflowInstance.setVarPool(maskVarPool(workflowInstance.getVarPool()));
+ workflowInstance.setDagData(mask(((WorkflowInstance)
source).getDagData()));
+ } else if (copy instanceof DagData) {
+ DagData dagData = (DagData) copy;
+ DagData original = (DagData) source;
+
dagData.setWorkflowDefinition(mask(original.getWorkflowDefinition()));
+ if (original.getTaskDefinitionList() != null) {
+
dagData.setTaskDefinitionList(original.getTaskDefinitionList().stream()
+ .map(SensitivePropertyUtils::mask)
+ .collect(Collectors.toList()));
+ }
+ } else if (copy instanceof WorkflowDefinition) {
+ WorkflowDefinition workflowDefinition = (WorkflowDefinition) copy;
+
workflowDefinition.setGlobalParams(maskGlobalParams(workflowDefinition.getGlobalParams()));
Review Comment:
Add different mask method is better.
```
public void mask(Map<String, Map<String, Object> source)
public void mask(DagData dagData)
public void mask(WorkflowDefinition workflow)
--
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]