How to configure a Play application to use Let's Encrypt certificate? - https

Once I obtain the certificate, how do I generate a JKS key store from it?
How do I configure the Play application to use this key store?
Anything else I need to do?

Here is a script to obtain (update) the letsencrypt certificate:
#!/bin/bash
/path/to/your/app/stop # stop the play application; especially if it is running on port 80 otherwise the certificate generation will fail
rm -rf /etc/letsencrypt.bak
mv /etc/letsencrypt /etc/letsencrypt.bak
./letsencrypt-auto certonly --standalone -n -m email#example.com --agree-tos -d example.com -d www.example.com
cd /etc/letsencrypt/live/example.com
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.p12 -CAfile chain.pem -caname root -passout pass:your_password
keytool -importkeystore -srcstorepass your_password -destkeystore keyStore.jks -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -storepass your_password
/path/to/your/app/start # start the application
You can schedule a cron job to run this script periodically as letsencrypt certificates currently expire after 90 days.
Once you obtain the certificate you need to modify the application start script as follows:
/path/to/your/app/app_name_script -Dhttps.port=443 -Dplay.server.https.keyStore.path=/etc/letsencrypt/live/example.com/keyStore.jks -Dplay.server.https.keyStore.password=your_password -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true # ... more parameters if required
Nearly there. When you run the application you get A- rating from SSL Labs. The rating downgrade is related to the Forward Secrecy. In order to sort out the Forward Secrecy issue (and get a full A rating) you need to specify the order of the cipher suites by implementing a custom SSLEngineProvider:
package controllers
import java.nio.file._
import java.security.KeyStore
import javax.net.ssl._
import play.core.ApplicationProvider
import play.server.api._
class CustomSslEngineProvider(appProvider: ApplicationProvider) extends SSLEngineProvider {
val priorityCipherSuites = List(
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA")
def readPassword(): Array[Char] = System.getProperty("play.server.https.keyStore.password").toCharArray
def readKeyInputStream(): java.io.InputStream = {
val keyPath = FileSystems.getDefault.getPath(System.getProperty("play.server.https.keyStore.path"))
Files.newInputStream(keyPath)
}
def readKeyManagers(): Array[KeyManager] = {
val password = readPassword()
val keyInputStream = readKeyInputStream()
try {
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
keyStore.load(keyInputStream, password)
val kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm)
kmf.init(keyStore, password)
kmf.getKeyManagers
} finally {
keyInputStream.close()
}
}
def createSSLContext(): SSLContext = {
val keyManagers = readKeyManagers()
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(keyManagers, Array.empty, null)
sslContext
}
override def createSSLEngine(): SSLEngine = {
val ctx = createSSLContext()
val sslEngine = ctx.createSSLEngine
val cipherSuites = sslEngine.getEnabledCipherSuites.toList
val orderedCipherSuites =
priorityCipherSuites.filter(cipherSuites.contains) ::: cipherSuites.filterNot(priorityCipherSuites.contains)
sslEngine.setEnabledCipherSuites(orderedCipherSuites.toArray)
val params = sslEngine.getSSLParameters
params.setUseCipherSuitesOrder(true)
sslEngine.setSSLParameters(params)
sslEngine
}
}
Do not forget to set
play.server.https.engineProvider=controllers.CustomSslEngineProvider
in your application.conf.
Tested with Play 2.5.x

I searched in various forums, in the end I came up with a very fast (and almost automated) solution:
First, as on the letsencrypt website they suggest, run these:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot
then run
sudo certbot certonly --standalone -d domain.name.com
(for wildcards it's a bit more complicated, but the remainder of this procedure should be the same)
at this point it should tell you where the keys are, on some directory like /etc/letsencrypt/live/domain.name.com/*.pem (three keys: fullchain, privkey, and a chain)
then run openssl (editing domain name and password)
sudo openssl pkcs12
-export -in /etc/letsencrypt/live/domain.name.com/fullchain.pem
-inkey /etc/letsencrypt/live/domain.name.com/privkey.pem
-out cert_and_key.p12
-CAfile /etc/letsencrypt/live/domain.name.com/chain.pem
-caname root
-passout pass:<insert some password here>
then keytool (editing keystore path and password)
sudo keytool
-importkeystore
-srcstorepass <the password you inserted above>
-destkeystore <path/key>.jks
-srckeystore cert_and_key.p12
-srcstoretype PKCS12
-storepass <the password you inserted above>
and finally you should find the jks key on the path you wrote above.
In application.conf:
play.server.https.keyStore.path = "<path/key>.jks"
play.server.https.keyStore.type = "JKS"
play.server.https.keyStore.password = "<the password you inserted above>"
Tested with Play 2.6.15, on Ubuntu 16 and 18

I recently had to do this, here's my file:
#!/usr/bin/env bash
sudo killall java #stop the application gracefully
rm -rf /etc/letsencrypt.bak
cp -r /etc/letsencrypt /etc/letsencrypt.bak
certbot renew --standalone
cd /etc/letsencrypt/live/example.com/
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert_and_key.p12 -CAfile chain.pem -caname root -passout pass:your_password
keytool -importkeystore -srcstorepass your_password -destkeystore keyStore.jks -srckeystore cert_and_key.p12 -srcstoretype PKCS12 -storepass your_password
After this, you'll need to set the properties when running the app using the same format as the accepted answer:
sudo /path/to/app -Dhttp.port=80 -Dhttps.port=443 -Dplay.server.https.keyStore.path=/etc/letsencrypt/live/api.ali.actor/keyStore.jks -Dplay.server.https.keyStore.password=your_password -Djdk.tls.ephemeralDHKeySize=2048 -Djdk.tls.rejectClientInitiatedRenegotiation=true

Related

How do I change the permissions of a file created in a script without using sudo?

I've got the following docker-compose file that creates a Cassandra cluster with SSL enabled. I have to mount the keystore and truststore files with a volume.
version: "3.3"
services:
cassandra-one:
image: bitnami/cassandra:3.11
ports:
- "9042:9042"
environment:
MAX_HEAP_SIZE: "400M"
MIN_HEAP_SIZE: "400M"
HEAP_NEWSIZE: "48M"
CASSANDRA_ENABLE_SCRIPTED_USER_DEFINED_FUNCTIONS: "true"
CASSANDRA_ENABLE_USER_DEFINED_FUNCTIONS: "true"
CASSANDRA_KEYSTORE_PASSWORD: "password"
CASSANDRA_TRUSTSTORE_PASSWORD: "password"
CASSANDRA_CLIENT_ENCRYPTION: "true"
volumes:
- ./keystore.p12:/bitnami/cassandra/secrets/keystore
- ./truststore.p12:/bitnami/cassandra/secrets/truststore
I use the following script to generate the key files needed.
#!/bin/bash
# Generate localhost_CA and localhost certs/keys
openssl genrsa -out localhost_CA.key 4096
openssl req -x509 -new -config localhost_CA.cfg -key localhost_CA.key -days 9999 -out localhost_CA.crt
openssl genrsa -out localhost.key 4096
openssl req -new -config localhost.cfg -key localhost.key -days 9999 -out localhost.csr
openssl x509 -req -in localhost.csr -CA localhost_CA.crt -CAkey localhost_CA.key -CAcreateserial -days 9999 -out localhost.crt
# generate keystore
openssl pkcs12 -export -out keystore.p12 -inkey localhost.key -in localhost.crt -passout pass:password
keytool -importkeystore -destkeystore keystore.jks -srcstoretype PKCS12 -srckeystore keystore.p12 -deststorepass "password" -srcstorepass "password"
# generate truststore
openssl pkcs12 -export -out truststore.p12 -inkey localhost.key -in localhost.crt -passout pass:password
keytool -importkeystore -destkeystore truststore.jks -srcstoretype PKCS12 -srckeystore truststore.p12 -deststorepass "password" -srcstorepass "password"
When I run docker-compose up I get the following error:
stackoverflow-example-cassandra-one-1 | Importing keystore /bitnami/cassandra/secrets/keystore to /opt/bitnami/cassandra/tmp/keystore.p12...
stackoverflow-example-cassandra-one-1 | keytool error: java.io.FileNotFoundException: /bitnami/cassandra/secrets/keystore (Permission denied)
So I have to run the following commands to fix the error and the services to start properly. This gives the files read permissions to the docker user (1001).
sudo chown -R 1001 keystore.p12
sudo chown -R 1001 truststore.p12
How can I do this step in the script without using sudo?
Below I'll put the *.cfg files so the script for generating the keys can be used.
localhost.cfg
[req]
encrypt_key = no
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
CN = localhost
localhost_CA.cfg
[dn]
C = US
ST = CA
L = Los Angeles
O = stackoverflow.com
CN = stackoverflow.com Test CA
[ca]
default_ca = stackoverflow_CA
[Shotover_CA]
private_key = Stackoverflow_CA.key
certificate = Stackoverflow_CA.crt
new_certs_dir = certs/new/
database = certs/database
RANDFILE = certs/.rand
default_md = sha256
policy = policy_anything
email_in_dn = false
serial = certs/serial
default_days = 365
x509_extensions = v3_ca
[policy_anything]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[v3_ca]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
basicConstraints = critical, CA:true
keyUsage = digitalSignature,keyEncipherment,cRLSign,keyCertSign
extendedKeyUsage = serverAuth
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

Creating certificate to sign GDB on Mac OS X from bash

I am trying to install gdb on Mac OS X by following link1 and link2. This process is done in four steps:
installing gdb using brew install gdb
creating a certificate
sign gdb using codesign -s [cert-name] [your-gdb-location]
How can I automate step 2 in a bash script?
This is my final code (based on here, here and here):
cat > myconfig.cnf << EOF
[ req ]
prompt = no
distinguished_name = my dn
[ my dn ]
# The bare minimum is probably a commonName
commonName = VENTOS
countryName = XX
localityName = Fun Land
organizationName = MyCo LLC LTD INC (d.b.a. OurCo)
organizationalUnitName = SSL Dept.
stateOrProvinceName = YY
emailAddress = ssl-admin#example.com
name = John Doe
surname = Doe
givenName = John
initials = JXD
dnQualifier = some
[ my server exts ]
keyUsage = digitalSignature
extendedKeyUsage = codeSigning
EOF
echo "generating the private key ..."
openssl genrsa -des3 -passout pass:foobar -out server.key 2048
echo ""
echo "generating the CSR (certificate signing request) ..."
openssl req -new -passin pass:foobar -passout pass:foobar -key server.key -out server.csr -config myconfig.cnf -extensions 'my server exts'
echo ""
echo "generating the self-signed certificate ..."
openssl x509 -req -passin pass:foobar -days 6666 -in server.csr -signkey server.key -out server.crt -extfile myconfig.cnf -extensions 'my server exts'
echo ""
echo "convert crt + RSA private key into a PKCS12 (PFX) file ..."
openssl pkcs12 -export -passin pass:foobar -passout pass:foobar -in server.crt -inkey server.key -out server.pfx
echo ""
echo "importing the certificate ..."
sudo security import server.pfx -k /Library/Keychains/System.keychain -P foobar
Now you can see the certificate listed in System keychains:
To sign gdb
sudo codesign -s VENTOS "$(which gdb)"

Padding errors using OpenSSL for encrypt/decrypt with Keys extracted from Digital Cert

I am using some command line Open SSL commands to encrypt and decrypt data using Public and Private keys extracted from a Digital Cert. When I try to decrypt I get PKCS padding errors. Can someone tell me where I'm going wrong?
These are the command I've been using:
a) Extract Public key: openssl x509 -pubkey -noout -in xxxxx.cer > xxxxxpublickey.pem
b) Extract Private Key:openssl pkcs12 -in xxxxxx.pfx -nocerts -out xxxxxprivatekey.pem -nodes
c) Encypt a key (.bin file): openssl enc -aes-256-cbc -in kenkey.bin -out kenkey_Key -pass file:xxxxxpublickey.pem
d) Decrypt key produced in c) openssl rsautl -decrypt -hexdump -in kenkey_key -inkey xxxxxprivatekey.key -out aeskey.txt
This produces errors like this:
RSA operation error 3248:error:0407109F:rsa
routines:RSA_padding_check_PKCS1_type_2:pkcs decoding
error:.\crypto\rsa\rsa_pk1.c:273: 3248:error:04065072:rsa
routines:RSA_EAY_PRIVATE_DECRYPT:padding check
failed:.\crypto\rsa\rsa_eay.c:602:

Distributed microservices using Kite and Kontrol

I am able to register my kite microservice to kontrol but unable to discover it,
kites, err := k.GetKites(&protocol.KontrolQuery{
Username: k.Config.Username,
Environment:k.Config.Environment,
Name:"myservice",
})enter code here
if err != nil {
fmt.Println("has error")
log.Fatalln(err)
}
I am getting authenticationError.
has error
2015/06/16 09:59:16 authenticationError: token contains an invalid number of segments
exit status 1
Also I am not able to find $USER_HOME/.kite/kite.key file.
I have figured it out. I need to export these environment variable,
export KONTROL_PORT=4099
export KONTROL_USERNAME="kontrol"
export KONTROL_STORAGE="etcd"
export KONTROL_KONTROLURL="http://127.0.0.1:4099/kite"
export KONTROL_PUBLICKEYFILE=~/certs/key_pub.pem
export KONTROL_PRIVATEKEYFILE=~/certs/key.pem
Then generate rsa token,
cd ~/certs/
openssl genrsa -out key.pem 2048
openssl rsa -in key.pem -pubout > key_pub.pem
openssl rsa -in key.pem -pubout > key_pub.pem
Run Kontrol CLI with -install flag.

openssl generates the same public key from bash script

Im trying to generate multiple pairs of private - public keys with openssl
Im using this bash script.
openssl genrsa -out /etc/dkim10.key 1024 && openssl rsa -in /etc/dkim.key -out /etc/dkim10.pub -pubout &&
openssl genrsa -out /etc/dkim11.key 1024 && openssl rsa -in /etc/dkim.key -out /etc/dkim11.pub -pubout &&
openssl genrsa -out /etc/dkim12.key 1024 && openssl rsa -in /etc/dkim.key -out /etc/dkim12.pub -pubout
the private keys are different but the public key is always the same. the .pub files are identical when compared with diff. the same happens if I try to generate the pairs one by one. is this normal ? and how can I make it generate different public keys?
You are using the same private key for each public key command: openssl rsa -in /etc/dkim.key.
You need to use the correct private key.

Resources