The Spring Cloud Config Server is not decrypting values when serving plain text config files. Is this known/expected behavior?
Detected Release Train: Dalston.SR4, Edgware.RELEASE
Detected Versions: 1.3.3.RELEASE, 1.4.0.RELEASE
Let's say I have a property file with an encrypted value, like so:
app.properties
# "mysecret"
spring.datasource.password = {cypher}682bc583f4641835fa2db009355293665d2647dade
If I try to access this property using "standard" (JSON) or "alternative format" (.properties,.yaml), this value is correctly decrypted by the config server.
GET /app/profile/branch
{
"name": "app",
"profiles": [
"profile"
],
"label": "branch",
"version": "1839be51feaa73138feef1ba8653bfe7a4c21fb3",
"state": null,
"propertySources": [
{
"name": "ssh://git-server/app.git/app.properties",
"source": {
"spring.datasource.password": "mysecret"
}
}
]
}
GET /branch/app-profile.properties
spring.datasource.password = mysecret
However, if I attempt to access this file using the "plain text" format, the value is not being decrypted.
GET /app/profile/branch/app.properties
# "mysecret"
spring.datasource.password = {cypher}682bc583f4641835fa2db009355293665d2647dade
Similarly, if I have an encrypted value stored in another text file format (.conf for instance), this value will not be decrypted when requesting this file via the config server.
GET /app/profile/branch/app.conf
{
password {cypher}682bc583f4641835fa2db009355293665d2647dade
}
When you hit /app/profile/branch/app.properties we are just serving up the raw file and we don't decrypt encrypted values in that case.
While just attempting an upgrade of spring-cloud-config-server from 1.2.2.RELEASE to 1.3.2.RELEASE it also stopped decrypting properties when calling the basic
$ curl http://user:password@localhost:PORT/APP-NAME/PROFILE/LABEL
Using the same JKS store and everything.
I've done some debugging and have been able to reproduce the problem and narrow down what I believe is the cause.
Spring Boot: 1.5.9
Spring Cloud Config Server: 1.3.3.RELEASE
Cloud Dependencies: Dalston.SR4
(Matches Release Trains described here)
When using a JKS to encrypt/decrypt, upon startup spring-cloud-config-server-1.3.3.RELEASE-sources.jar!/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java
provides configuration as follows:
@Configuration
@ConditionalOnProperty(value = "spring.cloud.config.server.encrypt.enabled", matchIfMissing = true)
protected static class EncryptorConfiguration {
@Autowired(required = false)
private TextEncryptorLocator locator;
@Autowired
private TextEncryptor encryptor;
@Bean
@ConditionalOnMissingBean
public EnvironmentEncryptor environmentEncryptor() {
TextEncryptorLocator locator = this.locator;
if (locator == null) {
locator = new SingleTextEncryptorLocator(encryptor);
}
return new CipherEnvironmentEncryptor(locator);
}
}
@Configuration
@ConditionalOnClass(RsaSecretEncryptor.class)
@ConditionalOnProperty(prefix = "encrypt.keyStore", value = "location", matchIfMissing = false)
protected static class KeyStoreConfiguration {
@Autowired
private KeyProperties key;
@Bean
@ConditionalOnMissingBean
public TextEncryptorLocator textEncryptorLocator() {
KeyStore keyStore = this.key.getKeyStore();
KeyStoreTextEncryptorLocator locator = new KeyStoreTextEncryptorLocator(
new KeyStoreKeyFactory(keyStore.getLocation(), keyStore.getPassword().toCharArray()),
keyStore.getSecret(), keyStore.getAlias());
locator.setRsaAlgorithm(this.key.getRsa().getAlgorithm());
locator.setSalt(this.key.getRsa().getSalt());
locator.setStrong(this.key.getRsa().isStrong());
return locator;
}
}
The problem is that EncryptorConfiguration evaluated first spring.cloud.config.server.encrypt.enabled=true and because the TextEncryptorLocator was NULL set it as SingleTextEncryptorLocator and used that to construct CipherEnvironmentEncryptor.
Afterwards, KeyStoreConfiguration evaluates, and returns a KeyStoreTextEncryptorLocator but the CipherEnvironmentEncryptor is already created and so ends up unable to decrypt with the JKS.
Setting breakpoints on:
Starting the embedded Config Server application in debug mode can confirm how things were wired together. Then starting another App that consults the Config Server and hitting the breakpoint you can confirm that the encrypted properties will not be decrypted.
I'm guessing there just is not an automated test covering JKS with decryption.
@ryanjbaxter could you explain why you don't decrypt values in plain text BUT replace placeholders? for me that's not really consistent. We would love to retrieve decrypted values as well actually.
I would also like to know, if this is by design or a bug, that passwords are not deciphered, while placeholders are resolved.
The posters above me have the same question I did. If these URLs only served raw text files, that'd be one thing, but "plain text" support does include a feature for text replacement.
If this behavior is by design, I think it should at least be documented as such.
Fighting the same problem and came to the same conclusion. This behavior simply brake the Dalston to Edgware update silently, as encrypted properties are now returned in an unencrypted form without a single warning, exception or log message.
This is a blocker issue for a ConfigServer supporting encrypted values, please fix it soon as possible.
Just following up on this issue. Secret de/encrypt is a major aspect of a Config Server. It was once working but has become broken and that's a big deal. This is a great project and if spring-cloud-config wants to be confidently regarded as Production-ready (and I think we all do) then this issue really needs some sort of handling.
What can be done? What needs to happen?
Can this issue be assigned, labelled, roadmapped, referenced, combined or something? Are maintainers aware of this problem? Some might be willing to offer a Pull Request.
@bplies-IAS I can confirm @ryanjbaxter's statement that decryption doesn't happen for the file API.
I just tried with the normal, non-file api, decrypts properly using Edgware.SR1.
@bplies-IAS I also confirmed it works with Dalston.SR5 (s-c-config 1.3.4), if you can provide a minimal project that recreates the problem, please open a new issue as this one is about decrypting in the file API which is a new feature.
@spencergibb Thanks for chiming in. The situation I had encountered had to do with JKS enciphered secrets no longer being decrypted. The @ConditionalOnProperty(prefix = "encrypt.keyStore", value = "location", matchIfMissing = false) did not appear to have the opportunity to register a correct TextEncryptorLocator before a different one was constructed first. Relevant code in a prior comment.
I can retry soon with Dalston.SR5 and see if it is fixed or not but unless there were a specific bug fix after SR4 I doubt it will.
I may have mixed the File API issue with a JKS issue due to similar sounding symptoms.
I just tried Dalston.SR5 (s-c-config 1.3.4) with JKS and it still isn't decrypting. Will make a separate issue as @spencergibb has asked.
Most helpful comment
Fighting the same problem and came to the same conclusion. This behavior simply brake the Dalston to Edgware update silently, as encrypted properties are now returned in an unencrypted form without a single warning, exception or log message.
This is a blocker issue for a ConfigServer supporting encrypted values, please fix it soon as possible.