Amazon Keyspace NoHostAvailableException - spring

I am running a Spring Boot application and using Spring boot cassandra to connect to keyspace.
Following are the properties being used:
spring.data.cassandra.contact-points=cassandra.us-east-2.amazonaws.com
spring.data.cassandra.port=9142
spring.data.cassandra.ssl=true
I am passing cassandra truststore key as vm argument.
From my local dev environment it works perfectly fine without any issue.
When I created a docker image with exactly same cassandra configuration and deployed it in AWS cloud (using ECS) it fails every time with following exception
Invocation of init method failed; nested exception is com.datastax.driver.core.exceptions.NoHostAvailableException: All host(s) tried for query failed (tried: cassandra.us-east-2.amazonaws.com/3.12.23.159:9142 (com.datastax.driver.core.exceptions.TransportException: cassandra.us-east-2.amazonaws.com/3.12.23.159:9142 Cannot connect)-
Here also I am passing trustore key as vm argument and verified certificate as well by enabling log.
Can some one please help me with this issue.

Use the following container as a reference on how to setup a container
https://github.com/aws-samples/amazon-keyspaces-toolkit
For Java apps you may need to add the pem to the truststore with the additional info
RUN mkdir $CQLSHRC_HOME
RUN yum install -y openssl && \
yum install -y java-1.8.0-openjdk && \
yum install -y tar
#create jks truststore
RUN openssl x509 -outform der -in $CQLSHRC_HOME/AmazonRootCA1.pem -out temp_file.der && \
keytool -import -alias new-cassandra -keystore $CQLSHRC_HOME/cassandra_truststore.jks -file temp_file.der -storepass amazon -noprompt
ENV javax.net.ssl.trustStore=$CQLSHRC_HOME/cassandra_truststore.jks
ENV javax.net.ssl.trustStorePassword=amazon

Related

Quarks docker run unable to find valid certification path to requested target

i tried to build a container that runs my Quarkus application in JVM mode, i was able to run
./mvnw package
docker build -f src/main/docker/Dockerfile.jvm -t quarkus/myapp-jvm .
but when I ran
docker run -i --rm -p 8080:8080 quarkus/myapp-jvm
it failed with error:
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I've already installed the certs
echo $GRAALVM_HOME
export JAVA_HOME=$GRAALVM_HOME
echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/graalvm-ce-java17-22.0.0.2/Contents/Home
sudo keytool -importcert -file netskope-bundle.pem -alias netskope-bundle -keystore $JAVA_HOME/lib/security/cacerts
on my box i also have Java 13 installed and added the same certs there too
/Library/Java/JavaVirtualMachines/zulu-13.jdk/Contents/Home
my setup:
java -version
openjdk version "17.0.2" 2022-01-18
OpenJDK Runtime Environment GraalVM CE 22.0.0.2 (build 17.0.2+8-jvmci-22.0-b05)
OpenJDK 64-Bit Server VM GraalVM CE 22.0.0.2 (build 17.0.2+8-jvmci-22.0-b05, mixed mode, sharing)
mvn -version
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: /usr/local/Cellar/maven/3.8.4/libexec
Java version: 17.0.2, vendor: GraalVM Community, runtime: /Library/Java/JavaVirtualMachines/graalvm-ce-java17-22.0.0.2/Contents/Home
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.7", arch: "x86_64", family: "mac"
why do i still get this error?
Add this to your application.properties file:
quarkus.tls.trust-all=true
I believe you are receiving this error because the certificates aren't in the cacerts of the JVM running inside your container.
I guess you only imported the certificates to the host machine.
In this project I added to the Dockerfile one instruction to copy the cert file and then another to import it to the JVM cacerts:
COPY certificates /tmp/ssl
RUN keytool -importcert -noprompt -keystore /etc/alternatives/jre/lib/security/cacerts -storepass changeit -file /tmp/ssl/b3-api.crt -alias "b3-api-root"
Complete Dockerfile
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3
ARG JAVA_PACKAGE=java-11-openjdk-headless
ARG RUN_JAVA_VERSION=1.3.8
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
# Install java and the run-java script
# Also set up permissions for user `1001`
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
&& microdnf update \
&& microdnf clean all \
&& mkdir /deployments \
&& chown 1001 /deployments \
&& chmod "g+rwX" /deployments \
&& chown 1001:root /deployments \
&& curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
&& chown 1001 /deployments/run-java.sh \
&& chmod 540 /deployments/run-java.sh \
&& echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=1001 target/quarkus-app/*.jar /deployments/
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
COPY certificates /tmp/ssl
RUN keytool -importcert -noprompt -keystore /etc/alternatives/jre/lib/security/cacerts -storepass changeit -file /tmp/ssl/b3-api.crt -alias "b3-api-root"
EXPOSE 8080
USER 1001
ENTRYPOINT [ "/deployments/run-java.sh" ]
Making sure the certificates are correct
If you imported the certificates correctly to the cacerts of the JVM of your host machine, running the application like this should work:
./mvnw quarkus:dev

LetsEncrypt cert as p12 fails instanceof CertEntry test in Spring Boot

I used LetsEncrypt's certbot to generate the cert and key pems:
sudo certbot certonly -a standalone -d footeware.ca
...and converted them to a p12:
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root
I moved the p12 to my development machine into my eclipse project's resources folder.
When I start the application and debug thru sun.security.pkcs12.PKCS12KeyStore#engineIsCertificateEntry, it finds the aliased entry but states it's not an instanceof sun.security.pkcs12.PKCS12KeyStore.CertEntry but rather a sun.security.pkcs12.PKCS12KeyStore$PrivateKeyEntry and so it fails with:
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
keytool -list on the p12:
Alias name: tomcat
Creation date: Jan. 3, 2022
Entry type: PrivateKeyEntry
Certificate chain length: 3
Certificate[1]:
Owner: CN=footeware.ca
Issuer: CN=R3, O=Let's Encrypt, C=US
What have I done wrong? Should the PrivateKeyEntry be something else?
Thanks #Saif for that link.
I did:
sudo update-ca-certificates -f
sudo /var/lib/dpkg/info/ca-certificates-java.postinst configure
...and used my original keystore.p12 (seems there was nothing wrong with it).
The solution was to change my application.properties' values to:
server.ssl.trust-store=file:/etc/ssl/certs/java/cacerts
server.ssl.trust-store-password=changeit
server.ssl.trust-store-type=JKS
I had been setting those properties to the keystore.p12 thinking they were one and the same (noob).
I deployed and started the appication jar, set my router to forward 443 to my server#8443 (instead of 80 to 8090 as it was) and I'm in with a happy https indicator!
Now I just have to fix the broken css that upgrading bootstrap seems to have caused. Pain that the cert prevents me from using localhost now as it only supports footeware.ca.
Any ideas there?

How to install self signed certificate for Java in Docker/Kubernetes?

I am running a Spring Boot application in Docker with Kubernetes.
While downloading an image I am getting the below error:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target
How can I solve this problem?
Try adding the certificates to the docker image and installing them via keytool
After adding certificate to the docker now i am able to access the remote site.
Assure I need to download files or access abc.com over https
Add below lines to your Docker file
USER root
RUN cd $JAVA_HOME/lib/security && echo -n | openssl s_client -connect abc.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > abc.com.crt && keytool -keystore cacerts -keypass changeit -storepass changeit -noprompt -import -v -trustcacerts -alias abc.com -file abc.com.crt

How do I generate X.509 certificate from key generated by openssl

I've a web server running on an ec2-instance which internally calls a REST server that is built using Spring Boot. Now, I am trying to get this REST server running under SSL. Here's what I've done so far:
1) Created a CSR & a key file using this command
openssl req -newkey rsa:2048 -nodes -keyout mydomain.key -out mydomain.csr
2) Copied 'csr' to get SSL certificate from GoDaddy.
3) Successfully installed the certificate under Nginx on my ec2-instance.
4) When I hit the home page under https, it works. I no longer get 'Not secure' message from the browser.
5) Login fails because it makes a REST call but REST server is not running under SSL so I am trying to get it running under SSL.
6) Ran following commands:
keytool -import -alias mydomain -keystore tomcat.keystore -trustcacerts -file mydomain.com.chained.crt
keytool -import -alias mydomain-key -keystore tomcat.keystore -trustcacerts -file mydomain.key
The previous command gives me an error message:
"keytool error: java.lang.Exception: Input not an X.509 certificate"
But this was the one created in step 1 above & the same file works under Nginx. What am I missing (other than the fact that I know very little about setting up SSLs!)? I need the second command to specify the value of 'server.ssl.keyAlias' in application.properties, I believe.
Not really an answer but overflowed comment.
You don't need to 'generate' an X.509 cert; you already got that from GoDaddy. If (and only if) the SpringBoot server is accessed by the same name(s) as (external) nginx -- which is unclear to me -- you need to convert the pair of private key AND certificate CHAIN from PEM format to a format Java uses. See:
How to import an existing x509 certificate and private key in Java keystore to use in SSL?
How can I set up a letsencrypt SSL certificate and use it in a Spring Boot application?
How to use .key and .crt file in java that generated by openssl?
Importing the private-key/public-certificate pair in the Java KeyStore
maybe Import key and SSL Certificate into java keystore
Thanks #Dave_thompson_085. Following 2 commands did the trick!
openssl pkcs12 -export -in mydomain.com.chained.crt -inkey mydomain.key -out keystore.p12 -name my-alias -caname root
keytool -importkeystore -deststorepass mypassword -destkeypass mypassword -destkeystore keystore.jks -srckeystore keystore.p12 -srcstoretype PKCS12 -srcstorepass mypassword -alias my-alias
and then in the application.properties I specified following properties:
server.port=8443
server.ssl.enabled=true
security.require-ssl=true
server.ssl.key-store=/etc/nginx/ssl/keystore.jks
server.ssl.key-store-password=mypassword
server.ssl.keyStoreType=JKS
server.ssl.keyAlias=my-alias

HTTPS not working with self signed certificate in tomcat

I am new to https configuration in tomcat. I googled a lot but that did not solve my problem.
I have an ec2 machine and tomcat deployed on it. I tried to create self signed certificate , which was easy to generate.I used my domain www.test.com(changed test with my server name) and keystore file was generated. Then I edited conf/server.xml for https configuration as described in ssl howto of tomcat docs.But https is not working. Though when I do "curl https:// localhost :8443 -k " I can get response but it is not working in browser. Takes to long to respond and boom I am done with nothing. Do I need a certificate or It will work with keystore file only? Please tell me .
Please help me out
Thanks
Hi Thanks for you answer, I found my issue and would like explain my resolution
1.) Curl was working but it was not responding in browser . I had to open port 8443 manually from security groups in aws. It was working then :).
2.) For all others if they face with the problem "Failed to establish chain from reply"
i) please check your keystore file. Is it the same used to generate CSR?
ii) Install intermediate certificates provided by your certificate authority.
For some of them you can follow
https://www.sslcertificaten.nl/download/Root_Certificaten/
use alias primary and secondary respectively
$JAVA_HOME/bin/keytool -import -alias primary -keystore sslkey -trustcacerts -file primary_cert.crt -storepass mypass
$JAVA_HOME/bin/keytool -import -alias secondary -keystore sslkey -trustcacerts -file secondary_cert.crt -storepass mypass
iii) finally import your certificate
$JAVA_HOME/bin/keytool -import -alias tomcat -keystore sslkey -trustcacerts -file www_mydomain_com.p7b -storepass mypass
Hope this helps
cheers
If curl works, then the problem is either in the browser or in the servlet - SSL setup should be correct. Check the log files of Tomcat for errors and set breakpoints in your servlets to see what happens.

Resources