[buildout]

extends =
  {{ template_logrotate_base }}

parts = 
  certificate-authority
  certificate-authority-server

[certificate-authority-parameters]
server-port = ${slap-configuration:configuration.ca-server-port}
server-https-port = ${slap-configuration:configuration.ca-server-https-port}
# Overrite this to set frontend or DNS URL (URL is used as CRL distribution point)
# Please set http not HTTPS scheme
crl-external-url = http://[${slap-configuration:ipv6-random}]:${:server-port}

[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
bin = ${buildout:directory}/bin
srv = ${buildout:directory}/srv
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
scripts = ${:etc}/run
services = ${:etc}/service
promises = ${:etc}/promise
ssl=${:etc}/ssl
ca-dir = ${directory:srv}/ca
ca-temp = ${:ca-dir}/tmp
client-body-temp-path = ${:ca-temp}/client_body_temp_path
proxy-temp-path = ${:ca-temp}/proxy_temp_path
fastcgi-temp-path = ${:ca-temp}/fastcgi_temp_path
uwsgi-temp-path = ${:ca-temp}/uwsgi_temp_path
scgi-temp-path = ${:ca-temp}/scgi_temp_path

[ca-directory]
recipe = slapos.cookbook:mkdirectory
root = ${directory:srv}/ssl
requests = ${:root}/requests
private = ${:root}/private
certs = ${:root}/certs
newcerts = ${:root}/newcerts
crl = ${:root}/crl

[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ openssl_executable_location }}
ca-dir = ${ca-directory:root}
requests-directory = ${ca-directory:requests}
wrapper = ${directory:services}/certificate_authority
ca-private = ${ca-directory:private}
ca-certs = ${ca-directory:certs}
ca-newcerts = ${ca-directory:newcerts}
ca-crl = ${ca-directory:crl}

[nginx-certificate-request-base]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:bin}/request-base-certificate
cert-file = ${ca-nginx-ssl-config:cert}
key-file = ${ca-nginx-ssl-config:key}
ca-cert = ${directory:ssl}/cacert.pem
parameters-extra = true
command-line = {{ certificate_request_bin }}
  --crt-file ${:cert-file}
  --key-file ${:key-file}
  --ca-url http://[${slap-configuration:ipv6-random}]:${certificate-authority-parameters:server-port}
  --ca-crt-file ${:ca-cert}

[nginx-certificate-request]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/request-server-certificate
command-line =
  ${nginx-certificate-request-base:wrapper-path}
  --cn nginx@certificate.authority
  --request

[ca-nginx-ssl-config]
# if ssl certificate is signed write to file so that zero-knowledge can read
recipe = plone.recipe.command
command = 
  if [ -s "${:key}" ] && [ -s "${:cert}" ]; then
  cat << EOF > ${:output}
  [ca-nginx-ssl]
  key=${:key}
  cert=${:cert}
  EOF
  fi
key = ${directory:ssl}/ca-cert.key
cert = ${directory:ssl}/ca-cert.crt
update-command = ${:command}
output = ${directory:etc}/ca-nginx-ssl.cfg
stop-on-error = true

[ca-nginx-ssl]
recipe = slapos.cookbook:zero-knowledge.read
file-path = ${ca-nginx-ssl-config:output}
# initials values are empty, the section https (ssl) in nginx config will be skipped
cert = 
key = 

[ca-nginx-conf-parameter]
ip = ${slap-configuration:ipv6-random}
port = ${certificate-authority-parameters:server-port}
https-port = ${certificate-authority-parameters:server-https-port}
pid-file = ${directory:run}/nginx-ca.pid
access-log = ${directory:log}/nginx-ca-access.log
error-log = ${directory:log}/nginx-ca-error.log
cert-file = ${ca-nginx-ssl:cert}
key-file = ${ca-nginx-ssl:key}
ca-conf = ${certificate-authority-conf:output}
workers-processes = 1
client-body-temp-path = ${directory:client-body-temp-path}
proxy-temp-path = ${directory:proxy-temp-path}
fastcgi-temp-path = ${directory:fastcgi-temp-path}
uwsgi-temp-path = ${directory:uwsgi-temp-path}
scgi-temp-path = ${directory:scgi-temp-path}
socket = ${certificate-authority-gunicorn:socket}

[ca-nginx-conf]
recipe = slapos.recipe.template:jinja2
template = {{ template_nginx_ca_conf }}
rendered = ${directory:etc}/nginx-ca.conf
mode = 0700
context =
  section parameter_dict ca-nginx-conf-parameter

[certificate-authority-conf]
recipe = collective.recipe.template
# Values here are intended to be changed in your instance. override this section
input = inline:
  ca-dir ${directory:ca-dir}
  # enable debug
  # debug
  # log-file ${directory:log}/ca-server.log
  subject ${slap-configuration:configuration.ca-subject}
  max-request-amount ${slap-configuration:configuration.max-request-amount}
  external-url ${certificate-authority-parameters:crl-external-url}
  # one year (in seconds)
  crt-life-time ${slap-configuration:configuration.crt-life-time}
  # crl-life-period correspond to about one week
  crl-life-period ${slap-configuration:configuration.crl-life-period}
  # ca-life-time = ca-life-period * crt-life-time
  ca-life-period ${slap-configuration:configuration.ca-life-period}
  # time before clean certificate on CA: 60*24*60*60
  crt-keep-time ${slap-configuration:configuration.crt-keep-time}

output = ${directory:etc}/ca.conf
mode = 700

[ca-nginx-graceful]
recipe = collective.recipe.template
input = inline:#!{{ dash_executable_location }}
  kill -HUP $(cat ${ca-nginx-conf-parameter:pid-file})

output = ${directory:scripts}/ca-server-graceful
mode = 700

[certificate-authority-gunicorn]
recipe = slapos.cookbook:wrapper
socket = ${directory:ca-dir}/ca.flaskserver.sock
command-line =  {{ gunicorn_bin }} caucase.wsgi:app -b unix:${:socket} -e CA_CONFIGURATION_FILE=${certificate-authority-conf:output} --error-logfile ${:log-file} --pid ${:pid-file} --capture-output --timeout 60 --threads 2 --log-level error --preload
log-file = ${directory:log}/ca-gunicorn-error.log
pid-file = ${directory:run}/ca-gunicorn.pid
wrapper-path = ${directory:services}/ca-gunicorn
#environment = #PATH=$${environ:PATH}:${git:location}/bin/
#  CA_CONFIGURATION_FILE=${certificate-authority-conf:output}
#  LANG=en_GB.UTF-8

[certificate-authority-server]
recipe = slapos.cookbook:wrapper
command-line = {{ ngix_location }}/sbin/nginx -p ${directory:ca-dir} -c ${ca-nginx-conf:rendered}
wrapper-path = ${directory:services}/ca-server
url = https://[${slap-configuration:ipv6-random}]:${certificate-authority-parameters:server-https-port}
insecure-url = ${certificate-authority-parameters:crl-external-url}
depends = 
  ${nginx-certificate-request:wrapper-path}
  ${certificate-authority-server-promise:filename}
  ${certificate-authority-https-server-promise:filename}
  ${ca-nginx-graceful:output}
  ${ca-certificate-renew-cron-entry:name}
  ${logrotate-ca-nginx:name}

[ca-server-certificate-renew]
recipe = collective.recipe.template
input = inline:
  #!{{ dash_executable_location }}

  d=$({{ openssl_executable_location }} x509 -enddate -noout -in ${nginx-certificate-request-base:cert-file} | cut -d'=' -f 2)
  cert_time=$(date -d "$d" +"%s")
  now=$(date +"%s")
  thresold=2592000  # 30*24*60*60  equivalent to one month in seconds
  remind=$(($cert_time - $now))

  if [ $remind -lt $thresold ]; then
    exec ${nginx-certificate-request-base:wrapper-path} --renew
    # run nginx grancefull restart to reload renewed certificates
    excec ${ca-nginx-graceful:output}
  fi

output = ${directory:bin}/server-certificate-renew
mode = 700

[ca-certificate-renew-cron-entry]
recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = ca-server-certificate-auto-renew
# check renew every-week
frequency = 5 4 * * 6
command = ${ca-server-certificate-renew:output}

[logrotate-ca-nginx]
< = logrotate-entry-base
name = certificate-authority-nginx-server
log = ${ca-nginx-conf-parameter:access-log} ${ca-nginx-conf-parameter:access-log}
post = {{ slapos_kill_bin }} --pidfile ${ca-nginx-conf-parameter:pid-file} -s USR1

[certificate-authority-server-promise]
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/${:filename}
filename = certificate-authority-server-listening-on-tcp
url = http://[${slap-configuration:ipv6-random}]:${certificate-authority-parameters:server-port}
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}

[certificate-authority-https-server-promise]
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/${:filename}
filename = certificate-authority-server-https-on-${certificate-authority-parameters:server-https-port}
url = https://[${slap-configuration:ipv6-random}]:${certificate-authority-parameters:server-https-port}
check-secure = 1
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}

[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}

configuration.ca-server-port = 8009
configuration.ca-server-https-port = 8010
# /CN=XXX is required
configuration.ca-subject = /C=Country/ST=State/L=City/OU=O-Unit/O=Company/CN=SlapOS Certificate Authority/emailAddress=xx@example.com
configuration.max-request-amount = 10
# one year (in seconds)
configuration.crt-life-time = 31536000
# crl-life-period correspond to about one week
configuration.crl-life-period = 0.02
# ca-life-period = ca-life-period * crt-life-time
configuration.ca-life-period = 10
# time before clean certificate on CA: 60*24*60*60
configuration.crt-keep-time = 5184000