Closed hohwille closed 9 years ago
Hey jorg. Once you enable jasypt-spring-boot the password property is required as specified in the documentation. Why would you import the library or add the annotation if you don't have any encrypted properties? For test purposes you don't need to add the @enableencryptableproperties annotation. I suggest you create a spring config class for your tests. That's always a better approach than using the full app spring configuration on unit tests. Apart of that matter, there is a test project in jasypt-spring-boot's repository and an example on how to pass the master password as a syste property. Are you running your app within tomcat deploying it as a war? Do you have a sample project where the issue manifests to I can take a look and troubleshoot? Best and thanks for your feedback
@ulisesbocchio thanks for your response.
application.properties
and then provide the password from the commandline, it is working. But my expectation is (compliant to spring-boot) that I can override the properties as specified. As a workaround I now have 3 application.properties
per project. 1 for productive defaults that is shipped with the WAR and does not contain a default password. 1 for tests (src/test/resources) and 1 for development that gets excluded when building the WAR. Not perfect but so far working.I will try if I can provide an isolated project somewhere on github to reproduce the problem. However, time is always short (too many other projects I am involved).
Alright buddy, you can add this to your Test Config when you don't want encryptable properties:
@EnableAutoConfiguration(exclude = JasyptSpringBootAutoConfiguration.class)
To effectively exclude the auto configuration, and you won't get an error.
I'll will work in a way of lazily initializing the bean on first use so in case you don't have any encrypted properties in your properties it will never fail if you don't setup the string encryptor correctly.
I'm still looking into the issue you mention overriding existing properties, hang on...
Alright so I was able to override any of the properties in the jasypt-spring-boot-demo app from either application.yml and encrypted.properties through the command line using JVM args. For instance:
-Djasypt.encryptor.poolSize=20 -DitemConfig.items[0].name=NEW_NAME -Dsecret.property=UNENCRPYPTED
I'm not sure why you mean by "But my expectation is (compliant to spring-boot) that I can override the properties as specified"
Thanks for the hints, mate. I can confirm that it is working properly if I launch the application directly as JAR or bootified WAR with
java -Djasypt.encryptor.password=******************* -jar webapps/demo.war
However if the WAR gets deployed to a tomcat and I add the system property to the tomcat launch then the bug occurrs. I even verified with ps that the system property is really set:
ps aux | grep jasypt | grep -v grep
app 11892 0.5 1.5 3486172 97452 ? Sl 00:39 3:13 /opt/java/latest8/bin/java -Dnop -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xloggc:logs/gc_log_app_2015-10-15_00-39-10.log -Djava.security.manager -Djava.security.policy=/etc/opt/catalina/app/catalina.policy -Djava.security.debug=failure -Djasypt.encryptor.password=****************** -Djava.awt.headless=true -Dmail.mime.charset=UTF-8 -Djavax.net.ssl.trustStore=/etc/opt/catalina/app/cacerts -Dcatalina.config=file:/etc/opt/catalina/app/catalina.properties -Djava.net.preferIPv4Stack=true -Xms256m -Xmx1024m -Djava.endorsed.dirs=/opt/catalina/latest8/endorsed -classpath /opt/catalina/latest8/bin/bootstrap.jar:/opt/catalina/latest8/bin/tomcat-juli.jar -Dcatalina.base=/home/app -Dcatalina.home=/opt/catalina/latest8 -Djava.io.tmpdir=/home/app/temp org.apache.catalina.startup.Bootstrap -config /etc/opt/catalina/app/server.xml start
Next I will check if that is a general problem so overriding other properties than jasypt ones will work or not. If that also does not work I have found a general "bug" in spring boot when running in tomcat (maybe only in combination with security manager). I will let you know...
Alright buddy, I see what the problem is now. How are you passing the properties to tomcat? Yo have some options, but I recommend either use tomcat/conf/catalina.properties or by creating a setenv.sh file in tomcat/bin. Then in setenv.sh you'll do something like this: `export JAVA_OPTS="-Djasypt.encryptor.poolSize=20 -DitemConfig.items[0].name=NEW_NAME -Dsecret.property=UNENCRPYPTED"``
I tested passing the password to the jasypt-spring-boot-demo-tomcat-ssl demo app packaging it as a WAR and rewriting SampleTomcatSslApplication with this:
@SpringBootApplication
@EnableEncryptableProperties
public class SampleTomcatSslApplication extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception {
System.setProperty("jasypt.encryptor.password", "password");
SpringApplication.run(SampleTomcatSslApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SampleTomcatSslApplication.class);
}
}
And I was able to set the password through a system property just fine running tomcat from IntelliJ Idea 13. Under VM options I specified -Djasypt.encryptor.password=password
in the run configurations. Internally, IntelliJ is using catalina.sh run
and setting environment variable: JAVA_OPTS="-Djasypt.encryptor.password=password"
. Which is basically one of the two solutions I recommended, and my test confirms it works.
Alright, version 1.3 should be in Central soon, I added lazy initialization of the StringEncryptor up until the first encrypted property is decrypted. So in case there are no "ENC(xxxx)" properties not setting any of the required properties won't prevent your application from working.
I tested passing the password to the jasypt-spring-boot-demo-tomcat-ssl demo app packaging it as a WAR and rewriting SampleTomcatSslApplication with this...
As I said if you run the WAR directly with spring boot there is no problem. The problem only happens when you run a regular tomcat and have the WAR deployed in tomcat/webapps/.
Alright, version 1.3 should be in Central soon, I added lazy initialization of the StringEncryptor...
Awesome. Thanks buddy, that is cool!
Yo have some options, but I recommend either use tomcat/conf/catalina.properties or by creating a setenv.sh file in tomcat/bin.
For the record I used setenv.sh
so that is not the solution.
Next I will check if that is a general problem so overriding other properties than jasypt ones will work or not. If that also does not work I have found a general "bug" in spring boot when running in tomcat (maybe only in combination with security manager). I will let you know...
I addded this to the config:
JAVA_OPTS="$JAVA_OPTS -Dspring.datasource.url=illegalURL"
Then I started tomcat and got this:
Caused by: java.sql.SQLException: Driver:oracle.jdbc.driver.OracleDriver@38874c24 returned null for URL:illegalURL
So, the default behaviour of spring boot is correct. However setting jasypt.encryptor.password
via System-Property does not work when using external tomcat (it seems that it does not even work if there is no default set in application.properties
).
can you please take a look at at jasypt-spring-boot-demo-tomcat-ssl?
I changed the configuration to package it as a WAR. I'm using tomcat tomcat 8.0.9 in Mac. I throw the WAR into $tomcat_home/webapps
and the create a file $tomcat_home/bin/setenv.sh
with this inside:
export JAVA_OPTS="jasypt.encryptor.password=password
Then, I run tomcat with $tomcat_home/bin/catalina.sh run
You can hit the demo endpoint at http://localhost:8080 to test the decryption. I would really like for you to put a sample project together in Github so I can take a look. From where I stand everything seems to work as expected.
Hi @ulisesbocchio just got to know about this wonderful spring boot starter on jasypt. Question is why are we forced to set jasypt.encryptor.password? If I can use a environmentconfig and set the password environment name(not even password) and create my stringencryptor? Really this feels like a restriction on using our custom encryptor.
@abuabdul the jasypt.encryptor.password
property is only required if you don't provide a custom StringEncryptor
. Basically, if you use jasypt-spring-boot
out of the box, a StringEncryptor
is pre-configured for you, and all you gotta input is the encryption/decryption password.
@ulisesbocchio you are correct. I set my custom string encryptor bean, and its working fine now. However i am facing the same issue in the Spring Boot JUnit Tests. Though i have configured the custom bean, it still forcing me to set jasypt.encryptor.password
Can you please upload your code to github so I can take a look?
@abuabdul Check out this sample project: https://github.com/ulisesbocchio/jasypt-spring-boot-samples/tree/master/jasypt-spring-boot-demo-custom-encryptor
Where you can start/test the app with no jasypt.encryptor.password
property whatsoever.
Hi @ulisesbocchio Thanks for your help. This is where i have hosted my code. https://github.com/B2OPlus/HTMLService. I reverted back to default stringencryptor. Since the way i have structured my code does not allow me to run tests with custom string encryptor (forcing me to set jasypt.encryptor.password for custom string encryptor). Please suggest a solution.
Thanks a lot for this. The custom encryptor fixed all my problems.
In case anyone has issues with this my configuration is as follows:
pom.xml
...
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.starter.version}</version>
</dependency>
...
application.yml
jasypt:
encryptor:
password: ${APP_ENCRYPTION_PASSWORD}
test: ENC(4DxzpnbrSONISyS4GEtiqQ==)
EncryptorConfig.java
@Configuration
public class EncryptorConfig {
@Bean
public static EnvironmentStringPBEConfig environmentVariablesConfiguration() {
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
config.setPasswordEnvName("APP_ENCRYPTION_PASSWORD");
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setStringOutputType("base64");
return config;
}
@Bean(name="jasyptStringEncryptor")
public static PooledPBEStringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
encryptor.setConfig(environmentVariablesConfiguration());
return encryptor;
}
}
TestController.java
@RestController()
public class TestController {
@Value("${test}")
private String test;
@GetMapping("/test")
public String getTest(){
return test;
}
}
Environment variable with the secret export APP_ENCRYPTION_PASSWORD=secretkey
Thanks a bunch @fredlo2010 and @ulisesbocchio If I did not find this page, I would have almost abandoned my efforts to try and use jasypt for springboot application. My problem is pretty similar to what was described by @fredlo2010. I am using AWS CodeBuild and CodeCommit to build and deploy my springboot application. All my source code is in GitHub, so AWS CodeBuild pulls the code from GitHub and runs the mvn package and it fails because its unable to decrypt the properties from application.properties. I was finding ways to tell the mvn package how to decrypt the jasypt encrypted passwords. Luckily i found this thread and @fredlo2010 you final comment helped me save a lot of time. Thanks a bunch guyz :)
I am glad I was able to help :)
I have two place 2 encrypted passwords in application.properties ..how can i do that? How can i maintain 2 different "jasypt.encryptor.algorithm" and "jasypt.encryptor.password" ??
Its not work for me.
Thanks a lot for this. The custom encryptor fixed all my problems.
In case anyone has issues with this my configuration is as follows:
pom.xml
... <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>${jasypt.starter.version}</version> </dependency> ...
application.yml
jasypt: encryptor: password: ${APP_ENCRYPTION_PASSWORD} test: ENC(4DxzpnbrSONISyS4GEtiqQ==)
EncryptorConfig.java
@Configuration public class EncryptorConfig { @Bean public static EnvironmentStringPBEConfig environmentVariablesConfiguration() { EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); config.setPasswordEnvName("APP_ENCRYPTION_PASSWORD"); config.setAlgorithm("PBEWithMD5AndDES"); config.setKeyObtentionIterations("1000"); config.setPoolSize("1"); config.setProviderName("SunJCE"); config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); config.setStringOutputType("base64"); return config; } @Bean(name="jasyptStringEncryptor") public static PooledPBEStringEncryptor stringEncryptor() { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setConfig(environmentVariablesConfiguration()); return encryptor; } }
TestController.java
@RestController() public class TestController { @Value("${test}") private String test; @GetMapping("/test") public String getTest(){ return test; } }
Environment variable with the secret export APP_ENCRYPTION_PASSWORD=secretkey
Thanks for the efforts, I have following jasypt dependency in my pom: `
` Would your code example work with this one?
For the one that want to test jasypt-spring-boot-demo-tomcat-ssl
using the Tomcat docker container:
jasypt-spring-boot-demo-tomcat-ssl> mvn clean install
docker run -it --rm -p 8080:8080 **--env jasypt.encryptor.password=***** -v $(pwd)/target/jasypt-spring-boot-demo-tomcat-ssl-0.1-SNAPSHOT.war:/usr/local/tomcat/webapps/app.war tomcat:9.0
then browse the webapp at http://localhost:8080/app/
I need to encrypt two database passwords at a time.
how can i pass two vm arguments like this -Djasypt.encryptor.password when i am trying to do it , it is giving me error
The whole story about spring-boot application properties is its flexibility. See here: http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html
Now, when I add your jasypt-spring-boot-starter as a dependency I can not start the application without having
jasypt.encryptor.password
set even if I have no encrypted password configured anywhere. This makes my unit tests fail, etc. So what I did is addingTo my application.properties that I deliver within the WAR file (in default package). Now I have an external application.properties in
tomcat/lib/config/application.properties
that defines encrypted passwords for DB, etc. Of course I want to provide the master password somewhere different as having it in the same file would be quite pointless (my plan is that I have a secret master password per environment that is available in one place on the involved machines while I then can have the configs with encrypted passwords stored in VCS but regular developers can not decrypt them without knowing the master password but they can build release packages including the correct configs).Now, I set the master password on the commandline as a system property. I verified that the system property is actually set and available in tomcat. However, it is not honored and jasypt will use the dummy password instead.
This is totally unexpected as it works for any other spring boot property like this. There might be a technical reason as you need early on bootstrapping and interception. However, a solution is required to externalize the master password from the actual properties file. Any solution or workaround is welcome. Thanks for your great work!