Skip to content

Instantly share code, notes, and snippets.

@flybyray
Last active May 10, 2022 01:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flybyray/ca01c7307c03525de7211c29bf23c402 to your computer and use it in GitHub Desktop.
Save flybyray/ca01c7307c03525de7211c29bf23c402 to your computer and use it in GitHub Desktop.
HowTo run a Play!Framework 1 application with SSL, creating jks certificate store

Steps to reproduce

run the sample app

this will build an image if required

docker-compose up -d

Dockerfile details

This is a multistage Dockerfile and will produce some sample certificates with ansible. playbook is using community collections to create self-signed CA and server certificate. With the last task it creates the jks keystore file which is copied into the resulting image and referenced by Play! application configuration default values.

extract the ca cert

docker-compose exec myapp cat /opt/myApp/conf/ca-certificate.pem

and if required convert it to some format suitable for your browser certificate management

open browser

application is running at:

configuration details

"The values below are the default values in Play!Framework"

### Keystore 
ssl.KeyManagerFactory.algorithm=SunX509
trustmanager.algorithm=JKS
keystore.password=secret
keystore.file=certificate.jks

references

Play!Framwork 1 documentation

version: "3.9"
services:
myapp:
build: .
ports:
- "9000:9000"
- "9443:9443"
command:
- /bin/bash
- -c
- >
"/opt/play/play" "start" "/opt/myApp" "--%prod" "--http.port=9000" "--https.port=9443" "-Dprecompiled=true" &&
echo please trust the following ca &&
cat /opt/myApp/conf/ca-certificate.pem &&
echo &&
touch /opt/myApp/logs/application.log &&
tail -f /opt/myApp/logs/application.log
volumes:
- logs:/opt/myApp/logs
volumes:
logs:
####
FROM openjdk:8u332-slim-buster
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates \
curl \
netbase \
python \
unzip \
wget \
; \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt
RUN curl -fsSLO https://downloads.typesafe.com/play/1.5.3/play-1.5.3.zip; \
unzip play-1.5.3.zip; \
rm -vf play-1.5.3.zip; \
mv play-1.5.3 play; \
echo | /opt/play/play new myApp; \
/opt/play/play precompile myApp
####
FROM quay.io/ansible/ansible-runner
RUN dnf makecache; \
dnf install -y \
java-1.8.0-openjdk-headless-fastdebug \
openssl \
;
RUN ansible-galaxy collection install \
community.crypto \
community.general \
;
COPY pb-keystore.yml /home/runner/
RUN ansible-playbook /home/runner/pb-keystore.yml
####
FROM openjdk:8u332-jre-slim-buster
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
python \
tini \
; \
rm -rf /var/lib/apt/lists/*
COPY --from=0 /opt/play /opt/play/
COPY --from=0 /opt/myApp /opt/myApp/
COPY log4j.properties /opt/myApp/conf/
COPY --from=1 /home/runner/ca-certificate.pem /opt/myApp/conf/
COPY --from=1 /home/runner/certificate.jks /opt/myApp/conf/
EXPOSE 9000 9443
ENTRYPOINT [ "/usr/bin/tini", "-g", "--" ]
log4j.rootLogger=ERROR, Rolling
log4j.logger.play=INFO
# Rolling files
log4j.appender.Rolling=org.apache.log4j.RollingFileAppender
log4j.appender.Rolling.File=/opt/myApp/logs/application.log
log4j.appender.Rolling.MaxFileSize=1MB
log4j.appender.Rolling.MaxBackupIndex=100
log4j.appender.Rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.Rolling.layout.ConversionPattern=%d{ABSOLUTE} %-5p ~ %m%n
---
- name: create jks file with certificate
hosts: localhost
become: false
connection: local
collections: [ community.crypto, community.general ]
vars:
secret_ca_passphrase: Ahsh7gaeeeBaov6j
tasks:
# start creating self-signed ca certificate
- name: Create private key with password protection
community.crypto.openssl_privatekey:
path: /home/runner/ca-certificate.key
passphrase: "{{ secret_ca_passphrase }}"
cipher: auto
- name: Create certificate signing request (CSR) for CA certificate
community.crypto.openssl_csr_pipe:
privatekey_path: /home/runner/ca-certificate.key
privatekey_passphrase: "{{ secret_ca_passphrase }}"
common_name: Testing CA
use_common_name_for_san: false # since we do not specify SANs, don't use CN as a SAN
basic_constraints:
- 'CA:TRUE'
basic_constraints_critical: yes
key_usage:
- keyCertSign
key_usage_critical: true
register: ca_csr
- name: Create self-signed CA certificate from CSR
community.crypto.x509_certificate:
path: /home/runner/ca-certificate.pem
csr_content: "{{ ca_csr.csr }}"
privatekey_path: /home/runner/ca-certificate.key
privatekey_passphrase: "{{ secret_ca_passphrase }}"
provider: selfsigned
# end creating self-signed ca certificate
# start creating server certificate
- name: Create private key for new certificate
community.crypto.openssl_privatekey:
path: /home/runner/certificate.key
size: 2048
run_once: true
- name: Create certificate signing request (CSR) for new certificate
community.crypto.openssl_csr_pipe:
privatekey_path: /home/runner/certificate.key
common_name: localhost
subject_alt_name:
- "DNS:localhost.localdomain"
- "DNS:myApp.cool"
key_usage:
- digitalSignature
- keyAgreement
- keyEncipherment
- nonRepudiation
extended_key_usage:
- serverAuth
run_once: true
register: csr
- name: Check whether certificate exists
stat:
path: /home/runner/certificate.pem
run_once: true
register: certificate_exists
- name: Read existing certificate if exists
slurp:
src: /home/runner/certificate.pem
when: certificate_exists.stat.exists
run_once: true
register: certificate
- name: Sign certificate with our CA
community.crypto.x509_certificate_pipe:
content: "{{ (certificate.content | b64decode) if certificate_exists.stat.exists else omit }}"
csr_content: "{{ csr.csr }}"
provider: ownca
ownca_path: /home/runner/ca-certificate.pem
ownca_privatekey_path: /home/runner/ca-certificate.key
ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
ownca_not_after: +3650d
ownca_not_before: "-1d"
run_once: true
register: certificate
- name: Write certificate file
copy:
dest: /home/runner/certificate.pem
content: "{{ certificate.certificate }}"
run_once: true
when: certificate is changed
# end creating server certificate
- name: Create a keystore for the given certificate/private key pair
community.general.java_keystore:
name: certificate
certificate_path: /home/runner/certificate.pem
private_key_path: /home/runner/certificate.key
password: secret
dest: /home/runner/certificate.jks
keystore_type: jks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment