Reputation: 29567
I have created a GitHub project that perfectly reproduces everything explained here.
I am building a Spring Boot app (with an embedded Jetty web container) and am trying to get it to serve self-signed OpenSSL certs when running locally (when running on staging or prod environments, the app will be serving a root CA-signed cert).
So to create the SSL capabilities, first I created the public key/CSR by issuing:
openssl req -x509 -newkey rsa:4096 -keyout myapp-key.pem -out myapp-csr.pem -days 3650
Then I created the JKS and imported my public key like so:
keytool -importcert -trustcacerts -file myapp-csr.pem -alias myorg -keystore myapp.jks
I then updated my application.yml
with SSL properties:
ssl:
key-store: 'myapp.jks'
key-store-password: '123456'
key-password: '123456'
I then run my Spring Boot app:
./gradlew build && java -Dspring.config=. -jar build/libs/spring-boot-troubleshooting.jar
So far so good -- no errors/exceptions/warnings at startup. I then open a new terminal and run:
curl -k -H "Content-Type: application/json" -X GET https://localhost:9200/health
curl: (35) SSL peer handshake failed, the server most likely requires a client certificate to connect
If I switch back over to the terminal where the app is running, I now see this in the console output:
06:14:00.149 [qtp1706099897-15] WARN org.eclipse.jetty.http.HttpParser - Illegal character 0x16 in state=START for buffer HeapByteBuffer@5b876b3[p=1,l=175,c=8192,r=174]={\x16<<<\x03\x01\x00\xAa\x01\x00\x00\xA6\x03\x03ZL\xBa\xF8T\x86r...\x00\x05\x01\x00\x00\x00\x00\x00\x12\x00\x00\x00\x17\x00\x00>>>-Type: applicatio...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
The -k
is to intentional ignore SSL since this is a self-signed cert. I've tried both with and without -k
and the result is the same.
I see evidence that this could be a MacOS issue for some reason, but frankly I'm not even sure where to start looking. Something wrong with the way I created the public/private key pair? Something wrong with the way I imported the public key/CSR into the JKS file? Something else wrong with any aspect of my configuration?
Upvotes: 1
Views: 4393
Reputation: 2423
@EJP explained root cause well. There is no private key in your myapp.jks file.
I can tell the solutions detailed. There are 3 solution. I tested them by your code and java 8.
only keytool - fastest one
remove existing myapp.jks and regenerate by keytool with these parameters.
keytool -genkeypair -dname "cn=Name Surname, ou=MyUnit, o=MyOrg, c=US" -alias myorg -keypass 123456 -storepass 123456 -validity 365 -keyalg RSA -keystore myapp.jks
only openssl
Create pkcs file by openssl named "myapp.p12".
openssl pkcs12 -inkey myapp-key.pem -in myapp-csr.pem -export -out myapp.p12;
change application.yml key-store: 'myapp.jks' to key-store: 'myapp.p12'
combination of them(current method).
Create pkcs file by openssl named "myapp.p12".
openssl pkcs12 -inkey myapp-key.pem -in myapp-csr.pem -export -out myapp.p12;
import it into jks file
keytool -importkeystore -srckeystore myapp.p12 -srcstoretype pkcs12 -destkeystore myapp.jks -deststoretype JKS
Upvotes: 1
Reputation: 2253
To perform the SSL handshake server keystore must contain both public certificate and private key. The easiest way to do it is to create a p12
bundle with private key and certificate and import both of them at once using importkeystore
command.
openssl req -x509 -newkey rsa:4096 -keyout myapp-key.pem -out myapp-csr.pem -days 3650 -subj '/CN=localhost'
openssl pkcs12 -export -in myapp-csr.pem -inkey myapp-key.pem -out keystore.p12
keytool -importkeystore -deststorepass 123456 -destkeystore keystore.jks -srckeystore keystore.p12 -srcstoretype PKCS12
Now you will be able to query your server using curl
.
curl -k -H "Content-Type: application/json" -X GET https://localhost:9200/health
curl --cacert myapp-csr.pem -H "Content-Type: application/json" https://localhost:9200/health
So basically your configuration is correct except for missing private key in keystore.
Upvotes: 1
Reputation: 311023
None of this makes sense.
openssl
at all.You need to use the keytool
, and nothing else, as follows:
keytool -genkey ...
keytool -selfcert ...
using the same alias both times.
keytool -export ...
keytool -import ...
into the clients' truststore file(s).Upvotes: -1