fix:配置加密机制
This commit is contained in:
parent
3a9a76c100
commit
e7f9c1d183
@ -1,7 +1,9 @@
|
|||||||
package com.cisd.tms.common.crypto.config;
|
package com.cisd.tms.common.crypto.config;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.env.EnvironmentPostProcessor;
|
import org.springframework.boot.env.EnvironmentPostProcessor;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@ -27,14 +29,18 @@ public class ConfigDecryptingEnvironmentPostProcessor implements EnvironmentPost
|
|||||||
@Override
|
@Override
|
||||||
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
|
||||||
Map<String, Object> decryptedValues = new LinkedHashMap<>();
|
Map<String, Object> decryptedValues = new LinkedHashMap<>();
|
||||||
|
Set<String> visitedPropertyNames = new HashSet<>();
|
||||||
for (PropertySource<?> propertySource : environment.getPropertySources()) {
|
for (PropertySource<?> propertySource : environment.getPropertySources()) {
|
||||||
if (!(propertySource instanceof EnumerablePropertySource<?> enumerablePropertySource)) {
|
if (!(propertySource instanceof EnumerablePropertySource<?> enumerablePropertySource)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (String propertyName : enumerablePropertySource.getPropertyNames()) {
|
for (String propertyName : enumerablePropertySource.getPropertyNames()) {
|
||||||
Object rawValue = enumerablePropertySource.getProperty(propertyName);
|
if (!visitedPropertyNames.add(propertyName)) {
|
||||||
if (rawValue instanceof String stringValue && encryptor.isEncrypted(stringValue)) {
|
continue;
|
||||||
decryptedValues.putIfAbsent(propertyName, encryptor.decryptIfNecessary(stringValue));
|
}
|
||||||
|
String resolvedValue = environment.getProperty(propertyName);
|
||||||
|
if (encryptor.isEncrypted(resolvedValue)) {
|
||||||
|
decryptedValues.put(propertyName, encryptor.decryptIfNecessary(resolvedValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,7 +93,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
|
|
||||||
Process process = null;
|
Process process = null;
|
||||||
try {
|
try {
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder("/bin/zsh", "-lc", command);
|
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-lc", command);
|
||||||
processBuilder.redirectErrorStream(true);
|
processBuilder.redirectErrorStream(true);
|
||||||
processBuilder.redirectOutput(logFile.toFile());
|
processBuilder.redirectOutput(logFile.toFile());
|
||||||
process = processBuilder.start();
|
process = processBuilder.start();
|
||||||
@ -897,7 +897,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
try {
|
try {
|
||||||
int code = runCommand(
|
int code = runCommand(
|
||||||
logFile,
|
logFile,
|
||||||
Arrays.asList("/bin/zsh", "-lc", applyCommand),
|
Arrays.asList("/bin/bash", "-lc", applyCommand),
|
||||||
false,
|
false,
|
||||||
loadDir,
|
loadDir,
|
||||||
buildStandardDbApplyEnvironment(loadDir, context)
|
buildStandardDbApplyEnvironment(loadDir, context)
|
||||||
@ -1031,7 +1031,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
try {
|
try {
|
||||||
int code = runCommand(
|
int code = runCommand(
|
||||||
logFile,
|
logFile,
|
||||||
Arrays.asList("/bin/zsh", "-lc", command),
|
Arrays.asList("/bin/bash", "-lc", command),
|
||||||
false,
|
false,
|
||||||
workingDirectory,
|
workingDirectory,
|
||||||
buildStandardStartEnvironment(stepName)
|
buildStandardStartEnvironment(stepName)
|
||||||
@ -1070,7 +1070,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
try {
|
try {
|
||||||
int code = runCommand(
|
int code = runCommand(
|
||||||
logFile,
|
logFile,
|
||||||
Arrays.asList("/bin/zsh", "-lc", command),
|
Arrays.asList("/bin/bash", "-lc", command),
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
buildStandardDbApplyEnvironment(null, context)
|
buildStandardDbApplyEnvironment(null, context)
|
||||||
@ -1246,7 +1246,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
.toAbsolutePath();
|
.toAbsolutePath();
|
||||||
Path logFile = prepareLogPath(task, step);
|
Path logFile = prepareLogPath(task, step);
|
||||||
try {
|
try {
|
||||||
int code = runCommand(logFile, Arrays.asList("/bin/zsh", "-lc", command), false, scriptDir);
|
int code = runCommand(logFile, Arrays.asList("/bin/bash", "-lc", command), false, scriptDir);
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
return InitStepExecutionResult.failure("cae_update 执行失败", code, logFile.toString());
|
return InitStepExecutionResult.failure("cae_update 执行失败", code, logFile.toString());
|
||||||
}
|
}
|
||||||
@ -1315,7 +1315,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
|
|
||||||
Path logFile = prepareLogPath(task, step);
|
Path logFile = prepareLogPath(task, step);
|
||||||
try {
|
try {
|
||||||
int code = runCommand(logFile, Arrays.asList("/bin/zsh", "-lc", command), false);
|
int code = runCommand(logFile, Arrays.asList("/bin/bash", "-lc", command), false);
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
return InitStepExecutionResult.failure("restart_tlq 执行失败", code, logFile.toString());
|
return InitStepExecutionResult.failure("restart_tlq 执行失败", code, logFile.toString());
|
||||||
}
|
}
|
||||||
@ -2246,7 +2246,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
try {
|
try {
|
||||||
int code = runCommand(
|
int code = runCommand(
|
||||||
logFile,
|
logFile,
|
||||||
Arrays.asList("/bin/zsh", "-lc", "pgrep -f " + quoteShellValue(pattern) + " >/dev/null"),
|
Arrays.asList("/bin/bash", "-lc", "pgrep -f " + quoteShellValue(pattern) + " >/dev/null"),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
@ -2270,7 +2270,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
try {
|
try {
|
||||||
int code = runCommand(
|
int code = runCommand(
|
||||||
logFile,
|
logFile,
|
||||||
Arrays.asList("/bin/zsh", "-lc", command),
|
Arrays.asList("/bin/bash", "-lc", command),
|
||||||
true,
|
true,
|
||||||
null,
|
null,
|
||||||
buildStandardDbApplyEnvironment(null, context)
|
buildStandardDbApplyEnvironment(null, context)
|
||||||
@ -2301,7 +2301,7 @@ public class ConfigurableInitStepExecutor implements InitStepExecutor {
|
|||||||
|
|
||||||
private void verifyRabbitObjectAbsent(Path logFile, String shellCommand, String message, List<String> failures) throws IOException {
|
private void verifyRabbitObjectAbsent(Path logFile, String shellCommand, String message, List<String> failures) throws IOException {
|
||||||
try {
|
try {
|
||||||
int code = runCommand(logFile, Arrays.asList("/bin/zsh", "-lc", shellCommand), true);
|
int code = runCommand(logFile, Arrays.asList("/bin/bash", "-lc", shellCommand), true);
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
failures.add(message);
|
failures.add(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,9 @@ package com.cisd.tms.common.crypto.config;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.WebApplicationType;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
|
|
||||||
@ -25,4 +27,35 @@ class ConfigDecryptingEnvironmentPostProcessorTest {
|
|||||||
Assertions.assertEquals("db-password", environment.getProperty("spring.datasource.password"));
|
Assertions.assertEquals("db-password", environment.getProperty("spring.datasource.password"));
|
||||||
Assertions.assertEquals("8080", environment.getProperty("server.port"));
|
Assertions.assertEquals("8080", environment.getProperty("server.port"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void decryptsEncryptedPlaceholderDefaultValuesBeforeBinding() {
|
||||||
|
ConfigTextEncryptor encryptor = ConfigTextEncryptor.withDefaultHardcodedKey();
|
||||||
|
String encryptedUsername = encryptor.encrypt("db-user");
|
||||||
|
StandardEnvironment environment = new StandardEnvironment();
|
||||||
|
environment.getPropertySources().addFirst(new MapPropertySource("test", Map.of(
|
||||||
|
"spring.datasource.username", "${TMS_DB_USER:" + encryptedUsername + "}"
|
||||||
|
)));
|
||||||
|
|
||||||
|
new ConfigDecryptingEnvironmentPostProcessor()
|
||||||
|
.postProcessEnvironment(environment, new SpringApplication(Object.class));
|
||||||
|
|
||||||
|
Assertions.assertEquals("db-user", environment.getProperty("spring.datasource.username"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void springBootAutoLoadsPostProcessorFromFactories() {
|
||||||
|
ConfigTextEncryptor encryptor = ConfigTextEncryptor.withDefaultHardcodedKey();
|
||||||
|
String encryptedUsername = encryptor.encrypt("dev-user");
|
||||||
|
SpringApplication application = new SpringApplication(Object.class);
|
||||||
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
application.setDefaultProperties(Map.of(
|
||||||
|
"tms.crypto.test.username", encryptedUsername,
|
||||||
|
"spring.main.banner-mode", "off"
|
||||||
|
));
|
||||||
|
|
||||||
|
try (ConfigurableApplicationContext context = application.run()) {
|
||||||
|
Assertions.assertEquals("dev-user", context.getEnvironment().getProperty("tms.crypto.test.username"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class RestoreCommandInvokerTest {
|
|||||||
Path logFile = tempDir.resolve("restore.log");
|
Path logFile = tempDir.resolve("restore.log");
|
||||||
|
|
||||||
int exitCode = invoker.run(
|
int exitCode = invoker.run(
|
||||||
List.of("/bin/zsh", "-lc", "printf 'hello-restore'"),
|
List.of("/bin/bash", "-lc", "printf 'hello-restore'"),
|
||||||
logFile,
|
logFile,
|
||||||
tempDir
|
tempDir
|
||||||
);
|
);
|
||||||
@ -35,7 +35,7 @@ class RestoreCommandInvokerTest {
|
|||||||
|
|
||||||
long started = System.nanoTime();
|
long started = System.nanoTime();
|
||||||
int exitCode = invoker.run(
|
int exitCode = invoker.run(
|
||||||
List.of("/bin/zsh", "-lc", "sleep 2; printf 'done'"),
|
List.of("/bin/bash", "-lc", "sleep 2; printf 'done'"),
|
||||||
logFile,
|
logFile,
|
||||||
tempDir
|
tempDir
|
||||||
);
|
);
|
||||||
@ -46,12 +46,13 @@ class RestoreCommandInvokerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void waitUntilLogContains(Path logFile, String expected) throws Exception {
|
private static void waitUntilLogContains(Path logFile, String expected) throws Exception {
|
||||||
long deadline = System.currentTimeMillis() + 1000;
|
long deadline = System.currentTimeMillis() + 5000;
|
||||||
while (System.currentTimeMillis() < deadline) {
|
while (System.currentTimeMillis() < deadline) {
|
||||||
if (Files.isRegularFile(logFile) && Files.readString(logFile).contains(expected)) {
|
if (Files.isRegularFile(logFile) && Files.readString(logFile).contains(expected)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Thread.sleep(20);
|
Thread.sleep(20);
|
||||||
}
|
}
|
||||||
|
Assertions.fail("restore log did not contain expected text: " + expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user