#!/usr/bin/env bash
# note: Script uses -batch and -subj, instead of interactive prompts.
# default environment variable values
CERT_TEMP_DIR=./cert-tmp
CA_CERT=$CERT_TEMP_DIR/ca.crt
SVR_CERT=$CERT_TEMP_DIR/server.crt
SVR_KEY=$CERT_TEMP_DIR/server.key
# Use a different CA for client so we can test CA mismatch
CLI_CA_CERT=$CERT_TEMP_DIR/clica.crt
CLI_CERT=$CERT_TEMP_DIR/client.crt
CLI_KEY=$CERT_TEMP_DIR/client.key
SAN=DNS.1:localhost,IP.1:127.0.0.1

set -e

# Skip cert creation if the certs already exist
if [ -d $CERT_TEMP_DIR ]
then
    echo "Certificate directory $CERT_TEMP_DIR exists. Skipping certificate creation."
    exit
fi

echo "Creating test CA cert and client and server cert/key..."

# create cert directory and files
mkdir -p $CERT_TEMP_DIR
touch index.txt
touch index.txt.attr
echo 1000 > serial
cat <<EOF >$CERT_TEMP_DIR/openssl.conf
[ ca ]
default_ca = CA_default

[ CA_default ]
dir               = .
certs             = $CERT_TEMP_DIR
crl_dir           = $CERT_TEMP_DIR
new_certs_dir     = $CERT_TEMP_DIR
database          = ./index.txt
serial            = ./serial
crlnumber         = ./crlnumber
crl               = ./crl/intermediate-ca.crl
crl_extensions    = crl_ext
default_crl_days  = 30
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
default_bits        = 4096
distinguished_name  = req_distinguished_name
string_mask         = utf8only
default_md          = sha256

[ req_distinguished_name ]
countryName                    = Country Name (2 letter code)
stateOrProvinceName            = State or Province Name
localityName                   = Locality Name
0.organizationName             = Organization Name
organizationalUnitName         = Organizational Unit Name
commonName                     = Common Name

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
basicConstraints = CA:FALSE
nsCertType = client
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth

[ server_cert ]
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS.1:localhost,IP.1:127.0.0.1
EOF

# CA private key (unencrypted)
openssl genrsa -out $CERT_TEMP_DIR/ca.key 4096
# Certificate Authority (self-signed certificate)
openssl req -config $CERT_TEMP_DIR/openssl.conf -new -x509 -days 3650 -sha256 -key $CERT_TEMP_DIR/ca.key -extensions v3_ca -out $CA_CERT -subj "/CN=fake-server-ca"

# Server private key (unencrypted)
openssl genrsa -out $SVR_KEY 2048
# Server certificate signing request (CSR)
openssl req -config $CERT_TEMP_DIR/openssl.conf -new -sha256 -key $SVR_KEY -out $CERT_TEMP_DIR/server.csr -subj "/CN=fake-server"
# Certificate Authority signs CSR to grant a certificate
openssl ca -batch -config $CERT_TEMP_DIR/openssl.conf -extensions server_cert -days 365 -notext -md sha256 -in $CERT_TEMP_DIR/server.csr -out $SVR_CERT -cert $CA_CERT -keyfile $CERT_TEMP_DIR/ca.key

# Client CA private key (unencrypted)
openssl genrsa -out $CERT_TEMP_DIR/clica.key 4096
# Certificate Authority (self-signed certificate)
openssl req -config $CERT_TEMP_DIR/openssl.conf -new -x509 -days 3650 -sha256 -key $CERT_TEMP_DIR/clica.key -extensions v3_ca -out $CLI_CA_CERT -subj "/CN=fake-client-ca"

# Client private key (unencrypted)
openssl genrsa -out $CLI_KEY 2048
# Client certificate signing request (CSR)
openssl req -config $CERT_TEMP_DIR/openssl.conf -new -sha256 -key $CLI_KEY -out $CERT_TEMP_DIR/client.csr -subj "/CN=fake-client"
# Certificate Authority signs CSR to grant a certificate
openssl ca -batch -config $CERT_TEMP_DIR/openssl.conf -extensions usr_cert -days 365 -notext -md sha256 -in $CERT_TEMP_DIR/client.csr -out $CLI_CERT -cert $CLI_CA_CERT -keyfile $CERT_TEMP_DIR/clica.key

# Remove unneeded files
rm -f index.* serial* $CERT_TEMP_DIR/*ca.key $CERT_TEMP_DIR/*.csr $CERT_TEMP_DIR/*.pem $CERT_TEMP_DIR/openssl.conf

echo "*******************************************************************"
echo "WARNING: Generated credentials are self-signed and should be used for testing purposes only."
