#!/bin/bash
# Copyright (c) 2012 Red Hat, Inc.
#
# This software is licensed to you under the GNU General Public License,
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
# along with this software; if not, see
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
#
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
#
set -e

umask 0077

DIR=$(mktemp -d) || exit 1
HOST=`hostname -f`

if [ -z "$HOST" ]
then
  HOST=`hostname`
fi

PWDFILE="password"
SEEDFILE="seed"
INST_DIR='/etc/pki/pulp/qpid'
VALID="12"
CA_PATH=""
CA_KEY_PATH=""

echo ""
echo "Working in: $DIR"
echo ""

#
# ========== SETUP ============
#
# prompt user for install directory
echo ""
echo "Please specify a directory into which the created NSS database
and associated certificates will be installed."
echo ""
read -p "Enter a directory [$INST_DIR]:" ans
if [ "${#ans}" -gt 0 ]
then
  INST_DIR=`readlink -f "$ans"`
fi
echo $INST_DIR

# prompt user for the DB password
echo ""
echo "Please enter a password for the NSS database.  Generated if not specified."
echo ""
read -sp "Enter a password:" ans
if [ "${#ans}" -gt 0 ]
then
  DB_PASSWORD=$ans
else
  DB_PASSWORD=$(dd if=/dev/urandom bs=8192 count=1 | sha256sum | cut -d " " -f 1)
fi

# prompt user for existing CA.
# may contain both key & certificate
echo ""
echo "Please specify a CA.  Generated if not specified."
echo ""
read -p "Enter a path: " ans
if [ "${#ans}" -gt 0 ]
then
  CA_PATH=$ans
  echo "Using CA: $CA_PATH"
  echo ""
  echo "Please specify the CA key"
  while [ "${#CA_KEY_PATH}" -eq 0 ]; do
    read -p "Enter a path: " ans
    CA_KEY_PATH=$ans
  done
  echo "Using CA key: $CA_KEY_PATH"
fi

# prompt user for this server's hostname, defaulting to the local fqdn
echo ""
echo "Please enter the hostname clients will use to connect to the qpid server."
echo "If not specified, '$HOST' will be used."
echo ""
read -p "Enter a hostname:" ans
if [ "${#ans}" -gt 0 ]
then
  HOST=$ans
fi
echo ""
echo "Using hostname: [$HOST]"

#
# ========== PASSWORD ===========
#

# create the password file
echo "$DB_PASSWORD" > $DIR/$PWDFILE

echo ""
echo "Password file created."

#
# ========== DATABASE ============
#

# create the nss db
certutil -N -d $DIR -f $DIR/$PWDFILE

echo ""
echo "Database created."

#
# =========== CA =================
#

# create/import the CA cert
echo ""
if [ "${#CA_PATH}" -eq 0 ]
then
  echo "Creating CA certificate:"
  SUBJECT="CN=redhat,O=pulp,ST=Alabama,C=US"
  dd if=/dev/urandom of=$DIR/$SEEDFILE bs=8192 count=1
  certutil -S -d $DIR -n "ca" -s $SUBJECT -t "TC,," -f $DIR/$PWDFILE -z $DIR/$SEEDFILE -x -v $VALID
  echo "CA created"
else
  openssl pkcs12 -export -in $CA_PATH -inkey $CA_KEY_PATH -out $DIR/ca.p12 -name "ca" \
      -passout file:$DIR/$PWDFILE
  pk12util -d $DIR -n "ca" -i ca.p12 -w $DIR/$PWDFILE -k $DIR/$PWDFILE
  certutil -d $DIR -n "ca" -M -t "TCu,Cu,Tuw" -f $DIR/$PWDFILE
  echo "CA certificate: $CA_PATH, imported"
fi
certutil -L -d $DIR -n "ca" -a -o $DIR/ca.crt -f $DIR/$PWDFILE


#
# =========== BROKER =============
#

# create broker cert signing request
echo ""
echo "Creating BROKER certificate:"
SUBJECT="CN=$HOST,O=pulp,ST=Alabama,C=US"
dd if=/dev/urandom of=$DIR/$SEEDFILE bs=8192 count=1
certutil -R -d $DIR -s $SUBJECT -a -o $DIR/broker.req -f $DIR/$PWDFILE -z $DIR/$SEEDFILE

# sign the broker cert w/ CA
certutil -C -d $DIR -c "ca" -v $VALID -uV -m1 -a -i $DIR/broker.req -f $DIR/$PWDFILE \
    -o $DIR/broker.crt

# import the broker cert
certutil -A -d $DIR -n "broker" -t ",," -a -i $DIR/broker.crt

echo "Broker certificate created."

#
# =========== CLIENT =============
#

# create the nss db
mkdir $DIR/client
certutil -N -d $DIR/client -f $DIR/$PWDFILE

# create client cert signing request
echo ""
echo "Creating CLIENT certificate:"
SUBJECT="CN=client,O=pulp,ST=Alabama,C=US"
dd if=/dev/urandom of=$DIR/$SEEDFILE bs=8192 count=1
certutil -R -d $DIR/client -s $SUBJECT -a -o $DIR/client.req -f $DIR/$PWDFILE -z $DIR/$SEEDFILE

# sign the client cert w/ CA
certutil -C -d $DIR -c "ca" -v $VALID -uC -m2 -a -i $DIR/client.req -f $DIR/$PWDFILE \
    -o $DIR/client.crt

# import the client cert
certutil -A -d $DIR/client -n "client" -t ",," -a -i $DIR/client.crt
echo "Client certificate created."

# export client p12 bundle
pk12util -d $DIR/client -n "client" -o $DIR/client.p12 -w $DIR/$PWDFILE -W $DB_PASSWORD \
    -k $DIR/$PWDFILE -K $DB_PASSWORD

# using openssl, generate a key & cert using the p12.
openssl pkcs12 -in $DIR/client.p12 -nodes -out $DIR/client.crt -password file:$DIR/$PWDFILE

echo "Client key & certificate exported"

#
# =========== INSTALL =============
#

# clean unused artifacts
rm $DIR/broker.req
rm $DIR/client.req
rm $DIR/client/cert8.db
rm $DIR/client/key3.db
rm $DIR/client/secmod.db
rmdir $DIR/client

# create target directory and install files
mkdir -p $INST_DIR
mkdir -p $INST_DIR/nss
cp $DIR/*.crt $INST_DIR
cp $DIR/*.db $INST_DIR/nss
cp $DIR/$PWDFILE $INST_DIR/nss

# update perms
chmod 640 $INST_DIR/*.crt
chgrp apache $INST_DIR/*.crt
chmod 640 $INST_DIR/nss/*
chgrp qpidd $INST_DIR/nss/*

echo ""
echo "Artifacts copied to: $INST_DIR."
echo ""

#
# =========== CLEANUP =============
#

for f in broker.crt ca.crt cert8.db client.crt client.p12 key3.db password secmod.db seed; do
    rm $DIR/$f
done
rmdir $DIR

#
# =========== POST =============
#

echo "Recommended properties in qpidd.conf:"
echo "
auth=no
# SSL
require-encryption=yes
ssl-require-client-authentication=yes
ssl-cert-db=$INST_DIR/nss
ssl-cert-password-file=$INST_DIR/nss/password
ssl-cert-name=broker
ssl-port=5671
...
"
echo ""
echo "Recommended properties in /etc/pulp/server.conf:"
echo "
...
[messaging]
url: ssl://$HOST:5671
cacert: $INST_DIR/ca.crt
clientcert: $INST_DIR/client.crt

[tasks]
broker_url: qpid://$HOST:5671/
celery_require_ssl: true
cacert: /etc/pki/pulp/qpid/ca.crt
keyfile: /etc/pki/pulp/qpid/client.crt
certfile: /etc/pki/pulp/qpid/client.crt
# login_method:
"

echo ""
echo "Recommended properties in /etc/pulp/consumer/consumer.conf:"
echo "
...
[messaging]
scheme=ssl
port=5671
cacert=$INST_DIR/ca.crt
clientcert=$INST_DIR/client.crt
"

echo "
NOTES:
  [1] The location for qpidd.conf depends on the version of Qpid installed.
      For 0.24+: /etc/qpid/qpidd.conf.
      For all earlier versions: /etc/qpidd.conf.

  [2] The $INST_DIR/ca.crt and $INST_DIR/client.crt certificates will
      need to be manually copied to each consumer.

  [3] The $INST_DIR/ca.crt and $INST_DIR/client.crt certificates will
      need to be manually copied to each worker.

  [4] The NSS DB password written to $INST_DIR/nss/$PWDFILE
"
