Spring Boot 2.7.1 LetsEncrypt PEM keystore throws Resource location must not be null - spring

So I read that Spring Boot now supports PEM since 2.7.0
https://docs.spring.io/spring-boot/docs/2.7.0-SNAPSHOT/reference/htmlsingle/#howto.webserver.configure-ssl 17.3.7. Configure SSL
So I am using PEM generated by certbot.
My application.properties
spring.jpa.generate-ddl=true
spring1.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=false
server.port=443
server.ssl.certificate=fullchain1.pem
server.ssl.certificate.certificate-private-key=privkey1.pem
server.ssl.trust-certificate=fullchain1.pem
When I launch I get
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Could not load key store 'null'
Caused by: org.springframework.boot.web.server.WebServerException: Could not load key store 'null'
Caused by: java.lang.IllegalArgumentException: Resource location must not be null

As per the documentation SSL configuration springboot
UPDATE:
Adding the content from link to directly in the answer, as link can
get updates
SSL can be configured declaratively by setting the various
server.ssl.* properties, typically in application.properties or
application.yml. The following example shows setting SSL properties
using a Java KeyStore file:
server.port=8443
server.ssl.key-store=classpath:keystore.jks
server.ssl.key-store-password=secret
server.ssl.key-password=another-secret
The following example shows setting SSL properties using PEM-encoded
certificate and private key files:
server.port=8443
server.ssl.certificate=classpath:my-cert.crt
server.ssl.certificate-private-key=classpath:my-cert.key
server.ssl.trust-certificate=classpath:ca-cert.crt
Your properties are not correctly declared,
server.ssl.certificate.certificate-private-key=privkey1.pem should be changed to server.ssl.certificate-private-key=privkey1.pem

So this workaround works
#Configuration
public class SSLConfig {
#Bean
public ConfigurableServletWebServerFactory webServerFactory() throws Exception {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
Ssl ssl = new Ssl();
ssl.setEnabled(true);
ssl.setCertificate("cert1.pem");
ssl.setCertificatePrivateKey("privkey1.pem");
ssl.setKeyStoreType("PKCS12");
ssl.setKeyStorePassword(""); // without this decrytption fails
factory.setSsl(ssl);
factory.setPort(443);
return factory;
}
}

server.ssl.key-store=file:///Users/...
Have you tried this way of setting the path? First, make sure your application up with the correct path, then dig into the next step.

Related

encrypt key Property binding error in spring boot 2.7.0

I have Spring boot 2.7.0 application which connects config server with following configuration to decrypt secrets. But when I include below configuration in (application.yml or bootstrap.yml) getting binding error. Not sure what is the root cause of this issue as format is correct for the keys but still getting this error. Same config is working fine with Spring boot 2.2.1.
I have used same config in application.yml without bootstrap.yml as it depricated in 2.7.0 but still same issue.
encrypt:
key-store:
location: file:${key.path}
password: anthem$$docker
alias: docker
secret: anthem$$docker
org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'encrypt.key-store.alias' to java.lang.String
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:384)
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:344)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:469)
at org.springframework.boot.context.properties.bind.Binder$$Lambda$78/234145890.bindProperty(Unknown Source)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:95)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:83)
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:59)
at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:473)
Description:
Failed to bind properties under 'encrypt.key-store.alias' to java.lang.String:
Property: encrypt.key-store.alias
Value: docker
Origin: class path resource [bootstrap.yml] - 40:12
Reason: org.springframework.boot.context.config.InactiveConfigDataAccessException: Inactive property source 'Config resource 'class path resource [bootstrap.yml]' via location 'optional:classpath:/' (document #5)' imported from location 'class path resource [bootstrap.yml]' cannot contain property 'encrypt.key-store.alias' [origin: class path resource [bootstrap.yml] - 40:12]
Action:
Update your application's configuration

Spring Cloud Discovery First Configuration Server Decryption Failed

I am trying discovery first implementation with Spring Cloud. I am getting failure for password decryption. I have .jks in the classpath. The same works when I go for Config First approach.
Following is the bootstrap.properties file for Config first approach.
eureka.instance.hostname=claims-dev
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.cloud.config.name=claim
spring.config.import=configserver:http://localhost:8888
spring.profiles.active=dev
spring.cloud.config.fail-fast=true
Following is the bootstrap for Discovery First approach.
eureka.instance.hostname=claims-dev
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/
spring.cloud.config.discovery.service-id=configserver
spring.cloud.config.discovery.enabled=true
spring.cloud.config.name=claim
spring.profiles.active=dev
spring.cloud.config.fail-fast=true
For Discovery First I am getting below exception
Caused by: java.lang.UnsupportedOperationException: No decryption for FailsafeTextEncryptor. Did you configure the keystore correctly?
at org.springframework.cloud.bootstrap.encrypt.TextEncryptorUtils$FailsafeTextEncryptor.decrypt(TextEncryptorUtils.java:188) ~[spring-cloud-context-3.1.0.jar:3.1.0]
at org.springframework.cloud.bootstrap.encrypt.AbstractEnvironmentDecrypt.decrypt(AbstractEnvironmentDecrypt.java:144) ~[spring-cloud-context-3.1.0.jar:3.1.0]
... 16 common frames omitted
What I am missing here?
UPDATE: Following are the config server properties
encrypt.keyStore.location=classpath:/store name
encrypt.keyStore.password=store password
encrypt.keyStore.alias=alias
encrypt.key-store.type=jks
spring.cloud.config.server.encrypt.enabled=false
It works if I opt for server side password decryption.

GRPC-Client : File does not contain valid certificates

I have a Springboot GRPC client which uses Self Signed Certificate & Private Key to establish a connection with the GRPC server.
File keyFile = new File(getClass().getClassLoader().getResource("certs/key.key").getFile());
File certFile = new File(getClass().getClassLoader().getResource("certs/cert.crt").getFile());
SslContext sslContext = GrpcSslContexts.forClient().keyManager(certFile, keyFile).build();
ManagedChannel channel = NettyChannelBuilder.forAddress(host, port).sslContext(sslContext).build();
The implementation works fine as expected in local springboot run via Intellij;
tested the interaction with server, works as expected but when i execute the jar created by my build(java -jar **-0.1.jar), i get the below exception.
I verified .crt & .key expiry and being available in the build .jar
Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: File does not contain valid certificates: file:\C:\Projects\**-0.1.jar!\BOOT-INF\classes!\certs\cert.crt
Any suggestion/direction for the solution will be of great help.
Thanks in advance.

Spring Boot not loading keystore specified in application.yml

I am attempting to run and test a Spring Boot application that I have packaged into a zip file and unpacked on a Linux VM. The zip contains everything the application needs (at least to my knowledge). When I attempt to execute the application, it starts but quickly fails because it cannot load a keystore needed for SSH/TLS secure communications.
I have the following in my application.yml:
server:
port: 8091
ssl:
enabled: true
protocol: TLS
trust-store-type: JKS
trust-store: classpath:keystore/server.keystore
trust-store-password: <hidden>
key-store-type: JKS
key-store: classpath:keystore/ra/server.keystore
key-store-password: <hidden>
The directory structure on the test system is as follows:
[centos#route-assessor route-assessor]$ ls -R
.:
config elastic-apm-agent-1.10.0.jar lib run-route-assessor.sh services-0.0.1-SNAPSHOT.jar
./config:
application.yml keystore log4j2.xml
./config/keystore:
mp ra rg server.keystore
./config/keystore/mp:
server.keystore
./config/keystore/ra:
server.keystore
./config/keystore/rg:
server.keystore
./lib
<dependency jars>
Here is the exception thrown:
[2019-10-23 13:21:31.419] main WARN : context.AnnotationConfigServletWebServerApplicationContext:557 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Could not load key store 'classpath:keystore/server.keystore'
The Spring Boot "runtime" obviously sees and accesses the config directory, but doesn't seem to see the keystore directory contained within. Do I need to specify the paths differently in application.yml or do I need to put the keystore files somewhere else?
Note: I can run this application with the application.yml configured as shown from eclipse without any problem. Granted, all resources are located in src/main/resources for that situation.
UPDATE:
As per #borban's suggestion, I modified the application.yml as follows:
key-store: file:config/keystore/ra/server.keystore
trust-store: file:config/keystore/server.keystore
That seems to have solved one problem, but I'm not out of the woods yet:
[2019-10-23 15:07:17.671] main ERROR: boot.SpringApplication:821 - Application run failed
org.springframework.boot.web.server.WebServerException: Unable to start embedded Jetty server
...
Caused by: java.lang.IllegalStateException: no valid keystore
...
As far as I know, my keystore files are valid and correct (I've been using them on my Windows development box for months). They are copied over as part of the zip distribution. Is there something maybe I'm missing?
I'm also a little concerned with a few other messages in the log. I'm not sure if they're related, but it seems that they could be:
[2019-10-23 15:07:10.153] main WARN : resource.Resource:126 - java.lang.IllegalArgumentException: URI is not hierarchical
[2019-10-23 15:07:10.155] main WARN : resource.Resource:126 - java.lang.IllegalArgumentException: URI is not hierarchical
I don't recall seeing them before.
Are you are trying to access this keystore outside of the classpath and from the filesystem itself? From the folder structure you are giving, that seems to be the case. If you remove the "classpath" prefix and then update your path appropriately, it should work.
From this post, it looks like you have to prefix with "file"
https://maven.apache.org/plugins/maven-resources-plugin/examples/resource-directory.html
You can use maven resource plugin to add the folders you need to the plugin:
https://maven.apache.org/plugins/maven-resources-plugin/examples/resource-directory.html
then use without classpath??

Spring Boot JMS & Batch

Previously everything worked properly. Today I configured Spring Batch together with my Spring Boot application and faced an issue with application.properties.
I have following properties encrypted with Jasypt:
spring.profiles.active=https
ENVIRONMENT=h2
#aws sqs
aws.sqs.account.access.key=ENC(kjsdh456fgkjhdfsgkjhdfg)
#queue message listener
queue.message.listener.task.executor.threads.number=1
queue.message.listener.task.executor.max.concurrent.consumers=1
Now, in order to configure Spring Batch I added
ENVIRONMENT=h2
to application.properties file.
also, I have added batch-h2.properties file:
# Placeholders batch.* for H2 database:
batch.jdbc.driver=org.h2.Driver
batch.jdbc.url=jdbc:h2:~/testdb;CIPHER=AES;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE
batch.jdbc.user=sa
batch.jdbc.password="sa sa"
batch.jdbc.testWhileIdle=false
batch.jdbc.validationQuery=
batch.drop.script=classpath:/org/springframework/batch/core/schema-drop-h2.sql
batch.schema.script=classpath:/org/springframework/batch/core/schema-h2.sql
batch.business.schema.script=classpath:/business-schema-h2.sql
batch.database.incrementer.class=org.springframework.jdbc.support.incrementer.H2SequenceMaxValueIncrementer
batch.database.incrementer.parent=sequenceIncrementerParent
batch.lob.handler.class=org.springframework.jdbc.support.lob.DefaultLobHandler
batch.grid.size=2
batch.jdbc.pool.size=6
batch.verify.cursor.position=true
batch.isolationlevel=ISOLATION_SERIALIZABLE
batch.table.prefix=BATCH_
and after that I continuously receiving following exception:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'aws.sqs.account.access.key' in string value "${aws.sqs.account.access.key}"
aws.sqs.account.access.key property now cannot be resolved.
I'm injecting this property into my configuration:
#Configuration
public class SQSConfig {
#Value("${aws.sqs.account.access.key}")
private String accessKey;
How to fix it ?

Resources