org.jasypt.exceptions.EncryptionOperationNotPossibleException - spring

I am using Jasypt-1.9.0 with Spring 3.1 and Hibernate 4.0.1. I have a requirement in my application to connect to database whose password(root) is stored in the encrypted form in the property file within the application.
I looked online and found the way with following links:
http://www.jasypt.org/spring31.html
http://www.jasypt.org/hibernate.html
http://www.jasypt.org/encrypting-configuration.html
I have done the following steps and configuration for my requirement:
Added jasypt-1.9.0 and jasypt-hibernate4-1.9.0 in build path.
Added following in my dispatcher-servlet file:
< bean id="propertyConfigurer"
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
< constructor-arg ref="configurationEncryptor" />
< property name="locations">
< list>
< value>classpath:database.properties< /value>
< /list>
< /property>
< /bean>
< bean id="configurationEncryptor"
class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
< property name="config" ref="environmentVariablesConfiguration" />
< /bean>
< bean id="environmentVariablesConfiguration"
class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
< property name="algorithm" value="PBEWithMD5AndDES" />
< property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" />
</bean>
Using CLI tool of Jasypt 1.9.0, I have generated the password
below(attached snapshot of CLI)
- Added a new Environment Varibale as APP_ENCRYPTION_PASSWORD with value as root
Added the encrypted password in database.properties file
db.driverClassName=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/db1
db.username=root
db.password=ENC(bmfeQmgP/hJrh+mj6NANKA==)
Now, if I run my application, the following exception appears:
org.jasypt.exceptions.EncryptionOperationNotPossibleException
at org.jasypt.encryption.pbe.StandardPBEByteEncryptor.decrypt(StandardPBEByteEncryptor.java:981)
at org.jasypt.encryption.pbe.StandardPBEStringEncryptor.decrypt(StandardPBEStringEncryptor.java:725)
at org.jasypt.properties.PropertyValueEncryptionUtils.decrypt(PropertyValueEncryptionUtils.java:72)

The question is most probably out of date, but for future seekers...
EncryptionOperationNotPossibleException is a general exception thrown by jasypt to mask other possible exceptions. This exception can occur when:
your jdk does not have the JCE unlimited strenght installed (most common case)
you had some data in the database that was encrypted before with other password
you had some data in database that were not encrypted before and you added encryption to some field
jasypt failed to decrypt the encrypted value from db because of some strange corruption of data
many many others, you just need to debug to find out the real cause..

If you don't specifiy all the params during encryption, Jasypt will use default values. Make sure to use those exact default values during decryption. Otherwise you may have troubles...
This work for me:
mvn jasypt:encrypt -Djasypt.encryptor.password='secret' \
-Djasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256 \
-Djasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator \
-Djasypt.encryptor.salt-generator-classname=org.jasypt.salt.RandomSaltGenerator \
-Djasypt.encryptor.key-obtention-iterations=1000 \
-Djasypt.plugin.path='file:application.yml'
mvn jasypt:decrypt -Djasypt.encryptor.password='secret' \
-Djasypt.encryptor.algorithm=PBEWITHHMACSHA512ANDAES_256 \
-Djasypt.encryptor.iv-generator-classname=org.jasypt.iv.RandomIvGenerator \
-Djasypt.encryptor.salt-generator-classname=org.jasypt.salt.RandomSaltGenerator \
-Djasypt.encryptor.key-obtention-iterations=1000 \
-Djasypt.plugin.path='file:application.yml'

I also experienced similar issue when encrypting property file values. I encrypted values in my local Windows machine and tried to deploy in Linux box but JRE versions were different, therefore encrypted values could not be decrypted. But I encrypted the values in Linux machine and decryption was successful.

I had a similar issue, but I realize when using the CLI tool and trying to decrypt the password you don't have to include the algorithm property and the password property needs to match the one used in the CLI Tool.
In their http://www.jasypt.org/encrypting-configuration.html
their example looks like this, but this doesn't work.
encryptor.setPassword("jasypt"); // could be got from web, env variable...
encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256");
encryptor.setIvGenerator(new RandomIvGenerator());
Solution:
encryptor.setPassword("MYPAS_WORD"); // Like in the CLI Tool
encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256"); //Remove this
encryptor.setIvGenerator(new RandomIvGenerator()); //Remove this as well
It'll work fine.
In your case you can remove the algorithm property and passwordEvnName needs to match the one used in CLI Tool.

Remove all above XML configuration and add the following bean to your configuration class:
#Bean public DataSource dataSource() {
DataSourceBuilder dataSourceBuilder =
DataSourceBuilder.create();
dataSourceBuilder.url(dbUrl);
dataSourceBuilder.username(username);
dataSourceBuilder.password(password);
return dataSourceBuilder.build();
}
Add values from properties like
#Value("${db.driverclassname}")
private String dbDriverClassName;
#Value("${db.url}")
private String dbUrl;
#Value("${db.username}")
private String dbUsername;
#Value("${db.password}")
private String dbPassword;
And pass these values above the data source.
Configure your encryption key in properties file like#
db.driverclassname=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/contactsdb
db.username=contactsuser
db.password=ENC(XcBjfjDDjxeyFBoaEPhG14wEzc6Ja+Xx
+hNPrJyQT888=
Don't create your encrypted key using cmd and jaspyt jar I will share the link for creating encryption key with your secret key:
Jasypt Online Encryption and Decryption
Add jaspyat dependency as per your version.
If you have to run on a server and if you are facing issues like password encryption not matches or not possible, then add one more bean of jdbc template:
#Bean
public JdbcTemplate jdbcTemplate(DataSource
dataSourcee)
{
return new JdbcTemplate(dataSource);
}
It works fine and no issues found.
Create the key using that tool. Because I have tried many times using jaspyt command line but the encryption is wrong and it is not supported. You can cross-check key generated using the above tool with the secret key.

Related

Client authentication failure on Neo4J

I basically followed the steps described here: https://docs.spring.io/spring-data/neo4j/docs/current/reference/html/#configure-spring-boot-project
My application.properties contains the following:
spring.neo4j.uri=neo4j://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=verySecret357
I have a Neo4jConfiguration Bean which only specifies the TransactionManager, rest is (supposedly) taken care of by spring-boot-starter-data-neo4j:
#Configuration
public class Neo4jConfiguration {
#Bean
public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver,
ReactiveDatabaseSelectionProvider databaseNameProvider) {
return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
}
}
Neo4j (5.3.0) runs in a Docker container I started with
docker run -d --name neo4j -p 7474:7474 -p 7687:7687 -e 'NEO4J_AUTH=neo4j/verySecret357' neo4j:4.4.11-community
I can access it through HTTP on my localhost:7474 and can authenticate using the credentials above.
Now, when I run my springboot app and try to create Nodes in Neo4j, I keep getting the same exception:
org.neo4j.driver.exceptions.AuthenticationException: The client is unauthorized due to authentication failure.
Running in debug, it however seems the client authentication scheme is correctly set:
Any thoughts on what I might be doing wrong ?
Edit: one thing though, I would assume that the "authToken" would contain a base64-encoded String (username:password) as the scheme is basic auth. It looks like it's not the case (using neo4j-java-driver:5.2.0).
Edit: seems to be related to the Docker image. A standalone neo4j instance works fine.

spring boot read property value from file content (not property file)

Is there a way to inject the value of a property from file content?
In my case i want to read a public certificate:
#ConstructorBinding
#ConfigurationProperties(prefix = "certificate")
#Value
public class Certificate {
String publicKey;
}
The certificate is in a file with content like
-----BEGIN CERTIFICATE-----
MIIC3DCCAcSgAwIBAgIGAYYWvEf6MA0GCSqGSIb3DQEBCwUAMC8xLTArBgNVBAMM
JDhjOGVmNjQxLTEwMGEtNDUxMi1iOTFhLWM3Mzc5NDcwMTdjMzAeFw0yMzAyMDMx
...
4/eJiZvtUhlPTZAeBCbmwHhLFufMRrYtOje/JLDcXFUhF4Ypb6BITbbWijJ7oMqP
1Amyt3eKiVhFdIVk1U4gp19wda4oeKP+5gaPTvAlYrN+EWdC1lUDRBipcM5zioFk
CwELjzRA2Dzg059g93NN7Q==
-----END CERTIFICATE-----
Currently i have 2 ways to load this as property:
load it in env variable with shell CERTIFICATE_PUBLIC_KEY="$(cat ./certs/device-cert.pem)" - need to run before
change the file to a property file beginning with certificate.publicKey=
and adding "\n" at every line end and adding it as additional property source
Is there a way to load the file content directly into a property on start?
At the moment i don't want to loose the Spring Boot Property feature - because it is really flexible.
If not possible i can of course just load the file and use its content.
It is possible with Spring. You can add the following option to your application properties file:
spring:
config:
import: configtree:/specify_the_path_where_your_file_is_located/
Then you should put your public key file to that location and give a name to this file according to your desired configuration properties:
certificate.publicKey
And you're done here! During application startup the content of that file will be injected to that property and will be both accesible from your configuration properties or from Environment bean

How to externalize configuration in Spring Boot using profiles?

I have an application where I would like to change a datasource password that is stored in a application.yml file. The password in the YML file is stored such as this:
----
spring:
profiles: production
datasource:
password: prodpassword
Note: I also have profiles for development and stage.
The password prop is set on a class using ConfigurationProperties such as follows:
#Component
#ConfigurationProperties(prefix="datasource")
public class DataSourceConnector {
private password;
public void setPassword(String password) {
this.password = password;
}
Now, I try to override the prodpassword with prodpa$$word via a command line arg but it doesn't work:
java -Dspring.profiles.active=production -jar /usr/share/myapp/myapp-1.0.jar --datasource.password='prodpa$$word'
I also tried creating an identical (except the new password) application.yml file outside of the jar. That doesn't work either.
java -Dspring.profiles.active=production -jar /usr/share/myapp/myapp-1.0.jar --spring.config.location=/usr/share/myapp/
Note: I left out the file name in the location param due to this note from http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config-profile-specific-properties:
If you have specified any files in spring.config.location, profile-specific variants of those files will not be considered. Use directories inspring.config.location if you also want to also use profile-specific properties.
How can I override datasource.password within the application.yml of the jar?
Edit:
The application is being started / stopped using supervisorctl.
After changing the config file that contains the java command, supervisorctl must reread the change:
supervisorctl reread
Next, activate the changes with:
supervisorctl update

How to get the host name in spring configuration file?

Is there any easy way to get the host name in spring configuration file ? Currently I am using Java code to get the host name and and auto wire the property in the bean . But looking for less coding approach if any !
Thanks
The following will give you the hostname in java
return InetAddress.getLocalHost().getHostName();
where InetAddress belongs to the java.net package. You can add that to your java configuration file. If you want to do it in xml, you can do the following
<bean id="localhostInetAddress"
class="java.net.InetAddress"
factory-method="getLocalHost"/>
<bean id="hostname"
factory-bean="localhostInetAddress"
factory-method="getHostName"/>

Configuring SSL on Tomcat/Spring Boot ("Could not find key store classpath:keystore.jks" error)

I'm trying to configure SSL. Hovever, I get an exception saying
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Could not find key store classpath:keystore.jks
This is my application-https.properties file:
server.port = 8443
server.ssl.key-store = classpath:keystore.jks
server.ssl.key-store-password = secret
server.ssl.key-password = another-secret
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/postgres?currentSchema=myschema
spring.datasource.username=postgresql
spring.datasource.password=postgresql
spring.datasource.driverClassName=org.postgresql.Driver
My application.properties:
spring.profiles.active=https
I've read documentation about ssl and I don't know what's wrong. Any help will be appreciated.
Make sure you did the following:
placed the .jks file inside main/resources.
you ran the command: mvn clean install
Keystore is not readable from classpath other than Spring. (In case of kafka we don't have any option and kafka always expect location to be on filesystem not in jar file.) So I suggest to use below property and give absolute path to keystore location.
application.properties
spring.kafka.ssl.key-store-location=file:certificate.jks
In code:
#Value("${spring.kafka.ssl.key-store-location}")
private Resource keystoreLocation;
props.put(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG, keystoreLocation.getFile().getAbsolutePath());
This way you can read the keystore. You may need to copy the file on file system rather than in Jar.

Resources