spring-cloud-commons icon indicating copy to clipboard operation
spring-cloud-commons copied to clipboard

It is not possible to provide they encryption key properties in later stage of application startup (e.g via EnvironmentPostProcessor).

Open kvmw opened this issue 1 month ago • 6 comments

Describe the bug TextEncryptorConfigBootstrapper.java#L67-L85 promotes KeyProperties, RsaProperties and TextEncryptor beans to ApplicationContext. When key properties are not available during bootstrap, default instances of KeyProperties, RsaProperties, and TextEncryptor (FailsafeTextEncryptor) are promoted.

In later stage of startup, if key properties are supplied (in my case via EnvironmentPostProcessor), they will be ignored by AutoConfiguration classes, because the relevant bean (TextEncryptor) is present in the ApplicationContext.

Sample

A simple spring-boot app like the following, with org.springframework.cloud:spring-cloud-config-server as dependency, shows the issue:

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

class Processor implements EnvironmentPostProcessor {
	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		final MutablePropertySources propertySources = environment.getPropertySources();

		propertySources.addFirst(new MapPropertySource("test", Map.of("encrypt.key", "my-secret-key")));
	}
}


@Component
class Test {

	@Autowired
	private TextEncryptor encryptor;

	@PostConstruct
	void test() {
		System.out.println("### Encryptor:: " + encryptor.getClass().getSimpleName());
	}
}

sample output:

### Encryptor:: FailsafeTextEncryptor

The output shows that FailsafeTextEncryptor is registered which cannot encrypt/decrypt any secret.

Workaround

Currently I workaround the issue by enabling the legacy bootstrap (e.g adding org.springframework.cloud:spring-cloud-starter-bootstrap as dependency). See the if condition in TextEncryptorConfigBootstrapper.java#L69-L71 which cancels the promotion, in case legacy bootstrap is enabled.

kvmw avatar Dec 05 '25 15:12 kvmw

Can you elaborate more on why you want this to work?

ryanjbaxter avatar Dec 11 '25 00:12 ryanjbaxter

Here is the use-case:

A config-server is tasked to fetch encrypted configuration properties from a git server. Encryption key is provided by platform during server startup. An EnvironmentPostProcessor is needed to read the platform provided key and add it to the property sources with the expected name (encrypt.key). At the moment, this is only possible by enabling the legacy bootstrap which seems odd to me.

Looking at EncryptionBootstrapConfiguration.java, I see that It can create the same beans ( KeyProperties, RsaProperties, and TextEncryptor) if they are missing. So I am wondering why TextEncryptorConfigBootstrapper.java#L67-L85 is needed to promote them?

kvmw avatar Dec 11 '25 10:12 kvmw

So I am wondering why TextEncryptorConfigBootstrapper.java#L67-L85 is needed to promote them?

Honestly I am not sure.

If we don't promote them with bootstrap enabled then, yes it looks like EncryptionBootstrapConfiguration.java should kick in.

If we don't promote and bootstrap is not enabled AND spring-cloud-config-server is on the classpath then it looks like DefaultTextEncryptionAutoConfiguration will get invoked and create the beans.

If we don't promote them and bootstrap is not enabled AND spring-cloud-config-server IS NOT on the classpath then there would be no TextEncryptor bean created, and that would be a breaking change IMO.

ryanjbaxter avatar Dec 11 '25 20:12 ryanjbaxter

yes, you are right. the third case would be a breaking change! unless something like DefaultTextEncryptionAutoConfiguration is added to spring-cloud-context module.

kvmw avatar Dec 12 '25 14:12 kvmw

The other thing I was thinking about was adding a property so we disable promoting of the beans (it would be disabled by default) allowing your use case to work without having to use bootstrap.

ryanjbaxter avatar Dec 12 '25 20:12 ryanjbaxter

The other thing I was thinking about was adding a property so we disable promoting of the beans (it would be disabled by default) allowing your use case to work without having to use bootstrap.

I don't think that's needed. A property just to resolve this corner case seems too much. My use case is working fine with the workaround at the moment. But I'll think about a solution without breaking changes.

kvmw avatar Dec 15 '25 13:12 kvmw