diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java index 403e04208..f4f1b37f6 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/DatasourceServiceImpl.java @@ -37,6 +37,7 @@ import org.apache.seatunnel.app.service.ITableSchemaService; import org.apache.seatunnel.app.thirdparty.datasource.DataSourceClientFactory; import org.apache.seatunnel.app.thirdparty.framework.SeaTunnelOptionRuleWrapper; +import org.apache.seatunnel.app.utils.ConfigShadeUtil; import org.apache.seatunnel.common.utils.JsonUtils; import org.apache.seatunnel.datasource.plugin.api.DataSourcePluginInfo; import org.apache.seatunnel.datasource.plugin.api.DatasourcePluginTypeEnum; @@ -53,6 +54,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Service; @@ -93,6 +95,9 @@ public class DatasourceServiceImpl extends SeatunnelBaseServiceImpl protected static final String DEFAULT_DATASOURCE_PLUGIN_VERSION = "1.0.0"; + @Value("${datasource.encryption.type:default}") + private String datasourceEncryptionType; + @Override public String createDatasource( Integer userId, @@ -113,6 +118,7 @@ public String createDatasource( throw new SeatunnelException( SeatunnelErrorEnum.DATASOURCE_PRAM_NOT_ALLOWED_NULL, "datasourceConfig"); } + ConfigShadeUtil.encryptData(datasourceConfig, datasourceEncryptionType); String datasourceConfigStr = JsonUtils.toJsonString(datasourceConfig); Datasource datasource = Datasource.builder() @@ -171,6 +177,7 @@ public boolean updateDatasource( datasource.setUpdateTime(new Date()); datasource.setDescription(description); if (MapUtils.isNotEmpty(datasourceConfig)) { + ConfigShadeUtil.encryptData(datasourceConfig, datasourceEncryptionType); String configJson = JsonUtils.toJsonString(datasourceConfig); datasource.setDatasourceConfig(configJson); } @@ -208,6 +215,7 @@ public boolean testDatasourceConnectionAble( String pluginVersion, Map datasourceConfig) { funcPermissionCheck(SeatunnelFuncPermissionKeyConstant.DATASOURCE_TEST_CONNECT, userId); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); return DataSourceClientFactory.getDataSourceClient() .checkDataSourceConnectivity(pluginName, datasourceConfig); } @@ -227,6 +235,7 @@ public boolean testDatasourceConnectionAble(Integer userId, Long datasourceId) { String configJson = datasource.getDatasourceConfig(); Map datasourceConfig = JsonUtils.toMap(configJson, String.class, String.class); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); String pluginName = datasource.getPluginName(); return DataSourceClientFactory.getDataSourceClient() .checkDataSourceConnectivity(pluginName, datasourceConfig); @@ -276,6 +285,7 @@ public List queryDatabaseByDatasourceName(String datasourceName) { Map datasourceConfig = JsonUtils.toMap(config, String.class, String.class); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); return DataSourceClientFactory.getDataSourceClient() .getDatabases(pluginName, datasourceConfig); } @@ -435,6 +445,7 @@ public PageInfo queryDatasourceList( datasource.getDatasourceConfig(), String.class, String.class); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); datasourceRes.setDatasourceConfig(datasourceConfig); datasourceRes.setCreateUserId(datasource.getCreateUserId()); datasourceRes.setUpdateUserId(datasource.getUpdateUserId()); @@ -504,7 +515,10 @@ public Map queryDatasourceConfigById(String datasourceId) { throw new SeatunnelException(SeatunnelErrorEnum.DATASOURCE_NOT_FOUND, datasourceId); } String configJson = datasource.getDatasourceConfig(); - return JsonUtils.toMap(configJson, String.class, String.class); + Map datasourceConfig = + JsonUtils.toMap(configJson, String.class, String.class); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); + return datasourceConfig; } @Override @@ -604,6 +618,7 @@ private static DatasourceDetailRes getDatasourceDetailRes(Datasource datasource) Map datasourceConfig = JsonUtils.toMap(datasource.getDatasourceConfig(), String.class, String.class); + ConfigShadeUtil.decryptData(datasourceConfig, datasourceEncryptionType); // convert option rule datasourceDetailRes.setDatasourceConfig(datasourceConfig); return datasourceDetailRes; diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java index 8d0b79579..e08e82a2a 100644 --- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/impl/JobInstanceServiceImpl.java @@ -17,6 +17,7 @@ package org.apache.seatunnel.app.service.impl; +import org.apache.seatunnel.app.utils.ConfigShadeUtil; import org.apache.seatunnel.shade.com.fasterxml.jackson.core.type.TypeReference; import org.apache.seatunnel.shade.com.typesafe.config.Config; import org.apache.seatunnel.shade.com.typesafe.config.ConfigFactory; @@ -73,6 +74,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonProcessingException; @@ -123,6 +125,9 @@ public class JobInstanceServiceImpl extends SeatunnelBaseServiceImpl @Resource private IJobMetricsService jobMetricsService; + @Value("${datasource.encryption.type:default}") + private String datasourceEncryptionType; + @Override public JobExecutorRes createExecuteResource( @NonNull Integer userId, @NonNull Long jobDefineId, JobExecParam executeParam) { @@ -326,6 +331,7 @@ public String generateJobConfig( .setJson(false) .setComments(false) .setOriginComments(false)); + env = env + "\"shade.identifier\"=" + datasourceEncryptionType + "\n"; String jobConfig = SeaTunnelConfigUtil.generateConfig(env, sources, transforms, sinks); return JobUtils.replaceJobConfigPlaceholders(jobConfig, executeParam); } @@ -571,6 +577,7 @@ private Config parseConfigWithOptionRule( String connectorType, Map config, OptionRule optionRule) { + ConfigShadeUtil.encryptData(config, datasourceEncryptionType); return parseConfigWithOptionRule( pluginType, connectorType, ConfigFactory.parseMap(config), optionRule); } diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/ConfigShadeUtil.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/ConfigShadeUtil.java new file mode 100644 index 000000000..c32f7c0ea --- /dev/null +++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/utils/ConfigShadeUtil.java @@ -0,0 +1,42 @@ +package org.apache.seatunnel.app.utils; + + +import lombok.extern.slf4j.Slf4j; +import org.apache.seatunnel.app.common.Constants; +import org.apache.seatunnel.core.starter.utils.ConfigShadeUtils; + +import java.util.Map; + +@Slf4j +public class ConfigShadeUtil { + + public static void encryptData(Map datasourceConfig, String datasourceEncryptionType) { + String password = datasourceConfig.get(Constants.PASSWORD); + if(!password.isEmpty()) { + try { + datasourceConfig.replace( + Constants.PASSWORD, + ConfigShadeUtils.encryptOption( + datasourceEncryptionType, password)); + } catch (IllegalArgumentException ex) { + log.warn("encrypt password failed"); + } + } + } + + public static void decryptData(Map datasourceConfig, String datasourceEncryptionType) { + String password = datasourceConfig.get(Constants.PASSWORD); + if(!password.isEmpty()) { + try { + datasourceConfig.replace( + Constants.PASSWORD, + ConfigShadeUtils.decryptOption( + datasourceEncryptionType, password)); + } catch (IllegalArgumentException ex) { + log.warn("decrypt password failed as password is not encrypted"); + } + } + } + + +} diff --git a/seatunnel-server/seatunnel-app/src/main/resources/application.yml b/seatunnel-server/seatunnel-app/src/main/resources/application.yml index a85295a6f..5f3731495 100644 --- a/seatunnel-server/seatunnel-app/src/main/resources/application.yml +++ b/seatunnel-server/seatunnel-app/src/main/resources/application.yml @@ -38,6 +38,10 @@ jwt: secretKey: algorithm: HS256 +datasource: + encryption: + type: base64 + --- spring: config: