diff --git a/src/backend/build.gradle b/src/backend/build.gradle index 867c4d6b44..89e354b33a 100644 --- a/src/backend/build.gradle +++ b/src/backend/build.gradle @@ -43,6 +43,17 @@ buildscript { } repositories { mavenLocal() + def extraMavenRepoUrls = System.getProperty("extraMavenRepoUrls") + if (extraMavenRepoUrls == null) { + extraMavenRepoUrls = System.getenv("extraMavenRepoUrls") + } + if (extraMavenRepoUrls != null) { + String[] repoUrls = extraMavenRepoUrls.trim().replace(" ", "").split(",") + for (String repoUrl : repoUrls) { + println("Add extra maven repo:" + repoUrl) + maven { url repoUrl } + } + } maven { url mavenRepoUrl } maven { url "https://plugins.gradle.org/m2/" } mavenCentral() @@ -119,6 +130,7 @@ ext { set('jcommanderVersion', "1.71") set('kubernetesJavaClientVersion', "11.0.4") set('springCloudKubernetesVersion', "2.0.6") + set('cryptoJavaSDKVersion', "1.0.1") if (System.getProperty("bkjobVersion")) { set('bkjobVersion', System.getProperty("bkjobVersion")) println "bkjobVersion:" + bkjobVersion @@ -161,6 +173,17 @@ allprojects { repositories { mavenLocal() + def extraMavenRepoUrls = System.getProperty("extraMavenRepoUrls") + if (extraMavenRepoUrls == null) { + extraMavenRepoUrls = System.getenv("extraMavenRepoUrls") + } + if (extraMavenRepoUrls != null) { + String[] repoUrls = extraMavenRepoUrls.trim().replace(" ", "").split(",") + for (String repoUrl : repoUrls) { + println("Add extra maven repo:" + repoUrl) + maven { url repoUrl } + } + } maven { url mavenRepoUrl } maven { url "https://plugins.gradle.org/m2/" } maven { @@ -298,6 +321,7 @@ subprojects { entry "hibernate-validator" } dependency "com.beust:jcommander:$jcommanderVersion" + dependency "com.tencent.bk.sdk:crypto-java-sdk:$cryptoJavaSDKVersion" } } dependencies { diff --git a/src/backend/commons/common-crypto/build.gradle b/src/backend/commons/common-crypto/build.gradle new file mode 100644 index 0000000000..95a9177c70 --- /dev/null +++ b/src/backend/commons/common-crypto/build.gradle @@ -0,0 +1,31 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +dependencies { + api project(':commons:common') + api project(':commons:common-utils') + api 'com.tencent.bk.sdk:crypto-java-sdk' + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/AESCryptor.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/AESCryptor.java new file mode 100644 index 0000000000..c97e0ef481 --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/AESCryptor.java @@ -0,0 +1,114 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +import com.tencent.bk.job.common.crypto.util.AESUtils; +import com.tencent.bk.sdk.crypto.annotation.Cryptor; +import com.tencent.bk.sdk.crypto.annotation.CryptorTypeEnum; +import com.tencent.bk.sdk.crypto.cryptor.AbstractSymmetricCryptor; +import com.tencent.bk.sdk.crypto.exception.CryptoException; +import org.slf4j.helpers.FormattingTuple; +import org.slf4j.helpers.MessageFormatter; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * 使用AES/CBC/PKCS5Padding的加密实现 + */ +@Cryptor(name = JobCryptorNames.AES_CBC, type = CryptorTypeEnum.SYMMETRIC) +public class AESCryptor extends AbstractSymmetricCryptor { + + @Override + public String getName() { + return JobCryptorNames.AES_CBC; + } + + @Override + public byte[] encryptIndeed(byte[] key, byte[] message) { + try { + return AESUtils.encrypt(message, key); + } catch (Exception e) { + FormattingTuple msg = MessageFormatter.arrayFormat( + "Fail to encrypt using {}, key.len={}, message.len={}", + new Object[]{ + getName(), + key.length, + message.length + } + ); + throw new CryptoException(msg.getMessage(), e); + } + } + + @Override + public byte[] decryptIndeed(byte[] key, byte[] encryptedMessage) { + try { + return AESUtils.decrypt(encryptedMessage, key); + } catch (Exception e) { + FormattingTuple msg = MessageFormatter.arrayFormat( + "Fail to decrypt using {}, key.len={}, encryptedMessage.len={}", + new Object[]{ + getName(), + key.length, + encryptedMessage.length + } + ); + throw new CryptoException(msg.getMessage(), e); + } + } + + @Override + public void encryptIndeed(String key, InputStream in, OutputStream out) { + try { + AESUtils.encrypt(in, out, key); + } catch (Exception e) { + FormattingTuple msg = MessageFormatter.arrayFormat( + "Fail to encrypt using {}, key.len={}", + new Object[]{ + getName(), + key.length() + } + ); + throw new CryptoException(msg.getMessage(), e); + } + } + + @Override + public void decryptIndeed(String key, InputStream in, OutputStream out) { + try { + AESUtils.decrypt(in, out, key); + } catch (Exception e) { + FormattingTuple msg = MessageFormatter.arrayFormat( + "Fail to decrypt using {}, key.len={}", + new Object[]{ + getName(), + key.length() + } + ); + throw new CryptoException(msg.getMessage(), e); + } + } +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoConfigService.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoConfigService.java new file mode 100644 index 0000000000..38b4182b7b --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoConfigService.java @@ -0,0 +1,103 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +/** + * 加密配置服务 + */ +@SuppressWarnings("unused") +@Slf4j +@Service +public class CryptoConfigService { + + private final EncryptConfig encryptConfig; + private final Map scenarioAlgorithms; + + public CryptoConfigService(@Autowired(required = false) EncryptConfig encryptConfig) { + this.encryptConfig = encryptConfig; + if (encryptConfig != null) { + this.scenarioAlgorithms = trimKeyValues(encryptConfig.getScenarioAlgorithms()); + } else { + this.scenarioAlgorithms = null; + } + } + + private Map trimKeyValues(Map map) { + if (map == null) { + return null; + } + Map resultMap = new HashMap<>(); + map.forEach((key, value) -> { + if (key != null) { + key = key.trim(); + } + if (value != null) { + value = value.trim(); + } + resultMap.put(key, value); + }); + return resultMap; + } + + /** + * 获取对称加密密钥 + * + * @return 对称加密密钥 + */ + public String getSymmetricPassword() { + return encryptConfig.getPassword(); + } + + /** + * 根据加密场景获取需要使用的加密算法 + * + * @param cryptoScenarioEnum 加密场景枚举值 + * @return 加密算法标识 + */ + public String getSymmetricAlgorithmByScenario(CryptoScenarioEnum cryptoScenarioEnum) { + if (cryptoScenarioEnum == null) { + return getDefaultSymmetricAlgorithm(); + } + if (scenarioAlgorithms != null && scenarioAlgorithms.containsKey(cryptoScenarioEnum.getValue())) { + return scenarioAlgorithms.get(cryptoScenarioEnum.getValue()); + } + return getDefaultSymmetricAlgorithm(); + } + + private String getDefaultSymmetricAlgorithm() { + if (encryptConfig.getType() == CryptoTypeEnum.SHANGMI) { + return CryptorNames.SM4; + } + return JobCryptorNames.AES_CBC; + } +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoScenarioEnum.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoScenarioEnum.java new file mode 100644 index 0000000000..17f06cf60c --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoScenarioEnum.java @@ -0,0 +1,61 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +/** + * 加密场景枚举值 + */ +public enum CryptoScenarioEnum { + // 脚本敏感参数 + SCRIPT_SENSITIVE_PARAM((byte) 0, "scriptSensitiveParam"), + // 密文变量 + CIPHER_VARIABLE((byte) 0, "cipherVariable"), + // DB账号的密码 + DATABASE_PASSWORD((byte) 0, "databasePassword"), + // 凭证信息 + CREDENTIAL((byte) 0, "credential"), + // 导出作业的密码 + EXPORT_JOB_PASSWORD((byte) 0, "exportJobPassword"), + // 导出作业的备份文件 + BACKUP_FILE((byte) 0, "backupFile"); + + // 加密类型:0为对称加密,1为非对称加密 + private final byte type; + // 场景标识 + private final String value; + + CryptoScenarioEnum(byte type, String value) { + this.type = type; + this.value = value; + } + + public String getValue() { + return value; + } + + public byte getType() { + return type; + } +} diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/AsymmetricEncryptor.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoTypeEnum.java similarity index 77% rename from src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/AsymmetricEncryptor.java rename to src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoTypeEnum.java index 629f63456f..e62cd98e10 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/AsymmetricEncryptor.java +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/CryptoTypeEnum.java @@ -22,19 +22,16 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.encrypt; +package com.tencent.bk.job.common.crypto; /** - * 非对称加密器 + * 加密类型枚举值 */ -public interface AsymmetricEncryptor extends Encryptor { +public enum CryptoTypeEnum { + + // 经典密码算法(RSA、AES等) + CLASSIC, + // 国家商用密码算法(SM2、SM4等) + SHANGMI - /** - * 校验消息的签名是否一致 通过公钥对消息内容进行校验signature内容(由私钥加签名) - * - * @param message 原消息内容 - * @param signature 消息的签名 - * @return 是否签名一致 - */ - boolean verify(String message, String signature); } diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/EncryptConfig.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/EncryptConfig.java new file mode 100644 index 0000000000..39b0d6ecaf --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/EncryptConfig.java @@ -0,0 +1,61 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +import com.tencent.bk.job.common.util.json.JsonUtils; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.Map; + +/** + * 加密配置 + */ +@ConfigurationProperties(prefix = "job.encrypt") +@ToString +@Getter +@Setter +@Slf4j +public class EncryptConfig { + + private CryptoTypeEnum type; + + private String password; + + /** + * 各个场景下使用的加密算法,不配置则使用默认算法 + */ + private Map scenarioAlgorithms = new HashMap<>(); + + @PostConstruct + public void print() { + log.info("EncryptConfig init: {}", JsonUtils.toJson(this)); + } +} diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/Encryptor.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/Encryptor.java similarity index 97% rename from src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/Encryptor.java rename to src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/Encryptor.java index 24f1a4b748..d9e631421b 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/Encryptor.java +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/Encryptor.java @@ -22,7 +22,7 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.encrypt; +package com.tencent.bk.job.common.crypto; /** * 加密器 diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/JobCryptorNames.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/JobCryptorNames.java new file mode 100644 index 0000000000..dba1a25b95 --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/JobCryptorNames.java @@ -0,0 +1,30 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +public class JobCryptorNames { + // 对称加密 + public static final String AES_CBC = "AES_CBC"; +} diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/RSAEncryptor.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/RSAEncryptor.java similarity index 67% rename from src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/RSAEncryptor.java rename to src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/RSAEncryptor.java index aa5ed36945..a795487046 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/encrypt/RSAEncryptor.java +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/RSAEncryptor.java @@ -22,39 +22,29 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.encrypt; +package com.tencent.bk.job.common.crypto; -import com.tencent.bk.job.common.util.crypto.RSAUtils; +import com.tencent.bk.job.common.crypto.util.RSAUtils; +import com.tencent.bk.sdk.crypto.exception.CryptoException; +import lombok.extern.slf4j.Slf4j; -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; import java.security.PublicKey; -public class RSAEncryptor implements AsymmetricEncryptor { - private PublicKey publicKey; +@Slf4j +public class RSAEncryptor implements Encryptor { - public RSAEncryptor(File rsaPubPermFile) throws IOException, GeneralSecurityException { - publicKey = RSAUtils.getPublicKey(rsaPubPermFile); - } + private final PublicKey publicKey; - public RSAEncryptor(String rsaPublicKeyBase64) throws IOException, GeneralSecurityException { + public RSAEncryptor(String rsaPublicKeyBase64) { publicKey = RSAUtils.getPublicKey(rsaPublicKeyBase64); } public String encrypt(String rawText) { try { return RSAUtils.encrypt(rawText, publicKey); - } catch (IOException | GeneralSecurityException e) { + } catch (CryptoException e) { + log.error("Fail to encrypt", e); return null; } } - - public boolean verify(String message, String signature) { - try { - return RSAUtils.verify(publicKey, message, signature); - } catch (Exception e) { - return false; - } - } } diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/SymmetricCryptoService.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/SymmetricCryptoService.java new file mode 100644 index 0000000000..9f4b2fa14d --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/SymmetricCryptoService.java @@ -0,0 +1,134 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto; + +import com.tencent.bk.sdk.crypto.cryptor.SymmetricCryptor; +import com.tencent.bk.sdk.crypto.cryptor.SymmetricCryptorFactory; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * 对称加密服务 + */ +@SuppressWarnings("unused") +@Slf4j +@Service +public class SymmetricCryptoService { + + private final CryptoConfigService cryptoConfigService; + private final Map cryptorMap = new HashMap<>(); + + @Autowired + public SymmetricCryptoService(CryptoConfigService cryptoConfigService) { + this.cryptoConfigService = cryptoConfigService; + } + + /** + * 对流数据加密,加密后的数据写入输出流中 + * + * @param key 密钥 + * @param in 输入流 + * @param out 输出流 + * @param cryptoScenarioEnum 加密场景 + */ + public void encrypt(String key, + InputStream in, + OutputStream out, + CryptoScenarioEnum cryptoScenarioEnum) { + String algorithm = cryptoConfigService.getSymmetricAlgorithmByScenario(cryptoScenarioEnum); + SymmetricCryptor cryptor = cryptorMap.computeIfAbsent(algorithm, SymmetricCryptorFactory::getCryptor); + cryptor.encrypt(key, in, out); + } + + /** + * 对明文信息加密,返回Base64编码的加密后的密文信息 + * + * @param message 要加密的明文信息,不可为空 + * @param cryptoScenarioEnum 加密场景 + * @return Base64编码的加密后的密文信息 + */ + public String encryptToBase64Str(String message, CryptoScenarioEnum cryptoScenarioEnum) { + return encryptToBase64Str(message, cryptoConfigService.getSymmetricAlgorithmByScenario(cryptoScenarioEnum)); + } + + /** + * 对明文信息加密,返回Base64编码的加密后的密文信息,明文为空则原样返回 + * + * @param message 要加密的明文信息 + * @param algorithm 加密算法,不可为空 + * @return Base64编码的加密后的密文信息 + */ + public String encryptToBase64Str(String message, String algorithm) { + assert StringUtils.isNotEmpty(algorithm); + if (StringUtils.isEmpty(message)) { + return message; + } + SymmetricCryptor cryptor = cryptorMap.computeIfAbsent(algorithm, SymmetricCryptorFactory::getCryptor); + return cryptor.encrypt(cryptoConfigService.getSymmetricPassword(), message); + } + + /** + * 对流数据解密,解密后的数据写入输出流中 + * + * @param key 密钥 + * @param in 输入流 + * @param out 输出流 + * @param algorithm 解密算法 + */ + public void decrypt(String key, + BufferedInputStream in, + OutputStream out, + String algorithm) { + SymmetricCryptor cryptor = cryptorMap.computeIfAbsent(algorithm, SymmetricCryptorFactory::getCryptor); + cryptor.decrypt(key, in, out); + } + + /** + * 对Base64编码的加密后的密文信息解密,返回解密后的明文,密文为空则原样返回 + * + * @param base64EncryptedMessage Base64编码的加密后的密文信息 + * @param algorithm 加密算法,不可为空 + * @return 解密后的明文信息 + */ + public String decrypt(String base64EncryptedMessage, String algorithm) { + assert StringUtils.isNotEmpty(algorithm); + if (StringUtils.isEmpty(base64EncryptedMessage)) { + return base64EncryptedMessage; + } + SymmetricCryptor cryptor = cryptorMap.computeIfAbsent(algorithm, SymmetricCryptorFactory::getCryptor); + return cryptor.decrypt( + cryptoConfigService.getSymmetricPassword(), + base64EncryptedMessage + ); + } +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/CipherVariableCryptoService.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/CipherVariableCryptoService.java new file mode 100644 index 0000000000..75a4120ffc --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/CipherVariableCryptoService.java @@ -0,0 +1,86 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto.scenario; + +import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 密文变量相关加解密服务 + */ +@Slf4j +@Service +public class CipherVariableCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public CipherVariableCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public String getCipherVariableEncryptAlgorithmByCipher(TaskVariableTypeEnum taskVariableTypeEnum, String cipher) { + if (!isCipherVariable(taskVariableTypeEnum) || StringUtils.isEmpty(cipher)) { + return CryptorNames.NONE; + } + String algorithm = CryptorMetaUtil.getCryptorNameFromCipher(cipher); + if (algorithm != null) { + return algorithm; + } + return CryptorNames.NONE; + } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean isCipherVariable(TaskVariableTypeEnum taskVariableTypeEnum) { + return TaskVariableTypeEnum.CIPHER == taskVariableTypeEnum; + } + + public String encryptTaskVariableIfNeeded(TaskVariableTypeEnum taskVariableTypeEnum, String taskVariable) { + if (!isCipherVariable(taskVariableTypeEnum)) { + return taskVariable; + } + return symmetricCryptoService.encryptToBase64Str(taskVariable, CryptoScenarioEnum.CIPHER_VARIABLE); + } + + public String decryptTaskVariableIfNeeded(TaskVariableTypeEnum taskVariableTypeEnum, + String encryptedTaskVariable) { + if (!isCipherVariable(taskVariableTypeEnum)) { + return encryptedTaskVariable; + } + String algorithm = getCipherVariableEncryptAlgorithmByCipher(taskVariableTypeEnum, encryptedTaskVariable); + if (StringUtils.isBlank(algorithm)) { + return encryptedTaskVariable; + } + return symmetricCryptoService.decrypt(encryptedTaskVariable, algorithm); + } + +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/DbPasswordCryptoService.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/DbPasswordCryptoService.java new file mode 100644 index 0000000000..f88cba43a2 --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/DbPasswordCryptoService.java @@ -0,0 +1,87 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto.scenario; + +import com.tencent.bk.job.common.constant.AccountCategoryEnum; +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.JobCryptorNames; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * DB账号密码相关加解密服务 + */ +@Slf4j +@Service +public class DbPasswordCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public DbPasswordCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public String getDbPasswordEncryptAlgorithmByCipher(AccountCategoryEnum accountCategoryEnum, String cipher) { + if (!isDbAccount(accountCategoryEnum) || StringUtils.isEmpty(cipher)) { + return CryptorNames.NONE; + } + String algorithm = CryptorMetaUtil.getCryptorNameFromCipher(cipher); + if (algorithm != null) { + return algorithm; + } + return JobCryptorNames.AES_CBC; + } + + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private boolean isDbAccount(AccountCategoryEnum accountCategoryEnum) { + return AccountCategoryEnum.DB == accountCategoryEnum; + } + + public String encryptDbPasswordIfNeeded(AccountCategoryEnum accountCategoryEnum, String dbPassword) { + if (!isDbAccount(accountCategoryEnum)) { + return dbPassword; + } + return symmetricCryptoService.encryptToBase64Str(dbPassword, CryptoScenarioEnum.DATABASE_PASSWORD); + } + + public String decryptDbPasswordIfNeeded(AccountCategoryEnum accountCategoryEnum, + String encryptedDbPassword) { + if (!isDbAccount(accountCategoryEnum)) { + return encryptedDbPassword; + } + String algorithm = getDbPasswordEncryptAlgorithmByCipher(accountCategoryEnum, encryptedDbPassword); + if (StringUtils.isBlank(algorithm)) { + return encryptedDbPassword; + } + return symmetricCryptoService.decrypt(encryptedDbPassword, algorithm); + } + +} diff --git a/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/SensitiveParamCryptoService.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/SensitiveParamCryptoService.java new file mode 100644 index 0000000000..31054d3911 --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/scenario/SensitiveParamCryptoService.java @@ -0,0 +1,76 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.common.crypto.scenario; + +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 脚本敏感参数相关加解密服务 + */ +@Slf4j +@Service +public class SensitiveParamCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public SensitiveParamCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public String getSecureParamEncryptAlgorithmByCipher(boolean secureParam, String cipher) { + if (!secureParam || StringUtils.isEmpty(cipher)) { + return CryptorNames.NONE; + } + String algorithm = CryptorMetaUtil.getCryptorNameFromCipher(cipher); + if (algorithm != null) { + return algorithm; + } + return CryptorNames.NONE; + } + + public String encryptParamIfNeeded(boolean secureParam, String param) { + if (!secureParam) { + return param; + } + return symmetricCryptoService.encryptToBase64Str(param, CryptoScenarioEnum.SCRIPT_SENSITIVE_PARAM); + } + + public String decryptParamIfNeeded(boolean secureParam, String encryptedParam) { + if (!secureParam) { + return encryptedParam; + } + String algorithm = getSecureParamEncryptAlgorithmByCipher(secureParam, encryptedParam); + return symmetricCryptoService.decrypt(encryptedParam, algorithm); + } + +} diff --git a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/AESUtils.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/AESUtils.java similarity index 64% rename from src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/AESUtils.java rename to src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/AESUtils.java index d8ec577ccc..a6b98a87ef 100644 --- a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/AESUtils.java +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/AESUtils.java @@ -22,22 +22,26 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.util.crypto; +package com.tencent.bk.job.common.crypto.util; import com.tencent.bk.job.common.util.Base64Util; +import com.tencent.bk.sdk.crypto.exception.CryptoException; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.helpers.MessageFormatter; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; +import java.util.Arrays; +@Slf4j public class AESUtils { /** * 加密/解密算法/工作模式/填充方式 @@ -45,36 +49,14 @@ public class AESUtils { private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding"; /** - * 加密数据 - * - * @param data 待加密数据 - * @param password 密钥 - * @return byte[] 加密后的数据 - */ - public static byte[] encrypt(byte[] data, String password) throws Exception { - return encrypt(data, password.getBytes(StandardCharsets.UTF_8)); - } - - /** - * 加密数据 + * 加密数据,并是使用base64编码 * * @param data 待加密数据 * @param password 密钥 * @return byte[] 加密后的数据 */ - public static byte[] encrypt(String data, String password) throws Exception { - return encrypt(data.getBytes(StandardCharsets.UTF_8), password.getBytes(StandardCharsets.UTF_8)); - } - - /** - * 加密数据 - * - * @param data 待加密数据 - * @param password 密钥 - * @return String 加密后的数据 - */ - public static String encryptToBase64EncodedCipherText(byte[] data, String password) throws Exception { - return Base64Util.encodeContentToStr(encrypt(data, password.getBytes(StandardCharsets.UTF_8))); + public static String encryptToBase64EncodedCipherText(String data, String password) throws CryptoException { + return Base64Util.encodeContentToStr(encrypt(data, password)); } /** @@ -84,41 +66,103 @@ public static String encryptToBase64EncodedCipherText(byte[] data, String passwo * @param password 密钥 * @return String 解密后的数据 */ - public static String decryptBase64EncodedDataToPlainText(String data, String password) throws Exception { + public static String decryptBase64EncodedDataToPlainText(String data, String password) throws CryptoException { return decryptToPlainText(Base64Util.decodeContentToByte(data), password); } /** - * 加密数据,并是使用base64编码 + * 加密数据 * - * @param data 待加密数据 - * @param password 密钥 + * @param data 待加密数据 + * @param key 密钥 * @return byte[] 加密后的数据 */ - public static String encryptToBase64EncodedCipherText(String data, String password) throws Exception { - return Base64Util.encodeContentToStr(encrypt(data, password)); + public static byte[] encrypt(byte[] data, byte[] key) throws CryptoException { + byte[] iv; + byte[] finalData; + try { + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(cipher, key)); + + iv = cipher.getIV(); + finalData = cipher.doFinal(data); + } catch (Exception e) { + String msg = MessageFormatter.arrayFormat( + "Fail to encrypt using {}, data.len={}, key.len={}", + new Object[]{CIPHER_ALGORITHM, data.length, key.length} + ).getMessage(); + throw new CryptoException(msg, e); + } + if (iv == null) { + throw new RuntimeException(String.format("CIPHER_ALGORITHM %s is invalid", CIPHER_ALGORITHM)); + } + byte[] finalDataWithIv = new byte[finalData.length + iv.length]; + System.arraycopy(iv, 0, finalDataWithIv, 0, iv.length); + System.arraycopy(finalData, 0, finalDataWithIv, iv.length, finalData.length); + return finalDataWithIv; } /** * 解密数据 * - * @param data 待解密数据 - * @param password 密钥 + * @param data 待解密数据 + * @param key 密钥 * @return byte[] 解密后的数据 */ - public static byte[] decrypt(byte[] data, String password) throws Exception { - return decrypt(data, password.getBytes(StandardCharsets.UTF_8)); + public static byte[] decrypt(byte[] data, byte[] key) throws CryptoException { + try { + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.DECRYPT_MODE, getKeySpec(cipher, key), getIvSpec(cipher, data)); + byte[] dataWithoutIv = new byte[data.length - cipher.getBlockSize()]; + System.arraycopy(data, cipher.getBlockSize(), dataWithoutIv, + 0, data.length - cipher.getBlockSize()); + return cipher.doFinal(dataWithoutIv); + } catch (Exception e) { + String msg = MessageFormatter.arrayFormat( + "Fail to decrypt using {}, data.len={}, key.len={}", + new Object[]{CIPHER_ALGORITHM, data.length, key.length} + ).getMessage(); + throw new CryptoException(msg, e); + } } - /** - * 解密数据 - * - * @param data 待解密数据 - * @param password 密钥 - * @return byte[] 解密后的数据 - */ - public static String decryptToPlainText(byte[] data, String password) throws Exception { - return new String(decrypt(data, password.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + public static void encrypt(InputStream in, OutputStream out, String password) throws CryptoException { + byte[] key = password.getBytes(StandardCharsets.UTF_8); + try { + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(cipher, key)); + byte[] arr = cipher.getIV(); + if (arr == null) { + throw new RuntimeException(String.format("CIPHER_ALGORITHM %s is invalid", CIPHER_ALGORITHM)); + } + out.write(arr); + write(in, out, cipher); + } catch (Exception e) { + String msg = MessageFormatter.format( + "Fail to encrypt using {}, password.len={}", CIPHER_ALGORITHM, password.length() + ).getMessage(); + throw new CryptoException(msg, e); + } + } + + public static void decrypt(InputStream in, OutputStream out, String password) throws CryptoException { + try { + log.debug("decrypt: in.available={}", in.available()); + byte[] key = password.getBytes(StandardCharsets.UTF_8); + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + byte[] iv = new byte[cipher.getBlockSize()]; + if (in.read(iv) < iv.length) { + throw new RuntimeException(); + } + log.debug("decrypt: iv={}", Arrays.toString(iv)); + cipher.init(Cipher.DECRYPT_MODE, getKeySpec(cipher, key), new IvParameterSpec(iv)); + write(in, out, cipher); + } catch (Exception e) { + String msg = MessageFormatter.format( + "Fail to decrypt using {}, password.len={}", CIPHER_ALGORITHM, password.length() + ).getMessage(); + throw new CryptoException(msg, e); + } } /** @@ -128,47 +172,19 @@ public static String decryptToPlainText(byte[] data, String password) throws Exc * @param password 密钥 * @return byte[] 解密后的数据 */ - public static String decryptToPlainText(String data, String password) throws Exception { - return new String(decrypt(data.getBytes(StandardCharsets.UTF_8), - password.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + private static String decryptToPlainText(byte[] data, String password) throws CryptoException { + return new String(decrypt(data, password.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); } /** * 加密数据 * - * @param data 待加密数据 - * @param key 密钥 + * @param data 待加密数据 + * @param password 密钥 * @return byte[] 加密后的数据 */ - public static byte[] encrypt(byte[] data, byte[] key) throws Exception { - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(cipher, key)); - - byte[] iv = cipher.getIV(); - byte[] finalData = cipher.doFinal(data); - if (iv == null) { - throw new RuntimeException(String.format("CIPHER_ALGORITHM %s is invalid", CIPHER_ALGORITHM)); - } - byte[] finalDataWithIv = new byte[finalData.length + iv.length]; - System.arraycopy(iv, 0, finalDataWithIv, 0, iv.length); - System.arraycopy(finalData, 0, finalDataWithIv, iv.length, finalData.length); - return finalDataWithIv; - } - - /** - * 解密数据 - * - * @param data 待解密数据 - * @param key 密钥 - * @return byte[] 解密后的数据 - */ - public static byte[] decrypt(byte[] data, byte[] key) throws Exception { - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - cipher.init(Cipher.DECRYPT_MODE, getKeySpec(cipher, key), getIvSpec(cipher, data)); - byte[] dataWithoutIv = new byte[data.length - cipher.getBlockSize()]; - System.arraycopy(data, cipher.getBlockSize(), dataWithoutIv, - 0, data.length - cipher.getBlockSize()); - return cipher.doFinal(dataWithoutIv); + private static byte[] encrypt(String data, String password) throws CryptoException { + return encrypt(data.getBytes(StandardCharsets.UTF_8), password.getBytes(StandardCharsets.UTF_8)); } private static IvParameterSpec getIvSpec(Cipher cipher, byte[] data) { @@ -186,34 +202,7 @@ private static SecretKeySpec getKeySpec(Cipher cipher, byte[] key) return new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"); } - public static void encrypt(File inFile, File outFile, String password) throws Exception { - byte[] key = password.getBytes(StandardCharsets.UTF_8); - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - cipher.init(Cipher.ENCRYPT_MODE, getKeySpec(cipher, key)); - try (FileInputStream in = new FileInputStream(inFile); FileOutputStream out = new FileOutputStream(outFile)) { - byte[] arr = cipher.getIV(); - if (arr == null) { - throw new RuntimeException(String.format("CIPHER_ALGORITHM %s is invalid", CIPHER_ALGORITHM)); - } - out.write(arr); - write(in, out, cipher); - } - } - - public static void decrypt(File inFile, File outFile, String password) throws Exception { - byte[] key = password.getBytes(StandardCharsets.UTF_8); - Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); - try (FileInputStream in = new FileInputStream(inFile); FileOutputStream out = new FileOutputStream(outFile)) { - byte[] iv = new byte[cipher.getBlockSize()]; - if (in.read(iv) < iv.length) { - throw new RuntimeException(); - } - cipher.init(Cipher.DECRYPT_MODE, getKeySpec(cipher, key), new IvParameterSpec(iv)); - write(in, out, cipher); - } - } - - private static void write(FileInputStream in, FileOutputStream out, Cipher cipher) throws Exception { + private static void write(InputStream in, OutputStream out, Cipher cipher) throws Exception { byte[] iBuffer = new byte[1024]; int len; while ((len = in.read(iBuffer)) != -1) { diff --git a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/RSAUtils.java b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/RSAUtils.java similarity index 53% rename from src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/RSAUtils.java rename to src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/RSAUtils.java index 08d7f5909e..b89561354b 100644 --- a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/crypto/RSAUtils.java +++ b/src/backend/commons/common-crypto/src/main/java/com/tencent/bk/job/common/crypto/util/RSAUtils.java @@ -22,17 +22,22 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.util.crypto; +package com.tencent.bk.job.common.crypto.util; import com.google.common.collect.Lists; import com.tencent.bk.job.common.util.Base64Util; +import com.tencent.bk.sdk.crypto.exception.CryptoException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.StringUtils; +import org.slf4j.helpers.MessageFormatter; import javax.crypto.Cipher; -import java.io.*; -import java.nio.charset.StandardCharsets; -import java.security.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; @@ -44,7 +49,6 @@ */ public class RSAUtils { private static final String KEY_ALGORITHM = "RSA"; - private static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; private static final String BEGIN_ENCRYPTED_PRIVATE_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; private static final String END_ENCRYPTED_PRIVATE_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; @@ -59,24 +63,48 @@ public class RSAUtils { private static final String CHARSET_NAME = "UTF-8"; private static final String LINE_SPLIT = "\n"; - private static List SKIP_STR = Lists.newArrayList( + private static final List SKIP_STR = Lists.newArrayList( BEGIN_PRIVATE_KEY, END_PRIVATE_KEY, BEGIN_PUBLIC_KEY, END_PUBLIC_KEY, BEGIN_ENCRYPTED_PRIVATE_KEY, END_ENCRYPTED_PRIVATE_KEY, BEGIN_RSA_PRIVATE_KEY, END_RSA_PRIVATE_KEY ); - private static String getPermKey(File permFile) throws IOException { - StringBuilder strKeyPEM = new StringBuilder(2048); - try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(permFile), - StandardCharsets.UTF_8))) { - String line; - while ((line = br.readLine()) != null) { - if (SKIP_STR.contains(line)) { - continue; - } - strKeyPEM.append(line).append(LINE_SPLIT); - } + public static RSAPrivateKey getPrivateKey(String rsaPrivateKeyBase64) throws CryptoException { + try { + String privateKeyPEM = getPermKey(rsaPrivateKeyBase64); + byte[] encoded = Base64.decodeBase64(privateKeyPEM); + return (RSAPrivateKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(encoded)); + } catch (Exception e) { + String msg = MessageFormatter.arrayFormat( + "Fail to getPrivateKey using {}, rsaPrivateKeyBase64.len={}", + new Object[]{KEY_ALGORITHM, rsaPrivateKeyBase64.length()} + ).getMessage(); + throw new CryptoException(msg, e); + } + } + + public static RSAPublicKey getPublicKey(String rsaPublicKeyBase64) throws CryptoException { + try { + byte[] encoded = Base64.decodeBase64(getPermKey(rsaPublicKeyBase64)); + return (RSAPublicKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(encoded)); + } catch (Exception e) { + String msg = MessageFormatter.arrayFormat( + "Fail to getPublicKey using {}, rsaPublicKeyBase64={}", + new Object[]{KEY_ALGORITHM, rsaPublicKeyBase64} + ).getMessage(); + throw new CryptoException(msg, e); + } + } + + public static String encrypt(String rawText, PublicKey publicKey) throws CryptoException { + try { + return encrypt(rawText.getBytes(CHARSET_NAME), publicKey); + } catch (Exception e) { + String msg = MessageFormatter.arrayFormat( + "Fail to getPublicKey using {}, rawText.len={}, publicKey={}", + new Object[]{KEY_ALGORITHM, rawText.length(), publicKey} + ).getMessage(); + throw new CryptoException(msg, e); } - return strKeyPEM.toString(); } private static String getPermKey(String permBase64) throws IOException { @@ -97,58 +125,10 @@ private static String getPermKey(String permBase64) throws IOException { return strKeyPEM.toString(); } - - public static RSAPrivateKey getPrivateKey(File rsaPrivatePermFile) throws IOException, GeneralSecurityException { - String privateKeyPEM = getPermKey(rsaPrivatePermFile); - byte[] encoded = Base64.decodeBase64(privateKeyPEM); - return (RSAPrivateKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(encoded)); - } - - public static RSAPrivateKey getPrivateKey(String rsaPrivateKeyBase64) throws IOException, GeneralSecurityException { - String privateKeyPEM = getPermKey(rsaPrivateKeyBase64); - byte[] encoded = Base64.decodeBase64(privateKeyPEM); - return (RSAPrivateKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(encoded)); - } - - public static RSAPublicKey getPublicKey(File rsaPublicPermFile) throws IOException, GeneralSecurityException { - String publicKeyPEM = getPermKey(rsaPublicPermFile); - byte[] encoded = Base64.decodeBase64(publicKeyPEM); - return (RSAPublicKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(encoded)); - } - - public static RSAPublicKey getPublicKey(String rsaPublicKeyBase64) throws IOException, GeneralSecurityException { - byte[] encoded = Base64.decodeBase64(getPermKey(rsaPublicKeyBase64)); - return (RSAPublicKey) KeyFactory.getInstance(KEY_ALGORITHM).generatePublic(new X509EncodedKeySpec(encoded)); - } - - public static String sign(PrivateKey privateKey, - String message) throws NoSuchAlgorithmException, InvalidKeyException, - SignatureException, UnsupportedEncodingException { - Signature sign = Signature.getInstance(SIGNATURE_ALGORITHM); - sign.initSign(privateKey); - sign.update(message.getBytes(CHARSET_NAME)); - return new String(Base64.encodeBase64(sign.sign()), CHARSET_NAME); - } - - public static boolean verify(PublicKey publicKey, String message, - String signature) throws SignatureException, NoSuchAlgorithmException, - UnsupportedEncodingException, InvalidKeyException { - Signature sign = Signature.getInstance(SIGNATURE_ALGORITHM); - sign.initVerify(publicKey); - sign.update(message.getBytes(CHARSET_NAME)); - return sign.verify(Base64.decodeBase64(signature.getBytes(CHARSET_NAME))); - } - - public static String encrypt(String rawText, PublicKey publicKey) throws IOException, GeneralSecurityException { + private static String encrypt(byte[] messageBytes, + PublicKey publicKey) throws GeneralSecurityException { Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); cipher.init(Cipher.ENCRYPT_MODE, publicKey); - return Base64.encodeBase64String(cipher.doFinal(rawText.getBytes(CHARSET_NAME))); - } - - public static String decrypt(String cipherText, - PrivateKey privateKey) throws IOException, GeneralSecurityException { - Cipher cipher = Cipher.getInstance(KEY_ALGORITHM); - cipher.init(Cipher.DECRYPT_MODE, privateKey); - return new String(cipher.doFinal(Base64.decodeBase64(cipherText)), CHARSET_NAME); + return Base64.encodeBase64String(cipher.doFinal(messageBytes)); } } diff --git a/src/backend/commons/common-crypto/src/main/resources/META-INF/services/com.tencent.bk.sdk.crypto.cryptor.SymmetricCryptor b/src/backend/commons/common-crypto/src/main/resources/META-INF/services/com.tencent.bk.sdk.crypto.cryptor.SymmetricCryptor new file mode 100644 index 0000000000..e91405d3e9 --- /dev/null +++ b/src/backend/commons/common-crypto/src/main/resources/META-INF/services/com.tencent.bk.sdk.crypto.cryptor.SymmetricCryptor @@ -0,0 +1 @@ +com.tencent.bk.job.common.crypto.AESCryptor diff --git a/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/crypto/AESUtilsTest.java b/src/backend/commons/common-crypto/src/test/java/com/tencent/bk/job/common/crypto/util/AESUtilsTest.java similarity index 84% rename from src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/crypto/AESUtilsTest.java rename to src/backend/commons/common-crypto/src/test/java/com/tencent/bk/job/common/crypto/util/AESUtilsTest.java index bcc191d214..2ae8fcb5ea 100644 --- a/src/backend/commons/common-utils/src/test/java/com/tencent/bk/job/common/util/crypto/AESUtilsTest.java +++ b/src/backend/commons/common-crypto/src/test/java/com/tencent/bk/job/common/crypto/util/AESUtilsTest.java @@ -22,27 +22,26 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.util.crypto; +package com.tencent.bk.job.common.crypto.util; +import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; - public class AESUtilsTest { @Test - void testEncryptToBase64EncodedCipherText() throws Exception { + void testEncryptToBase64EncodedCipherText() { String text = "job"; String encryptPassword = "job#123"; String encryptedData = AESUtils.encryptToBase64EncodedCipherText(text, encryptPassword); - assertThat(encryptedData).isNotEmpty(); + AssertionsForClassTypes.assertThat(encryptedData).isNotEmpty(); } @Test - void testDecryptBase64EncodedCipherText() throws Exception { + void testDecryptBase64EncodedCipherText() { String encryptedBase64EncodedData = "GQ6kLqtMevL8z/kXGVANQ+VP5o2Bt30yzXALfZbeOoY="; String encryptPassword = "job#123"; String decodeData = AESUtils.decryptBase64EncodedDataToPlainText(encryptedBase64EncodedData, encryptPassword); - assertThat(decodeData).isEqualTo("job"); + AssertionsForClassTypes.assertThat(decodeData).isEqualTo("job"); } } diff --git a/src/backend/commons/common-jwt/build.gradle b/src/backend/commons/common-jwt/build.gradle new file mode 100644 index 0000000000..1f45f95659 --- /dev/null +++ b/src/backend/commons/common-jwt/build.gradle @@ -0,0 +1,29 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +dependencies { + api project(':commons:common-crypto') + api 'com.google.guava:guava' + api 'io.jsonwebtoken:jjwt' +} diff --git a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/BasicJwtManager.java b/src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/BasicJwtManager.java similarity index 91% rename from src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/BasicJwtManager.java rename to src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/BasicJwtManager.java index 10ebb6b3ca..d691ec92fc 100644 --- a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/BasicJwtManager.java +++ b/src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/BasicJwtManager.java @@ -22,19 +22,17 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.common.util.jwt; +package com.tencent.bk.job.common.jwt; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import com.tencent.bk.job.common.util.crypto.RSAUtils; +import com.tencent.bk.job.common.crypto.util.RSAUtils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import lombok.extern.slf4j.Slf4j; -import java.io.IOException; -import java.security.GeneralSecurityException; import java.security.PrivateKey; import java.security.PublicKey; import java.time.Instant; @@ -51,17 +49,16 @@ public class BasicJwtManager implements JwtManager { private final Cache tokenCache = CacheBuilder.newBuilder() .maximumSize(9999).expireAfterWrite(5, TimeUnit.MINUTES).build(); - public BasicJwtManager(String privateKeyBase64, - String publicKeyBase64) throws IOException, GeneralSecurityException { + public BasicJwtManager(String privateKeyBase64, String publicKeyBase64) { this.privateKey = RSAUtils.getPrivateKey(privateKeyBase64); this.publicKey = RSAUtils.getPublicKey(publicKeyBase64); log.info("Init JwtManager successfully!"); } /** - * 获取JWT jwt token + * 获取 jwt token * - * @return + * @return jwt token */ @Override public String getToken() { @@ -89,7 +86,7 @@ public String generateToken() { * 验证JWT * * @param token jwt token - * @return + * @return 是否通过 */ @Override public boolean verifyJwt(String token) { diff --git a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/JwtManager.java b/src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/JwtManager.java similarity index 75% rename from src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/JwtManager.java rename to src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/JwtManager.java index edfbf16267..3af1eacfb1 100644 --- a/src/backend/commons/common-utils/src/main/java/com/tencent/bk/job/common/util/jwt/JwtManager.java +++ b/src/backend/commons/common-jwt/src/main/java/com/tencent/bk/job/common/jwt/JwtManager.java @@ -1,4 +1,4 @@ -package com.tencent.bk.job.common.util.jwt; +package com.tencent.bk.job.common.jwt; public interface JwtManager { String getToken(); diff --git a/src/backend/commons/common-security/build.gradle b/src/backend/commons/common-security/build.gradle index e540f42654..9dd2dfe762 100644 --- a/src/backend/commons/common-security/build.gradle +++ b/src/backend/commons/common-security/build.gradle @@ -24,6 +24,7 @@ dependencies { api project(':commons:common-utils') + api project(':commons:common-jwt') implementation 'io.jsonwebtoken:jjwt' implementation 'com.google.guava:guava' implementation 'org.springframework.cloud:spring-cloud-starter-openfeign' diff --git a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/autoconfigure/ServiceSecurityAutoConfiguration.java b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/autoconfigure/ServiceSecurityAutoConfiguration.java index 929c828213..5792b83cfb 100644 --- a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/autoconfigure/ServiceSecurityAutoConfiguration.java +++ b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/autoconfigure/ServiceSecurityAutoConfiguration.java @@ -25,7 +25,7 @@ package com.tencent.bk.job.common.security.autoconfigure; import com.tencent.bk.job.common.security.jwt.AutoUpdateJwtManager; -import com.tencent.bk.job.common.util.jwt.JwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; diff --git a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignBasicAuthRequestInterceptor.java b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignBasicAuthRequestInterceptor.java index cca93f1d90..20ce1124aa 100644 --- a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignBasicAuthRequestInterceptor.java +++ b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignBasicAuthRequestInterceptor.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.common.security.feign; -import com.tencent.bk.job.common.util.jwt.JwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import feign.RequestInterceptor; import feign.RequestTemplate; import lombok.extern.slf4j.Slf4j; diff --git a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignSecurityConfiguration.java b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignSecurityConfiguration.java index d9ca0cb5df..3bcb543977 100644 --- a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignSecurityConfiguration.java +++ b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/feign/FeignSecurityConfiguration.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.common.security.feign; -import com.tencent.bk.job.common.util.jwt.JwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -36,7 +36,6 @@ public class FeignSecurityConfiguration { * Feign 服务认证拦截 * * @param jwtManager jwt管理 - * @return */ @Bean public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor(@Autowired JwtManager jwtManager) { diff --git a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/jwt/AutoUpdateJwtManager.java b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/jwt/AutoUpdateJwtManager.java index 76dc95b062..81d05b7e8d 100644 --- a/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/jwt/AutoUpdateJwtManager.java +++ b/src/backend/commons/common-security/src/main/java/com/tencent/bk/job/common/security/jwt/AutoUpdateJwtManager.java @@ -1,16 +1,12 @@ package com.tencent.bk.job.common.security.jwt; -import com.tencent.bk.job.common.util.jwt.BasicJwtManager; +import com.tencent.bk.job.common.jwt.BasicJwtManager; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; -import java.io.IOException; -import java.security.GeneralSecurityException; - @Slf4j public class AutoUpdateJwtManager extends BasicJwtManager { - public AutoUpdateJwtManager(String privateKeyBase64, String publicKeyBase64) - throws IOException, GeneralSecurityException { + public AutoUpdateJwtManager(String privateKeyBase64, String publicKeyBase64) { super(privateKeyBase64, publicKeyBase64); } diff --git a/src/backend/commons/common-utils/build.gradle b/src/backend/commons/common-utils/build.gradle index e4f8643cb9..9e99e455ec 100644 --- a/src/backend/commons/common-utils/build.gradle +++ b/src/backend/commons/common-utils/build.gradle @@ -32,7 +32,6 @@ dependencies { api 'org.apache.commons:commons-collections4' api 'commons-codec:commons-codec' api 'com.google.guava:guava' - api 'io.jsonwebtoken:jjwt' api 'org.apache.commons:commons-lang3' api 'joda-time:joda-time' compileOnly 'org.projectlombok:lombok' diff --git a/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/interceptor/ServiceSecurityInterceptor.java b/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/interceptor/ServiceSecurityInterceptor.java index 9162095b2d..0d1da2ab1b 100644 --- a/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/interceptor/ServiceSecurityInterceptor.java +++ b/src/backend/commons/common-web/src/main/java/com/tencent/bk/job/common/web/interceptor/ServiceSecurityInterceptor.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.common.web.interceptor; -import com.tencent.bk.job.common.util.jwt.JwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import com.tencent.bk.job.common.web.exception.ServiceNoAuthException; import com.tencent.bk.job.common.web.util.ProfileUtil; import lombok.extern.slf4j.Slf4j; diff --git a/src/backend/commons/common/build.gradle b/src/backend/commons/common/build.gradle index 6108748b4a..e01861dcee 100644 --- a/src/backend/commons/common/build.gradle +++ b/src/backend/commons/common/build.gradle @@ -45,6 +45,7 @@ dependencies { implementation 'com.cronutils:cron-utils' implementation 'commons-validator:commons-validator' implementation 'org.springframework.cloud:spring-cloud-sleuth-instrumentation' + implementation 'com.tencent.bk.sdk:crypto-java-sdk' compileOnly 'org.springframework:spring-web' compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/common/consts/account/AccountCategoryEnum.java b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/AccountCategoryEnum.java similarity index 96% rename from src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/common/consts/account/AccountCategoryEnum.java rename to src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/AccountCategoryEnum.java index cc2042c456..7604303b77 100644 --- a/src/backend/job-manage/api-job-manage/src/main/java/com/tencent/bk/job/manage/common/consts/account/AccountCategoryEnum.java +++ b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/constant/AccountCategoryEnum.java @@ -22,12 +22,10 @@ * IN THE SOFTWARE. */ -package com.tencent.bk.job.manage.common.consts.account; +package com.tencent.bk.job.common.constant; /** * 账号分类 - * - * @date 2019/09/19 */ public enum AccountCategoryEnum { SYSTEM(1, "system"), diff --git a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/model/dto/CmdbTopoNodeDTO.java b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/model/dto/CmdbTopoNodeDTO.java index 41163b3459..fe8145945b 100644 --- a/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/model/dto/CmdbTopoNodeDTO.java +++ b/src/backend/commons/common/src/main/java/com/tencent/bk/job/common/model/dto/CmdbTopoNodeDTO.java @@ -37,7 +37,7 @@ @NoArgsConstructor @AllArgsConstructor @ApiModel("业务拓扑节点") -public class CmdbTopoNodeDTO { +public class CmdbTopoNodeDTO implements Cloneable { @ApiModelProperty("节点ID") private Long id; @ApiModelProperty("节点类型,module-模块,set-集群,biz-业务") @@ -62,4 +62,13 @@ public static CmdbTopoNodeDTO fromVO(TargetNodeVO targetNode) { cmdbTopoNodeDTO.setNodeType(targetNode.getObjectId()); return cmdbTopoNodeDTO; } + + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + public CmdbTopoNodeDTO clone() { + CmdbTopoNodeDTO nodeDTO = new CmdbTopoNodeDTO(); + nodeDTO.setId(id); + nodeDTO.setNodeType(nodeType); + return nodeDTO; + } } diff --git a/src/backend/job-backup/boot-job-backup/src/main/java/com/tencent/bk/job/backup/JobBackupBootApplication.java b/src/backend/job-backup/boot-job-backup/src/main/java/com/tencent/bk/job/backup/JobBackupBootApplication.java index 55d0de443d..0dcec3fbf4 100644 --- a/src/backend/job-backup/boot-job-backup/src/main/java/com/tencent/bk/job/backup/JobBackupBootApplication.java +++ b/src/backend/job-backup/boot-job-backup/src/main/java/com/tencent/bk/job/backup/JobBackupBootApplication.java @@ -25,6 +25,7 @@ package com.tencent.bk.job.backup; import com.tencent.bk.job.common.config.FeatureToggleConfig; +import com.tencent.bk.job.common.crypto.EncryptConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; @@ -41,7 +42,7 @@ @EnableCaching @EnableFeignClients @EnableScheduling -@EnableConfigurationProperties({FeatureToggleConfig.class}) +@EnableConfigurationProperties({FeatureToggleConfig.class, EncryptConfig.class}) @DependsOn("applicationContextRegister") public class JobBackupBootApplication { public static void main(String[] args) { diff --git a/src/backend/job-backup/service-job-backup/build.gradle b/src/backend/job-backup/service-job-backup/build.gradle index 308d34f84a..19c66dab8b 100644 --- a/src/backend/job-backup/service-job-backup/build.gradle +++ b/src/backend/job-backup/service-job-backup/build.gradle @@ -33,6 +33,7 @@ dependencies { api project(":commons:common-security") api project(":commons:common-redis") api project(":commons:common") + api project(":commons:common-crypto") implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-jdbc") diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/BackupFileCryptoService.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/BackupFileCryptoService.java new file mode 100644 index 0000000000..8d26ba699c --- /dev/null +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/BackupFileCryptoService.java @@ -0,0 +1,81 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.backup.crypto; + +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.JobCryptorNames; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.exception.CryptoException; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; + +/** + * 导入导出文件相关加解密服务 + */ +@Slf4j +@Service +public class BackupFileCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public BackupFileCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public void encryptBackupFile(String password, File inFile, File outFile) { + try (FileInputStream in = new FileInputStream(inFile); FileOutputStream out = new FileOutputStream(outFile)) { + symmetricCryptoService.encrypt(password, in, out, CryptoScenarioEnum.BACKUP_FILE); + } catch (Exception e) { + throw new CryptoException("Fail to encrypt backupFile", e); + } + } + + public void decryptBackupFile(String password, File inFile, File outFile) { + try { + FileInputStream in = new FileInputStream(inFile); + BufferedInputStream bis = new BufferedInputStream(in); + String algorithm = CryptorMetaUtil.getCryptorNameFromCipherStream(bis); + if (StringUtils.isBlank(algorithm)) { + algorithm = JobCryptorNames.AES_CBC; + } + try (FileOutputStream out = new FileOutputStream(outFile)) { + log.debug("Use {} to decryptBackupFile", algorithm); + symmetricCryptoService.decrypt(password, bis, out, algorithm); + } + } catch (Exception e) { + throw new CryptoException("Fail to decrypt backupFile", e); + } + } + +} diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/ExportJobPasswordCryptoService.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/ExportJobPasswordCryptoService.java new file mode 100644 index 0000000000..9f2ff9f488 --- /dev/null +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/crypto/ExportJobPasswordCryptoService.java @@ -0,0 +1,79 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.backup.crypto; + +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * 作业导出任务密码相关加解密服务 + */ +@Slf4j +@Service +public class ExportJobPasswordCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public ExportJobPasswordCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public String getExportJobPasswordEncryptAlgorithmByCipher(String cipher) { + if (StringUtils.isEmpty(cipher)) { + return CryptorNames.NONE; + } + String algorithm = CryptorMetaUtil.getCryptorNameFromCipher(cipher); + if (algorithm != null) { + return algorithm; + } + return CryptorNames.NONE; + } + + public String encryptExportJobPassword(String exportJobPassword) { + if (StringUtils.isEmpty(exportJobPassword)) { + return exportJobPassword; + } + return symmetricCryptoService.encryptToBase64Str(exportJobPassword, CryptoScenarioEnum.EXPORT_JOB_PASSWORD); + } + + public String decryptExportJobPassword(String encryptedExportJobPassword) { + if (StringUtils.isEmpty(encryptedExportJobPassword)) { + return encryptedExportJobPassword; + } + String algorithm = getExportJobPasswordEncryptAlgorithmByCipher(encryptedExportJobPassword); + if (StringUtils.isBlank(algorithm)) { + return encryptedExportJobPassword; + } + return symmetricCryptoService.decrypt(encryptedExportJobPassword, algorithm); + } + +} diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/dao/impl/ExportJobDAOImpl.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/dao/impl/ExportJobDAOImpl.java index 92ab47c6b7..43a85688c4 100644 --- a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/dao/impl/ExportJobDAOImpl.java +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/dao/impl/ExportJobDAOImpl.java @@ -24,15 +24,23 @@ package com.tencent.bk.job.backup.dao.impl; +import com.fasterxml.jackson.core.type.TypeReference; import com.tencent.bk.job.backup.constant.BackupJobStatusEnum; +import com.tencent.bk.job.backup.constant.SecretHandlerEnum; import com.tencent.bk.job.backup.dao.ExportJobDAO; +import com.tencent.bk.job.backup.model.dto.BackupTemplateInfoDTO; import com.tencent.bk.job.backup.model.dto.ExportJobInfoDTO; import com.tencent.bk.job.backup.model.tables.ExportJob; import com.tencent.bk.job.backup.model.tables.records.ExportJobRecord; -import com.tencent.bk.job.backup.util.DbRecordMapper; +import com.tencent.bk.job.backup.crypto.ExportJobPasswordCryptoService; import com.tencent.bk.job.common.util.json.JsonMapper; +import com.tencent.bk.job.common.util.json.JsonUtils; import lombok.extern.slf4j.Slf4j; -import org.jooq.*; +import org.jooq.Condition; +import org.jooq.DSLContext; +import org.jooq.Record13; +import org.jooq.Result; +import org.jooq.UpdateSetMoreStep; import org.jooq.types.UByte; import org.jooq.types.ULong; import org.springframework.beans.factory.annotation.Autowired; @@ -42,6 +50,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; /** * @since 28/7/2020 12:26 @@ -52,26 +61,48 @@ public class ExportJobDAOImpl implements ExportJobDAO { private static final ExportJob TABLE = ExportJob.EXPORT_JOB; private final DSLContext context; + private final ExportJobPasswordCryptoService exportJobPasswordCryptoService; @Autowired - public ExportJobDAOImpl(@Qualifier("job-backup-dsl-context") DSLContext context) { + public ExportJobDAOImpl(@Qualifier("job-backup-dsl-context") DSLContext context, + ExportJobPasswordCryptoService exportJobPasswordCryptoService) { this.context = context; + this.exportJobPasswordCryptoService = exportJobPasswordCryptoService; } @Override public String insertExportJob(ExportJobInfoDTO exportJobInfo) { - if (1 == context.insertInto(TABLE) - .columns(TABLE.ID, TABLE.APP_ID, TABLE.CREATOR, TABLE.CREATE_TIME, TABLE.UPDATE_TIME, TABLE.STATUS, - TABLE.PASSWORD, TABLE.PACKAGE_NAME, TABLE.SECRET_HANDLER, TABLE.EXPIRE_TIME, TABLE.TEMPLATE_PLAN_INFO, - TABLE.FILE_NAME, TABLE.LOCALE) - .values(exportJobInfo.getId(), ULong.valueOf(exportJobInfo.getAppId()), exportJobInfo.getCreator(), - ULong.valueOf(exportJobInfo.getCreateTime()), ULong.valueOf(exportJobInfo.getUpdateTime()), - UByte.valueOf(exportJobInfo.getStatus().getStatus()), exportJobInfo.getPassword(), - exportJobInfo.getPackageName(), UByte.valueOf(exportJobInfo.getSecretHandler().getType()), + int affectedNum = context.insertInto(TABLE) + .columns( + TABLE.ID, + TABLE.APP_ID, + TABLE.CREATOR, + TABLE.CREATE_TIME, + TABLE.UPDATE_TIME, + TABLE.STATUS, + TABLE.PASSWORD, + TABLE.PACKAGE_NAME, + TABLE.SECRET_HANDLER, + TABLE.EXPIRE_TIME, + TABLE.TEMPLATE_PLAN_INFO, + TABLE.FILE_NAME, + TABLE.LOCALE + ).values( + exportJobInfo.getId(), + ULong.valueOf(exportJobInfo.getAppId()), + exportJobInfo.getCreator(), + ULong.valueOf(exportJobInfo.getCreateTime()), + ULong.valueOf(exportJobInfo.getUpdateTime()), + UByte.valueOf(exportJobInfo.getStatus().getStatus()), + exportJobPasswordCryptoService.encryptExportJobPassword(exportJobInfo.getPassword()), + exportJobInfo.getPackageName(), + UByte.valueOf(exportJobInfo.getSecretHandler().getType()), ULong.valueOf(exportJobInfo.getExpireTime()), JsonMapper.nonEmptyMapper().toJson(exportJobInfo.getTemplateInfo()), - exportJobInfo.getFileName(), LocaleContextHolder.getLocale().toLanguageTag()) - .execute()) { + exportJobInfo.getFileName(), + LocaleContextHolder.getLocale().toLanguageTag() + ).execute(); + if (1 == affectedNum) { return exportJobInfo.getId(); } else { return null; @@ -85,13 +116,24 @@ public ExportJobInfoDTO getExportJobById(Long appId, String jobId) { if (appId > 0) { conditions.add(TABLE.APP_ID.equal(ULong.valueOf(appId))); } - Record13 record = context.select(TABLE.ID, TABLE.APP_ID, TABLE.CREATOR, TABLE.CREATE_TIME, - TABLE.UPDATE_TIME, TABLE.STATUS, TABLE.PASSWORD, TABLE.PACKAGE_NAME, TABLE.SECRET_HANDLER, - TABLE.EXPIRE_TIME, TABLE.TEMPLATE_PLAN_INFO, TABLE.FILE_NAME, TABLE.LOCALE) - .from(TABLE).where(conditions).fetchOne(); - return DbRecordMapper.convertRecordToExportJobInfo(record); + String, String> record = + context.select( + TABLE.ID, + TABLE.APP_ID, + TABLE.CREATOR, + TABLE.CREATE_TIME, + TABLE.UPDATE_TIME, + TABLE.STATUS, + TABLE.PASSWORD, + TABLE.PACKAGE_NAME, + TABLE.SECRET_HANDLER, + TABLE.EXPIRE_TIME, + TABLE.TEMPLATE_PLAN_INFO, + TABLE.FILE_NAME, + TABLE.LOCALE + ).from(TABLE).where(conditions).fetchOne(); + return convertRecordToExportJobInfo(record); } @Override @@ -99,18 +141,32 @@ public List getExportJobByUser(Long appId, String username) { List conditions = new ArrayList<>(); conditions.add(TABLE.CREATOR.equal(username)); conditions.add(TABLE.APP_ID.equal(ULong.valueOf(appId))); - conditions.add(TABLE.STATUS.in(UByte.valueOf(BackupJobStatusEnum.SUBMIT.getStatus()), + conditions.add(TABLE.STATUS.in( + UByte.valueOf(BackupJobStatusEnum.SUBMIT.getStatus()), UByte.valueOf(BackupJobStatusEnum.PROCESSING.getStatus()), - UByte.valueOf(BackupJobStatusEnum.ALL_SUCCESS.getStatus()))); + UByte.valueOf(BackupJobStatusEnum.ALL_SUCCESS.getStatus()) + )); Result< Record13> result = context.select(TABLE.ID, TABLE.APP_ID, TABLE.CREATOR, TABLE.CREATE_TIME, - TABLE.UPDATE_TIME, TABLE.STATUS, TABLE.PASSWORD, TABLE.PACKAGE_NAME, TABLE.SECRET_HANDLER, - TABLE.EXPIRE_TIME, TABLE.TEMPLATE_PLAN_INFO, TABLE.FILE_NAME, TABLE.LOCALE) - .from(TABLE).where(conditions).fetch(); + String>> result = + context.select( + TABLE.ID, + TABLE.APP_ID, + TABLE.CREATOR, + TABLE.CREATE_TIME, + TABLE.UPDATE_TIME, + TABLE.STATUS, + TABLE.PASSWORD, + TABLE.PACKAGE_NAME, + TABLE.SECRET_HANDLER, + TABLE.EXPIRE_TIME, + TABLE.TEMPLATE_PLAN_INFO, + TABLE.FILE_NAME, + TABLE.LOCALE + ).from(TABLE).where(conditions).fetch(); List exportJobInfoList = new ArrayList<>(); - result.forEach(record -> exportJobInfoList.add(DbRecordMapper.convertRecordToExportJobInfo(record))); + result.forEach(record -> exportJobInfoList.add(convertRecordToExportJobInfo(record))); return exportJobInfoList; } @@ -124,7 +180,10 @@ public boolean updateExportJob(ExportJobInfoDTO exportInfo) { UpdateSetMoreStep updateStep = context.update(TABLE).set(TABLE.UPDATE_TIME, ULong.valueOf(System.currentTimeMillis())); - updateStep = updateStep.set(TABLE.PASSWORD, exportInfo.getPassword()); + updateStep = updateStep.set( + TABLE.PASSWORD, + exportJobPasswordCryptoService.encryptExportJobPassword(exportInfo.getPassword()) + ); if (exportInfo.getStatus() != null) { updateStep = updateStep.set(TABLE.STATUS, UByte.valueOf(exportInfo.getStatus().getStatus())); @@ -145,11 +204,23 @@ public List listOldExportJob() { Result< Record13> result = - context.select(TABLE.ID, TABLE.APP_ID, TABLE.CREATOR, TABLE.CREATE_TIME, TABLE.UPDATE_TIME, - TABLE.STATUS, TABLE.PASSWORD, TABLE.PACKAGE_NAME, TABLE.SECRET_HANDLER, TABLE.EXPIRE_TIME, - TABLE.TEMPLATE_PLAN_INFO, TABLE.FILE_NAME, TABLE.LOCALE).from(TABLE).where(conditions).fetch(); + context.select( + TABLE.ID, + TABLE.APP_ID, + TABLE.CREATOR, + TABLE.CREATE_TIME, + TABLE.UPDATE_TIME, + TABLE.STATUS, + TABLE.PASSWORD, + TABLE.PACKAGE_NAME, + TABLE.SECRET_HANDLER, + TABLE.EXPIRE_TIME, + TABLE.TEMPLATE_PLAN_INFO, + TABLE.FILE_NAME, + TABLE.LOCALE + ).from(TABLE).where(conditions).fetch(); List exportJobInfoList = new ArrayList<>(); - result.forEach(record -> exportJobInfoList.add(DbRecordMapper.convertRecordToExportJobInfo(record))); + result.forEach(record -> exportJobInfoList.add(convertRecordToExportJobInfo(record))); return exportJobInfoList; } @@ -161,4 +232,33 @@ public boolean setCleanMark(Long appId, String jobId) { return 1 == context.update(TABLE).set(TABLE.IS_CLEANED, UByte.valueOf(1)).where(conditions).execute(); } + public ExportJobInfoDTO convertRecordToExportJobInfo( + Record13 record) { + if (record == null) { + return null; + } + ExportJob table = ExportJob.EXPORT_JOB; + ExportJobInfoDTO exportJobInfo = new ExportJobInfoDTO(); + exportJobInfo.setId(record.get(table.ID)); + exportJobInfo.setAppId(record.get(table.APP_ID).longValue()); + exportJobInfo.setCreator(record.get(table.CREATOR)); + exportJobInfo.setCreateTime(record.get(table.CREATE_TIME).longValue()); + exportJobInfo.setUpdateTime(record.get(table.UPDATE_TIME).longValue()); + exportJobInfo.setStatus(BackupJobStatusEnum.valueOf(record.get(table.STATUS).intValue())); + + // 导出密码解密 + String encryptedPassword = record.get(table.PASSWORD); + exportJobInfo.setPassword(exportJobPasswordCryptoService.decryptExportJobPassword(encryptedPassword)); + + exportJobInfo.setPackageName(record.get(table.PACKAGE_NAME)); + exportJobInfo.setSecretHandler(SecretHandlerEnum.valueOf(record.get(table.SECRET_HANDLER).intValue())); + exportJobInfo.setExpireTime(record.get(table.EXPIRE_TIME).longValue()); + exportJobInfo.setTemplateInfo(JsonUtils.fromJson(record.get(table.TEMPLATE_PLAN_INFO), + new TypeReference>() { + })); + exportJobInfo.setFileName(record.get(table.FILE_NAME)); + exportJobInfo.setLocale(Locale.forLanguageTag(record.get(table.LOCALE))); + return exportJobInfo; + } } diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ExportJobExecutor.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ExportJobExecutor.java index c5e109a1e9..c2f16a5bf4 100644 --- a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ExportJobExecutor.java +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ExportJobExecutor.java @@ -45,11 +45,11 @@ import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.constant.JobConstants; import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; +import com.tencent.bk.job.backup.crypto.BackupFileCryptoService; import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.common.i18n.service.MessageI18nService; import com.tencent.bk.job.common.util.Base64Util; import com.tencent.bk.job.common.util.FileUtil; -import com.tencent.bk.job.common.util.crypto.AESUtils; import com.tencent.bk.job.common.util.file.ZipUtil; import com.tencent.bk.job.common.util.json.JsonMapper; import com.tencent.bk.job.manage.common.consts.task.TaskFileTypeEnum; @@ -111,16 +111,22 @@ public class ExportJobExecutor { private final ArtifactoryConfig artifactoryConfig; private final BackupStorageConfig backupStorageConfig; private final LocalFileConfigForBackup localFileConfig; + private final BackupFileCryptoService backupFileCryptoService; @Autowired - public ExportJobExecutor(ExportJobService exportJobService, TaskTemplateService taskTemplateService, - TaskPlanService taskPlanService, ScriptService scriptService, - AccountService accountService, LogService logService, - StorageService storageService, MessageI18nService i18nService, + public ExportJobExecutor(ExportJobService exportJobService, + TaskTemplateService taskTemplateService, + TaskPlanService taskPlanService, + ScriptService scriptService, + AccountService accountService, + LogService logService, + StorageService storageService, + MessageI18nService i18nService, ArtifactoryClient artifactoryClient, ArtifactoryConfig artifactoryConfig, BackupStorageConfig backupStorageConfig, - LocalFileConfigForBackup localFileConfig) { + LocalFileConfigForBackup localFileConfig, + BackupFileCryptoService backupFileCryptoService) { this.exportJobService = exportJobService; this.taskTemplateService = taskTemplateService; this.taskPlanService = taskPlanService; @@ -133,6 +139,7 @@ public ExportJobExecutor(ExportJobService exportJobService, TaskTemplateService this.artifactoryConfig = artifactoryConfig; this.backupStorageConfig = backupStorageConfig; this.localFileConfig = localFileConfig; + this.backupFileCryptoService = backupFileCryptoService; File storageDirectory = new File(storageService.getStoragePath().concat(JOB_EXPORT_FILE_PREFIX)); checkDirectory(storageDirectory); @@ -305,7 +312,7 @@ private String encryptFile(ExportJobInfoDTO exportInfo, File zipFile) { i18nService.getI18n(LogMessage.START_ENCRYPTING)); File finalFileTmp = new File(zipFile.getPath().concat(".enc.tmp")); try { - AESUtils.encrypt(zipFile, finalFileTmp, exportInfo.getPassword()); + backupFileCryptoService.encryptBackupFile(exportInfo.getPassword(), zipFile, finalFileTmp); FileUtils.deleteQuietly(zipFile); } catch (Exception e) { log.error("Error while processing export job! Encrypt failed!", e); diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ImportJobExecutor.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ImportJobExecutor.java index 02ee725571..14907bd152 100644 --- a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ImportJobExecutor.java +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/executor/ImportJobExecutor.java @@ -53,7 +53,7 @@ import com.tencent.bk.job.common.util.file.ZipUtil; import com.tencent.bk.job.common.util.json.JsonMapper; import com.tencent.bk.job.common.util.json.JsonUtils; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.task.TaskScriptSourceEnum; import com.tencent.bk.job.manage.common.consts.task.TaskStepTypeEnum; import com.tencent.bk.job.manage.model.inner.ServiceAccountDTO; diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/service/impl/ImportJobServiceImpl.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/service/impl/ImportJobServiceImpl.java index 8c46293d2e..dc3854e2e4 100644 --- a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/service/impl/ImportJobServiceImpl.java +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/service/impl/ImportJobServiceImpl.java @@ -37,10 +37,10 @@ import com.tencent.bk.job.backup.service.ImportJobService; import com.tencent.bk.job.backup.service.LogService; import com.tencent.bk.job.backup.service.StorageService; +import com.tencent.bk.job.backup.crypto.BackupFileCryptoService; import com.tencent.bk.job.common.i18n.service.MessageI18nService; import com.tencent.bk.job.common.redis.util.LockUtils; import com.tencent.bk.job.common.util.JobContextUtil; -import com.tencent.bk.job.common.util.crypto.AESUtils; import com.tencent.bk.job.common.util.file.ZipUtil; import com.tencent.bk.job.manage.model.web.vo.task.TaskPlanVO; import com.tencent.bk.job.manage.model.web.vo.task.TaskTemplateVO; @@ -77,14 +77,19 @@ public class ImportJobServiceImpl implements ImportJobService { private final StorageService storageService; private final LogService logService; private final MessageI18nService i18nService; + private final BackupFileCryptoService backupFileCryptoService; @Autowired - public ImportJobServiceImpl(ImportJobDAO importJobDAO, StorageService storageService, LogService logService, - MessageI18nService i18nService) { + public ImportJobServiceImpl(ImportJobDAO importJobDAO, + StorageService storageService, + LogService logService, + MessageI18nService i18nService, + BackupFileCryptoService backupFileCryptoService) { this.importJobDAO = importJobDAO; this.storageService = storageService; this.logService = logService; this.i18nService = i18nService; + this.backupFileCryptoService = backupFileCryptoService; } @Override @@ -284,7 +289,7 @@ public Boolean checkPassword(String username, Long appId, String jobId, String p new File(parentPath.concat(File.separatorChar + uploadFile.getName() + Constant.JOB_IMPORT_DECRYPT_SUFFIX)); try { - AESUtils.decrypt(uploadFile, decryptedFile, password); + backupFileCryptoService.decryptBackupFile(password, uploadFile, decryptedFile); logService.addImportLog(appId, jobId, i18nService.getI18n(LogMessage.CORRECT_PASSWORD)); FileUtils.deleteQuietly(uploadFile); importInfo.setFileName(importInfo.getFileName().concat(Constant.JOB_IMPORT_DECRYPT_SUFFIX)); @@ -292,6 +297,7 @@ public Boolean checkPassword(String username, Long appId, String jobId, String p parseFile(username, appId, jobId); return true; } catch (Exception e) { + log.warn("Fail to decrypt backupFile", e); logService.addImportLog(appId, jobId, i18nService.getI18n(LogMessage.WRONG_PASSWORD), LogEntityTypeEnum.RETRY_PASSWORD); importInfo.setStatus(BackupJobStatusEnum.WRONG_PASSWORD); diff --git a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/util/DbRecordMapper.java b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/util/DbRecordMapper.java index 848e11fc2d..1db15596f9 100644 --- a/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/util/DbRecordMapper.java +++ b/src/backend/job-backup/service-job-backup/src/main/java/com/tencent/bk/job/backup/util/DbRecordMapper.java @@ -28,9 +28,10 @@ import com.tencent.bk.job.backup.constant.BackupJobStatusEnum; import com.tencent.bk.job.backup.constant.DuplicateIdHandlerEnum; import com.tencent.bk.job.backup.constant.LogEntityTypeEnum; -import com.tencent.bk.job.backup.constant.SecretHandlerEnum; -import com.tencent.bk.job.backup.model.dto.*; -import com.tencent.bk.job.backup.model.tables.ExportJob; +import com.tencent.bk.job.backup.model.dto.BackupTemplateInfoDTO; +import com.tencent.bk.job.backup.model.dto.IdNameInfoDTO; +import com.tencent.bk.job.backup.model.dto.ImportJobInfoDTO; +import com.tencent.bk.job.backup.model.dto.LogEntityDTO; import com.tencent.bk.job.backup.model.tables.ImportJob; import com.tencent.bk.job.common.util.json.JsonUtils; import org.jooq.Record13; @@ -46,32 +47,6 @@ */ public class DbRecordMapper { - public static ExportJobInfoDTO convertRecordToExportJobInfo( - Record13 record) { - if (record == null) { - return null; - } - ExportJob table = ExportJob.EXPORT_JOB; - ExportJobInfoDTO exportJobInfo = new ExportJobInfoDTO(); - exportJobInfo.setId(record.get(table.ID)); - exportJobInfo.setAppId(record.get(table.APP_ID).longValue()); - exportJobInfo.setCreator(record.get(table.CREATOR)); - exportJobInfo.setCreateTime(record.get(table.CREATE_TIME).longValue()); - exportJobInfo.setUpdateTime(record.get(table.UPDATE_TIME).longValue()); - exportJobInfo.setStatus(BackupJobStatusEnum.valueOf(record.get(table.STATUS).intValue())); - exportJobInfo.setPassword(record.get(table.PASSWORD)); - exportJobInfo.setPackageName(record.get(table.PACKAGE_NAME)); - exportJobInfo.setSecretHandler(SecretHandlerEnum.valueOf(record.get(table.SECRET_HANDLER).intValue())); - exportJobInfo.setExpireTime(record.get(table.EXPIRE_TIME).longValue()); - exportJobInfo.setTemplateInfo(JsonUtils.fromJson(record.get(table.TEMPLATE_PLAN_INFO), - new TypeReference>() { - })); - exportJobInfo.setFileName(record.get(table.FILE_NAME)); - exportJobInfo.setLocale(Locale.forLanguageTag(record.get(table.LOCALE))); - return exportJobInfo; - } - public static ImportJobInfoDTO convertRecordToImportJobInfo( Record13 record) { diff --git a/src/backend/job-crontab/api-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/inner/ServerDTO.java b/src/backend/job-crontab/api-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/inner/ServerDTO.java index 8f31bb3a58..e489f70d48 100644 --- a/src/backend/job-crontab/api-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/inner/ServerDTO.java +++ b/src/backend/job-crontab/api-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/inner/ServerDTO.java @@ -48,7 +48,7 @@ @PersistenceObject @ApiModel("目标服务器,四个不可同时为空") @Data -public class ServerDTO { +public class ServerDTO implements Cloneable { /** * 全局变量名 *

@@ -214,4 +214,38 @@ public void standardizeDynamicGroupId() { this.dynamicGroupIds = standardDynamicGroupIdList; } } + + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + public ServerDTO clone() { + ServerDTO serverDTO = new ServerDTO(); + serverDTO.setVariable(variable); + if (null != ips) { + List cloneIps = new ArrayList<>(ips.size()); + for (HostDTO ip : ips) { + if (ip != null) { + cloneIps.add(ip.clone()); + } else { + cloneIps.add(null); + } + } + serverDTO.setIps(cloneIps); + } + if (null != dynamicGroupIds) { + List cloneDynamicGroupIds = new ArrayList<>(dynamicGroupIds); + serverDTO.setDynamicGroupIds(cloneDynamicGroupIds); + } + if (null != topoNodes) { + List cloneTopoNodes = new ArrayList<>(topoNodes.size()); + for (CmdbTopoNodeDTO topoNode : topoNodes) { + if (topoNode != null) { + cloneTopoNodes.add(topoNode.clone()); + } else { + cloneTopoNodes.add(null); + } + } + serverDTO.setTopoNodes(cloneTopoNodes); + } + return serverDTO; + } } diff --git a/src/backend/job-crontab/boot-job-crontab/src/main/java/com/tencent/bk/job/crontab/JobCrontabBootApplication.java b/src/backend/job-crontab/boot-job-crontab/src/main/java/com/tencent/bk/job/crontab/JobCrontabBootApplication.java index 0d5ca00673..50bea8c338 100644 --- a/src/backend/job-crontab/boot-job-crontab/src/main/java/com/tencent/bk/job/crontab/JobCrontabBootApplication.java +++ b/src/backend/job-crontab/boot-job-crontab/src/main/java/com/tencent/bk/job/crontab/JobCrontabBootApplication.java @@ -25,6 +25,7 @@ package com.tencent.bk.job.crontab; import com.tencent.bk.job.common.config.FeatureToggleConfig; +import com.tencent.bk.job.common.crypto.EncryptConfig; import com.tencent.bk.job.crontab.config.JobQuartzProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -32,12 +33,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.openfeign.EnableFeignClients; -/** - * @date 2019/09/20 - */ @SpringBootApplication(scanBasePackages = "com.tencent.bk.job", exclude = {RedisAutoConfiguration.class}) @EnableFeignClients -@EnableConfigurationProperties({FeatureToggleConfig.class, JobQuartzProperties.class}) +@EnableConfigurationProperties({FeatureToggleConfig.class, JobQuartzProperties.class, EncryptConfig.class}) public class JobCrontabBootApplication { public static void main(String[] args) { diff --git a/src/backend/job-crontab/boot-job-crontab/src/test/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImplIntegrationTest.java b/src/backend/job-crontab/boot-job-crontab/src/test/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImplIntegrationTest.java index 6f2a5fe330..90fc4f9991 100644 --- a/src/backend/job-crontab/boot-job-crontab/src/test/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImplIntegrationTest.java +++ b/src/backend/job-crontab/boot-job-crontab/src/test/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImplIntegrationTest.java @@ -357,7 +357,8 @@ void updateCronJobById() { @Test void giveCronJobIdReturnDeleteSuccess() { - assertThat(cronJobDAO.getCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId())).isEqualTo(CRON_JOB_1); + CronJobInfoDTO cronJobInfoDTO = cronJobDAO.getCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId()); + assertThat(cronJobInfoDTO).isEqualTo(CRON_JOB_1); assertThat(cronJobDAO.deleteCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId())).isTrue(); assertThat(cronJobDAO.deleteCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId())).isFalse(); assertThat(cronJobDAO.getCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId())).isNull(); @@ -399,7 +400,8 @@ void insertCronJobReturnCorrectId() { CRON_JOB_1.setNotifyUser(userRoleInfo); CRON_JOB_1.setNotifyChannel(Arrays.asList(UUID.randomUUID().toString(), UUID.randomUUID().toString())); CRON_JOB_1.setId(cronJobDAO.insertCronJob(CRON_JOB_1)); - assertThat(cronJobDAO.getCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId())).isEqualTo(CRON_JOB_1); + CronJobInfoDTO cronJobInfoDTO = cronJobDAO.getCronJobById(CRON_JOB_1.getAppId(), CRON_JOB_1.getId()); + assertThat(cronJobInfoDTO).isEqualTo(CRON_JOB_1); } @Test diff --git a/src/backend/job-crontab/boot-job-crontab/src/test/resources/init_cron_job_data.sql b/src/backend/job-crontab/boot-job-crontab/src/test/resources/init_cron_job_data.sql index 64dae34e1c..04aa2c2eca 100644 --- a/src/backend/job-crontab/boot-job-crontab/src/test/resources/init_cron_job_data.sql +++ b/src/backend/job-crontab/boot-job-crontab/src/test/resources/init_cron_job_data.sql @@ -29,32 +29,32 @@ INSERT INTO `cron_job` (id, app_id, name, creator, task_template_id, task_plan_i create_time, last_modify_user, last_modify_time, end_time, notify_offset, notify_user, notify_channel) VALUES (1, 2, 'cron_job_1', 'userC', 1, 100, null, null, '* * * * *', null, - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', null, 1, 0, '1546272000', 'userT', '1546272000', 0, 600, '{"userList":["userC", "userJ"], "roleList":["JOB_ROLE_1", "JOB_ROLE_2"]}', '["wechat", "email"]'), (2, 2, 'cron_job_2', 'userT', 2, 200, null, null, null, '1546272000', - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 1, 0, 1, '1546272000', 'userT', '1546272000', 0, 600, '{"userList":["userT", "userJ"], "roleList":["JOB_ROLE_3", "JOB_ROLE_4"]}', '["email"]'), (3, 2, 'cron_job_3', 'userC', 3, 300, null, null, '* * * * *', null, - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 0, 1, 0, '1546272000', 'userC', '1546272000', 1577808000, 0, null, null), (4, 2, 'cron_job_4', 'userT', 4, 400, null, null, null, '1546272000', - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', null, 1, 0, '1546272000', 'userC', '1546272000', 0, 0, null, null), (5, 2, 'cron_job_5', 'userC', 5, 500, null, null, '* * * * *', null, - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 1, 1, 0, '1546272000', 'userT', '1546272000', 0, 0, null, null), (6, 2, 'cron_job_6', 'userT', null, null, 'aaaa', 1, null, '1546272000', - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 0, 1, 0, '1546272000', 'userT', '1546272000', 0, 0, null, null), (7, 2, 'cron_job_7', 'userC', null, null, 'bbbb', 2, '* * * * *', null, - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', null, 0, 1, '1546272000', 'userC', '1546272000', 0, 0, null, null), (8, 2, 'cron_job_8', 'userT', null, null, 'cccc', 3, null, '1546272000', - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 1, 1, 0, '1546272000', 'userC', '1546272000', 0, 0, null, null), (9, 2, 'cron_job_9', 'userC', null, null, 'vvvv', 4, '* * * * *', null, - '[{"id":null,"name":"a","type":3,"value":"b","server":null},{"id":null,"name":"b","type":4,"value":"c","server":null}]', + '[{"id":null,"name":"a","type":3,"value":"b","cipherEncryptAlgorithm":"None","server":null},{"id":null,"name":"b","type":4,"value":"c","cipherEncryptAlgorithm":"None","server":null}]', 0, 1, 0, '1546272000', 'userC', '1546272000', 0, 0, null, null) ; diff --git a/src/backend/job-crontab/service-job-crontab/build.gradle b/src/backend/job-crontab/service-job-crontab/build.gradle index c56cd6de1e..d76a4fe324 100644 --- a/src/backend/job-crontab/service-job-crontab/build.gradle +++ b/src/backend/job-crontab/service-job-crontab/build.gradle @@ -24,6 +24,7 @@ apply plugin: 'io.spring.dependency-management' dependencies { + api project(":commons:common-crypto") api project(":commons:common-redis") api project(":commons:common-web") api project(':commons:common-security') diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/CronJobDAO.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/CronJobDAO.java index 0860fe261b..9aadb5e032 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/CronJobDAO.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/CronJobDAO.java @@ -178,11 +178,11 @@ PageData listPageCronJobsByCondition(CronJobInfoDTO cronJobCondi /** * 根据ID更新定时任务的变量值 * - * @param id 定时任务ID - * @param variableValueStr 变量值字符串 + * @param id 定时任务ID + * @param cronJobWithVarsDTO 含变量的定时任务数据 * @return 受影响行数 */ - int updateVariableById(Long id, String variableValueStr); + int updateVariableById(Long id, CronJobWithVarsDTO cronJobWithVarsDTO); // 删除 diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImpl.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImpl.java index 75328a169f..e132ccd09a 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImpl.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/dao/impl/CronJobDAOImpl.java @@ -102,13 +102,14 @@ public List listBasicCronJobWithHostVars(List appIdLis .orderBy(TABLE.ID) .limit(start, limit) .fetch(); - return records.map(record -> new CronJobWithVarsDTO( - record.get(TABLE.ID).longValue(), - record.get(TABLE.APP_ID).longValue(), - record.get(TABLE.NAME), - JsonUtils.fromJson(record.get(TABLE.VARIABLE_VALUE), new TypeReference>() { - }) - )); + return records.map(record -> { + CronJobWithVarsDTO cronJobWithVarsDTO = new CronJobWithVarsDTO(); + cronJobWithVarsDTO.setId(record.get(TABLE.ID).longValue()); + cronJobWithVarsDTO.setAppId(record.get(TABLE.APP_ID).longValue()); + cronJobWithVarsDTO.setName(record.get(TABLE.NAME)); + cronJobWithVarsDTO.decryptAndSetVariableValue(record.get(TABLE.VARIABLE_VALUE)); + return cronJobWithVarsDTO; + }); } @Override @@ -194,7 +195,9 @@ private List buildConditionList(CronJobInfoDTO cronJobCondition, } private long getPageCronJobCount(List conditions) { - return context.selectCount().from(TABLE).where(conditions).fetchOne(0, Long.class); + Long count = context.selectCount().from(TABLE).where(conditions).fetchOne(0, Long.class); + assert count != null; + return count; } @Override @@ -272,7 +275,7 @@ public long insertCronJob(CronJobInfoDTO cronJob) { DbUtils.getJooqLongValue(cronJob.getTaskTemplateId()), DbUtils.getJooqLongValue(cronJob.getTaskPlanId()), cronJob.getScriptId(), DbUtils.getJooqLongValue(cronJob.getScriptVersionId()), cronJob.getCronExpression(), - DbUtils.getJooqLongValue(cronJob.getExecuteTime()), JsonUtils.toJson(cronJob.getVariableValue()), + DbUtils.getJooqLongValue(cronJob.getExecuteTime()), cronJob.getEncryptedVariableValue(), lastExecuteStatus, DbUtils.getBooleanValue(cronJob.getEnable()), DbUtils.getBooleanValue(cronJob.getDelete()), ULong.valueOf(cronJob.getCreateTime()), cronJob.getLastModifyUser(), ULong.valueOf(cronJob.getLastModifyTime()), @@ -329,7 +332,7 @@ public boolean updateCronJobById(CronJobInfoDTO cronJob) { updateStep.setNull(TABLE.CRON_EXPRESSION); } if (CollectionUtils.isNotEmpty(cronJob.getVariableValue())) { - updateStep = updateStep.set(TABLE.VARIABLE_VALUE, JsonUtils.toJson(cronJob.getVariableValue())); + updateStep = updateStep.set(TABLE.VARIABLE_VALUE, cronJob.getEncryptedVariableValue()); } if (cronJob.getLastExecuteStatus() != null) { updateStep = updateStep.set(TABLE.LAST_EXECUTE_STATUS, UByte.valueOf(cronJob.getLastExecuteStatus())); @@ -384,10 +387,10 @@ public boolean updateCronJobErrorById(CronJobInfoDTO cronJobErrorInfo) { } @Override - public int updateVariableById(Long id, String variableValueStr) { + public int updateVariableById(Long id, CronJobWithVarsDTO cronJobWithVarsDTO) { return context .update(TABLE) - .set(TABLE.VARIABLE_VALUE, variableValueStr) + .set(TABLE.VARIABLE_VALUE, cronJobWithVarsDTO.getEncryptedVariableValue()) .where(TABLE.ID.eq(ULong.valueOf(id))) .execute(); } @@ -398,7 +401,11 @@ public boolean deleteCronJobById(long appId, long cronJobId) { conditions.add(TABLE.ID.equal(ULong.valueOf(cronJobId))); conditions.add(TABLE.APP_ID.equal(ULong.valueOf(appId))); conditions.add(TABLE.IS_DELETED.equal(UByte.valueOf(0))); - return context.update(TABLE).set(TABLE.IS_DELETED, UByte.valueOf(1)).where(conditions).limit(1).execute() == 1; + return context.update(TABLE) + .set(TABLE.IS_DELETED, UByte.valueOf(1)) + .where(conditions) + .limit(1) + .execute() == 1; } @Override @@ -410,7 +417,9 @@ public boolean checkCronJobName(long appId, long cronJobId, String name) { conditions.add(TABLE.ID.notEqual(ULong.valueOf(cronJobId))); } conditions.add(TABLE.NAME.equal(name)); - return context.selectCount().from(TABLE).where(conditions).fetchOne(0, Integer.class) == 0; + Integer count = context.selectCount().from(TABLE).where(conditions).fetchOne(0, Integer.class); + assert count != null; + return count == 0; } @Override @@ -436,7 +445,7 @@ public boolean insertCronJobWithId(CronJobInfoDTO cronJob) { cronJob.getCreator(), DbUtils.getJooqLongValue(cronJob.getTaskTemplateId()), DbUtils.getJooqLongValue(cronJob.getTaskPlanId()), cronJob.getScriptId(), DbUtils.getJooqLongValue(cronJob.getScriptVersionId()), cronJob.getCronExpression(), - DbUtils.getJooqLongValue(cronJob.getExecuteTime()), JsonUtils.toJson(cronJob.getVariableValue()), + DbUtils.getJooqLongValue(cronJob.getExecuteTime()), cronJob.getEncryptedVariableValue(), lastExecuteStatus, DbUtils.getBooleanValue(cronJob.getEnable()), DbUtils.getBooleanValue(cronJob.getDelete()), ULong.valueOf(cronJob.getCreateTime()), cronJob.getLastModifyUser(), ULong.valueOf(cronJob.getLastModifyTime()), @@ -512,8 +521,10 @@ public Integer countCronJob(Long appId, Boolean active, Boolean cron) { conditions.add(TABLE.EXECUTE_TIME.isNotNull().and(TABLE.CRON_EXPRESSION.isNull())); } } - return context.selectCount().from(TABLE) - .where(conditions).fetchOne().value1(); + Record1 record = context.selectCount().from(TABLE) + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } private CronJobInfoDTO convertToCronJobDTO(Record21>() { - })); + cronJobInfoDTO.decryptAndSetVariableValue(record.get(TABLE.VARIABLE_VALUE)); standardizeDynamicGroupId(cronJobInfoDTO.getVariableValue()); cronJobInfoDTO.setLastExecuteStatus(record.get(TABLE.LAST_EXECUTE_STATUS).intValue()); cronJobInfoDTO.setEnable(record.get(TABLE.IS_ENABLE).intValue() == 1); diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/migration/AddHostIdForCronVariableMigrationTask.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/migration/AddHostIdForCronVariableMigrationTask.java index 4f2448c7e3..1ebef8a4e2 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/migration/AddHostIdForCronVariableMigrationTask.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/migration/AddHostIdForCronVariableMigrationTask.java @@ -26,7 +26,6 @@ import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; import com.tencent.bk.job.common.model.dto.HostDTO; -import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.crontab.dao.CronJobDAO; import com.tencent.bk.job.crontab.model.dto.CronJobVariableDTO; import com.tencent.bk.job.crontab.model.dto.CronJobWithVarsDTO; @@ -150,16 +149,15 @@ private AddHostIdResult updateHostIdForCronVariables(List appIdList, boole if (!existsHostId(cronJobWithVarsDTO)) { continue; } - String variableValueStr = JsonUtils.toJson(cronJobWithVarsDTO.getVariableValue()); if (isDryRun) { log.info( "[DryRun]set variable_value={} for cronJob(id={})", - variableValueStr, + cronJobWithVarsDTO.getEncryptedVariableValue(), cronJobWithVarsDTO.getId() ); count += 1; } else { - count += cronJobDAO.updateVariableById(cronJobWithVarsDTO.getId(), variableValueStr); + count += cronJobDAO.updateVariableById(cronJobWithVarsDTO.getId(), cronJobWithVarsDTO); } } watch.stop(); diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobInfoDTO.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobInfoDTO.java index 8a32e586f1..0911958549 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobInfoDTO.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobInfoDTO.java @@ -64,10 +64,10 @@ * @since 23/12/2019 21:03 */ @Data -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor -public class CronJobInfoDTO { +public class CronJobInfoDTO extends EncryptEnableVariables { /** * 定时任务 ID */ @@ -118,11 +118,6 @@ public class CronJobInfoDTO { */ private Long executeTime; - /** - * 变量值列表 - */ - private List variableValue; - /** * 上次执行状态 */ diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobVariableDTO.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobVariableDTO.java index 833fb56e92..57f0119747 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobVariableDTO.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobVariableDTO.java @@ -46,7 +46,7 @@ @EqualsAndHashCode @NoArgsConstructor @AllArgsConstructor -public class CronJobVariableDTO { +public class CronJobVariableDTO implements Cloneable { /** * 变量 ID */ @@ -155,4 +155,18 @@ public ServiceCronJobVariableDTO toServiceCronJobVariableDTO() { variable.setServer(server); return variable; } + + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + public CronJobVariableDTO clone() { + CronJobVariableDTO cronJobVariableDTO = new CronJobVariableDTO(); + cronJobVariableDTO.setId(id); + cronJobVariableDTO.setType(type); + cronJobVariableDTO.setName(name); + cronJobVariableDTO.setValue(value); + if (server != null) { + cronJobVariableDTO.setServer(server.clone()); + } + return cronJobVariableDTO; + } } diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobWithVarsDTO.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobWithVarsDTO.java index b93d955588..56a92843ed 100644 --- a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobWithVarsDTO.java +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/CronJobWithVarsDTO.java @@ -35,10 +35,10 @@ * 含有基本信息与变量信息的定时任务实体 */ @Data -@EqualsAndHashCode +@EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor -public class CronJobWithVarsDTO { +public class CronJobWithVarsDTO extends EncryptEnableVariables { /** * 定时任务 ID */ diff --git a/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/EncryptEnableVariables.java b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/EncryptEnableVariables.java new file mode 100644 index 0000000000..44c6d08125 --- /dev/null +++ b/src/backend/job-crontab/service-job-crontab/src/main/java/com/tencent/bk/job/crontab/model/dto/EncryptEnableVariables.java @@ -0,0 +1,96 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.crontab.model.dto; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.tencent.bk.job.common.crypto.scenario.CipherVariableCryptoService; +import com.tencent.bk.job.common.util.ApplicationContextRegister; +import com.tencent.bk.job.common.util.json.JsonUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 可加密变量 + */ +@Data +@EqualsAndHashCode +@NoArgsConstructor +@AllArgsConstructor +public class EncryptEnableVariables { + + /** + * 变量值列表 + */ + protected List variableValue; + + public String getEncryptedVariableValue() { + CipherVariableCryptoService cipherVariableCryptoService = + ApplicationContextRegister.getBean(CipherVariableCryptoService.class); + if (CollectionUtils.isEmpty(this.variableValue)) { + return JsonUtils.toJson(this.variableValue); + } + List cloneVariableList = new ArrayList<>(this.variableValue.size()); + for (CronJobVariableDTO cronJobVariableDTO : this.variableValue) { + CronJobVariableDTO cloneCronJobVariable = cronJobVariableDTO.clone(); + String encryptedValue = cipherVariableCryptoService.encryptTaskVariableIfNeeded( + cloneCronJobVariable.getType(), + cloneCronJobVariable.getValue() + ); + cloneCronJobVariable.setValue(encryptedValue); + cloneVariableList.add(cloneCronJobVariable); + } + return JsonUtils.toJson(cloneVariableList); + } + + public void decryptAndSetVariableValue(String encryptedVariableValue) { + CipherVariableCryptoService cipherVariableCryptoService = + ApplicationContextRegister.getBean(CipherVariableCryptoService.class); + if (StringUtils.isBlank(encryptedVariableValue)) { + this.variableValue = new ArrayList<>(); + } + this.variableValue = JsonUtils.fromJson( + encryptedVariableValue, + new TypeReference>() { + } + ); + if (CollectionUtils.isEmpty(this.variableValue)) { + return; + } + for (CronJobVariableDTO cronJobVariableDTO : this.variableValue) { + String decryptedValue = cipherVariableCryptoService.decryptTaskVariableIfNeeded( + cronJobVariableDTO.getType(), + cronJobVariableDTO.getValue() + ); + cronJobVariableDTO.setValue(decryptedValue); + } + } +} diff --git a/src/backend/job-execute/boot-job-execute/src/main/java/com/tencent/bk/job/execute/JobExecuteBootApplication.java b/src/backend/job-execute/boot-job-execute/src/main/java/com/tencent/bk/job/execute/JobExecuteBootApplication.java index 065e9f81f5..80d873a4dd 100644 --- a/src/backend/job-execute/boot-job-execute/src/main/java/com/tencent/bk/job/execute/JobExecuteBootApplication.java +++ b/src/backend/job-execute/boot-job-execute/src/main/java/com/tencent/bk/job/execute/JobExecuteBootApplication.java @@ -25,6 +25,7 @@ package com.tencent.bk.job.execute; import com.tencent.bk.job.common.config.FeatureToggleConfig; +import com.tencent.bk.job.common.crypto.EncryptConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; @@ -36,7 +37,7 @@ @SpringBootApplication(scanBasePackages = "com.tencent.bk.job", exclude = {RedisAutoConfiguration.class}) @EnableDiscoveryClient @EnableFeignClients -@EnableConfigurationProperties({FeatureToggleConfig.class}) +@EnableConfigurationProperties({FeatureToggleConfig.class, EncryptConfig.class}) public class JobExecuteBootApplication { public static void main(String[] args) { diff --git a/src/backend/job-execute/boot-job-execute/src/test/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImplIntegrationTest.java b/src/backend/job-execute/boot-job-execute/src/test/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImplIntegrationTest.java index c37a8dc8ef..974635a6bd 100644 --- a/src/backend/job-execute/boot-job-execute/src/test/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImplIntegrationTest.java +++ b/src/backend/job-execute/boot-job-execute/src/test/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImplIntegrationTest.java @@ -273,7 +273,7 @@ public void testGetScriptStepInstance() { assertThat(returnStepInstance.getResolvedScriptParam()).isEqualTo("var1"); assertThat(returnStepInstance.getScriptType()).isEqualTo(1); assertThat(returnStepInstance.getTimeout()).isEqualTo(1000); - assertThat(returnStepInstance.isSecureParam()).isEqualTo(false); + assertThat(returnStepInstance.isSecureParam()).isEqualTo(true); } @Test @@ -365,7 +365,7 @@ public void testAddFileStepInstance() { assertThat(savedStepInstance.getFileSourceList().get(0).getServers().getIpList()).isNotEmpty(); assertThat(savedStepInstance.getFileSourceList().get(0).getServers().getIpList()) .containsOnly(new HostDTO(1L, - "10.10.10.10")); + "10.10.10.10")); assertThat(savedStepInstance.getFileSourceList().get(0).getFiles()).isNotEmpty(); assertThat(savedStepInstance.getFileSourceList().get(0).getFiles().get(0).getFilePath()) .isEqualTo("/tmp/1.log"); @@ -427,7 +427,7 @@ public void testAddConfirmStepInstance() { @Test void testUpdateResolvedScriptParam() { - stepInstanceDAO.updateResolvedScriptParam(1L, "resolved_var"); + stepInstanceDAO.updateResolvedScriptParam(1L, true, "resolved_var"); ScriptStepInstanceDTO updatedStepInstance = stepInstanceDAO.getScriptStepInstance(1L); assertThat(updatedStepInstance).isNotNull(); diff --git a/src/backend/job-execute/boot-job-execute/src/test/resources/init_step_instance_data.sql b/src/backend/job-execute/boot-job-execute/src/test/resources/init_step_instance_data.sql index 962cc07651..cb6d196b68 100644 --- a/src/backend/job-execute/boot-job-execute/src/test/resources/init_step_instance_data.sql +++ b/src/backend/job-execute/boot-job-execute/src/test/resources/init_step_instance_data.sql @@ -28,27 +28,27 @@ truncate table step_instance_file; truncate table step_instance_confirm; insert into job_execute.step_instance (id,app_id,task_instance_id,step_id,name,type,target_servers,operator,status,execute_count,start_time,end_time,total_time, -create_time,step_num,step_order) values (1,2,1,1,'task1-step1',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868800000,1572868801000,1111,1572868800000,2,1); + create_time,step_num,step_order) values (1,2,1,1,'task1-step1',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868800000,1572868801000,1111,1572868800000,2,1); insert into job_execute.step_instance (id,app_id,task_instance_id,step_id,name,type,target_servers,operator,status,execute_count,start_time,end_time,total_time, -create_time,step_num,step_order) values (2,2,1,2,'task1-step2',2,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868801000,1572868802000,1112,1572868800000,2,2); + create_time,step_num,step_order) values (2,2,1,2,'task1-step2',2,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868801000,1572868802000,1112,1572868800000,2,2); insert into job_execute.step_instance (id,app_id,task_instance_id,step_id,name,type,target_servers,operator,status,execute_count,start_time,end_time,total_time, -create_time,step_num,step_order) values (3,2,2,-1,'fast_execute_task_name',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868800000,1572868801000,1111,1572868800000,1,1); + create_time,step_num,step_order) values (3,2,2,-1,'fast_execute_task_name',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,1572868800000,1572868801000,1111,1572868800000,1,1); insert into job_execute.step_instance (id,app_id,task_instance_id,step_id,name,type,target_servers,operator,status,execute_count,start_time,end_time,total_time, -create_time,step_num,step_order) values (4,2,3,-1,'fast_execute_task_name',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,null,1572868801000,0,null,1,1); + create_time,step_num,step_order) values (4,2,3,-1,'fast_execute_task_name',1,'{"ipList":[{"cloudAreaId":0,"ip":"127.0.0.1"}]}','admin',3,0,null,1572868801000,0,null,1,1); insert into job_execute.step_instance_script(step_instance_id,script_content,script_type,script_param,resolved_script_param,execution_timeout,system_account_id,system_account, -db_account_id,db_type,db_account,db_password,db_port,script_source,script_id,script_version_id) values (1,'script_content',1,'${var1}','var1',1000,1,'root',11,1,'root','db_password',3306,1,NULL,NULL); + db_account_id,db_type,db_account,db_password,db_port,script_source,script_id,script_version_id,is_secure_param) values (1,'script_content',1,'${var1}','var1',1000,1,'root',11,1,'root','ESKsXn+pF9hACG3BSYG38ZnUjQQ8bUcOylREiEnDTPU=',3306,1,NULL,NULL,1); insert into job_execute.step_instance_file(step_instance_id,file_source,resolved_file_source,file_target_path,file_target_name,resolved_file_target_path,file_upload_speed_limit,file_download_speed_limit, -file_duplicate_handle,not_exist_path_handler,execution_timeout,system_account_id,system_account) values (2,'[{"files":[{ "filePath":"/${log_dir}/1.log" }],"localUpload":false}]', -'[{"files":[{ "resolvedFilePath":"/tmp/1.log", "filePath":"/${log_dir}/1.log" }],"localUpload":false}]','/${log_dir}/','2.log','/tmp/', -100,100,1,1,1000,1,'root'); + file_duplicate_handle,not_exist_path_handler,execution_timeout,system_account_id,system_account) values (2,'[{"files":[{ "filePath":"/${log_dir}/1.log" }],"localUpload":false}]', + '[{"files":[{ "resolvedFilePath":"/tmp/1.log", "filePath":"/${log_dir}/1.log" }],"localUpload":false}]','/${log_dir}/','2.log','/tmp/', + 100,100,1,1,1000,1,'root'); insert into job_execute.step_instance_confirm(step_instance_id,confirm_message,confirm_users,confirm_roles,notify_channels,confirm_reason) values ( -3,'confirm_message','admin,test','JOB_RESOURCE_TRIGGER_USER','weixin','confirm_reason'); + 3,'confirm_message','admin,test','JOB_RESOURCE_TRIGGER_USER','weixin','confirm_reason'); diff --git a/src/backend/job-execute/boot-job-execute/src/test/resources/test.properties b/src/backend/job-execute/boot-job-execute/src/test/resources/test.properties index 60e2c486d7..2533add134 100644 --- a/src/backend/job-execute/boot-job-execute/src/test/resources/test.properties +++ b/src/backend/job-execute/boot-job-execute/src/test/resources/test.properties @@ -30,3 +30,5 @@ app.secret=job iam.system-id=bk_job iam.base-url=http://bkiam.service.consul:9080/ job.encrypt.password=test +job.encrypt.scenarioAlgorithms.scriptSensitiveParam=None +job.encrypt.scenarioAlgorithms.cipherVariable=None diff --git a/src/backend/job-execute/service-job-execute/build.gradle b/src/backend/job-execute/service-job-execute/build.gradle index 166a684efc..c445e216e0 100644 --- a/src/backend/job-execute/service-job-execute/build.gradle +++ b/src/backend/job-execute/service-job-execute/build.gradle @@ -31,6 +31,7 @@ dependencies { api project(":job-manage:api-job-manage") api project(":job-logsvr:api-job-logsvr") api project(':commons:gse-sdk') + api project(":commons:common-crypto") api project(':commons:common-security') api project(':commons:common-redis') api project(":commons:cmdb-sdk-ext") diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteSQLResourceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteSQLResourceImpl.java index 679adc3c88..82d767ecb6 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteSQLResourceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteSQLResourceImpl.java @@ -54,7 +54,7 @@ import com.tencent.bk.job.execute.service.AccountService; import com.tencent.bk.job.execute.service.ScriptService; import com.tencent.bk.job.execute.service.TaskExecuteService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.script.ScriptTypeEnum; import com.tencent.bk.job.manage.model.inner.ServiceScriptDTO; import lombok.extern.slf4j.Slf4j; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteScriptResourceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteScriptResourceImpl.java index a3355747fd..54f44fb678 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteScriptResourceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastExecuteScriptResourceImpl.java @@ -54,7 +54,7 @@ import com.tencent.bk.job.execute.service.AccountService; import com.tencent.bk.job.execute.service.ScriptService; import com.tencent.bk.job.execute.service.TaskExecuteService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.script.ScriptTypeEnum; import com.tencent.bk.job.manage.model.inner.ServiceScriptDTO; import lombok.extern.slf4j.Slf4j; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastPushFileResourceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastPushFileResourceImpl.java index cb3697d0f3..e06c304448 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastPushFileResourceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbFastPushFileResourceImpl.java @@ -57,7 +57,7 @@ import com.tencent.bk.job.execute.model.esb.v2.request.EsbFastPushFileRequest; import com.tencent.bk.job.execute.service.AccountService; import com.tencent.bk.job.execute.service.TaskExecuteService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.task.TaskFileTypeEnum; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -267,9 +267,7 @@ private List convertFileSource(long appId, List fileSourceDTO.setFileType(TaskFileTypeEnum.SERVER.getType()); List files = new ArrayList<>(); if (fileSource.getFiles() != null) { - fileSource.getFiles().forEach(file -> { - files.add(new FileDetailDTO(file)); - }); + fileSource.getFiles().forEach(file -> files.add(new FileDetailDTO(file))); } fileSourceDTO.setFiles(files); fileSourceDTO.setServers(convertToStandardServers(fileSource.getTargetServer(), fileSource.getIpList(), diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbPushConfigFileResourceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbPushConfigFileResourceImpl.java index 7ba656406b..ad01424ac6 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbPushConfigFileResourceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/api/esb/v2/impl/EsbPushConfigFileResourceImpl.java @@ -56,7 +56,7 @@ import com.tencent.bk.job.execute.service.AccountService; import com.tencent.bk.job.execute.service.AgentService; import com.tencent.bk.job.execute.service.TaskExecuteService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.task.TaskFileTypeEnum; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/StepInstanceDAO.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/StepInstanceDAO.java index 88a7a2970b..d3878c35bb 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/StepInstanceDAO.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/StepInstanceDAO.java @@ -114,15 +114,16 @@ void updateStepExecutionInfo(long stepInstanceId, RunStatusEnum status, Long sta * 更新解析之后的脚本参数 * * @param stepInstanceId 步骤实例ID + * @param isSecureParam 是否为敏感参数 * @param resolvedScriptParam 解析之后的脚本参数 */ - void updateResolvedScriptParam(long stepInstanceId, String resolvedScriptParam); + void updateResolvedScriptParam(long stepInstanceId, boolean isSecureParam, String resolvedScriptParam); /** * 更新变量解析之后的源文件 * * @param stepInstanceId 步骤实例ID - * @param resolvedFileSources + * @param resolvedFileSources 解析后的源文件信息 */ void updateResolvedSourceFile(long stepInstanceId, List resolvedFileSources); @@ -175,16 +176,16 @@ List> listFastPushFileSource(Long appId, DuplicateHandlerEnu /** * 根据taskInstanceId获取一个stepInstanceId,用于快速脚本/文件任务 * - * @param taskInstanceId - * @return + * @param taskInstanceId 作业实例ID + * @return 步骤实例ID */ Long getStepInstanceId(long taskInstanceId); /** * 根据stepInstanceId获取脚本类型 * - * @param stepInstanceId - * @return + * @param stepInstanceId 步骤实例ID + * @return 脚本类型 */ Byte getScriptTypeByStepInstanceId(long stepInstanceId); diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImpl.java index c81d934784..76894edcea 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/StepInstanceDAOImpl.java @@ -25,8 +25,11 @@ package com.tencent.bk.job.execute.dao.impl; import com.fasterxml.jackson.core.type.TypeReference; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.DuplicateHandlerEnum; import com.tencent.bk.job.common.constant.NotExistPathHandlerEnum; +import com.tencent.bk.job.common.crypto.scenario.DbPasswordCryptoService; +import com.tencent.bk.job.common.crypto.scenario.SensitiveParamCryptoService; import com.tencent.bk.job.common.util.Utils; import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.execute.common.constants.RunStatusEnum; @@ -98,37 +101,59 @@ public class StepInstanceDAOImpl implements StepInstanceDAO { }; private final DSLContext CTX; + private final SensitiveParamCryptoService sensitiveParamCryptoService; + private final DbPasswordCryptoService dbPasswordCryptoService; @Autowired - public StepInstanceDAOImpl(@Qualifier("job-execute-dsl-context") DSLContext CTX) { + public StepInstanceDAOImpl(@Qualifier("job-execute-dsl-context") DSLContext CTX, + SensitiveParamCryptoService sensitiveParamCryptoService, + DbPasswordCryptoService dbPasswordCryptoService) { this.CTX = CTX; + this.sensitiveParamCryptoService = sensitiveParamCryptoService; + this.dbPasswordCryptoService = dbPasswordCryptoService; } @Override public Long addStepInstanceBase(StepInstanceBaseDTO stepInstance) { StepInstance t = StepInstance.STEP_INSTANCE; - Record record = CTX.insertInto(t, t.STEP_ID, t.TASK_INSTANCE_ID, t.APP_ID, t.NAME, t.TYPE, - t.OPERATOR, t.STATUS, t.EXECUTE_COUNT, t.START_TIME, t.END_TIME, t.TOTAL_TIME, - t.TARGET_SERVERS, t.CREATE_TIME, t.IGNORE_ERROR, t.STEP_NUM, - t.STEP_ORDER, t.BATCH) - .values(stepInstance.getStepId(), - stepInstance.getTaskInstanceId(), - stepInstance.getAppId(), - stepInstance.getName(), - JooqDataTypeUtil.toByte(stepInstance.getExecuteType()), - stepInstance.getOperator(), - stepInstance.getStatus().getValue().byteValue(), - stepInstance.getExecuteCount(), - stepInstance.getStartTime(), - stepInstance.getEndTime(), - stepInstance.getTotalTime(), - stepInstance.getTargetServers() == null ? null : JsonUtils.toJson(stepInstance.getTargetServers()), - stepInstance.getCreateTime(), - stepInstance.isIgnoreError() ? Byte.valueOf("1") : Byte.valueOf("0"), - stepInstance.getStepNum(), - stepInstance.getStepOrder(), - (short) stepInstance.getBatch()) - .returning(t.ID).fetchOne(); + Record record = CTX.insertInto(t, + t.STEP_ID, + t.TASK_INSTANCE_ID, + t.APP_ID, + t.NAME, + t.TYPE, + t.OPERATOR, + t.STATUS, + t.EXECUTE_COUNT, + t.START_TIME, + t.END_TIME, + t.TOTAL_TIME, + t.TARGET_SERVERS, + t.CREATE_TIME, + t.IGNORE_ERROR, + t.STEP_NUM, + t.STEP_ORDER, + t.BATCH + ).values( + stepInstance.getStepId(), + stepInstance.getTaskInstanceId(), + stepInstance.getAppId(), + stepInstance.getName(), + JooqDataTypeUtil.toByte(stepInstance.getExecuteType()), + stepInstance.getOperator(), + stepInstance.getStatus().getValue().byteValue(), + stepInstance.getExecuteCount(), + stepInstance.getStartTime(), + stepInstance.getEndTime(), + stepInstance.getTotalTime(), + stepInstance.getTargetServers() == null ? null : JsonUtils.toJson(stepInstance.getTargetServers()), + stepInstance.getCreateTime(), + stepInstance.isIgnoreError() ? Byte.valueOf("1") : Byte.valueOf("0"), + stepInstance.getStepNum(), + stepInstance.getStepOrder(), + (short) stepInstance.getBatch() + ).returning(t.ID).fetchOne(); + assert record != null; return record.getValue(t.ID); } @@ -140,49 +165,76 @@ public void addScriptStepInstance(StepInstanceDTO stepInstance) { scriptSourceByteValue = scriptSource.byteValue(); } StepInstanceScript t = StepInstanceScript.STEP_INSTANCE_SCRIPT; - CTX.insertInto(t, t.STEP_INSTANCE_ID, t.SCRIPT_CONTENT, t.SCRIPT_TYPE, t.SCRIPT_PARAM, t.RESOLVED_SCRIPT_PARAM, - t.EXECUTION_TIMEOUT, t.SYSTEM_ACCOUNT_ID, t.SYSTEM_ACCOUNT, t.DB_ACCOUNT_ID, - t.DB_TYPE, t.DB_ACCOUNT, t.DB_PASSWORD, t.DB_PORT, t.SCRIPT_SOURCE, t.SCRIPT_ID, t.SCRIPT_VERSION_ID, - t.IS_SECURE_PARAM) - .values(stepInstance.getId(), - stepInstance.getScriptContent(), - JooqDataTypeUtil.toByte(stepInstance.getScriptType()), - stepInstance.getScriptParam(), - stepInstance.getResolvedScriptParam(), - stepInstance.getTimeout(), - stepInstance.getAccountId(), - stepInstance.getAccount(), - stepInstance.getDbAccountId(), - JooqDataTypeUtil.toByte(stepInstance.getDbType()), - stepInstance.getDbAccount(), - stepInstance.getDbPass(), - stepInstance.getDbPort(), - scriptSourceByteValue, - stepInstance.getScriptId(), - stepInstance.getScriptVersionId(), - stepInstance.isSecureParam() ? JooqDataTypeUtil.toByte(1) : - JooqDataTypeUtil.toByte(0) - ).execute(); + CTX.insertInto(t, + t.STEP_INSTANCE_ID, + t.SCRIPT_CONTENT, + t.SCRIPT_TYPE, + t.SCRIPT_PARAM, + t.RESOLVED_SCRIPT_PARAM, + t.EXECUTION_TIMEOUT, + t.SYSTEM_ACCOUNT_ID, + t.SYSTEM_ACCOUNT, + t.DB_ACCOUNT_ID, + t.DB_TYPE, + t.DB_ACCOUNT, + t.DB_PASSWORD, + t.DB_PORT, + t.SCRIPT_SOURCE, + t.SCRIPT_ID, + t.SCRIPT_VERSION_ID, + t.IS_SECURE_PARAM + ).values( + stepInstance.getId(), + stepInstance.getScriptContent(), + JooqDataTypeUtil.toByte(stepInstance.getScriptType()), + sensitiveParamCryptoService.encryptParamIfNeeded( + stepInstance.isSecureParam(), stepInstance.getScriptParam()), + sensitiveParamCryptoService.encryptParamIfNeeded( + stepInstance.isSecureParam(), stepInstance.getResolvedScriptParam()), + stepInstance.getTimeout(), + stepInstance.getAccountId(), + stepInstance.getAccount(), + stepInstance.getDbAccountId(), + JooqDataTypeUtil.toByte(stepInstance.getDbType()), + stepInstance.getDbAccount(), + dbPasswordCryptoService.encryptDbPasswordIfNeeded(AccountCategoryEnum.DB, stepInstance.getDbPass()), + stepInstance.getDbPort(), + scriptSourceByteValue, + stepInstance.getScriptId(), + stepInstance.getScriptVersionId(), + stepInstance.isSecureParam() ? JooqDataTypeUtil.toByte(1) : + JooqDataTypeUtil.toByte(0) + ).execute(); } @Override public void addFileStepInstance(StepInstanceDTO stepInstance) { StepInstanceFile t = StepInstanceFile.STEP_INSTANCE_FILE; - CTX.insertInto(t, t.STEP_INSTANCE_ID, t.FILE_SOURCE, t.FILE_TARGET_PATH, t.FILE_TARGET_NAME, - t.FILE_UPLOAD_SPEED_LIMIT, t.FILE_DOWNLOAD_SPEED_LIMIT, t.FILE_DUPLICATE_HANDLE, t.NOT_EXIST_PATH_HANDLER, - t.EXECUTION_TIMEOUT, t.SYSTEM_ACCOUNT_ID, t.SYSTEM_ACCOUNT) - .values(stepInstance.getId(), - JsonUtils.toJson(stepInstance.getFileSourceList()), - stepInstance.getFileTargetPath(), - stepInstance.getFileTargetName(), - stepInstance.getFileUploadSpeedLimit(), - stepInstance.getFileDownloadSpeedLimit(), - JooqDataTypeUtil.toByte(stepInstance.getFileDuplicateHandle()), - JooqDataTypeUtil.toUByte(stepInstance.getNotExistPathHandler()), - stepInstance.getTimeout(), - stepInstance.getAccountId(), - stepInstance.getAccount() - ).execute(); + CTX.insertInto(t, + t.STEP_INSTANCE_ID, + t.FILE_SOURCE, + t.FILE_TARGET_PATH, + t.FILE_TARGET_NAME, + t.FILE_UPLOAD_SPEED_LIMIT, + t.FILE_DOWNLOAD_SPEED_LIMIT, + t.FILE_DUPLICATE_HANDLE, + t.NOT_EXIST_PATH_HANDLER, + t.EXECUTION_TIMEOUT, + t.SYSTEM_ACCOUNT_ID, + t.SYSTEM_ACCOUNT + ).values( + stepInstance.getId(), + JsonUtils.toJson(stepInstance.getFileSourceList()), + stepInstance.getFileTargetPath(), + stepInstance.getFileTargetName(), + stepInstance.getFileUploadSpeedLimit(), + stepInstance.getFileDownloadSpeedLimit(), + JooqDataTypeUtil.toByte(stepInstance.getFileDuplicateHandle()), + JooqDataTypeUtil.toUByte(stepInstance.getNotExistPathHandler()), + stepInstance.getTimeout(), + stepInstance.getAccountId(), + stepInstance.getAccount() + ).execute(); } @Override @@ -203,10 +255,24 @@ public void addConfirmStepInstance(StepInstanceDTO stepInstance) { @Override public ScriptStepInstanceDTO getScriptStepInstance(long stepInstanceId) { StepInstanceScript t = StepInstanceScript.STEP_INSTANCE_SCRIPT; - Record record = CTX.select(t.STEP_INSTANCE_ID, t.SCRIPT_CONTENT, t.SCRIPT_TYPE, t.SCRIPT_PARAM, - t.RESOLVED_SCRIPT_PARAM, t.EXECUTION_TIMEOUT, t.SYSTEM_ACCOUNT_ID, t.SYSTEM_ACCOUNT, - t.DB_ACCOUNT_ID, t.DB_ACCOUNT, t.DB_TYPE, t.DB_PASSWORD, t.DB_PORT, t.SCRIPT_SOURCE, t.SCRIPT_ID, - t.SCRIPT_VERSION_ID, t.IS_SECURE_PARAM + Record record = CTX.select( + t.STEP_INSTANCE_ID, + t.SCRIPT_CONTENT, + t.SCRIPT_TYPE, + t.SCRIPT_PARAM, + t.RESOLVED_SCRIPT_PARAM, + t.EXECUTION_TIMEOUT, + t.SYSTEM_ACCOUNT_ID, + t.SYSTEM_ACCOUNT, + t.DB_ACCOUNT_ID, + t.DB_ACCOUNT, + t.DB_TYPE, + t.DB_PASSWORD, + t.DB_PORT, + t.SCRIPT_SOURCE, + t.SCRIPT_ID, + t.SCRIPT_VERSION_ID, + t.IS_SECURE_PARAM ).from(t) .where(t.STEP_INSTANCE_ID.eq(stepInstanceId)).fetchOne(); return extractScriptInfo(record); @@ -221,17 +287,38 @@ private ScriptStepInstanceDTO extractScriptInfo(Record record) { stepInstance.setStepInstanceId(record.get(t.STEP_INSTANCE_ID)); stepInstance.setScriptContent(record.get(t.SCRIPT_CONTENT)); stepInstance.setScriptType(JooqDataTypeUtil.toInteger(record.get(t.SCRIPT_TYPE))); - stepInstance.setScriptParam(record.get(t.SCRIPT_PARAM)); - stepInstance.setResolvedScriptParam(record.get(t.RESOLVED_SCRIPT_PARAM)); + stepInstance.setSecureParam(record.get(t.IS_SECURE_PARAM).intValue() == 1); + String encryptedScriptParam = record.get(t.SCRIPT_PARAM); + + // 敏感参数解密 + String scriptParam = sensitiveParamCryptoService.decryptParamIfNeeded( + stepInstance.isSecureParam(), + encryptedScriptParam + ); + stepInstance.setScriptParam(scriptParam); + String encryptedResolvedScriptParam = record.get(t.RESOLVED_SCRIPT_PARAM); + String resolvedScriptParam = sensitiveParamCryptoService.decryptParamIfNeeded( + stepInstance.isSecureParam(), + encryptedResolvedScriptParam + ); + stepInstance.setResolvedScriptParam(resolvedScriptParam); + stepInstance.setTimeout(record.get(t.EXECUTION_TIMEOUT)); stepInstance.setAccountId(record.get(t.SYSTEM_ACCOUNT_ID)); stepInstance.setAccount(record.get(t.SYSTEM_ACCOUNT)); stepInstance.setDbAccountId(record.get(t.DB_ACCOUNT_ID)); stepInstance.setDbType(JooqDataTypeUtil.toInteger(record.get(t.DB_TYPE))); stepInstance.setDbAccount(record.get(t.DB_ACCOUNT)); - stepInstance.setDbPass(record.get(t.DB_PASSWORD)); + + // 账号密码解密 + String encryptedDbPassword = record.get(t.DB_PASSWORD); + String dbPassword = dbPasswordCryptoService.decryptDbPasswordIfNeeded( + AccountCategoryEnum.DB, + encryptedDbPassword + ); + + stepInstance.setDbPass(dbPassword); stepInstance.setDbPort(record.get(t.DB_PORT)); - stepInstance.setSecureParam(record.get(t.IS_SECURE_PARAM).intValue() == 1); Byte scriptSource = record.get(t.SCRIPT_SOURCE); if (scriptSource == null) { stepInstance.setScriptSource(1); @@ -246,11 +333,20 @@ private ScriptStepInstanceDTO extractScriptInfo(Record record) { @Override public FileStepInstanceDTO getFileStepInstance(long stepInstanceId) { StepInstanceFile t = StepInstanceFile.STEP_INSTANCE_FILE; - Record record = CTX.select(t.STEP_INSTANCE_ID, t.FILE_SOURCE, t.FILE_TARGET_PATH, - t.FILE_TARGET_NAME, t.RESOLVED_FILE_TARGET_PATH, t.FILE_UPLOAD_SPEED_LIMIT, t.FILE_DOWNLOAD_SPEED_LIMIT, + Record record = CTX.select( + t.STEP_INSTANCE_ID, + t.FILE_SOURCE, + t.FILE_TARGET_PATH, + t.FILE_TARGET_NAME, + t.RESOLVED_FILE_TARGET_PATH, + t.FILE_UPLOAD_SPEED_LIMIT, + t.FILE_DOWNLOAD_SPEED_LIMIT, t.FILE_DUPLICATE_HANDLE, - t.NOT_EXIST_PATH_HANDLER, t.EXECUTION_TIMEOUT, t.SYSTEM_ACCOUNT_ID, t.SYSTEM_ACCOUNT) - .from(t) + t.NOT_EXIST_PATH_HANDLER, + t.EXECUTION_TIMEOUT, + t.SYSTEM_ACCOUNT_ID, + t.SYSTEM_ACCOUNT + ).from(t) .where(t.STEP_INSTANCE_ID.eq(stepInstanceId)).fetchOne(); return extractFileInfo(record); } @@ -288,8 +384,14 @@ private FileStepInstanceDTO extractFileInfo(Record record) { @Override public ConfirmStepInstanceDTO getConfirmStepInstance(long stepInstanceId) { StepInstanceConfirm t = StepInstanceConfirm.STEP_INSTANCE_CONFIRM; - Record record = CTX.select(t.STEP_INSTANCE_ID, t.CONFIRM_MESSAGE, t.CONFIRM_REASON, t.CONFIRM_USERS, - t.CONFIRM_ROLES, t.NOTIFY_CHANNELS).from(t) + Record record = CTX.select( + t.STEP_INSTANCE_ID, + t.CONFIRM_MESSAGE, + t.CONFIRM_REASON, + t.CONFIRM_USERS, + t.CONFIRM_ROLES, + t.NOTIFY_CHANNELS + ).from(t) .where(t.STEP_INSTANCE_ID.eq(stepInstanceId)).fetchOne(); return extractConfirmInfo(record); } @@ -505,10 +607,12 @@ private UpdateSetMoreStep buildBasicUpdateSetMoreStep(RunSta } @Override - public void updateResolvedScriptParam(long stepInstanceId, String resolvedScriptParam) { + public void updateResolvedScriptParam(long stepInstanceId, boolean isSecureParam, String resolvedScriptParam) { StepInstanceScript t = StepInstanceScript.STEP_INSTANCE_SCRIPT; - CTX.update(t).set(t.RESOLVED_SCRIPT_PARAM, resolvedScriptParam) - .where(t.STEP_INSTANCE_ID.eq(stepInstanceId)) + CTX.update(t) + .set(t.RESOLVED_SCRIPT_PARAM, sensitiveParamCryptoService.encryptParamIfNeeded( + isSecureParam, resolvedScriptParam + )).where(t.STEP_INSTANCE_ID.eq(stepInstanceId)) .execute(); } @@ -587,18 +691,24 @@ public Byte getScriptTypeByStepInstanceId(long stepInstanceId) { } public Integer countStepInstanceByConditions(Collection conditions) { - return CTX.selectCount().from(T_STEP_INSTANCE) - .where(conditions).fetchOne().value1(); + Record1 record = CTX.selectCount().from(T_STEP_INSTANCE) + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } public Integer countStepInstanceScriptByConditions(Collection conditions) { - return CTX.selectCount().from(TABLE_STEP_INSTANCE_SCRIPT) - .where(conditions).fetchOne().value1(); + Record1 record = CTX.selectCount().from(TABLE_STEP_INSTANCE_SCRIPT) + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } public Integer countStepInstanceFileByConditions(Collection conditions) { - return CTX.selectCount().from(TABLE_STEP_INSTANCE_FILE) - .where(conditions).fetchOne().value1(); + Record1 record = CTX.selectCount().from(TABLE_STEP_INSTANCE_FILE) + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } @Override @@ -686,9 +796,8 @@ private List genStepInstanceFileConditions(Collection stepInsta } else { conditions.add(TABLE_STEP_INSTANCE_FILE.FILE_DUPLICATE_HANDLE.isNotNull()); } - } else { - // fileDupliateHandle与fileDupliateHandleNull同时为null表示FILE_DUPLICATE_HANDLE字段不作任何筛选 } + // fileDupliateHandle与fileDupliateHandleNull同时为null表示FILE_DUPLICATE_HANDLE字段不作任何筛选 } if (notExistPathHandler != null) { conditions.add(TABLE_STEP_INSTANCE_FILE.NOT_EXIST_PATH_HANDLER.eq(UByte.valueOf(notExistPathHandler.getValue()))); @@ -699,9 +808,8 @@ private List genStepInstanceFileConditions(Collection stepInsta } else { conditions.add(TABLE_STEP_INSTANCE_FILE.NOT_EXIST_PATH_HANDLER.isNotNull()); } - } else { - // notExistPathHandler与notExistPathHandlerNull同时为null表示NOT_EXIST_PATH_HANDLER字段不作任何筛选 } + // notExistPathHandler与notExistPathHandlerNull同时为null表示NOT_EXIST_PATH_HANDLER字段不作任何筛选 } return conditions; } @@ -722,9 +830,8 @@ private List genConditions(Long appId, DuplicateHandlerEnum fileDupli } else { conditions.add(TABLE_STEP_INSTANCE_FILE.FILE_DUPLICATE_HANDLE.isNotNull()); } - } else { - // fileDupliateHandle与fileDupliateHandleNull同时为null表示FILE_DUPLICATE_HANDLE字段不作任何筛选 } + // fileDupliateHandle与fileDupliateHandleNull同时为null表示FILE_DUPLICATE_HANDLE字段不作任何筛选 } if (notExistPathHandler != null) { conditions.add(TABLE_STEP_INSTANCE_FILE.NOT_EXIST_PATH_HANDLER.eq(UByte.valueOf(notExistPathHandler.getValue()))); @@ -735,9 +842,8 @@ private List genConditions(Long appId, DuplicateHandlerEnum fileDupli } else { conditions.add(TABLE_STEP_INSTANCE_FILE.NOT_EXIST_PATH_HANDLER.isNotNull()); } - } else { - // notExistPathHandler与notExistPathHandlerNull同时为null表示NOT_EXIST_PATH_HANDLER字段不作任何筛选 } + // notExistPathHandler与notExistPathHandlerNull同时为null表示NOT_EXIST_PATH_HANDLER字段不作任何筛选 } if (runStatus != null) { conditions.add(T_STEP_INSTANCE.STATUS.eq(runStatus.getValue().byteValue())); @@ -767,9 +873,7 @@ public List> listFastPushFileSource(Long appId, DuplicateHan try { Result> records = query.fetch(); List> resultList = new ArrayList<>(); - records.forEach(record -> { - resultList.add(convertStringToFileSourceDTO((String) record.get(0))); - }); + records.forEach(record -> resultList.add(convertStringToFileSourceDTO((String) record.get(0)))); return resultList; } catch (Exception e) { String msg = MessageFormatter.format( diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/TaskInstanceVariableDAOImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/TaskInstanceVariableDAOImpl.java index a9651f0ef7..2966f630b5 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/TaskInstanceVariableDAOImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/dao/impl/TaskInstanceVariableDAOImpl.java @@ -24,12 +24,15 @@ package com.tencent.bk.job.execute.dao.impl; +import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; +import com.tencent.bk.job.common.crypto.scenario.CipherVariableCryptoService; import com.tencent.bk.job.execute.common.util.JooqDataTypeUtil; import com.tencent.bk.job.execute.dao.TaskInstanceVariableDAO; import com.tencent.bk.job.execute.engine.model.TaskVariableDTO; import org.jooq.DSLContext; import org.jooq.InsertValuesStep5; import org.jooq.Record; +import org.jooq.Record6; import org.jooq.Result; import org.jooq.generated.tables.TaskInstanceVariable; import org.jooq.generated.tables.records.TaskInstanceVariableRecord; @@ -46,18 +49,27 @@ @Repository public class TaskInstanceVariableDAOImpl implements TaskInstanceVariableDAO { private static final TaskInstanceVariable TABLE = TaskInstanceVariable.TASK_INSTANCE_VARIABLE; - private DSLContext ctx; + + private final DSLContext ctx; + private final CipherVariableCryptoService cipherVariableCryptoService; @Autowired - public TaskInstanceVariableDAOImpl(@Qualifier("job-execute-dsl-context") DSLContext ctx) { + public TaskInstanceVariableDAOImpl(@Qualifier("job-execute-dsl-context") DSLContext ctx, + CipherVariableCryptoService cipherVariableCryptoService) { this.ctx = ctx; + this.cipherVariableCryptoService = cipherVariableCryptoService; } @Override public List getByTaskInstanceId(long taskInstanceId) { - Result result = ctx.select(TABLE.ID, TABLE.TASK_INSTANCE_ID, TABLE.NAME, TABLE.TYPE, TABLE.IS_CHANGEABLE, - TABLE.VALUE) - .from(TABLE) + Result> result = ctx.select( + TABLE.ID, + TABLE.TASK_INSTANCE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.IS_CHANGEABLE, + TABLE.VALUE + ).from(TABLE) .where(TABLE.TASK_INSTANCE_ID.eq(taskInstanceId)) .fetch(); List taskVariables = new ArrayList<>(); @@ -73,7 +85,10 @@ private TaskVariableDTO extract(Record record) { taskVariable.setTaskInstanceId(record.get(TABLE.TASK_INSTANCE_ID)); taskVariable.setName(record.get(TABLE.NAME)); taskVariable.setType(JooqDataTypeUtil.toInteger(record.get(TABLE.TYPE))); - taskVariable.setValue(record.get(TABLE.VALUE)); + TaskVariableTypeEnum taskVarType = TaskVariableTypeEnum.valOf(taskVariable.getType()); + String encryptedValue = record.get(TABLE.VALUE); + String value = cipherVariableCryptoService.decryptTaskVariableIfNeeded(taskVarType, encryptedValue); + taskVariable.setValue(value); taskVariable.setChangeable(JooqDataTypeUtil.toInteger(record.get(TABLE.IS_CHANGEABLE)).equals(1)); return taskVariable; } @@ -91,12 +106,25 @@ public void deleteByTaskInstanceId(long taskInstanceId) { @Override public void saveTaskInstanceVariables(List taskVarList) { InsertValuesStep5 insertStep = - ctx.insertInto(TABLE).columns(TABLE.TASK_INSTANCE_ID, TABLE.NAME, TABLE.TYPE, TABLE.VALUE, - TABLE.IS_CHANGEABLE); + ctx.insertInto(TABLE) + .columns( + TABLE.TASK_INSTANCE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.VALUE, + TABLE.IS_CHANGEABLE + ); - taskVarList.forEach(taskVar -> insertStep.values(taskVar.getTaskInstanceId(), - taskVar.getName(), JooqDataTypeUtil.toByte(taskVar.getType()), - taskVar.getValue(), JooqDataTypeUtil.toByte(taskVar.isChangeable() ? 1 : 0))); + taskVarList.forEach(taskVar -> { + TaskVariableTypeEnum taskVarType = TaskVariableTypeEnum.valOf(taskVar.getType()); + insertStep.values( + taskVar.getTaskInstanceId(), + taskVar.getName(), + JooqDataTypeUtil.toByte(taskVar.getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(taskVarType, taskVar.getValue()), + JooqDataTypeUtil.toByte(taskVar.isChangeable() ? 1 : 0) + ); + }); insertStep.execute(); } diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/FileGseTaskStartCommand.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/FileGseTaskStartCommand.java index 7fe2a22a4d..9d19989274 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/FileGseTaskStartCommand.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/FileGseTaskStartCommand.java @@ -69,7 +69,7 @@ import com.tencent.bk.job.execute.service.TaskInstanceVariableService; import com.tencent.bk.job.logsvr.consts.FileTaskModeEnum; import com.tencent.bk.job.logsvr.model.service.ServiceHostLogDTO; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -221,7 +221,7 @@ private void parseSrcFiles() { private void setAccountInfoForSourceFiles(Set sendFiles) { Map accounts = new HashMap<>(); sendFiles.forEach(sendFile -> { - String accountKey = sendFile.getAccountId() == null ? ("id_" + sendFile.getAccountId()) + String accountKey = sendFile.getAccountId() == null ? ("id_null") : ("alias_" + sendFile.getAccountAlias()); AccountDTO account = accounts.computeIfAbsent(accountKey, k -> accountService.getAccount(sendFile.getAccountId(), AccountCategoryEnum.SYSTEM, diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/SQLScriptGseTaskStartCommand.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/SQLScriptGseTaskStartCommand.java index 41992b79f4..38436dd568 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/SQLScriptGseTaskStartCommand.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/SQLScriptGseTaskStartCommand.java @@ -25,14 +25,10 @@ package com.tencent.bk.job.execute.engine.executor; import com.google.common.collect.Maps; -import com.tencent.bk.job.common.constant.ErrorCode; -import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.common.gse.GseClient; import com.tencent.bk.job.common.gse.util.ScriptRequestBuilder; import com.tencent.bk.job.common.gse.v2.model.Agent; import com.tencent.bk.job.common.gse.v2.model.ExecuteScriptRequest; -import com.tencent.bk.job.common.util.Base64Util; -import com.tencent.bk.job.common.util.crypto.AESUtils; import com.tencent.bk.job.execute.config.JobExecuteConfig; import com.tencent.bk.job.execute.engine.evict.TaskEvictPolicyExecutor; import com.tencent.bk.job.execute.engine.listener.event.TaskExecuteMQEventDispatcher; @@ -203,15 +199,7 @@ private String buildRunSqlShellParams(String sqlScriptFileName) { sb.append(" EMPTY"); } if (StringUtils.isNotBlank(stepInstance.getDbPass()) && !StringUtils.equals("null", stepInstance.getDbPass())) { - String dbPassword; - try { - dbPassword = AESUtils.decryptToPlainText(Base64Util.decodeContentToByte(stepInstance.getDbPass()), - jobExecuteConfig.getEncryptPassword()); - } catch (Exception e) { - log.error("Decrypt db password failed!", e); - throw new InternalException(ErrorCode.INTERNAL_ERROR); - } - sb.append(" ").append(dbPassword); + sb.append(" ").append(stepInstance.getDbPass()); } else { sb.append(" EMPTY"); } diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/ScriptGseTaskStartCommand.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/ScriptGseTaskStartCommand.java index 75bc3d56b4..257032c8be 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/ScriptGseTaskStartCommand.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/engine/executor/ScriptGseTaskStartCommand.java @@ -246,7 +246,11 @@ private String resolveScriptParamVariables(String scriptParam) { private void updateResolvedScriptParamIfNecessary(String originParam, String resolvedScriptParam) { // 只有存在变量解析之后才需要update if (!resolvedScriptParam.equals(originParam)) { - taskInstanceService.updateResolvedScriptParam(stepInstance.getId(), resolvedScriptParam); + taskInstanceService.updateResolvedScriptParam( + stepInstance.getId(), + stepInstance.isSecureParam(), + resolvedScriptParam + ); } } @@ -391,6 +395,7 @@ private String escapeSingleQuote(String value) { return value.replaceAll("'", "'\\\\''"); } + @SuppressWarnings({"StringBufferReplaceableByString", "StringBufferMayBeStringBuilder"}) private String buildWrapperScriptWithConstParamOnly(String declareFileName, String userScriptFileName) { StringBuffer sb = new StringBuffer(1024); sb.append("#!/bin/bash\n"); @@ -605,6 +610,7 @@ private String buildOutputVarsOnExitFunction(TaskVariablesAnalyzeResult taskVari return sb.toString(); } + @SuppressWarnings("StringBufferReplaceableByString") private String buildGetJobParamsScript(String varOutputFileName) { StringBuilder sb = new StringBuilder(1024); sb.append("#!/bin/bash\n"); diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/model/AccountDTO.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/model/AccountDTO.java index 062ef6eaff..319c484a11 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/model/AccountDTO.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/model/AccountDTO.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.execute.model; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import lombok.Data; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/AccountService.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/AccountService.java index 6701310da0..81d176c29c 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/AccountService.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/AccountService.java @@ -26,7 +26,7 @@ import com.tencent.bk.job.common.exception.ServiceException; import com.tencent.bk.job.execute.model.AccountDTO; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; /** * 账号服务 @@ -35,8 +35,8 @@ public interface AccountService { /** * 获取账号信息 * - * @param accountId - * @return + * @param accountId 账号ID + * @return 账号信息 */ AccountDTO getAccountById(Long accountId) throws ServiceException; @@ -53,9 +53,9 @@ public interface AccountService { /** * 根据业务ID和账号别名获取系统账号信息 * - * @param alias - * @param appId - * @return + * @param alias 账号别名 + * @param appId Job业务ID + * @return 账号信息 */ AccountDTO getSystemAccountByAlias(String alias, Long appId) throws ServiceException; @@ -65,7 +65,7 @@ public interface AccountService { * @param accountCategory 账号类型 * @param appId 业务ID * @param alias 账号别名 - * @return + * @return 账号信息 */ AccountDTO getAccountByAlias(AccountCategoryEnum accountCategory, Long appId, String alias) throws ServiceException; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/TaskInstanceService.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/TaskInstanceService.java index 750b38c8ee..7efad20a4b 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/TaskInstanceService.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/TaskInstanceService.java @@ -55,7 +55,7 @@ public interface TaskInstanceService { * 获取作业实例详情-包含步骤信息和全局变量信息 * * @param taskInstanceId 作业实例 ID - * @return + * @return 作业实例 */ TaskInstanceDTO getTaskInstanceDetail(long taskInstanceId); @@ -162,15 +162,16 @@ void updateStepExecutionInfo(long stepInstanceId, RunStatusEnum status, * 更新解析之后的脚本参数 * * @param stepInstanceId 步骤实例ID + * @param isSecureParam 是否为敏感参数 * @param resolvedScriptParam 解析之后的脚本参数 */ - void updateResolvedScriptParam(long stepInstanceId, String resolvedScriptParam); + void updateResolvedScriptParam(long stepInstanceId, boolean isSecureParam, String resolvedScriptParam); /** * 更新变量解析之后的源文件 * * @param stepInstanceId 步骤实例ID - * @param resolvedFileSources + * @param resolvedFileSources 解析后的源文件信息 */ void updateResolvedSourceFile(long stepInstanceId, List resolvedFileSources); diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/AccountServiceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/AccountServiceImpl.java index 52896e1b0e..0e8d5f76c7 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/AccountServiceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/AccountServiceImpl.java @@ -27,6 +27,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.common.exception.ServiceException; @@ -34,7 +35,6 @@ import com.tencent.bk.job.execute.client.AccountResourceClient; import com.tencent.bk.job.execute.model.AccountDTO; import com.tencent.bk.job.execute.service.AccountService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.inner.ServiceAccountDTO; import lombok.extern.slf4j.Slf4j; @@ -52,26 +52,26 @@ public class AccountServiceImpl implements AccountService { private final LoadingCache accountCache = CacheBuilder.newBuilder() .maximumSize(10000).expireAfterWrite(1, TimeUnit.MINUTES). - build(new CacheLoader() { - @Override - public AccountDTO load(String accountKey) { - String[] accountProps = accountKey.split("#"); - String keyType = accountProps[0]; - if ("account_alias".equals(keyType)) { - AccountCategoryEnum accountCategory = - AccountCategoryEnum.valOf(Integer.parseInt(accountProps[1])); - long appId = Long.parseLong(accountProps[2]); - String accountAlias = accountProps[3]; - return getAccountByAlias(accountCategory, appId, accountAlias); - } else if ("account_id".equals(keyType)) { - long accountId = Long.parseLong(accountProps[1]); - return getAccountById(accountId); - } else { - return null; - } + build(new CacheLoader() { + @Override + public AccountDTO load(String accountKey) { + String[] accountProps = accountKey.split("#"); + String keyType = accountProps[0]; + if ("account_alias".equals(keyType)) { + AccountCategoryEnum accountCategory = + AccountCategoryEnum.valOf(Integer.parseInt(accountProps[1])); + long appId = Long.parseLong(accountProps[2]); + String accountAlias = accountProps[3]; + return getAccountByAlias(accountCategory, appId, accountAlias); + } else if ("account_id".equals(keyType)) { + long accountId = Long.parseLong(accountProps[1]); + return getAccountById(accountId); + } else { + return null; } } - ); + } + ); @Autowired public AccountServiceImpl(AccountResourceClient accountResourceClient) { diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskExecuteServiceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskExecuteServiceImpl.java index 07f2fb14f9..4bd62114a7 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskExecuteServiceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskExecuteServiceImpl.java @@ -94,7 +94,7 @@ import com.tencent.bk.job.execute.service.TaskPlanService; import com.tencent.bk.job.execute.util.LoggerFactory; import com.tencent.bk.job.manage.common.consts.JobResourceStatusEnum; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.notify.JobRoleEnum; import com.tencent.bk.job.manage.common.consts.notify.ResourceTypeEnum; import com.tencent.bk.job.manage.common.consts.script.ScriptTypeEnum; diff --git a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskInstanceServiceImpl.java b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskInstanceServiceImpl.java index cefe3faf14..0f5e774425 100644 --- a/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskInstanceServiceImpl.java +++ b/src/backend/job-execute/service-job-execute/src/main/java/com/tencent/bk/job/execute/service/impl/TaskInstanceServiceImpl.java @@ -238,8 +238,8 @@ public void updateStepExecutionInfo(long stepInstanceId, RunStatusEnum status, L } @Override - public void updateResolvedScriptParam(long stepInstanceId, String resolvedScriptParam) { - stepInstanceDAO.updateResolvedScriptParam(stepInstanceId, resolvedScriptParam); + public void updateResolvedScriptParam(long stepInstanceId, boolean isSecureParam, String resolvedScriptParam) { + stepInstanceDAO.updateResolvedScriptParam(stepInstanceId, isSecureParam, resolvedScriptParam); } @Override diff --git a/src/backend/job-gateway/src/main/java/com/tencent/bk/job/gateway/filter/global/AddJwtHeaderGlobalFilter.java b/src/backend/job-gateway/src/main/java/com/tencent/bk/job/gateway/filter/global/AddJwtHeaderGlobalFilter.java index cb7e6e0a3f..af371a33d0 100644 --- a/src/backend/job-gateway/src/main/java/com/tencent/bk/job/gateway/filter/global/AddJwtHeaderGlobalFilter.java +++ b/src/backend/job-gateway/src/main/java/com/tencent/bk/job/gateway/filter/global/AddJwtHeaderGlobalFilter.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.gateway.filter.global; -import com.tencent.bk.job.common.util.jwt.JwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; diff --git a/src/backend/job-manage/boot-job-manage/src/main/java/com/tencent/bk/job/manage/JobManageBootApplication.java b/src/backend/job-manage/boot-job-manage/src/main/java/com/tencent/bk/job/manage/JobManageBootApplication.java index 08f4a2e0ce..b18918e5aa 100644 --- a/src/backend/job-manage/boot-job-manage/src/main/java/com/tencent/bk/job/manage/JobManageBootApplication.java +++ b/src/backend/job-manage/boot-job-manage/src/main/java/com/tencent/bk/job/manage/JobManageBootApplication.java @@ -25,6 +25,7 @@ package com.tencent.bk.job.manage; import com.tencent.bk.job.common.config.FeatureToggleConfig; +import com.tencent.bk.job.common.crypto.EncryptConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; @@ -34,7 +35,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication(scanBasePackages = "com.tencent.bk.job", exclude = {RedisAutoConfiguration.class}) -@EnableConfigurationProperties({FeatureToggleConfig.class}) +@EnableConfigurationProperties({FeatureToggleConfig.class, EncryptConfig.class}) @EnableCaching @EnableFeignClients @EnableScheduling diff --git a/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/AccountDAOImplIntegrationTest.java b/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/AccountDAOImplIntegrationTest.java index bdcac5f80e..c06da4ea77 100644 --- a/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/AccountDAOImplIntegrationTest.java +++ b/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/AccountDAOImplIntegrationTest.java @@ -26,7 +26,7 @@ import com.tencent.bk.job.common.model.BaseSearchCondition; import com.tencent.bk.job.common.model.PageData; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import org.junit.jupiter.api.DisplayName; @@ -319,6 +319,7 @@ void testBatchUpdateDbAccountPassword() { AccountDTO account1 = new AccountDTO(); account1.setId(3L); account1.setDbPassword("ax798sdfs"); + account1.setCategory(AccountCategoryEnum.DB); updateAccounts.add(account1); accountDAO.batchUpdateDbAccountPassword(updateAccounts); diff --git a/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImplIntegrationTest.java b/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImplIntegrationTest.java index 36bd804d7f..b458113b2e 100644 --- a/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImplIntegrationTest.java +++ b/src/backend/job-manage/boot-job-manage/src/test/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImplIntegrationTest.java @@ -219,16 +219,13 @@ void givenWrongVariableIdOrTemplateIdReturnDeleteFailed() { void givenNewVariableInfoReturnUpdateSuccess() { assertThat(taskVariableDAO.updateVariableById(VARIABLE_1)).isTrue(); VARIABLE_1.setName(UUID.randomUUID().toString()); - VARIABLE_1.setType(TaskVariableTypeEnum.CIPHER); + VARIABLE_1.setType(TaskVariableTypeEnum.STRING); VARIABLE_1.setDescription(UUID.randomUUID().toString()); VARIABLE_1.setDefaultValue(UUID.randomUUID().toString()); VARIABLE_1.setChangeable(!VARIABLE_1.getChangeable()); VARIABLE_1.setRequired(!VARIABLE_1.getRequired()); assertThat(taskVariableDAO.updateVariableById(VARIABLE_1)).isTrue(); - assertThat(taskVariableDAO.getVariableById(VARIABLE_1.getTemplateId(), VARIABLE_1.getId())) - .isNotEqualTo(VARIABLE_1); - VARIABLE_1.setType(TaskVariableTypeEnum.STRING); assertThat(taskVariableDAO.getVariableById(VARIABLE_1.getTemplateId(), VARIABLE_1.getId())) .isEqualTo(VARIABLE_1); } diff --git a/src/backend/job-manage/boot-job-manage/src/test/resources/init_account_data.sql b/src/backend/job-manage/boot-job-manage/src/test/resources/init_account_data.sql index 4168a73ade..b7d4ad6a17 100644 --- a/src/backend/job-manage/boot-job-manage/src/test/resources/init_account_data.sql +++ b/src/backend/job-manage/boot-job-manage/src/test/resources/init_account_data.sql @@ -25,14 +25,14 @@ truncate table account; insert into job_manage.account (id,account,alias,category,type,app_id,grantee,remark,os,password,db_password,db_port,db_system_account_id, -creator,create_time,last_modify_user,last_modify_time) + creator,create_time,last_modify_user,last_modify_time) values (1,'root','root',1,1,2,'user1,user2','root-linux','Linux',NULL,NULL,NULL,NULL,'admin', 1569550210000, 'admin', 1569550210000); insert into job_manage.account (id,account,alias,category,type,app_id,grantee,remark,os,password,db_password,db_port,db_system_account_id, -creator,create_time,last_modify_user,last_modify_time) + creator,create_time,last_modify_user,last_modify_time) values (2,'system','system',1,2,2,'user1,user2','system-window','Windows','mypassword',NULL,NULL,NULL,'admin', 1569550210000, 'admin', 1569550210000); insert into job_manage.account (id,account,alias,category,type,app_id,grantee,remark,os,password,db_password,db_port,db_system_account_id, -creator,create_time,last_modify_user,last_modify_time) -values (3,'job','job',2,9,2,'user1,user2','db-mysql-job',NULL,NULL,'dbpassword',3600,1,'admin', 1569550210000, 'admin', 1569550210000); + creator,create_time,last_modify_user,last_modify_time) +values (3,'job','job',2,9,2,'user1,user2','db-mysql-job',NULL,NULL,'YXZ/qDVUEdeMAs/8aTuhNAL+RaY95fl8zGlQXko7nMg=',3600,1,'admin', 1569550210000, 'admin', 1569550210000); insert into job_manage.account (id,account,alias,category,type,app_id,grantee,remark,os,password,db_password,db_port,db_system_account_id, -creator,create_time,last_modify_user,last_modify_time) + creator,create_time,last_modify_user,last_modify_time) values (4,'root','root-v2',1,1,2,'user1,user2','root-linux','Linux',NULL,NULL,NULL,NULL,'admin', 1569550210000, 'admin', 1569636611000); diff --git a/src/backend/job-manage/boot-job-manage/src/test/resources/template/init_template_variable_data.sql b/src/backend/job-manage/boot-job-manage/src/test/resources/template/init_template_variable_data.sql index b9b00f3a25..8b9915c1cb 100644 --- a/src/backend/job-manage/boot-job-manage/src/test/resources/template/init_template_variable_data.sql +++ b/src/backend/job-manage/boot-job-manage/src/test/resources/template/init_template_variable_data.sql @@ -25,18 +25,18 @@ USE `job_manage`; TRUNCATE TABLE `task_template_variable`; INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (1, 10000, '测试1', 1, 'test1', '这是一个测试变量1', true, true); +VALUES (1, 10000, '测试1', 1, 'test1', '这是一个测试变量1', true, true); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (2, 10000, '测试2', 2, 'test2', '这是一个测试变量2', false, false); +VALUES (2, 10000, '测试2', 2, 'test2', '这是一个测试变量2', false, false); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (3, 10000, '测试3', 3, 'test3', '这是一个测试变量3', true, false); +VALUES (3, 10000, '测试3', 3, 'test3', '这是一个测试变量3', true, false); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (4, 10000, '测试4', 4, 'test4', '这是一个测试变量4', false, true); +VALUES (4, 10000, '测试4', 4, 'test4', '这是一个测试变量4', false, true); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (5, 20000, '测试5', 1, 'test5', '这是一个测试变量5', true, true); +VALUES (5, 20000, '测试5', 1, 'test5', '这是一个测试变量5', true, true); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (6, 20000, '测试6', 2, 'test6', '这是一个测试变量6', false, false); +VALUES (6, 20000, '测试6', 2, 'test6', '这是一个测试变量6', false, false); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (7, 20000, '测试7', 3, 'test7', '这是一个测试变量7', true, false); +VALUES (7, 20000, '测试7', 3, 'test7', '这是一个测试变量7', true, false); INSERT INTO `task_template_variable` (id, template_id, name, type, default_value, description, is_changeable, is_required) - VALUES (8, 20000, '测试8', 4, 'test8', '这是一个测试变量8', false, true); +VALUES (8, 20000, '测试8', 4, 'test8', '这是一个测试变量8', false, true); diff --git a/src/backend/job-manage/service-job-manage/build.gradle b/src/backend/job-manage/service-job-manage/build.gradle index 6b7e21f646..3c3f0cee40 100644 --- a/src/backend/job-manage/service-job-manage/build.gradle +++ b/src/backend/job-manage/service-job-manage/build.gradle @@ -30,6 +30,7 @@ dependencies { api project(":job-crontab:api-job-crontab") api project(":job-analysis:api-job-analysis") api project(":commons:common") + api project(":commons:common-crypto") api project(":commons:common-security") api project(":commons:common-redis") api project(":commons:cmdb-sdk-ext") diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetDBAccountListResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetDBAccountListResourceImpl.java index cdb96c89d3..1b59633d42 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetDBAccountListResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetDBAccountListResourceImpl.java @@ -24,17 +24,16 @@ package com.tencent.bk.job.manage.api.esb.impl; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.esb.metrics.EsbApiTimed; import com.tencent.bk.job.common.esb.model.EsbResp; import com.tencent.bk.job.common.esb.util.EsbDTOAppScopeMappingHelper; import com.tencent.bk.job.common.exception.InvalidParamException; -import com.tencent.bk.job.common.i18n.service.MessageI18nService; import com.tencent.bk.job.common.metrics.CommonMetricNames; import com.tencent.bk.job.common.model.ValidateResult; import com.tencent.bk.job.common.service.AppScopeMappingService; import com.tencent.bk.job.common.util.date.DateUtils; import com.tencent.bk.job.manage.api.esb.EsbGetDBAccountListResource; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.esb.EsbDBAccountDTO; import com.tencent.bk.job.manage.model.esb.request.EsbGetDBAccountListRequest; @@ -54,15 +53,12 @@ @Slf4j public class EsbGetDBAccountListResourceImpl implements EsbGetDBAccountListResource { private final AccountService accountService; - private final MessageI18nService i18nService; private final AppScopeMappingService appScopeMappingService; @Autowired public EsbGetDBAccountListResourceImpl(AccountService accountService, - MessageI18nService i18nService, AppScopeMappingService appScopeMappingService) { this.accountService = accountService; - this.i18nService = i18nService; this.appScopeMappingService = appScopeMappingService; } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetOSAccountResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetOSAccountResourceImpl.java index 8641093fd7..7648babe91 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetOSAccountResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/esb/impl/EsbGetOSAccountResourceImpl.java @@ -31,7 +31,7 @@ import com.tencent.bk.job.common.service.AppScopeMappingService; import com.tencent.bk.job.common.util.date.DateUtils; import com.tencent.bk.job.manage.api.esb.EsbGetOSAccountResource; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.esb.EsbAccountDTO; import com.tencent.bk.job.manage.model.esb.request.EsbGetOSAccountListRequest; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceAccountResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceAccountResourceImpl.java index 64950241b1..ced2941cc0 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceAccountResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceAccountResourceImpl.java @@ -37,7 +37,7 @@ import com.tencent.bk.job.common.util.date.DateUtils; import com.tencent.bk.job.manage.api.inner.ServiceAccountResource; import com.tencent.bk.job.manage.auth.AccountAuthService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.inner.ServiceAccountDTO; import com.tencent.bk.job.manage.model.web.request.AccountCreateUpdateReq; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceTaskPlanResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceTaskPlanResourceImpl.java index dfeba78d53..3181df8b39 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceTaskPlanResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/inner/impl/ServiceTaskPlanResourceImpl.java @@ -24,15 +24,14 @@ package com.tencent.bk.job.manage.api.inner.impl; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; import com.tencent.bk.job.common.exception.InvalidParamException; import com.tencent.bk.job.common.exception.NotFoundException; -import com.tencent.bk.job.common.i18n.service.MessageI18nService; import com.tencent.bk.job.common.model.InternalResponse; import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.manage.api.inner.ServiceTaskPlanResource; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.task.TaskFileTypeEnum; import com.tencent.bk.job.manage.common.consts.task.TaskStepTypeEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; @@ -88,20 +87,16 @@ public class ServiceTaskPlanResourceImpl implements ServiceTaskPlanResource { private final AccountService accountService; - private final MessageI18nService i18nService; - @Autowired public ServiceTaskPlanResourceImpl( TaskPlanService taskPlanService, @Qualifier("TaskPlanVariableServiceImpl") AbstractTaskVariableService taskVariableService, ScriptService scriptService, - AccountService accountService, - MessageI18nService i18nService) { + AccountService accountService) { this.taskPlanService = taskPlanService; this.taskVariableService = taskVariableService; this.scriptService = scriptService; this.accountService = accountService; - this.i18nService = i18nService; } @Override @@ -465,9 +460,7 @@ private List buildVariables(TaskPlanInfoDTO plan) { return null; } List variableDTOS = new ArrayList<>(); - plan.getVariableList().forEach(variableDTO -> { - variableDTOS.add(buildVariable(variableDTO)); - }); + plan.getVariableList().forEach(variableDTO -> variableDTOS.add(buildVariable(variableDTO))); return variableDTOS; } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/tmp/impl/TmpAppAccountResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/tmp/impl/TmpAppAccountResourceImpl.java index b77574483b..f3730bd0b7 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/tmp/impl/TmpAppAccountResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/tmp/impl/TmpAppAccountResourceImpl.java @@ -24,15 +24,14 @@ package com.tencent.bk.job.manage.api.tmp.impl; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.exception.AlreadyExistsException; import com.tencent.bk.job.common.exception.InvalidParamException; -import com.tencent.bk.job.common.i18n.service.MessageI18nService; import com.tencent.bk.job.common.model.Response; import com.tencent.bk.job.common.util.Utils; import com.tencent.bk.job.common.util.json.JsonUtils; import com.tencent.bk.job.manage.api.tmp.TmpAppAccountResource; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.tmp.TmpAccountCreateUpdateReq; @@ -46,13 +45,11 @@ @Slf4j @RestController public class TmpAppAccountResourceImpl implements TmpAppAccountResource { - private AccountService accountService; - private MessageI18nService i18nService; + private final AccountService accountService; @Autowired - public TmpAppAccountResourceImpl(AccountService accountService, MessageI18nService i18nService) { + public TmpAppAccountResourceImpl(AccountService accountService) { this.accountService = accountService; - this.i18nService = i18nService; } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/web/impl/WebAppAccountResourceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/web/impl/WebAppAccountResourceImpl.java index 7e0995b826..153fcfc789 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/web/impl/WebAppAccountResourceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/api/web/impl/WebAppAccountResourceImpl.java @@ -44,7 +44,7 @@ import com.tencent.bk.job.common.util.date.DateUtils; import com.tencent.bk.job.manage.api.web.WebAppAccountResource; import com.tencent.bk.job.manage.auth.AccountAuthService; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.config.JobManageConfig; import com.tencent.bk.job.manage.model.dto.AccountDTO; @@ -130,7 +130,7 @@ public Response updateAccount(String username, private boolean checkUpdateAccountParam(AccountCreateUpdateReq req) { // 账号名称是不能更新的,所以这里不用校验 if (req.getId() == null) { - log.warn("Id is invalid, id={}", req.getId()); + log.warn("Id is invalid, id=null"); return false; } if (req.getCategory() != null && req.getCategory().equals(AccountCategoryEnum.DB.getValue()) diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/config/JobManageAutoConfiguration.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/config/JobManageAutoConfiguration.java index 7a2e66aaa4..44777badd5 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/config/JobManageAutoConfiguration.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/config/JobManageAutoConfiguration.java @@ -25,8 +25,8 @@ package com.tencent.bk.job.manage.config; import com.tencent.bk.job.common.artifactory.sdk.ArtifactoryClient; -import com.tencent.bk.job.common.encrypt.Encryptor; -import com.tencent.bk.job.common.encrypt.RSAEncryptor; +import com.tencent.bk.job.common.crypto.Encryptor; +import com.tencent.bk.job.common.crypto.RSAEncryptor; import com.tencent.bk.job.common.esb.metrics.EsbApiTimedAspect; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/crypto/CredentialCryptoService.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/crypto/CredentialCryptoService.java new file mode 100644 index 0000000000..e0a28f32d0 --- /dev/null +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/crypto/CredentialCryptoService.java @@ -0,0 +1,74 @@ +/* + * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License. + * + * License for BK-JOB蓝鲸智云作业平台: + * -------------------------------------------------------------------- + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and + * to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +package com.tencent.bk.job.manage.crypto; + +import com.tencent.bk.job.common.crypto.CryptoScenarioEnum; +import com.tencent.bk.job.common.crypto.JobCryptorNames; +import com.tencent.bk.job.common.crypto.SymmetricCryptoService; +import com.tencent.bk.sdk.crypto.cryptor.consts.CryptorNames; +import com.tencent.bk.sdk.crypto.util.CryptorMetaUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * DB账号密码相关加解密服务 + */ +@Slf4j +@Service +public class CredentialCryptoService { + + private final SymmetricCryptoService symmetricCryptoService; + + @Autowired + public CredentialCryptoService(SymmetricCryptoService symmetricCryptoService) { + this.symmetricCryptoService = symmetricCryptoService; + } + + public String getCredentialEncryptAlgorithmByCipher(String cipher) { + if (StringUtils.isEmpty(cipher)) { + return CryptorNames.NONE; + } + String algorithm = CryptorMetaUtil.getCryptorNameFromCipher(cipher); + if (algorithm != null) { + return algorithm; + } + return JobCryptorNames.AES_CBC; + } + + public String encryptCredential(String credentialValue) { + return symmetricCryptoService.encryptToBase64Str(credentialValue, CryptoScenarioEnum.CREDENTIAL); + } + + public String decryptCredential(String encryptedCredential) { + String algorithm = getCredentialEncryptAlgorithmByCipher(encryptedCredential); + if (StringUtils.isBlank(algorithm)) { + return encryptedCredential; + } + return symmetricCryptoService.decrypt(encryptedCredential, algorithm); + } + +} diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/AccountDAO.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/AccountDAO.java index b8b8e69e2e..1687097ddc 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/AccountDAO.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/AccountDAO.java @@ -26,7 +26,7 @@ import com.tencent.bk.job.common.model.BaseSearchCondition; import com.tencent.bk.job.common.model.PageData; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.dto.AccountDisplayDTO; @@ -41,7 +41,7 @@ public interface AccountDAO { /** * 新增账号 * - * @param account + * @param account 账号信息 * @return 账号ID */ long saveAccountWithId(AccountDTO account); @@ -49,7 +49,7 @@ public interface AccountDAO { /** * 新增账号 * - * @param account + * @param account 账号信息 * @return 账号ID */ long saveAccount(AccountDTO account); @@ -57,57 +57,57 @@ public interface AccountDAO { /** * 根据ID获取账号信息 * - * @param accountId - * @return + * @param accountId 账号ID + * @return 账号信息 */ AccountDTO getAccountById(Long accountId); /** * 根据ID批量获取账号信息 * - * @param accountIds - * @return + * @param accountIds 账号ID集合 + * @return 账号展示信息列表 */ List listAccountDisplayInfoByIds(Collection accountIds); /** * 根据appId与account获取账号信息 * - * @param appId - * @param account - * @return + * @param appId Job业务ID + * @param account 账号名 + * @return 账号信息 */ AccountDTO getAccountByAccount(Long appId, String account); /** * 更新账号 * - * @param account + * @param account 账号信息 */ void updateAccount(AccountDTO account); /** * 删除账号 * - * @param accountId + * @param accountId 账号ID */ void deleteAccount(Long accountId); /** * 分页查询账号列表 * - * @param accountQuery - * @param baseSearchCondition - * @return + * @param accountQuery 账号查询条件 + * @param baseSearchCondition 基础搜索条件 + * @return 账号分页数据 */ PageData listPageAccount(AccountDTO accountQuery, BaseSearchCondition baseSearchCondition); /** * 分页搜索账号列表 * - * @param keyword - * @param baseSearchCondition - * @return + * @param keyword 关键字 + * @param baseSearchCondition 基础搜索条件 + * @return 账号分页数据 */ PageData searchPageAccount(Long appId, String keyword, BaseSearchCondition baseSearchCondition); @@ -116,7 +116,7 @@ public interface AccountDAO { * * @param appId 业务ID * @param category 账号类型,如果传入null,表示所有类型 - * @return + * @return 账号列表 */ List listAllAppAccount(Long appId, AccountCategoryEnum category, BaseSearchCondition baseSearchCondition); @@ -163,7 +163,7 @@ List listAllAppAccount(Long appId, AccountCategoryEnum category, * 判断系统账号是否被DB账号引用 * * @param accountId 系统账号ID - * @return + * @return 是否被引用 */ boolean isAccountRefByDbAccount(Long accountId); diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/TaskVariableDAO.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/TaskVariableDAO.java index 3d0793fdc5..57573d3c17 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/TaskVariableDAO.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/TaskVariableDAO.java @@ -109,18 +109,4 @@ public interface TaskVariableDAO { boolean batchInsertVariableWithId(List variableList); boolean updateVariableByName(TaskVariableDTO variable); - - /** - * 查询所有的主机变量 - */ - List listHostVariables(); - - /** - * 更新变量的值 - * - * @param id 主机变量ID - * @param value 变量值 - * @return 更新结果 - */ - boolean updateVariableValue(Long id, String value); } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/AccountDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/AccountDAOImpl.java index cb20ab9920..843b9e5f03 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/AccountDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/AccountDAOImpl.java @@ -24,10 +24,11 @@ package com.tencent.bk.job.manage.dao.impl; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; +import com.tencent.bk.job.common.crypto.scenario.DbPasswordCryptoService; import com.tencent.bk.job.common.model.BaseSearchCondition; import com.tencent.bk.job.common.model.PageData; import com.tencent.bk.job.common.util.date.DateUtils; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.common.util.JooqDataTypeUtil; import com.tencent.bk.job.manage.dao.AccountDAO; @@ -50,6 +51,7 @@ import org.jooq.generated.tables.TaskTemplateStepFile; import org.jooq.generated.tables.TaskTemplateStepFileList; import org.jooq.generated.tables.TaskTemplateStepScript; +import org.jooq.generated.tables.records.AccountRecord; import org.jooq.types.UByte; import org.jooq.types.ULong; import org.springframework.beans.factory.annotation.Autowired; @@ -64,56 +66,118 @@ @Repository public class AccountDAOImpl implements AccountDAO { private static final Account TB_ACCOUNT = Account.ACCOUNT; - private static final TableField[] ALL_FILED = {TB_ACCOUNT.ID, TB_ACCOUNT.ACCOUNT_, TB_ACCOUNT.ALIAS, - TB_ACCOUNT.CATEGORY, TB_ACCOUNT.TYPE, TB_ACCOUNT.APP_ID, TB_ACCOUNT.GRANTEE, TB_ACCOUNT.REMARK, - TB_ACCOUNT.OS, TB_ACCOUNT.PASSWORD, TB_ACCOUNT.DB_PASSWORD, TB_ACCOUNT.DB_PORT, TB_ACCOUNT.DB_SYSTEM_ACCOUNT_ID, - TB_ACCOUNT.CREATOR, TB_ACCOUNT.CREATE_TIME, TB_ACCOUNT.LAST_MODIFY_USER, TB_ACCOUNT.LAST_MODIFY_TIME}; - private DSLContext ctx; + private static final TableField[] ALL_FILED = { + TB_ACCOUNT.ID, + TB_ACCOUNT.ACCOUNT_, + TB_ACCOUNT.ALIAS, + TB_ACCOUNT.CATEGORY, + TB_ACCOUNT.TYPE, + TB_ACCOUNT.APP_ID, + TB_ACCOUNT.GRANTEE, + TB_ACCOUNT.REMARK, + TB_ACCOUNT.OS, + TB_ACCOUNT.PASSWORD, + TB_ACCOUNT.DB_PASSWORD, + TB_ACCOUNT.DB_PORT, + TB_ACCOUNT.DB_SYSTEM_ACCOUNT_ID, + TB_ACCOUNT.CREATOR, + TB_ACCOUNT.CREATE_TIME, + TB_ACCOUNT.LAST_MODIFY_USER, + TB_ACCOUNT.LAST_MODIFY_TIME + }; + private final DSLContext ctx; + private final DbPasswordCryptoService dbPasswordCryptoService; @Autowired - public AccountDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext create) { + public AccountDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext create, + DbPasswordCryptoService dbPasswordCryptoService) { this.ctx = create; + this.dbPasswordCryptoService = dbPasswordCryptoService; } @Override public long saveAccountWithId(AccountDTO account) { - Record record = ctx.insertInto(TB_ACCOUNT, TB_ACCOUNT.ID, TB_ACCOUNT.ACCOUNT_, TB_ACCOUNT.ALIAS, - TB_ACCOUNT.CATEGORY, TB_ACCOUNT.TYPE, TB_ACCOUNT.APP_ID, TB_ACCOUNT.GRANTEE, - TB_ACCOUNT.REMARK, TB_ACCOUNT.OS, TB_ACCOUNT.PASSWORD, TB_ACCOUNT.DB_PASSWORD, TB_ACCOUNT.DB_PORT, + Record record = ctx.insertInto( + TB_ACCOUNT, + TB_ACCOUNT.ID, + TB_ACCOUNT.ACCOUNT_, + TB_ACCOUNT.ALIAS, + TB_ACCOUNT.CATEGORY, + TB_ACCOUNT.TYPE, + TB_ACCOUNT.APP_ID, + TB_ACCOUNT.GRANTEE, + TB_ACCOUNT.REMARK, + TB_ACCOUNT.OS, + TB_ACCOUNT.PASSWORD, + TB_ACCOUNT.DB_PASSWORD, + TB_ACCOUNT.DB_PORT, TB_ACCOUNT.DB_SYSTEM_ACCOUNT_ID, - TB_ACCOUNT.CREATOR, TB_ACCOUNT.CREATE_TIME, TB_ACCOUNT.LAST_MODIFY_USER, TB_ACCOUNT.LAST_MODIFY_TIME) - .values(account.getId(), account.getAccount(), account.getAlias(), - JooqDataTypeUtil.getByteFromInteger(account.getCategory().getValue()), - JooqDataTypeUtil.getByteFromInteger(account.getType().getType()), account.getAppId(), - account.getGrantees(), - account.getRemark(), account.getOs(), account.getPassword(), account.getDbPassword(), - account.getDbPort(), - account.getDbSystemAccountId(), account.getCreator(), ULong.valueOf(account.getCreateTime()), - account.getLastModifyUser(), - ULong.valueOf(account.getLastModifyTime())) - .returning(TB_ACCOUNT.ID) + TB_ACCOUNT.CREATOR, + TB_ACCOUNT.CREATE_TIME, + TB_ACCOUNT.LAST_MODIFY_USER, + TB_ACCOUNT.LAST_MODIFY_TIME + ).values( + account.getId(), + account.getAccount(), + account.getAlias(), + JooqDataTypeUtil.getByteFromInteger(account.getCategory().getValue()), + JooqDataTypeUtil.getByteFromInteger(account.getType().getType()), + account.getAppId(), + account.getGrantees(), + account.getRemark(), + account.getOs(), + account.getPassword(), + dbPasswordCryptoService.encryptDbPasswordIfNeeded(account.getCategory(), account.getDbPassword()), + account.getDbPort(), + account.getDbSystemAccountId(), + account.getCreator(), + ULong.valueOf(account.getCreateTime()), + account.getLastModifyUser(), + ULong.valueOf(account.getLastModifyTime()) + ).returning(TB_ACCOUNT.ID) .fetchOne(); + assert record != null; return record.get(TB_ACCOUNT.ID); } @Override public long saveAccount(AccountDTO account) { - Record record = ctx.insertInto(TB_ACCOUNT, TB_ACCOUNT.ACCOUNT_, TB_ACCOUNT.ALIAS, TB_ACCOUNT.CATEGORY, - TB_ACCOUNT.TYPE, TB_ACCOUNT.APP_ID, TB_ACCOUNT.GRANTEE, - TB_ACCOUNT.REMARK, TB_ACCOUNT.OS, TB_ACCOUNT.PASSWORD, TB_ACCOUNT.DB_PASSWORD, TB_ACCOUNT.DB_PORT, + Record record = ctx.insertInto(TB_ACCOUNT, + TB_ACCOUNT.ACCOUNT_, + TB_ACCOUNT.ALIAS, + TB_ACCOUNT.CATEGORY, + TB_ACCOUNT.TYPE, + TB_ACCOUNT.APP_ID, + TB_ACCOUNT.GRANTEE, + TB_ACCOUNT.REMARK, + TB_ACCOUNT.OS, + TB_ACCOUNT.PASSWORD, + TB_ACCOUNT.DB_PASSWORD, + TB_ACCOUNT.DB_PORT, TB_ACCOUNT.DB_SYSTEM_ACCOUNT_ID, - TB_ACCOUNT.CREATOR, TB_ACCOUNT.CREATE_TIME, TB_ACCOUNT.LAST_MODIFY_USER, TB_ACCOUNT.LAST_MODIFY_TIME) - .values(account.getAccount(), account.getAlias(), - JooqDataTypeUtil.getByteFromInteger(account.getCategory().getValue()), - JooqDataTypeUtil.getByteFromInteger(account.getType().getType()), account.getAppId(), - account.getGrantees(), - account.getRemark(), account.getOs(), account.getPassword(), account.getDbPassword(), - account.getDbPort(), - account.getDbSystemAccountId(), account.getCreator(), ULong.valueOf(account.getCreateTime()), - account.getLastModifyUser(), - ULong.valueOf(DateUtils.currentTimeMillis())) - .returning(TB_ACCOUNT.ID) + TB_ACCOUNT.CREATOR, + TB_ACCOUNT.CREATE_TIME, + TB_ACCOUNT.LAST_MODIFY_USER, + TB_ACCOUNT.LAST_MODIFY_TIME + ).values(account.getAccount(), + account.getAlias(), + JooqDataTypeUtil.getByteFromInteger(account.getCategory().getValue()), + JooqDataTypeUtil.getByteFromInteger(account.getType().getType()), + account.getAppId(), + account.getGrantees(), + account.getRemark(), + account.getOs(), + account.getPassword(), + dbPasswordCryptoService.encryptDbPasswordIfNeeded(account.getCategory(), account.getDbPassword()), + account.getDbPort(), + account.getDbSystemAccountId(), + account.getCreator(), + ULong.valueOf(account.getCreateTime()), + account.getLastModifyUser(), + ULong.valueOf(DateUtils.currentTimeMillis()) + ).returning(TB_ACCOUNT.ID) .fetchOne(); + assert record != null; return record.get(TB_ACCOUNT.ID); } @@ -134,8 +198,8 @@ public List listAccountDisplayInfoByIds(Collection acco TB_ACCOUNT.ALIAS, TB_ACCOUNT.CATEGORY, TB_ACCOUNT.TYPE, - TB_ACCOUNT.APP_ID) - .from(TB_ACCOUNT) + TB_ACCOUNT.APP_ID + ).from(TB_ACCOUNT) .where(conditions) .and(TB_ACCOUNT.IS_DELETED.eq(UByte.valueOf(0))) .fetch(); @@ -210,7 +274,15 @@ private AccountDTO extract(Record record) { account.setRemark(record.get(TB_ACCOUNT.REMARK)); account.setOs(record.get(TB_ACCOUNT.OS)); account.setPassword(record.get(TB_ACCOUNT.PASSWORD)); - account.setDbPassword(record.get(TB_ACCOUNT.DB_PASSWORD)); + + // 解密DB账号密码 + String encryptedDbPassword = record.get(TB_ACCOUNT.DB_PASSWORD); + String dbPassword = dbPasswordCryptoService.decryptDbPasswordIfNeeded( + account.getCategory(), + encryptedDbPassword + ); + + account.setDbPassword(dbPassword); account.setDbPort(record.get(TB_ACCOUNT.DB_PORT)); account.setDbSystemAccountId(record.get(TB_ACCOUNT.DB_SYSTEM_ACCOUNT_ID)); account.setCreator(record.get(TB_ACCOUNT.CREATOR)); @@ -222,7 +294,7 @@ private AccountDTO extract(Record record) { @Override public void updateAccount(AccountDTO account) { - UpdateSetMoreStep update = ctx.update(TB_ACCOUNT) + UpdateSetMoreStep update = ctx.update(TB_ACCOUNT) .set(TB_ACCOUNT.GRANTEE, account.getGrantees()) .set(TB_ACCOUNT.REMARK, account.getRemark()) .set(TB_ACCOUNT.DB_PORT, account.getDbPort()) @@ -236,7 +308,10 @@ public void updateAccount(AccountDTO account) { update.set(TB_ACCOUNT.PASSWORD, account.getPassword()); } if (StringUtils.isNotEmpty(account.getDbPassword())) { - update.set(TB_ACCOUNT.DB_PASSWORD, account.getDbPassword()); + update.set(TB_ACCOUNT.DB_PASSWORD, dbPasswordCryptoService.encryptDbPasswordIfNeeded( + account.getCategory(), + account.getDbPassword() + )); } update.where(TB_ACCOUNT.ID.eq(account.getId())) .execute(); @@ -252,12 +327,6 @@ private void deleteAccountHardly(Long accountId) { .where(TB_ACCOUNT.ID.eq(accountId)).execute(); } - private void deleteAccountSoftly(Long accountId) { - ctx.update(TB_ACCOUNT) - .set(TB_ACCOUNT.IS_DELETED, UByte.valueOf(1)) - .where(TB_ACCOUNT.ID.eq(accountId)).execute(); - } - @Override public PageData searchPageAccount(Long appId, String keyword, BaseSearchCondition baseSearchCondition) { @@ -306,7 +375,7 @@ public PageData listPageAccountByConditions(BaseSearchCondition base int start = baseSearchCondition.getStartOrDefault(0); int length = baseSearchCondition.getLengthOrDefault(10); - Result result = + Result result = ctx.select(ALL_FILED) .from(TB_ACCOUNT) .where(conditions) @@ -334,7 +403,9 @@ public PageData listPageAccountByConditions(BaseSearchCondition base */ private long getPageAccountCount(Long appId, String keyword, BaseSearchCondition baseSearchCondition) { List conditions = buildConditionList(appId, keyword, baseSearchCondition); - return ctx.selectCount().from(TB_ACCOUNT).where(conditions).fetchOne(0, Long.class); + Long count = ctx.selectCount().from(TB_ACCOUNT).where(conditions).fetchOne(0, Long.class); + assert count != null; + return count; } @@ -343,7 +414,9 @@ private long getPageAccountCount(Long appId, String keyword, BaseSearchCondition */ private long getPageAccountCount(AccountDTO accountQuery, BaseSearchCondition baseSearchCondition) { List conditions = buildConditionList(accountQuery, baseSearchCondition); - return ctx.selectCount().from(TB_ACCOUNT).where(conditions).fetchOne(0, Long.class); + Long count = ctx.selectCount().from(TB_ACCOUNT).where(conditions).fetchOne(0, Long.class); + assert count != null; + return count; } private List buildConditionList(AccountDTO accountQuery, BaseSearchCondition baseSearchCondition) { @@ -380,7 +453,7 @@ private List buildConditionList(AccountDTO accountQuery, BaseSearchCo private List buildConditionList(Long appId, String keyword, BaseSearchCondition baseSearchCondition) { List conditions = new ArrayList<>(); - Condition condition = null; + Condition condition; if (keyword != null) { String likeKeyword = "%" + keyword + "%"; condition = TB_ACCOUNT.ID.like(likeKeyword); @@ -433,10 +506,10 @@ public Integer countAllAppAccount(Collection conditions) { public List listAllAppAccount(Collection conditions, BaseSearchCondition baseSearchCondition) { - SelectConditionStep select = ctx.select(ALL_FILED) + SelectConditionStep select = ctx.select(ALL_FILED) .from(TB_ACCOUNT) .where(conditions); - Result result = null; + Result result; if (baseSearchCondition == null) { result = select.fetch(); } else { @@ -452,9 +525,7 @@ public List listAllAppAccount(Collection conditions, } List accountDTOS = new ArrayList<>(); if (result.size() != 0) { - result.into(record -> { - accountDTOS.add(extract(record)); - }); + result.into(record -> accountDTOS.add(extract(record))); } return accountDTOS; } @@ -591,8 +662,12 @@ public void batchUpdateDbAccountPassword(List updatedAccounts) { } private void updateDbPasswordAccount(DSLContext dsl, AccountDTO account) { - dsl.update(TB_ACCOUNT).set(TB_ACCOUNT.DB_PASSWORD, account.getDbPassword()) - .where(TB_ACCOUNT.ID.eq(account.getId())) + dsl.update(TB_ACCOUNT).set( + TB_ACCOUNT.DB_PASSWORD, dbPasswordCryptoService.encryptDbPasswordIfNeeded( + account.getCategory(), + account.getDbPassword() + ) + ).where(TB_ACCOUNT.ID.eq(account.getId())) .and(TB_ACCOUNT.CATEGORY.eq(JooqDataTypeUtil.getByteFromInteger(AccountCategoryEnum.DB.getValue()))) .execute(); } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/CredentialDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/CredentialDAOImpl.java index 98d390650d..89b7ff43c5 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/CredentialDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/impl/CredentialDAOImpl.java @@ -25,14 +25,12 @@ package com.tencent.bk.job.manage.dao.impl; import com.fasterxml.jackson.core.type.TypeReference; +import com.tencent.bk.job.manage.crypto.CredentialCryptoService; import com.tencent.bk.job.common.model.BaseSearchCondition; import com.tencent.bk.job.common.model.PageData; import com.tencent.bk.job.common.model.dto.CommonCredential; -import com.tencent.bk.job.common.util.Base64Util; import com.tencent.bk.job.common.util.JobUUID; -import com.tencent.bk.job.common.util.crypto.AESUtils; import com.tencent.bk.job.common.util.json.JsonUtils; -import com.tencent.bk.job.manage.config.JobTicketConfig; import com.tencent.bk.job.manage.dao.CredentialDAO; import com.tencent.bk.job.manage.model.dto.CredentialDTO; import com.tencent.bk.job.manage.model.inner.resp.ServiceCredentialDisplayDTO; @@ -59,13 +57,14 @@ public class CredentialDAOImpl implements CredentialDAO { private static final Credential defaultTable = Credential.CREDENTIAL; - private final JobTicketConfig jobTicketConfig; private final DSLContext defaultDSLContext; + private final CredentialCryptoService credentialCryptoService; @Autowired - public CredentialDAOImpl(JobTicketConfig jobTicketConfig, DSLContext dslContext) { - this.jobTicketConfig = jobTicketConfig; + public CredentialDAOImpl(DSLContext dslContext, + CredentialCryptoService credentialCryptoService) { this.defaultDSLContext = dslContext; + this.credentialCryptoService = credentialCryptoService; } @Override @@ -92,10 +91,7 @@ public String insertCredential(DSLContext dslContext, CredentialDTO credentialDT credentialDTO.getName(), credentialDTO.getType(), credentialDTO.getDescription(), - AESUtils.encryptToBase64EncodedCipherText( - credentialStr, - jobTicketConfig.getEncryptPassword() - ), + credentialCryptoService.encryptCredential(credentialStr), credentialDTO.getCreator(), credentialDTO.getCreateTime(), credentialDTO.getLastModifyUser(), @@ -123,9 +119,7 @@ public String updateCredentialById(DSLContext dslContext, CredentialDTO credenti .set(defaultTable.NAME, credentialDTO.getName()) .set(defaultTable.TYPE, credentialDTO.getType()) .set(defaultTable.DESCRIPTION, credentialDTO.getDescription()) - .set(defaultTable.VALUE, AESUtils.encryptToBase64EncodedCipherText( - credentialStr, - jobTicketConfig.getEncryptPassword())) + .set(defaultTable.VALUE, credentialCryptoService.encryptCredential(credentialStr)) .set(defaultTable.LAST_MODIFY_USER, credentialDTO.getLastModifyUser()) .set(defaultTable.LAST_MODIFY_TIME, System.currentTimeMillis()) .where(defaultTable.ID.eq(credentialDTO.getId())); @@ -305,9 +299,8 @@ public PageData listPageCredentialByConditions( private CredentialDTO convertRecordToDto(Record record) { try { - String credentialStr = AESUtils.decryptToPlainText( - Base64Util.decodeContentToByte(record.get(defaultTable.VALUE)), - jobTicketConfig.getEncryptPassword() + String credentialStr = credentialCryptoService.decryptCredential( + record.get(defaultTable.VALUE) ); log.debug("Get credential from DB:{}", credentialStr); return new CredentialDTO( diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanScriptStepDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanScriptStepDAOImpl.java index b3ca3d7235..7901b76acb 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanScriptStepDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanScriptStepDAOImpl.java @@ -25,10 +25,10 @@ package com.tencent.bk.job.manage.dao.plan.impl; import com.tencent.bk.job.common.constant.ErrorCode; +import com.tencent.bk.job.common.crypto.scenario.SensitiveParamCryptoService; import com.tencent.bk.job.common.exception.InternalException; +import com.tencent.bk.job.manage.common.consts.script.ScriptTypeEnum; import com.tencent.bk.job.manage.common.consts.task.TaskScriptSourceEnum; -import com.tencent.bk.job.manage.common.consts.task.TaskTypeEnum; -import com.tencent.bk.job.manage.common.util.DbRecordMapper; import com.tencent.bk.job.manage.common.util.JooqDataTypeUtil; import com.tencent.bk.job.manage.dao.TaskScriptStepDAO; import com.tencent.bk.job.manage.model.dto.task.TaskScriptStepDTO; @@ -37,6 +37,7 @@ import org.apache.commons.lang3.StringUtils; import org.jooq.Condition; import org.jooq.DSLContext; +import org.jooq.Record1; import org.jooq.Record15; import org.jooq.Result; import org.jooq.generated.tables.TaskPlan; @@ -68,11 +69,46 @@ public class TaskPlanScriptStepDAOImpl implements TaskScriptStepDAO { private static final TaskPlanStep tableTTStep = TaskPlanStep.TASK_PLAN_STEP; private static final TaskPlanStepScript tableTTStepScript = TaskPlanStepScript.TASK_PLAN_STEP_SCRIPT; - private DSLContext context; + private final DSLContext context; + private final SensitiveParamCryptoService sensitiveParamCryptoService; @Autowired - public TaskPlanScriptStepDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context) { + public TaskPlanScriptStepDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context, + SensitiveParamCryptoService sensitiveParamCryptoService) { this.context = context; + this.sensitiveParamCryptoService = sensitiveParamCryptoService; + } + + private TaskScriptStepDTO convertRecordToTaskScriptStep(Record15 record) { + if (record == null) { + return null; + } + TaskScriptStepDTO taskScriptStep = new TaskScriptStepDTO(); + taskScriptStep.setId(record.get(TABLE.ID).longValue()); + taskScriptStep.setPlanId((record.get(TABLE.PLAN_ID)).longValue()); + taskScriptStep.setStepId((record.get(TABLE.STEP_ID)).longValue()); + taskScriptStep.setScriptSource(TaskScriptSourceEnum.valueOf((record.get(TABLE.SCRIPT_TYPE)).intValue())); + taskScriptStep.setScriptId(record.get(TABLE.SCRIPT_ID)); + if (record.get(TABLE.SCRIPT_VERSION_ID) != null) { + taskScriptStep.setScriptVersionId((record.get(TABLE.SCRIPT_VERSION_ID)).longValue()); + } + taskScriptStep.setContent(record.get(TABLE.CONTENT)); + taskScriptStep.setLanguage(ScriptTypeEnum.valueOf((record.get(TABLE.LANGUAGE)).intValue())); + taskScriptStep.setTimeout((record.get(TABLE.SCRIPT_TIMEOUT)).longValue()); + taskScriptStep.setAccount((record.get(TABLE.EXECUTE_ACCOUNT)).longValue()); + taskScriptStep.setExecuteTarget(TaskTargetDTO.fromJsonString(record.get(TABLE.DESTINATION_HOST_LIST))); + taskScriptStep.setSecureParam((record.get(TABLE.IS_SECURE_PARAM)).intValue() == 1); + String encryptedScriptParam = record.get(TABLE.SCRIPT_PARAM); + + // 敏感参数解密 + taskScriptStep.setScriptParam(sensitiveParamCryptoService.decryptParamIfNeeded( + taskScriptStep.getSecureParam(), encryptedScriptParam + )); + + taskScriptStep.setStatus((record.get(TABLE.STATUS)).intValue()); + taskScriptStep.setIgnoreError((record.get(TABLE.IGNORE_ERROR)).intValue() == 1); + return taskScriptStep; } @Override @@ -83,17 +119,29 @@ public List listScriptStepByParentId(long parentId) { Record15> result = context - .select(TABLE.ID, TABLE.PLAN_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, - TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, - TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, - TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .from(TABLE).where(conditions).fetch(); + .select( + TABLE.ID, + TABLE.PLAN_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetch(); List taskScriptStepList = new ArrayList<>(); - if (result != null && result.size() >= 1) { + if (result.size() >= 1) { result.map(record -> taskScriptStepList - .add(DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.PLAN))); + .add(convertRecordToTaskScriptStep(record))); } return taskScriptStepList; } @@ -106,17 +154,31 @@ public Map listScriptStepByIds(List stepIdList) { Record15> result = context - .select(TABLE.ID, TABLE.PLAN_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, - TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, - TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, - TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .from(TABLE).where(conditions).fetch(); + .select( + TABLE.ID, + TABLE.PLAN_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetch(); Map taskScriptStepMap = new HashMap<>(stepIdList.size()); - if (result != null && result.size() >= 1) { - result.map(record -> taskScriptStepMap.put(record.get(TABLE.STEP_ID).longValue(), - DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.PLAN))); + if (result.size() >= 1) { + result.map(record -> taskScriptStepMap.put( + record.get(TABLE.STEP_ID).longValue(), + convertRecordToTaskScriptStep(record)) + ); } return taskScriptStepMap; } @@ -126,12 +188,25 @@ public TaskScriptStepDTO getScriptStepById(long stepId) { List conditions = new ArrayList<>(); conditions.add(TABLE.STEP_ID.eq(ULong.valueOf(stepId))); Record15 record = context.select(TABLE.ID, TABLE.PLAN_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, - TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, TABLE.SCRIPT_TIMEOUT, - TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, TABLE.IS_SECURE_PARAM, TABLE.STATUS, - TABLE.IGNORE_ERROR).from(TABLE).where(conditions).fetchOne(); + UByte> record = context.select( + TABLE.ID, + TABLE.PLAN_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetchOne(); if (record != null) { - return DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.PLAN); + return convertRecordToTaskScriptStep(record); } else { return null; } @@ -149,17 +224,38 @@ public long insertScriptStep(TaskScriptStepDTO scriptStep) { ignoreError = UByte.valueOf(1); } TaskPlanStepScriptRecord record = context.insertInto(TABLE) - .columns(TABLE.PLAN_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, TABLE.SCRIPT_VERSION_ID, - TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, - TABLE.DESTINATION_HOST_LIST, TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .values(ULong.valueOf(scriptStep.getPlanId()), ULong.valueOf(scriptStep.getStepId()), - UByte.valueOf(scriptStep.getScriptSource().getType()), scriptStep.getScriptId(), + .columns( + TABLE.PLAN_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).values( + ULong.valueOf(scriptStep.getPlanId()), + ULong.valueOf(scriptStep.getStepId()), + UByte.valueOf(scriptStep.getScriptSource().getType()), + scriptStep.getScriptId(), scriptStep.getScriptVersionId() == null ? null : ULong.valueOf(scriptStep.getScriptVersionId()), - scriptStep.getContent(), UByte.valueOf(scriptStep.getLanguage().getValue()), - scriptStep.getScriptParam(), ULong.valueOf(scriptStep.getTimeout()), - ULong.valueOf(scriptStep.getAccount()), scriptStep.getExecuteTarget().toJsonString(), isSecureParam, - status, ignoreError) - .returning(TABLE.ID).fetchOne(); + scriptStep.getContent(), + UByte.valueOf(scriptStep.getLanguage().getValue()), + sensitiveParamCryptoService.encryptParamIfNeeded(scriptStep.getSecureParam(), scriptStep.getScriptParam()), + ULong.valueOf(scriptStep.getTimeout()), + ULong.valueOf(scriptStep.getAccount()), + scriptStep.getExecuteTarget().toJsonString(), + isSecureParam, + status, + ignoreError + ).returning(TABLE.ID).fetchOne(); + assert record != null; return record.getId().longValue(); } @@ -189,10 +285,12 @@ public int countScriptSteps(Long appId, TaskScriptSourceEnum scriptSource) { if (scriptSource != null) { conditions.add(tableTTStepScript.SCRIPT_TYPE.eq(UByte.valueOf(scriptSource.getType()))); } - return context.selectCount().from(tableTTStepScript) + Record1 record = context.selectCount().from(tableTTStepScript) .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) .join(tableTaskPlan).on(tableTTStep.PLAN_ID.eq(tableTaskPlan.ID)) - .where(conditions).fetchOne().value1(); + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } @Override @@ -204,10 +302,12 @@ public int countScriptCitedByStepsByScriptIds(Long appId, List scriptIdL if (scriptIdList != null) { conditions.add(tableTTStepScript.SCRIPT_ID.in(scriptIdList)); } - return context.select(DSL.countDistinct(tableTTStepScript.SCRIPT_ID)).from(tableTTStepScript) + Record1 record = context.select(DSL.countDistinct(tableTTStepScript.SCRIPT_ID)).from(tableTTStepScript) .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) .join(tableTaskPlan).on(tableTTStep.PLAN_ID.eq(tableTaskPlan.ID)) - .where(conditions).fetchOne().value1(); + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } @Override @@ -219,10 +319,12 @@ public int countScriptStepsByScriptIds(Long appId, List scriptIdList) { if (scriptIdList != null) { conditions.add(tableTTStepScript.SCRIPT_ID.in(scriptIdList)); } - return context.selectCount().from(tableTTStepScript) + Record1 record = context.selectCount().from(tableTTStepScript) .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) .join(tableTaskPlan).on(tableTTStep.PLAN_ID.eq(tableTaskPlan.ID)) - .where(conditions).fetchOne().value1(); + .where(conditions).fetchOne(); + assert record != null; + return record.value1(); } @Override diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanVariableDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanVariableDAOImpl.java index 285e272098..7957fa1fbf 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanVariableDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/plan/impl/TaskPlanVariableDAOImpl.java @@ -27,8 +27,8 @@ import com.tencent.bk.job.common.constant.Bool; import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; +import com.tencent.bk.job.common.crypto.scenario.CipherVariableCryptoService; import com.tencent.bk.job.common.exception.InternalException; -import com.tencent.bk.job.manage.common.util.JooqDataTypeUtil; import com.tencent.bk.job.manage.dao.TaskVariableDAO; import com.tencent.bk.job.manage.model.dto.task.TaskVariableDTO; import lombok.extern.slf4j.Slf4j; @@ -66,10 +66,13 @@ public class TaskPlanVariableDAOImpl implements TaskVariableDAO { TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED}; private final DSLContext context; + private final CipherVariableCryptoService cipherVariableCryptoService; @Autowired - public TaskPlanVariableDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context) { + public TaskPlanVariableDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context, + CipherVariableCryptoService cipherVariableCryptoService) { this.context = context; + this.cipherVariableCryptoService = cipherVariableCryptoService; } @Override @@ -91,7 +94,13 @@ private TaskVariableDTO extract(Record record) { taskVariable.setPlanId(record.get(TABLE.PLAN_ID).longValue()); taskVariable.setName(record.get(TABLE.NAME)); taskVariable.setType(TaskVariableTypeEnum.valOf(record.get(TABLE.TYPE).intValue())); - taskVariable.setDefaultValue(record.get(TABLE.DEFAULT_VALUE)); + String encryptedDefaultValue = record.get(TABLE.DEFAULT_VALUE); + // 密文变量解密 + String defaultValue = cipherVariableCryptoService.decryptTaskVariableIfNeeded( + taskVariable.getType(), + encryptedDefaultValue + ); + taskVariable.setDefaultValue(defaultValue); taskVariable.setDescription(record.get(TABLE.DESCRIPTION)); taskVariable.setChangeable(Bool.isTrue(record.get(TABLE.IS_CHANGEABLE).byteValue())); taskVariable.setRequired(Bool.isTrue(record.get(TABLE.IS_REQUIRED).byteValue())); @@ -120,12 +129,26 @@ public TaskVariableDTO getVariableByName(long parentId, String varName) { @Override public long insertVariable(TaskVariableDTO variable) { TaskPlanVariableRecord record = context.insertInto(TABLE) - .columns(TABLE.TEMPLATE_VARIABLE_ID, TABLE.PLAN_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, - TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED) - .values(ULong.valueOf(variable.getId()), ULong.valueOf(variable.getPlanId()), variable.getName(), - UByte.valueOf(variable.getType().getType()), variable.getDefaultValue(), variable.getDescription(), - getChangeable(variable.getChangeable()), getRequired(variable.getRequired())) - .returning(TABLE.TEMPLATE_VARIABLE_ID).fetchOne(); + .columns( + TABLE.TEMPLATE_VARIABLE_ID, + TABLE.PLAN_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ).values( + ULong.valueOf(variable.getId()), + ULong.valueOf(variable.getPlanId()), + variable.getName(), + UByte.valueOf(variable.getType().getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue()), + variable.getDescription(), + getChangeable(variable.getChangeable()), + getRequired(variable.getRequired()) + ).returning(TABLE.TEMPLATE_VARIABLE_ID).fetchOne(); + assert record != null; return record.getTemplateVariableId().longValue(); } @@ -135,13 +158,29 @@ public List batchInsertVariables(List variableList) { return Collections.emptyList(); } InsertValuesStep8 insertStep = context.insertInto(TABLE).columns(TABLE.TEMPLATE_VARIABLE_ID, TABLE.PLAN_ID, - TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED); - - variableList.forEach(variable -> insertStep.values(ULong.valueOf(variable.getId()), - ULong.valueOf(variable.getPlanId()), variable.getName(), UByte.valueOf(variable.getType().getType()), - variable.getDefaultValue(), variable.getDescription(), getChangeable(variable.getChangeable()), - getRequired(variable.getRequired()))); + UByte> insertStep = context.insertInto(TABLE) + .columns( + TABLE.TEMPLATE_VARIABLE_ID, + TABLE.PLAN_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ); + + variableList.forEach(variable -> + insertStep.values( + ULong.valueOf(variable.getId()), + ULong.valueOf(variable.getPlanId()), + variable.getName(), + UByte.valueOf(variable.getType().getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue()), + variable.getDescription(), + getChangeable(variable.getChangeable()), + getRequired(variable.getRequired()) + )); Result result = insertStep.returning(TABLE.TEMPLATE_VARIABLE_ID).fetch(); List variableIdList = new ArrayList<>(variableList.size()); @@ -170,7 +209,9 @@ public boolean updateVariableById(TaskVariableDTO variable) { if (variable.getType().isNeedMask() && variable.getDefaultValue().equals(variable.getType().getMask())) { updateStep = context.update(TABLE).set(TABLE.DEFAULT_VALUE, TABLE.DEFAULT_VALUE); } else { - updateStep = context.update(TABLE).set(TABLE.DEFAULT_VALUE, variable.getDefaultValue()); + updateStep = context.update(TABLE) + .set(TABLE.DEFAULT_VALUE, + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue())); } if (StringUtils.isNotBlank(variable.getName())) { updateStep.set(TABLE.NAME, variable.getName()); @@ -214,7 +255,11 @@ public boolean updateVariableByName(TaskVariableDTO variable) { conditions.add(TABLE.PLAN_ID.equal(ULong.valueOf(variable.getPlanId()))); conditions.add(TABLE.NAME.equal(variable.getName())); return 1 == - context.update(TABLE).set(TABLE.DEFAULT_VALUE, variable.getDefaultValue()).where(conditions).limit(1).execute(); + context.update(TABLE) + .set(TABLE.DEFAULT_VALUE, + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue())) + .where(conditions).limit(1) + .execute(); } private UByte getChangeable(Boolean changeable) { @@ -232,24 +277,4 @@ private UByte getRequired(Boolean required) { } return isRequired; } - - @Override - public List listHostVariables() { - List conditions = new ArrayList<>(); - conditions.add(TABLE.TYPE.eq(JooqDataTypeUtil.buildUByte(TaskVariableTypeEnum.HOST_LIST.getType()))); - - Result result = context.select(ALL_FIELDS).from(TABLE).where(conditions).fetch(); - return result.map(this::extract); - } - - @Override - public boolean updateVariableValue(Long id, String value) { - List conditions = new ArrayList<>(); - conditions.add(TABLE.ID.eq(JooqDataTypeUtil.buildULong(id))); - int result = context.update(TABLE) - .set(TABLE.DEFAULT_VALUE, value) - .where(conditions) - .execute(); - return result == 1; - } } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateScriptStepDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateScriptStepDAOImpl.java index e7d6fee284..3c02fdedda 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateScriptStepDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateScriptStepDAOImpl.java @@ -24,9 +24,9 @@ package com.tencent.bk.job.manage.dao.template.impl; +import com.tencent.bk.job.common.crypto.scenario.SensitiveParamCryptoService; +import com.tencent.bk.job.manage.common.consts.script.ScriptTypeEnum; import com.tencent.bk.job.manage.common.consts.task.TaskScriptSourceEnum; -import com.tencent.bk.job.manage.common.consts.task.TaskTypeEnum; -import com.tencent.bk.job.manage.common.util.DbRecordMapper; import com.tencent.bk.job.manage.common.util.JooqDataTypeUtil; import com.tencent.bk.job.manage.dao.TaskScriptStepDAO; import com.tencent.bk.job.manage.model.dto.task.TaskScriptStepDTO; @@ -35,6 +35,7 @@ import org.apache.commons.lang3.StringUtils; import org.jooq.Condition; import org.jooq.DSLContext; +import org.jooq.Record1; import org.jooq.Record15; import org.jooq.Record3; import org.jooq.Result; @@ -68,11 +69,46 @@ public class TaskTemplateScriptStepDAOImpl implements TaskScriptStepDAO { private static final TaskTemplateStep tableTTStep = TaskTemplateStep.TASK_TEMPLATE_STEP; private static final TaskTemplateStepScript tableTTStepScript = TaskTemplateStepScript.TASK_TEMPLATE_STEP_SCRIPT; - private DSLContext context; + private final DSLContext context; + private final SensitiveParamCryptoService sensitiveParamCryptoService; @Autowired - public TaskTemplateScriptStepDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context) { + public TaskTemplateScriptStepDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context, + SensitiveParamCryptoService sensitiveParamCryptoService) { this.context = context; + this.sensitiveParamCryptoService = sensitiveParamCryptoService; + } + + private TaskScriptStepDTO convertRecordToTaskScriptStep(Record15 record) { + if (record == null) { + return null; + } + TaskScriptStepDTO taskScriptStep = new TaskScriptStepDTO(); + taskScriptStep.setId(record.get(TABLE.ID).longValue()); + taskScriptStep.setTemplateId((record.get(TABLE.TEMPLATE_ID)).longValue()); + taskScriptStep.setStepId((record.get(TABLE.STEP_ID)).longValue()); + taskScriptStep.setScriptSource(TaskScriptSourceEnum.valueOf((record.get(TABLE.SCRIPT_TYPE)).intValue())); + taskScriptStep.setScriptId(record.get(TABLE.SCRIPT_ID)); + if (record.get(TABLE.SCRIPT_VERSION_ID) != null) { + taskScriptStep.setScriptVersionId((record.get(TABLE.SCRIPT_VERSION_ID)).longValue()); + } + taskScriptStep.setContent(record.get(TABLE.CONTENT)); + taskScriptStep.setLanguage(ScriptTypeEnum.valueOf((record.get(TABLE.LANGUAGE)).intValue())); + taskScriptStep.setTimeout((record.get(TABLE.SCRIPT_TIMEOUT)).longValue()); + taskScriptStep.setAccount((record.get(TABLE.EXECUTE_ACCOUNT)).longValue()); + taskScriptStep.setExecuteTarget(TaskTargetDTO.fromJsonString(record.get(TABLE.DESTINATION_HOST_LIST))); + taskScriptStep.setSecureParam((record.get(TABLE.IS_SECURE_PARAM)).intValue() == 1); + String encryptedScriptParam = record.get(TABLE.SCRIPT_PARAM); + + // 敏感参数解密 + taskScriptStep.setScriptParam(sensitiveParamCryptoService.decryptParamIfNeeded( + taskScriptStep.getSecureParam(), encryptedScriptParam + )); + + taskScriptStep.setStatus((record.get(TABLE.STATUS)).intValue()); + taskScriptStep.setIgnoreError((record.get(TABLE.IGNORE_ERROR)).intValue() == 1); + return taskScriptStep; } @Override @@ -83,17 +119,30 @@ public List listScriptStepByParentId(long parentId) { Record15> result = context - .select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, - TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, - TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, - TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .from(TABLE).where(conditions).fetch(); + .select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetch(); List taskScriptStepList = new ArrayList<>(); - if (result != null && result.size() >= 1) { - result.map(record -> taskScriptStepList - .add(DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.TEMPLATE))); + if (result.size() >= 1) { + result.map(record -> + taskScriptStepList.add(convertRecordToTaskScriptStep(record)) + ); } return taskScriptStepList; } @@ -106,17 +155,31 @@ public Map listScriptStepByIds(List stepIdList) { Record15> result = context - .select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, - TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, - TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, - TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .from(TABLE).where(conditions).fetch(); + .select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetch(); Map taskScriptStepMap = new HashMap<>(stepIdList.size()); - if (result != null && result.size() >= 1) { - result.map(record -> taskScriptStepMap.put(record.get(TABLE.STEP_ID).longValue(), - DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.TEMPLATE))); + if (result.size() >= 1) { + result.map(record -> taskScriptStepMap.put( + record.get(TABLE.STEP_ID).longValue(), + convertRecordToTaskScriptStep(record) + )); } return taskScriptStepMap; } @@ -126,12 +189,25 @@ public TaskScriptStepDTO getScriptStepById(long stepId) { List conditions = new ArrayList<>(); conditions.add(TABLE.STEP_ID.eq(ULong.valueOf(stepId))); Record15 record = context.select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, - TABLE.SCRIPT_ID, TABLE.SCRIPT_VERSION_ID, TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, - TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, TABLE.DESTINATION_HOST_LIST, TABLE.IS_SECURE_PARAM, - TABLE.STATUS, TABLE.IGNORE_ERROR).from(TABLE).where(conditions).fetchOne(); + UByte> record = context.select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).from(TABLE).where(conditions).fetchOne(); if (record != null) { - return DbRecordMapper.convertRecordToTaskScriptStep(record, TaskTypeEnum.TEMPLATE); + return convertRecordToTaskScriptStep(record); } else { return null; } @@ -148,18 +224,38 @@ public long insertScriptStep(TaskScriptStepDTO scriptStep) { ignoreError = UByte.valueOf(1); } TaskTemplateStepScriptRecord record = context.insertInto(TABLE) - .columns(TABLE.TEMPLATE_ID, TABLE.STEP_ID, TABLE.SCRIPT_TYPE, TABLE.SCRIPT_ID, TABLE.SCRIPT_VERSION_ID, - TABLE.CONTENT, TABLE.LANGUAGE, TABLE.SCRIPT_PARAM, TABLE.SCRIPT_TIMEOUT, TABLE.EXECUTE_ACCOUNT, - TABLE.DESTINATION_HOST_LIST, TABLE.IS_SECURE_PARAM, TABLE.STATUS, TABLE.IGNORE_ERROR) - .values(ULong.valueOf(scriptStep.getTemplateId()), ULong.valueOf(scriptStep.getStepId()), - UByte.valueOf(scriptStep.getScriptSource().getType()), scriptStep.getScriptId(), + .columns( + TABLE.TEMPLATE_ID, + TABLE.STEP_ID, + TABLE.SCRIPT_TYPE, + TABLE.SCRIPT_ID, + TABLE.SCRIPT_VERSION_ID, + TABLE.CONTENT, + TABLE.LANGUAGE, + TABLE.SCRIPT_PARAM, + TABLE.SCRIPT_TIMEOUT, + TABLE.EXECUTE_ACCOUNT, + TABLE.DESTINATION_HOST_LIST, + TABLE.IS_SECURE_PARAM, + TABLE.STATUS, + TABLE.IGNORE_ERROR + ).values( + ULong.valueOf(scriptStep.getTemplateId()), + ULong.valueOf(scriptStep.getStepId()), + UByte.valueOf(scriptStep.getScriptSource().getType()), + scriptStep.getScriptId(), scriptStep.getScriptVersionId() == null ? null : ULong.valueOf(scriptStep.getScriptVersionId()), - scriptStep.getContent(), UByte.valueOf(scriptStep.getLanguage().getValue()), - scriptStep.getScriptParam(), ULong.valueOf(scriptStep.getTimeout()), + scriptStep.getContent(), + UByte.valueOf(scriptStep.getLanguage().getValue()), + sensitiveParamCryptoService.encryptParamIfNeeded(scriptStep.getSecureParam(), scriptStep.getScriptParam()), + ULong.valueOf(scriptStep.getTimeout()), ULong.valueOf(scriptStep.getAccount()), - scriptStep.getExecuteTarget() == null ? null : scriptStep.getExecuteTarget().toJsonString(), isSecureParam, - UByte.valueOf(scriptStep.getStatus()), ignoreError) - .returning(TABLE.ID).fetchOne(); + scriptStep.getExecuteTarget() == null ? null : scriptStep.getExecuteTarget().toJsonString(), + isSecureParam, + UByte.valueOf(scriptStep.getStatus()), + ignoreError + ).returning(TABLE.ID).fetchOne(); + assert record != null; return record.getId().longValue(); } @@ -181,7 +277,8 @@ public boolean updateScriptStepById(TaskScriptStepDTO scriptStep) { scriptStep.getScriptVersionId() == null ? null : ULong.valueOf(scriptStep.getScriptVersionId())) .set(TABLE.CONTENT, scriptStep.getContent()) .set(TABLE.LANGUAGE, UByte.valueOf(scriptStep.getLanguage().getValue())) - .set(TABLE.SCRIPT_PARAM, scriptStep.getScriptParam()) + .set(TABLE.SCRIPT_PARAM, sensitiveParamCryptoService.encryptParamIfNeeded( + scriptStep.getSecureParam(), scriptStep.getScriptParam())) .set(TABLE.SCRIPT_TIMEOUT, ULong.valueOf(scriptStep.getTimeout())) .set(TABLE.EXECUTE_ACCOUNT, ULong.valueOf(scriptStep.getAccount())) .set(TABLE.DESTINATION_HOST_LIST, @@ -209,7 +306,7 @@ public List batchListScriptStepIdByParentIds(List templ Result> result = context .select(TABLE.TEMPLATE_ID, TABLE.SCRIPT_ID, TABLE.SCRIPT_VERSION_ID).from(TABLE).where(conditions).fetch(); List taskScriptStepList = new ArrayList<>(); - if (result != null && result.size() > 0) { + if (result.size() > 0) { result.map(record -> { TaskScriptStepDTO taskScriptStep = new TaskScriptStepDTO(); taskScriptStep.setTemplateId(record.get(TABLE.TEMPLATE_ID).longValue()); @@ -239,10 +336,16 @@ public int countScriptSteps(Long appId, TaskScriptSourceEnum scriptSource) { if (scriptSource != null) { conditions.add(tableTTStepScript.SCRIPT_TYPE.eq(UByte.valueOf(scriptSource.getType()))); } - return context.selectCount().from(tableTTStepScript) - .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) - .join(tableTaskTemplate).on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) - .where(conditions).fetchOne().value1(); + Record1 record = context.selectCount() + .from(tableTTStepScript) + .join(tableTTStep) + .on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) + .join(tableTaskTemplate) + .on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) + .where(conditions) + .fetchOne(); + assert record != null; + return record.value1(); } @Override @@ -254,10 +357,16 @@ public int countScriptCitedByStepsByScriptIds(Long appId, List scriptIdL if (scriptIdList != null) { conditions.add(tableTTStepScript.SCRIPT_ID.in(scriptIdList)); } - return context.select(DSL.countDistinct(tableTTStepScript.SCRIPT_ID)).from(tableTTStepScript) - .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) - .join(tableTaskTemplate).on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) - .where(conditions).fetchOne().value1(); + Record1 record = context.select(DSL.countDistinct(tableTTStepScript.SCRIPT_ID)) + .from(tableTTStepScript) + .join(tableTTStep) + .on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) + .join(tableTaskTemplate) + .on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) + .where(conditions) + .fetchOne(); + assert record != null; + return record.value1(); } @Override @@ -269,10 +378,16 @@ public int countScriptStepsByScriptIds(Long appId, List scriptIdList) { if (scriptIdList != null) { conditions.add(tableTTStepScript.SCRIPT_ID.in(scriptIdList)); } - return context.selectCount().from(tableTTStepScript) - .join(tableTTStep).on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) - .join(tableTaskTemplate).on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) - .where(conditions).fetchOne().value1(); + Record1 record = context.selectCount() + .from(tableTTStepScript) + .join(tableTTStep) + .on(tableTTStep.ID.eq(tableTTStepScript.STEP_ID)) + .join(tableTaskTemplate) + .on(tableTTStep.TEMPLATE_ID.eq(tableTaskTemplate.ID)) + .where(conditions) + .fetchOne(); + assert record != null; + return record.value1(); } @Override diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImpl.java index 2d632ffcaa..beeabe4083 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/dao/template/impl/TaskTemplateVariableDAOImpl.java @@ -26,6 +26,7 @@ import com.tencent.bk.job.common.constant.ErrorCode; import com.tencent.bk.job.common.constant.TaskVariableTypeEnum; +import com.tencent.bk.job.common.crypto.scenario.CipherVariableCryptoService; import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.manage.common.util.JooqDataTypeUtil; import com.tencent.bk.job.manage.dao.TaskVariableDAO; @@ -39,7 +40,6 @@ import org.jooq.Record; import org.jooq.Record8; import org.jooq.Result; -import org.jooq.TableField; import org.jooq.generated.tables.TaskTemplateVariable; import org.jooq.generated.tables.records.TaskTemplateVariableRecord; import org.jooq.types.UByte; @@ -63,14 +63,14 @@ public class TaskTemplateVariableDAOImpl implements TaskVariableDAO { private static final TaskTemplateVariable TABLE = TaskTemplateVariable.TASK_TEMPLATE_VARIABLE; - private static final TableField[] ALL_FIELDS = {TABLE.ID, TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, - TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED}; - - private DSLContext context; + private final DSLContext context; + private final CipherVariableCryptoService cipherVariableCryptoService; @Autowired - public TaskTemplateVariableDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context) { + public TaskTemplateVariableDAOImpl(@Qualifier("job-manage-dsl-context") DSLContext context, + CipherVariableCryptoService cipherVariableCryptoService) { this.context = context; + this.cipherVariableCryptoService = cipherVariableCryptoService; } @Override @@ -83,9 +83,16 @@ public List listVariablesByParentId(long parentId) { Record8> records = context - .select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, - TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED) - .from(TABLE).where(conditions).fetch(); + .select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ).from(TABLE).where(conditions).fetch(); List taskVariableList = new ArrayList<>(); @@ -102,8 +109,16 @@ public TaskVariableDTO getVariableById(long parentId, long id) { conditions.add(TABLE.ID.eq(ULong.valueOf(id))); conditions.add(TABLE.TEMPLATE_ID.eq(ULong.valueOf(parentId))); Record8 record = - context.select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, - TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED).from(TABLE).where(conditions).fetchOne(); + context.select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ).from(TABLE).where(conditions).fetchOne(); if (record != null) { return extract(record); } else { @@ -120,7 +135,13 @@ private TaskVariableDTO extract(Record record) { taskVariable.setTemplateId(Objects.requireNonNull(record.get(TABLE.TEMPLATE_ID)).longValue()); taskVariable.setName(record.get(TABLE.NAME)); taskVariable.setType(TaskVariableTypeEnum.valOf(Objects.requireNonNull(record.get(TABLE.TYPE)).intValue())); - taskVariable.setDefaultValue(record.get(TABLE.DEFAULT_VALUE)); + String encryptedDefaultValue = record.get(TABLE.DEFAULT_VALUE); + // 密文变量解密 + String defaultValue = cipherVariableCryptoService.decryptTaskVariableIfNeeded( + taskVariable.getType(), + encryptedDefaultValue + ); + taskVariable.setDefaultValue(defaultValue); taskVariable.setDescription(record.get(TABLE.DESCRIPTION)); taskVariable.setChangeable(Objects.requireNonNull(record.get(TABLE.IS_CHANGEABLE)).intValue() == 1); taskVariable.setRequired(Objects.requireNonNull(record.get(TABLE.IS_REQUIRED)).intValue() == 1); @@ -133,8 +154,16 @@ public TaskVariableDTO getVariableByName(long parentId, String name) { conditions.add(TABLE.NAME.eq(name)); conditions.add(TABLE.TEMPLATE_ID.eq(ULong.valueOf(parentId))); Result> records = - context.select(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, - TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED).from(TABLE).where(conditions).fetch(); + context.select( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ).from(TABLE).where(conditions).fetch(); if (records.size() > 0) { return extract(records.get(0)); } else { @@ -145,12 +174,23 @@ public TaskVariableDTO getVariableByName(long parentId, String name) { @Override public long insertVariable(TaskVariableDTO variable) { TaskTemplateVariableRecord record = context.insertInto(TABLE) - .columns(TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, - TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED) - .values(ULong.valueOf(variable.getTemplateId()), variable.getName(), - UByte.valueOf(variable.getType().getType()), variable.getDefaultValue(), variable.getDescription(), - getChangeable(variable.getChangeable()), getRequired(variable.getRequired())) - .returning(TABLE.ID).fetchOne(); + .columns( + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ).values( + ULong.valueOf(variable.getTemplateId()), + variable.getName(), + UByte.valueOf(variable.getType().getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue()), + variable.getDescription(), + getChangeable(variable.getChangeable()), + getRequired(variable.getRequired()) + ).returning(TABLE.ID).fetchOne(); if (record != null) { return record.getId().longValue(); } else { @@ -164,12 +204,28 @@ public List batchInsertVariables(List variableList) { return Collections.emptyList(); } InsertValuesStep7 insertStep = - context.insertInto(TABLE).columns(TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, TABLE.DEFAULT_VALUE, - TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED); - - variableList.forEach(variable -> insertStep.values(ULong.valueOf(variable.getTemplateId()), variable.getName(), - UByte.valueOf(variable.getType().getType()), variable.getDefaultValue(), variable.getDescription(), - getChangeable(variable.getChangeable()), getRequired(variable.getRequired()))); + context.insertInto(TABLE) + .columns( + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ); + + variableList.forEach(variable -> + insertStep.values( + ULong.valueOf(variable.getTemplateId()), + variable.getName(), + UByte.valueOf(variable.getType().getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue()), + variable.getDescription(), + getChangeable(variable.getChangeable()), + getRequired(variable.getRequired()) + ) + ); Result result = insertStep.returning(TABLE.ID).fetch(); List variableIdList = new ArrayList<>(variableList.size()); @@ -205,14 +261,23 @@ public boolean updateVariableById(TaskVariableDTO variable) { } if (variable.getType().isNeedMask() && variable.getDefaultValue().equals(variable.getType().getMask())) { - return 1 == context.update(TABLE).set(TABLE.NAME, variable.getName()) - .set(TABLE.DESCRIPTION, variable.getDescription()).set(TABLE.IS_CHANGEABLE, isChangeable) - .set(TABLE.IS_REQUIRED, isRequired).where(conditions).limit(1).execute(); + return 1 == context.update(TABLE) + .set(TABLE.NAME, variable.getName()) + .set(TABLE.DESCRIPTION, variable.getDescription()) + .set(TABLE.IS_CHANGEABLE, isChangeable) + .set(TABLE.IS_REQUIRED, isRequired) + .where(conditions).limit(1) + .execute(); } - return 1 == context.update(TABLE).set(TABLE.NAME, variable.getName()) - .set(TABLE.DESCRIPTION, variable.getDescription()).set(TABLE.DEFAULT_VALUE, variable.getDefaultValue()) - .set(TABLE.IS_CHANGEABLE, isChangeable).set(TABLE.IS_REQUIRED, isRequired).where(conditions).limit(1) + return 1 == context.update(TABLE) + .set(TABLE.NAME, variable.getName()) + .set(TABLE.DESCRIPTION, variable.getDescription()) + .set(TABLE.DEFAULT_VALUE, + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue())) + .set(TABLE.IS_CHANGEABLE, isChangeable) + .set(TABLE.IS_REQUIRED, isRequired) + .where(conditions).limit(1) .execute(); } @@ -234,13 +299,28 @@ public int deleteVariableByParentId(long parentId) { @Override public boolean batchInsertVariableWithId(List variableList) { InsertValuesStep8 insertStep = context.insertInto(TABLE).columns(TABLE.ID, TABLE.TEMPLATE_ID, TABLE.NAME, TABLE.TYPE, - TABLE.DEFAULT_VALUE, TABLE.DESCRIPTION, TABLE.IS_CHANGEABLE, TABLE.IS_REQUIRED); + UByte> insertStep = context.insertInto(TABLE). + columns( + TABLE.ID, + TABLE.TEMPLATE_ID, + TABLE.NAME, + TABLE.TYPE, + TABLE.DEFAULT_VALUE, + TABLE.DESCRIPTION, + TABLE.IS_CHANGEABLE, + TABLE.IS_REQUIRED + ); for (TaskVariableDTO variable : variableList) { - insertStep = insertStep.values(JooqDataTypeUtil.buildULong(variable.getId()), - ULong.valueOf(variable.getTemplateId()), variable.getName(), - UByte.valueOf(variable.getType().getType()), variable.getDefaultValue(), variable.getDescription(), - getChangeable(variable.getChangeable()), getRequired(variable.getRequired())); + insertStep = insertStep.values( + JooqDataTypeUtil.buildULong(variable.getId()), + ULong.valueOf(variable.getTemplateId()), + variable.getName(), + UByte.valueOf(variable.getType().getType()), + cipherVariableCryptoService.encryptTaskVariableIfNeeded(variable.getType(), variable.getDefaultValue()), + variable.getDescription(), + getChangeable(variable.getChangeable()), + getRequired(variable.getRequired()) + ); } return insertStep.execute() > 0; } @@ -265,24 +345,4 @@ private UByte getRequired(Boolean required) { } return isRequired; } - - @Override - public List listHostVariables() { - List conditions = new ArrayList<>(); - conditions.add(TABLE.TYPE.eq(JooqDataTypeUtil.buildUByte(TaskVariableTypeEnum.HOST_LIST.getType()))); - - Result result = context.select(ALL_FIELDS).from(TABLE).where(conditions).fetch(); - return result.map(this::extract); - } - - @Override - public boolean updateVariableValue(Long id, String value) { - List conditions = new ArrayList<>(); - conditions.add(TABLE.ID.eq(JooqDataTypeUtil.buildULong(id))); - int result = context.update(TABLE) - .set(TABLE.DEFAULT_VALUE, value) - .where(conditions) - .execute(); - return result == 1; - } } diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/migration/EncryptDbAccountPasswordMigrationTask.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/migration/EncryptDbAccountPasswordMigrationTask.java index 692f47d866..dba07f1006 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/migration/EncryptDbAccountPasswordMigrationTask.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/migration/EncryptDbAccountPasswordMigrationTask.java @@ -24,12 +24,12 @@ package com.tencent.bk.job.manage.migration; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.ErrorCode; +import com.tencent.bk.job.common.crypto.util.AESUtils; import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.common.exception.InvalidParamException; import com.tencent.bk.job.common.model.Response; -import com.tencent.bk.job.common.util.crypto.AESUtils; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.config.JobManageConfig; import com.tencent.bk.job.manage.dao.AccountDAO; import com.tencent.bk.job.manage.model.dto.AccountDTO; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDTO.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDTO.java index 4969e19a45..c46902373a 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDTO.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDTO.java @@ -25,7 +25,7 @@ package com.tencent.bk.job.manage.model.dto; import com.tencent.bk.job.common.esb.util.EsbDTOAppScopeMappingHelper; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.esb.v3.response.EsbAccountV3DTO; import com.tencent.bk.job.manage.model.inner.ServiceAccountDTO; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDisplayDTO.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDisplayDTO.java index 9e74d49d87..28002c6b7c 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDisplayDTO.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/model/dto/AccountDisplayDTO.java @@ -24,7 +24,7 @@ package com.tencent.bk.job.manage.model.dto; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import lombok.Getter; import lombok.Setter; diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/AccountService.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/AccountService.java index 707391d73b..02059dbb7f 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/AccountService.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/AccountService.java @@ -27,7 +27,7 @@ import com.tencent.bk.job.common.exception.ServiceException; import com.tencent.bk.job.common.model.BaseSearchCondition; import com.tencent.bk.job.common.model.PageData; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.model.dto.AccountDTO; import com.tencent.bk.job.manage.model.dto.AccountDisplayDTO; @@ -44,7 +44,7 @@ public interface AccountService { /** * 新增账号 * - * @param account + * @param account 账号信息 * @return 账号ID */ long saveAccount(AccountDTO account) throws ServiceException; @@ -53,7 +53,7 @@ public interface AccountService { * 根据ID获取账号信息 * * @param accountId 账号Id - * @return + * @return 账号信息 */ AccountDTO getAccountById(Long accountId) throws ServiceException; @@ -68,32 +68,32 @@ public interface AccountService { /** * 根据ID获取账号信息 * - * @param appId - * @param account - * @return + * @param appId Job业务ID + * @param account 账号名称 + * @return 账号信息 */ AccountDTO getAccountByAccount(Long appId, String account) throws ServiceException; /** * 更新账号 * - * @param account + * @param account 账号信息 */ void updateAccount(AccountDTO account) throws ServiceException; /** * 删除账号 * - * @param accountId + * @param accountId 账号ID */ void deleteAccount(Long accountId) throws ServiceException; /** * 分页查询账号列表 * - * @param accountQuery - * @param baseSearchCondition - * @return + * @param accountQuery 账号查询条件 + * @param baseSearchCondition 基础搜索条件 + * @return 账号分页数据 */ PageData listPageAccount(AccountDTO accountQuery, BaseSearchCondition baseSearchCondition) throws ServiceException; @@ -101,9 +101,9 @@ PageData listPageAccount(AccountDTO accountQuery, BaseSearchConditio /** * 分页搜索账号列表 * - * @param keyword - * @param baseSearchCondition - * @return + * @param keyword 关键字 + * @param baseSearchCondition 基础搜索条件 + * @return 账号分页数据 */ PageData searchPageAccount( Long appId, String keyword, @@ -112,10 +112,10 @@ PageData searchPageAccount( /** * 根据别名获取账号信息 * - * @param appId - * @param category - * @param alias - * @return + * @param appId Job业务ID + * @param category 账号类别 + * @param alias 账号别名 + * @return 账号信息 */ AccountDTO getAccount(Long appId, AccountCategoryEnum category, String alias); @@ -146,7 +146,7 @@ List listAllAppAccount(Long appId, AccountCategoryEnum category, * 系统账号是否被DB账号依赖 * * @param accountId 系统账号ID - * @return + * @return 是否被依赖 */ boolean isSystemAccountRefByDbAccount(Long accountId); diff --git a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/impl/AccountServiceImpl.java b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/impl/AccountServiceImpl.java index fa763cbaea..ab508c74a0 100644 --- a/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/impl/AccountServiceImpl.java +++ b/src/backend/job-manage/service-job-manage/src/main/java/com/tencent/bk/job/manage/service/impl/AccountServiceImpl.java @@ -24,10 +24,10 @@ package com.tencent.bk.job.manage.service.impl; +import com.tencent.bk.job.common.constant.AccountCategoryEnum; import com.tencent.bk.job.common.constant.ErrorCode; -import com.tencent.bk.job.common.encrypt.Encryptor; +import com.tencent.bk.job.common.crypto.Encryptor; import com.tencent.bk.job.common.exception.AlreadyExistsException; -import com.tencent.bk.job.common.exception.InternalException; import com.tencent.bk.job.common.exception.InvalidParamException; import com.tencent.bk.job.common.exception.NotFoundException; import com.tencent.bk.job.common.exception.ServiceException; @@ -40,9 +40,7 @@ import com.tencent.bk.job.common.util.check.StringCheckHelper; import com.tencent.bk.job.common.util.check.TrimChecker; import com.tencent.bk.job.common.util.check.exception.StringCheckException; -import com.tencent.bk.job.common.util.crypto.AESUtils; import com.tencent.bk.job.common.util.date.DateUtils; -import com.tencent.bk.job.manage.common.consts.account.AccountCategoryEnum; import com.tencent.bk.job.manage.common.consts.account.AccountTypeEnum; import com.tencent.bk.job.manage.common.consts.globalsetting.OSTypeEnum; import com.tencent.bk.job.manage.config.JobManageConfig; @@ -109,9 +107,6 @@ public long saveAccount(AccountDTO account) throws ServiceException { , account.getDbSystemAccountId(), dbSystemAccount.getAppId()); throw new NotFoundException(ErrorCode.DB_SYSTEM_ACCOUNT_IS_INVALID); } - if (StringUtils.isNotEmpty(account.getDbPassword())) { - account.setDbPassword(encryptPassword(account.getDbPassword())); - } } if (account.getId() == null) { return accountDAO.saveAccount(account); @@ -160,22 +155,10 @@ public void updateAccount(AccountDTO account) throws ServiceException { if (StringUtils.isNotEmpty(account.getPassword())) { account.setPassword(encryptor.encrypt(account.getPassword())); } - if (account.getCategory() == AccountCategoryEnum.DB && StringUtils.isNotEmpty(account.getDbPassword())) { - account.setDbPassword(encryptPassword(account.getDbPassword())); - } log.info("Update account, account={}", account); accountDAO.updateAccount(account); } - private String encryptPassword(String text) throws ServiceException { - try { - return AESUtils.encryptToBase64EncodedCipherText(text, jobManageConfig.getEncryptPassword()); - } catch (Exception e) { - log.error("Encrypt password error", e); - throw new InternalException(ErrorCode.INTERNAL_ERROR); - } - } - @Override public void deleteAccount(Long accountId) throws ServiceException { log.info("Delete account, accountId={}", accountId); diff --git a/src/backend/settings.gradle b/src/backend/settings.gradle index 22a7a3f2e3..524842ba04 100644 --- a/src/backend/settings.gradle +++ b/src/backend/settings.gradle @@ -33,12 +33,14 @@ include 'commons:cmdb-sdk-ext' include 'commons:paas-sdk' include 'commons:gse-sdk' include 'commons:common-iam' +include 'commons:common-jwt' include 'commons:common-utils' include 'commons:common-otel' include 'commons:common-redis' include 'commons:common-security' include 'commons:common-discovery' include 'commons:common-consul' +include 'commons:common-crypto' include 'commons:common-k8s' include 'commons:common-statistics' include 'commons:common-service' diff --git a/src/backend/upgrader/build.gradle b/src/backend/upgrader/build.gradle index 99086efd57..0e9525d5ab 100644 --- a/src/backend/upgrader/build.gradle +++ b/src/backend/upgrader/build.gradle @@ -39,6 +39,7 @@ dependencies { api project(":commons:common-api") api project(":commons:common-iam") api project(":commons:common-utils") + api project(":commons:common-jwt") api project(":commons:esb-sdk") api project(":commons:cmdb-sdk-model") api project(":commons:artifactory-sdk") diff --git a/src/backend/upgrader/src/main/java/com/tencent/bk/job/upgrader/task/UseAccountPermissionMigrationTask.java b/src/backend/upgrader/src/main/java/com/tencent/bk/job/upgrader/task/UseAccountPermissionMigrationTask.java index 049f905a9b..d432e3c8c4 100644 --- a/src/backend/upgrader/src/main/java/com/tencent/bk/job/upgrader/task/UseAccountPermissionMigrationTask.java +++ b/src/backend/upgrader/src/main/java/com/tencent/bk/job/upgrader/task/UseAccountPermissionMigrationTask.java @@ -35,10 +35,10 @@ import com.tencent.bk.job.common.iam.dto.EsbIamPathItem; import com.tencent.bk.job.common.iam.dto.EsbIamSubject; import com.tencent.bk.job.common.iam.util.BusinessAuthHelper; +import com.tencent.bk.job.common.jwt.BasicJwtManager; +import com.tencent.bk.job.common.jwt.JwtManager; import com.tencent.bk.job.common.model.dto.AppResourceScope; import com.tencent.bk.job.common.util.json.JsonUtils; -import com.tencent.bk.job.common.util.jwt.BasicJwtManager; -import com.tencent.bk.job.common.util.jwt.JwtManager; import com.tencent.bk.job.upgrader.anotation.ExecuteTimeEnum; import com.tencent.bk.job.upgrader.anotation.RequireTaskParam; import com.tencent.bk.job.upgrader.anotation.UpgradeTask; @@ -55,8 +55,6 @@ import lombok.extern.slf4j.Slf4j; import org.slf4j.helpers.MessageFormatter; -import java.io.IOException; -import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -108,10 +106,10 @@ public void init() { (String) getProperties().get(ParamNameConsts.CONFIG_PROPERTY_JOB_SECURITY_PUBLIC_KEY_BASE64); String securityPrivateKeyBase64 = (String) getProperties().get(ParamNameConsts.CONFIG_PROPERTY_JOB_SECURITY_PRIVATE_KEY_BASE64); - JwtManager jwtManager = null; + JwtManager jwtManager; try { jwtManager = new BasicJwtManager(securityPrivateKeyBase64, securityPublicKeyBase64); - } catch (IOException | GeneralSecurityException e) { + } catch (Exception e) { String msg = "Fail to generate jwt auth token"; log.error(msg, e); throw new InternalException(msg, e, ErrorCode.INTERNAL_ERROR); @@ -123,9 +121,7 @@ public void init() { ); this.basicAppInfoList = getAllNormalAppInfoFromManage(); appInfoMap = new HashMap<>(); - basicAppInfoList.forEach(basicAppInfo -> { - appInfoMap.put(basicAppInfo.getAppId(), basicAppInfo.getName()); - }); + basicAppInfoList.forEach(basicAppInfo -> appInfoMap.put(basicAppInfo.getAppId(), basicAppInfo.getName())); } private IamClient getIamClient() { @@ -170,8 +166,8 @@ private List getAllNormalAppInfoFromManage() { /** * 根据策略计算出有权限的业务Id列表 * - * @param policy - * @return + * @param policy 策略 + * @return 有权限的业务ID列表 */ private List getAuthorizedAppIdList(Policy policy) { BusinessAuthHelper businessAuthHelper = jobIamHelper.businessAuthHelper(); @@ -186,8 +182,8 @@ private List getAuthorizedAppIdList(Policy policy) { /** * 根据业务ID获取业务名称 * - * @param appId - * @return + * @param appId 业务ID + * @return 业务名称 */ private String getAppNameById(Long appId) { if (appInfoMap.containsKey(appId)) return appInfoMap.get(appId); @@ -300,11 +296,10 @@ public void printSeparateLine() { } public void showPolicies(List policies) { - policies.forEach(policy -> { + policies.forEach(policy -> log.info("{}: {} expiredAt {}, expression:{}", policy.getId(), policy.getSubject().getType() + ":" + policy.getSubject().getName(), - policy.getExpiredAt(), JsonUtils.toJson(policy.getExpression())); - }); + policy.getExpiredAt(), JsonUtils.toJson(policy.getExpression()))); } @Override @@ -319,14 +314,15 @@ public boolean execute(String[] args) { printSeparateLine(); log.info("Begin to auth according to oldPolicies:"); // 2.新权限数据授权 - oldAuthorizedPolicies.forEach(policy -> { + oldAuthorizedPolicies.forEach(policy -> log.info( "auth {}:{}:{}:{}", policy.getSubject().getType(), policy.getSubject().getName(), policy.getExpiredAt(), - authByPolicy(policy)); - }); + authByPolicy(policy) + ) + ); // 3.新权限策略查询 String newActionId = ActionId.USE_ACCOUNT; List newAuthorizedPolicies = queryAuthorizedPolicies(newActionId); diff --git a/support-files/kubernetes/charts/bk-job/VALUES_LOG.md b/support-files/kubernetes/charts/bk-job/VALUES_LOG.md index f742218c85..9c05399464 100644 --- a/support-files/kubernetes/charts/bk-job/VALUES_LOG.md +++ b/support-files/kubernetes/charts/bk-job/VALUES_LOG.md @@ -1,4 +1,13 @@ # chart values 更新日志 +## 0.5.0 +1.增加 加密类型 配置 +```yaml +job: + encrypt: + # 可选值:CLASSIC(经典国际算法RSA、AES等),SHANGMI(国家商用密码算法SM2、SM4等) + type: "CLASSIC" +``` + ## 0.4.5 1.增加 bkDomain 配置 diff --git a/support-files/kubernetes/charts/bk-job/templates/configmap-common.yaml b/support-files/kubernetes/charts/bk-job/templates/configmap-common.yaml index d79953ed11..4877d80566 100644 --- a/support-files/kubernetes/charts/bk-job/templates/configmap-common.yaml +++ b/support-files/kubernetes/charts/bk-job/templates/configmap-common.yaml @@ -93,6 +93,7 @@ data: public-key-base64: {{ .Values.job.security.publicKeyBase64 }} edition: {{ .Values.job.edition }} encrypt: + type: {{ .Values.job.encrypt.type }} password: {{ .Values.job.encrypt.password }} web: url: {{ include "job.web.url" . }} diff --git a/support-files/kubernetes/charts/bk-job/values.yaml b/support-files/kubernetes/charts/bk-job/values.yaml index 9e47a9c565..359f742ffe 100644 --- a/support-files/kubernetes/charts/bk-job/values.yaml +++ b/support-files/kubernetes/charts/bk-job/values.yaml @@ -573,6 +573,8 @@ job: # 获取actuator监控数据的密码,部署时生成填入 password: actuator_password encrypt: + # 可选值:CLASSIC(经典国际算法RSA、AES等),SHANGMI(国家商用密码算法SM2、SM4等) + type: "CLASSIC" # 用于加密作业平台中存储的数据库密码的密码 password: "job#2021" features: diff --git a/support-files/templates/#etc#job#job-common#application.yml b/support-files/templates/#etc#job#job-common#application.yml index cf3c396325..d041807ca5 100644 --- a/support-files/templates/#etc#job#job-common#application.yml +++ b/support-files/templates/#etc#job#job-common#application.yml @@ -80,6 +80,7 @@ job: edition: ce {% endif -%} encrypt: + type: __BK_CRYPTO_TYPE__ password: __BK_JOB_ENCRYPT_PASSWORD__ web: url: __BK_JOB_PUBLIC_URL__ diff --git a/support-files/templates/job.env b/support-files/templates/job.env index ca8fb9b425..ff24f58bd3 100644 --- a/support-files/templates/job.env +++ b/support-files/templates/job.env @@ -15,6 +15,7 @@ BK_IAM_PRIVATE_URL= BK_LICENSE_PRIVATE_URL= CONSUL_HTTP_PORT=8500 CONSUL_SCHEME=http +BK_CRYPTO_TYPE=CLASSIC # Job通用 BK_JOB_SECURITY_PRIVATE_KEY_BASE64=