Hello,
The following code snippet running on Spring Boot 1.5.12 RELEASE:
public class UnicodePropertiesPropertySourceLoader implements PropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[]{"properties"};
}
@Override
public PropertySource<?> load(String name, Resource resource, String profile) throws IOException {
if (profile == null) {
Properties properties = new Properties();
PropertyResourceBundle bundle = new PropertyResourceBundle(new InputStreamReader(resource.getInputStream(), "UTF-8"));
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
properties.setProperty(key, bundle.getString(key));
}
if (!properties.isEmpty()) {
return new PropertiesPropertySource(name, properties);
}
}
return null;
}
}
Has to be migrated for Spring Boot 2.0.3 RELEASE:
public class UnicodePropertiesPropertySourceLoader implements PropertySourceLoader {
private static final String PROPERTIES_FILE_EXTENSION = ".properties";
@Override
public String[] getFileExtensions() {
return new String[]{"properties"};
}
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
Properties properties = new Properties();
PropertyResourceBundle bundle = new PropertyResourceBundle(new InputStreamReader(resource.getInputStream(), "UTF-8"));
Enumeration<String> keys = bundle.getKeys();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
properties.setProperty(key, bundle.getString(key));
}
if (!properties.isEmpty()) {
return Collections
.singletonList(new OriginTrackedMapPropertySource(name, properties));
}
return null;
}
After and before the migration, debugging the load method, the properties are loaded just fine for encoded rows, like:
email.hello=!Congrats
But when you load the property using:
@Value("${email.hello}")
The property becomes wrong for the new version of Spring Boot:
脗!Congrats
My spring.factories under META-INF is set to:
# Custom PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=my.package.UnicodePropertiesPropertySourceLoader
I know that my class UnicodePropertiesPropertySourceLoader is loaded just fine with all the properties encoded to UTF-8, but the problem is when I try to obtain each property with the @Value annotation, this happen for the version of SpringBoot 2.0.3.Release
Could you please provide a sample application that shows the problem. It's a little hard to tell what the actual values you're using are from the GitHub comment.
It looks like you need UTF-8 encoded properties. I wonder if we might be able to make the existing OriginTrackedPropertiesLoader easier to subclass to do that.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Hello, @spring-issuemaster I am also getting this issue as well. I have it isolated down to a simple project here: https://github.com/ryber/spring-props/
Note:
@Value value is not encrypted.@ryber The PropertySourceLoader interface is really designed to allow additional file types to be loaded. Since there's a built in PropertiesPropertySourceLoader providing properties file support I think your loader might be getting called in addition the the regular one.
We should probably guard against that, or at least improve the Javadoc. You might want to look into the EnvironmentPostProcessor as an alternative way of modifying properties. I think that's how Spring Cloud Config supports encryption.
thanks @philwebb, now that I'm looking at EnvironmentPostProcessor I totally remember doing it this way before. (I was sure I never did one of those old school META-INF factories before)
In any case, just FYI I went down the PropertySourceLoader path because googling lead to some blogs and SO questions implying that was the right way. So you may get more of those from time to time without maybe some official Spring documentation or logging that points in a better direction.
FYI, in my case I couldn't just use the jasypt-spring-boot-starter because we are using KMS in this project.
So you may get more of those from time to time without maybe some official Spring documentation or logging that points in a better direction.
@ryber thanks for the feedback. There are 3 somewhat-related reference to PropertySourceLoader in the documentation, two of them in this section that describes the EnvironmentPostProcessor should be used to customize the Environment.
What am I missing? Do you have something else in mind to avoid users choosing the wrong path?
I think the main issue is that EnvironmentPostProcessor is kind of general catch all for doing "stuff" to the environments. I was looking specifically for encrypting properties. And so are a lot of other people. "Security By Design" is starting to be a major thing (thank goodness) and I think it would be great if Spring Boot incorporated that our of the gate.
If you google for "Encrypt Spring Boot properties" the Spring documentation is nowhere in the entire first page. and even the description of EnvironmentPostProcessor isn't clear about specifically overriding or manipulating the existing spring managed properties.
I would encourage Spring Boot to include a first line support of encrypted properties and some clear documentation for people to do it on day 1. I would hope that such a feature might have 1 that works out of the box (possibly jasypt) and also the ability to override for those who want other decryptors like KMS, Vault, etc.
Some discussion on encrypted property source is in #1312. My current feeling is that providing good encryption support is hard and we should leave it to Spring Cloud Vault (although I agree that the lack of documentation is problematic).
although I agree that the lack of documentation is problematic
By this I mean that it seems like encryption is a common issue so it would be nice if we mention it in the docs, even if it's just a link to Spring Cloud Vault.
Most helpful comment
@ryber The
PropertySourceLoaderinterface is really designed to allow additional file types to be loaded. Since there's a built inPropertiesPropertySourceLoaderproviding properties file support I think your loader might be getting called in addition the the regular one.We should probably guard against that, or at least improve the Javadoc. You might want to look into the
EnvironmentPostProcessoras an alternative way of modifying properties. I think that's how Spring Cloud Config supports encryption.