Commit a45cf41a authored by Vincent Pelletier's avatar Vincent Pelletier Committed by Łukasz Nowak

stack/caucase: Update for caucase 0.9.2

Jerome Perrin:

Update stack/caucase/README.rst
parent 5cf13d50
caucase - CA for Users, CA for SErvices
Slapos integration
==================
This software release library provides macros to help you integrate caucase
into your software release.
``buildout.cfg`` declares caucase dependencies.
``caucase.jinja2.library`` declares jinja2 macros to deploy client and
server components of caucase.
Software
--------
This exposes the following sections:
- ``caucase-eggs``: Generate scripts to work with certificates using `caucase commands`_. In the software buildout's ``bin`` directory.
- ``caucase-jinja2-library``: Provide macros to generate sections that will use scripts created by ``caucase-eggs`` section.
.. _`caucase commands`: https://lab.nexedi.com/nexedi/caucase/blob/master/README.rst#commands
.. note::
``caucase-eggs`` needs to be listed in ``parts=`` of the software buildout or referenced by another installed part.
.. note:: ``caucase-jinja2-library`` needs to be referenced in an installed section using ``slapos.recipe.template`` from software buildout to make macros available in the the context of instance buildout. From ``software.cfg``:
.. code::
ini
[instance]
recipe = slapos.recipe.template:jinja2
import-list =
file caucase caucase-jinja2-library:target
Server
------
.. topic:: caucased(prefix, caucased_path, data_dir, netloc, service_auto_approve_count=0, key_len=None, promise=None)
This macro produces the following sections which you will want to reference sothey get instanciated:
- `<prefix>`: Creates `<caucased>` executable file to start `caucased`,
and `<data_dir>` directory for its data storage needs.
`caucased` will listend on `netloc`, which must be of the format
`hostname[:port]`, where hostname may be an IPv4 (ex: `127.0.0.1`), an IPv6
(ex: `[::1]`), or a domain name (ex: `localhost`). Port, when provided, must
be numeric. If port is not provided, it default to `80`.
If port is `80`, ``caucased`` will listen on `80` and `443` for given
hostname. This is *not* the recommended usage.
If port is not `80`, ``caucased`` will listen on it *and* its immediate next
higher port (ex: ``[::1]:8009`` will listen on both ``[::1]:8009`` and
``[::1]:8010``). This is the recommended usage.
- ``<prefix>-promise``: (only produced if ``<promise>`` is not None). Creates an
executable at the path given in ``<promise>``, which will attempt to connect to
``caucase`` server, and fail if it detects any anomaly (port not listening,
protocol error, certificate discrepancy...).
Client
------
.. topic:: ``rerequest(prefix, buildout_bin_directory, template, csr, key)``
- ``<prefix>``: Creates ``<rerequest>`` executable file to run ``caucase-rerequest``.
This script allows you to re-issue a CSR using a locally-generated private key.
.. topic:: ``updater(prefix, buildout_bin_directory, updater_path, url, data_dir, crt_path, ca_path, crl_path, key_path=None, on_renew=None, max_sleep=None, mode='service', template_csr_pem=None, openssl=None)``
- ``<prefix>``: Creates ``<updater>`` executable file to start ``caucase-updater``, and ``<data_dir>`` directory for its data storage needs.
``caucase-updater`` will monitor a key pair, corresponding CA certificate and CRL, and renew them before expiration.
.. note::
You can find more information about any argument mentioned above calling ``<command> --help <argument>``
[buildout] [buildout]
extends = extends =
buildout.hash.cfg buildout.hash.cfg
../../component/apache/buildout.cfg ../slapos.cfg
../../component/nginx/buildout.cfg ../../component/python-cryptography/buildout.cfg
../../component/curl/buildout.cfg
../../component/dash/buildout.cfg
../../component/openssl/buildout.cfg
../../component/bcrypt/buildout.cfg
../../stack/logrotate/buildout.cfg
parts = parts =
instance-caucase slapos-cookbook
[caucase-extra-eggs] [caucase-eggs]
recipe = zc.recipe.egg recipe = zc.recipe.egg
interpreter = python_ca
eggs = eggs =
gunicorn # for WSGI HTTP Server ${python-cryptography:egg}
futures caucase
caucase # certificate authority
${bcrypt:egg}
# are also required
plone.recipe.command
collective.recipe.template
slapos.toolbox
scripts = scripts =
slapos-kill
gunicorn
caucase caucase
caucase-cli caucase-probe
caucase-cliweb caucase-updater
caucased
caucased-manage
[template-ca-download-base] [caucase-jinja2-library-eggs]
recipe = hexagonit.recipe.download recipe = zc.recipe.egg
ignore-existing = true eggs =
download-only = true ${slapos-cookbook:eggs}
url = ${:_profile_base_location_}/${:filename} plone.recipe.command
mode = 0644 slapos.recipe.template
[template-httpd-auth-conf]
<= template-ca-download-base
[template-nginx-ca-conf]
<= template-ca-download-base
[template-caucase] [caucase-jinja2-library]
<= template-ca-download-base recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:filename} url = ${:_profile_base_location_}/${:filename}
mode = 0644
[template-authenticated-server] depends = ${caucase-jinja2-library-eggs:eggs}
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}
rendered = ${buildout:directory}/template-authenticated-server.cfg
context =
key apache_location apache:location
key template_logrotate_base template-logrotate-base:rendered
raw certificate_request_bin ${buildout:directory}/bin/caucase-cliweb
raw curl_executable_location ${curl:location}/bin/curl
raw dash_executable_location ${dash:location}/bin/dash
raw slapos_kill_bin ${buildout:directory}/bin/slapos-kill
raw template_httpd_auth_conf ${template-httpd-auth-conf:location}/${template-httpd-auth-conf:filename}
raw openssl_executable_location ${openssl:location}/bin/openssl
raw python_bin ${buildout:directory}/bin/${caucase-extra-eggs:interpreter}
[instance-caucase]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}
rendered = ${buildout:directory}/template.cfg
context =
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key nginx_location nginx:location
key template_logrotate_base template-logrotate-base:rendered
raw caucase_template ${template-caucase:location}/${template-caucase:filename}
raw curl_executable_location ${curl:location}/bin/curl
raw caucase_bin ${buildout:directory}/bin/caucase
raw certificate_request_bin ${buildout:directory}/bin/caucase-cliweb
raw template_nginx_ca_conf ${template-nginx-ca-conf:location}/${template-nginx-ca-conf:filename}
raw dash_executable_location ${dash:location}/bin/dash
raw slapos_kill_bin ${buildout:directory}/bin/slapos-kill
raw gunicorn_bin ${buildout:directory}/bin/gunicorn
raw openssl_executable_location ${openssl:location}/bin/openssl
raw python_bin ${buildout:directory}/bin/${caucase-extra-eggs:interpreter}
[versions] [versions]
Flask-User = 0.6.19 caucase = 0.9.2
apache-libcloud = 2.1.0
bcrypt = 3.1.3
caucase = 0.1.4
futures = 3.1.1
gitdb2 = 2.0.2
gunicorn = 19.7.1
slapos.recipe.template = 4.3
slapos.toolbox = 0.81
smmap2 = 2.0.3
PyJWT = 1.6.4
# Required by:
# caucase==0.1.4
Flask-AlchemyDumps = 0.0.10
# Required by:
# Flask-User==0.6.19
Flask-Login = 0.4.0
# Required by:
# Flask-User==0.6.19
Flask-Mail = 0.9.1
# Required by:
# Flask-AlchemyDumps==0.0.10
# Flask-User==0.6.19
Flask-SQLAlchemy = 2.3.2
# Required by:
# Flask-AlchemyDumps==0.0.10
Flask-Script = 2.0.6
# Required by:
# Flask-User==0.6.19
Flask-WTF = 0.14.2
# Required by:
# slapos.toolbox==0.71
GitPython = 2.1.5
# Required by:
# slapos.toolbox==0.71
PyRSS2Gen = 1.1
# Required by:
# Flask-AlchemyDumps==0.0.10
SQLAlchemy = 1.1.15
# Required by:
# Flask-AlchemyDumps==0.0.10
Unipath = 1.1
# Required by:
# Flask-WTF==0.14.2
WTForms = 2.1
# Required by:
# slapos.toolbox==0.71
atomize = 0.2.0
# Required by:
# Flask-Mail==0.9.1
blinker = 1.4
# Required by:
# slapos.toolbox==0.71
dnspython = 1.15.0
# Required by:
# slapos.toolbox==0.71
erp5.util = 0.4.51
# Required by:
# slapos.toolbox==0.71
feedparser = 5.2.1
# Required by:
# slapos.toolbox==0.71
lockfile = 0.12.2
# Required by:
# slapos.toolbox==0.71
passlib = 1.7.1
# Required by:
# caucase==0.1.4
pem = 17.1.0 pem = 17.1.0
# Required by:
# caucase==0.1.4
pyasn1 = 0.2.3
# Required by:
# caucase==0.1.4
pyasn1-modules = 0.0.9
# Required by:
# Flask-User==0.6.19
pycryptodome = 3.4.7
...@@ -13,22 +13,6 @@ ...@@ -13,22 +13,6 @@
# section inheritance (< = ...) are NOT supported (but you should really # section inheritance (< = ...) are NOT supported (but you should really
# not need these here). # not need these here).
[template-httpd-auth-conf] [caucase-jinja2-library]
filename = template-httpd-auth.conf.in filename = caucase.jinja2.library
md5sum = ea445b0a9b143d12b5700a71ac06293c md5sum = 7b8b0736a7c30a16c5f9f97e69052077
[template-nginx-ca-conf]
filename = ca-nginx.conf.in
md5sum = d8bebf1629aacffd619541f363687b4a
[template-authenticated-server]
filename = instance-auth-server.cfg.jinja2.in
md5sum = c005cfef03a0c2e504fcfa075e59934a
[template-caucase]
filename = instance-caucase.cfg.jinja2.in
md5sum = bab4cf56121f964eaad1abfba695d307
[instance-caucase]
filename = instance.cfg.in
md5sum = eb9d2ab646717d123b0472da5194d77f
worker_processes {{ parameter_dict['workers-processes'] }};
pid {{ parameter_dict['pid-file'] }};
error_log {{ parameter_dict['error-log'] }};
daemon off;
events {
worker_connections 1024;
accept_mutex off;
}
http {
# include mime.types;
default_type application/octet-stream;
access_log {{ parameter_dict['access-log'] }} combined;
client_max_body_size 10M;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
sendfile on;
upstream app_server {
# for UNIX domain socket setups
server unix:{{ parameter_dict['socket'] }} fail_timeout=0;
}
{% if parameter_dict['cert-file'] and parameter_dict['key-file'] -%}
server {
listen [{{ parameter_dict['ip'] }}]:{{ parameter_dict['https-port'] }} ssl;
server_name _;
ssl_certificate {{ parameter_dict['cert-file'] }};
ssl_certificate_key {{ parameter_dict['key-file'] }};
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 90s;
client_body_temp_path {{ parameter_dict['client-body-temp-path'] }};
proxy_temp_path {{ parameter_dict['proxy-temp-path'] }};
fastcgi_temp_path {{ parameter_dict['fastcgi-temp-path'] }};
uwsgi_temp_path {{ parameter_dict['uwsgi-temp-path'] }};
scgi_temp_path {{ parameter_dict['scgi-temp-path'] }};
location / {
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Host $http_host;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
send_timeout 90;
proxy_pass http://app_server;
}
}
{% endif -%}
server {
listen [{{ parameter_dict['ip'] }}]:{{ parameter_dict['port'] }};
server_name _;
keepalive_timeout 90s;
client_body_temp_path {{ parameter_dict['client-body-temp-path'] }};
proxy_temp_path {{ parameter_dict['proxy-temp-path'] }};
fastcgi_temp_path {{ parameter_dict['fastcgi-temp-path'] }};
uwsgi_temp_path {{ parameter_dict['uwsgi-temp-path'] }};
scgi_temp_path {{ parameter_dict['scgi-temp-path'] }};
location ~ ^(/admin|/user) {
# http is not used for /admin and /user
}
location / {
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header Host $http_host;
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
send_timeout 90;
proxy_pass http://app_server;
}
}
}
{% macro caucased(
prefix,
buildout_bin_directory,
caucased_path,
data_dir,
netloc,
service_auto_approve_count=0,
user_auto_approve_count=1,
key_len=None,
backup_dir=None,
promise=None
) -%}
[{{ prefix }}-directory]
recipe = slapos.cookbook:mkdirectory
data-dir = {{ data_dir }}
mode = 0750
[{{ prefix }}]
recipe = slapos.cookbook:wrapper
wrapper-path = {{ caucased_path }}
command-line = '{{ buildout_bin_directory }}/caucased'
--db '${ {{- prefix }}-directory:data-dir}/caucase.sqlite'
--server-key '${ {{- prefix }}-directory:data-dir}/server.key.pem'
--netloc '{{ netloc }}'
{% if key_len %}--key-len '{{ key_len }}' {%- endif %}
{% if backup_dir %}--backup-directory {{ backup_dir }} {%- endif %}
--service-auto-approve-count '{{ service_auto_approve_count }}'
--user-auto-approve-count '{{ user_auto_approve_count }}'
--lock-auto-approve-count
{% if promise -%}
[{{ prefix }}-promise]
recipe = slapos.cookbook:wrapper
wrapper-path = {{ promise }}
command-line = '{{ buildout_bin_directory }}/caucase-probe' 'http://{{ netloc }}'
{%- endif %}
{%- endmacro %}
{% macro updater(
prefix,
buildout_bin_directory,
updater_path,
url,
data_dir,
crt_path,
ca_path,
crl_path,
key_path=None,
on_renew=None,
max_sleep=None,
mode='service',
template_csr_pem=None,
openssl=None
) -%}
[{{ prefix }}-directory]
recipe = slapos.cookbook:mkdirectory
data-dir = {{ data_dir }}
{% if template_csr_pem -%}
[{{ prefix }}-provided-csr-content]
content = {{ dumps(template_csr_pem) }}
[{{ prefix }}-provided-csr]
recipe = slapos.recipe.template:jinja2
mode = 644
template = inline:{{ '{{ content }}' }}
rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem
context = key content {{ prefix }}-provided-csr-content:content
{{ rerequest(
prefix=prefix ~ '-csr',
template='${provided-csr:rendered}',
csr='${:csr}',
key='${apache-conf-ssl:key}',
)}}
{%- else -%}
[{{ prefix }}-csr]
recipe = plone.recipe.command
command = '{{ openssl }}' req -newkey rsa:2048 -batch -new -nodes -subj /CN=example.com -keyout '{{ key_path or crt_path }}' -out '${:csr}'
{%- endif %}
csr = ${ {{- prefix }}-directory:data-dir}/good.csr.pem
[{{ prefix }}]
recipe = slapos.cookbook:wrapper
wrapper-path = {{ updater_path }}
command-line = '{{ buildout_bin_directory }}/caucase-updater'
--ca-url '{{ url }}'
--cas-ca '${ {{- prefix }}-directory:data-dir}/cas.crt.pem'
--mode '{{ mode }}'
--csr '${ {{- prefix }}-csr:csr}'
--crt '{{ crt_path }}'
--ca '{{ ca_path }}'
--crl '{{ crl_path }}'
{% if key_path %}--key '{{ key_path }}' {%- endif %}
--on-renew '{{ on_renew }}'
{% if max_sleep %}--max-sleep '{{ max_sleep }}' {%- endif %}
{%- endmacro %}
{% macro rerequest(prefix, buildout_bin_directory, template, csr, key) -%}
[{{ prefix }}]
recipe = plone.recipe.command
command = '{{ buildout_bin_directory }}/caucase-rerequest' --template '{{ template }}' --csr '{{ csr }}' --key '{{ key }}'
{%- endmacro %}
[buildout]
extends =
{{ template_logrotate_base }}
parts =
authenticated-httpd-server
[authenticated-server-parameters]
ca-url =
common-name = instance@${slap-configuration:instance-title}
server-port = 8286
custom-httpd-file =
web-directory = ${directory:document-root}
[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
bin = ${buildout:directory}/bin
srv = ${buildout:directory}/srv
var = ${buildout:directory}/var
ssl = ${:etc}/ssl
run = ${:var}/run
log = ${:var}/log
scripts = ${:etc}/run
services = ${:etc}/service
promises = ${:etc}/promise
document-root = ${:srv}/private
[certificate-request-base]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:bin}/request-instance-certificate
cert-file = ${directory:ssl}/instance.cert.pem
key-file = ${directory:ssl}/instance.key.pem
ca-cert = ${directory:ssl}/cacert.pem
command-line = {{ certificate_request_bin }}
--crt-file ${:cert-file}
--key-file ${:key-file}
--ca-url ${authenticated-server-parameters:ca-url}
--ca-crt-file ${:ca-cert}
--no-check-certificate
# XXX - using --no-check-certificate which is insecure with https.
[server-certificate-request]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:scripts}/request-instance-certificate
command-line =
${certificate-request-base:wrapper-path}
--cn ${authenticated-server-parameters:common-name}
--request
[authenticated-httpd-conf-parameter]
ip = ${slap-configuration:ipv6-random}
port = ${authenticated-server-parameters:server-port}
pid-file = ${directory:run}/httpd-auth.pid
dav-lock = ${directory:var}/DavLockdb
access-log = ${directory:log}/httpd-auth-access.log
error-log = ${directory:log}/httpd-auth-error.log
cert-file = ${certificate-request-base:cert-file}
key-file = ${certificate-request-base:key-file}
ca-cert = ${certificate-request-base:ca-cert}
url = https://[${:ip}]:${:port}
private = ${authenticated-server-parameters:web-directory}
httpd-include-file = ${authenticated-server-parameters:custom-httpd-file}
crl =
[authenticated-httpd-conf]
recipe = slapos.recipe.template:jinja2
template = {{ template_httpd_auth_conf }}
rendered = ${directory:etc}/httpd-auth.conf
mode = 0744
context =
section parameter_dict authenticated-httpd-conf-parameter
[authenticated-httpd-graceful]
recipe = collective.recipe.template
input = inline:
#!{{ dash_executable_location }}
kill -USR1 $(cat ${authenticated-httpd-conf-parameter:pid-file})
output = ${directory:scripts}/authenticated-httpd-graceful
mode = 700
[authenticated-httpd-server]
recipe = slapos.cookbook:wrapper
command-line = {{ apache_location }}/bin/httpd -f ${authenticated-httpd-conf:rendered} -DFOREGROUND
wrapper-path = ${directory:services}/authenticated-httpd-server
wait-for-files =
${certificate-request-base:cert-file}
${certificate-request-base:key-file}
${certificate-request-base:ca-cert}
url = ${authenticated-httpd-conf-parameter:url}
depends =
${authenticated-httpd-promise:filename}
${authenticated-httpd-graceful:output}
${server-certificate-request:wrapper-path}
${logrotate-authenticated-httpd:name}
${certificate-renew-cron-entry:name}
[certificate-renew]
recipe = collective.recipe.template
input = inline:
#!{{ dash_executable_location }}
d=$({{ openssl_executable_location }} x509 -enddate -noout -in ${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 ${certificate-request-base:wrapper-path} --renew
exec ${authenticated-httpd-graceful:output}
fi
output = ${directory:bin}/certificate-renew
mode = 700
[certificate-renew-cron-entry]
recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = certificate-auto-renew
frequency = 5 6 * * 6
command = ${certificate-renew:output}
[logrotate-authenticated-httpd]
< = logrotate-entry-base
name = authenticated-httpd-server
log = ${authenticated-httpd-conf-parameter:access-log} ${authenticated-httpd-conf-parameter:access-log}
post = {{ slapos_kill_bin }} --pidfile ${authenticated-httpd-conf-parameter:pid-file} -s USR1
[authenticated-httpd-promise]
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/${:filename}
filename = authenticated-httpd-is-available
url = ${authenticated-httpd-conf-parameter:url}
check-secure = 1
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}
cert-file = ${certificate-request-base:cert-file}
key-file = ${certificate-request-base:key-file}
ca-cert-file = ${certificate-request-base:ca-cert}
[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}
{% set part_list = [] -%}
{% set ipv6 = (ipv6 | list)[0] -%}
{% set default_subject = '/C=FR/O=Company/CN=SlapOS Certificate Authority/emailAddress=xx@example.com' -%}
{% if slapparameter_dict is not defined -%}
{% set slapparameter_dict = {} -%}
{% endif -%}
[ca-parameters]
server-port = {{ slapparameter_dict.get('server-port', 8009) }}
server-https-port = {{ slapparameter_dict.get('server-https-port', 8010) }}
ipv6 = {{ ipv6 }}
# Overrite this to set frontend or DNS URL (URL is used as CRL distribution point)
# Please set http not HTTPS scheme
crl-external-url = {{ slapparameter_dict.get('external-url', 'http://[${:ipv6}]:${:server-port}') }}
# /CN=XXX is required and should be unique
ca-subject = {{ slapparameter_dict.get('ca-subject', default_subject) }}
# Number of pending csr to accept
max-request-amount = {{ slapparameter_dict.get('max-request-amount', 10) }}
# one year (in seconds)
crt-life-time = {{ slapparameter_dict.get('crt-life-time', 31536000) }}
# crl-life-period correspond to about one week
crl-life-period = {{ slapparameter_dict.get('crl-life-period', 0.02) }}
# ca-life-period = ca-life-period * crt-life-time
ca-life-period = {{ slapparameter_dict.get('ca-life-period', 10) }}
# time before clean certificate on CA: 60*24*60*60
crt-keep-time = {{ slapparameter_dict.get('crt-keep-time', 5184000) }}
# number of csr to sign automaticaly, minimum value is 1
{% if int(slapparameter_dict.get('auto-sign-csr-amount', 1)) < 1 -%}
auto-sign-csr-amount = 1
{% else -%}
auto-sign-csr-amount = {{ slapparameter_dict.get('auto-sign-csr-amount', 1) }}
{% endif -%}
[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
[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
command-line = {{ certificate_request_bin }}
--crt-file ${:cert-file}
--key-file ${:key-file}
--ca-url http://[${ca-parameters:ipv6}]:${ca-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 = ${ca-parameters:ipv6}
port = ${ca-parameters:server-port}
https-port = ${ca-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 = ${caucase-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 = ${caucase-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
[caucase-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 ${ca-parameters:ca-subject}
max-request-amount ${ca-parameters:max-request-amount}
external-url ${ca-parameters:crl-external-url}
# one year (in seconds)
crt-life-time ${ca-parameters:crt-life-time}
# crl-life-period correspond to about one week
crl-life-period ${ca-parameters:crl-life-period}
# ca-life-time = ca-life-period * crt-life-time
ca-life-period ${ca-parameters:ca-life-period}
# time before clean certificate on CA: 60*24*60*60
crt-keep-time ${ca-parameters:crt-keep-time}
# number of csr to sign automaticaly
auto-sign-csr-amount ${ca-parameters:auto-sign-csr-amount}
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
[caucase-gunicorn]
recipe = slapos.cookbook:wrapper
socket = ${directory:ca-dir}/ng.sock
command-line = {{ gunicorn_bin }} caucase.wsgi:app -b unix:${:socket} -e CA_CONFIGURATION_FILE=${caucase-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
[caucase-server]
recipe = slapos.cookbook:wrapper
command-line = {{ nginx_location }}/sbin/nginx -p ${directory:ca-dir} -c ${ca-nginx-conf:rendered}
wrapper-path = ${directory:services}/caucase-server
url = https://[${ca-parameters:ipv6}]:${ca-parameters:server-https-port}
http-url = ${ca-parameters:crl-external-url}
depends =
${nginx-certificate-request:wrapper-path}
${caucase-https-server-promise:filename}
${ca-nginx-graceful:output}
${ca-certificate-renew-cron-entry:name}
${logrotate-ca-nginx:name}
# Disabled to be re-implemented.
# ${caucase-server-promise:filename}
[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
time = weekly
# 2592000 = 30*24*60*60 equivalent to one month in seconds
command = ${nginx-certificate-request-base:wrapper-path} --renew --threshold 2592000 --on-renew="${ca-nginx-graceful:output}"
[logrotate-ca-nginx]
< = logrotate-entry-base
name = caucase-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
# This promise is disabled as it requires user to take action so the buildout
# will fail for way too long, and overload master. Please reimplement on a
# better way
#[caucase-server-promise]
#recipe = slapos.cookbook:check_url_available
#path = ${directory:promises}/${:filename}
#filename = caucase-server-listening-on-tcp
#url = http://[${ca-parameters:ipv6}]:${ca-parameters:server-port}
#dash_path = {{ dash_executable_location }}
#curl_path = {{ curl_executable_location }}
#
[caucase-https-server-promise]
recipe = slapos.cookbook:check_url_available
path = ${directory:promises}/${:filename}
filename = caucase-server-https-on-${ca-parameters:server-https-port}
url = https://[${ca-parameters:ipv6}]:${ca-parameters:server-https-port}
check-secure = 1
dash_path = {{ dash_executable_location }}
curl_path = {{ curl_executable_location }}
{% if publish_parameter is defined and publish_parameter == 'yes' -%}
[publish-connection-parameter]
recipe = slapos.cookbook:publish.serialised
http-url = ${caucase-server:http-url}
https-url = ${caucase-server:url}
init-user = admin
{% do part_list.append('publish-connection-parameter') -%}
{% endif -%}
[buildout]
extends =
{{ template_logrotate_base }}
parts =
caucase-server
# Complete parts with sections
{{ part_list | join('\n ') }}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[buildout]
parts =
switch-softwaretype
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[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}
[dynamic-template-caucase]
recipe = slapos.recipe.template:jinja2
filename = ${:_buildout_section_name_}.cfg
rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/${:filename}
template = {{ caucase_template }}
extensions = jinja2.ext.do
extra-context =
context =
key ipv4 slap-configuration:ipv4
key ipv6 slap-configuration:ipv6
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key slapparameter_dict slap-configuration:configuration
raw gunicorn_bin {{ gunicorn_bin }}
raw template_logrotate_base {{ template_logrotate_base }}
raw certificate_request_bin {{ certificate_request_bin }}
raw template_nginx_ca_conf {{ template_nginx_ca_conf }}
raw nginx_location {{ nginx_location }}
raw slapos_kill_bin {{ slapos_kill_bin }}
raw dash_executable_location {{ dash_executable_location }}
raw curl_executable_location {{ curl_executable_location }}
raw publish_parameter yes
[switch-softwaretype]
recipe = slapos.cookbook:softwaretype
default = ${dynamic-template-caucase:rendered}
Listen [{{ parameter_dict['ip'] }}]:{{ parameter_dict['port'] }}
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule mime_module modules/mod_mime.so
LoadModule dir_module modules/mod_dir.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule alias_module modules/mod_alias.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
LoadModule env_module modules/mod_env.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
ServerAdmin admin@
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
PidFile "{{ parameter_dict['pid-file'] }}"
ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
CustomLog "{{ parameter_dict['access-log'] }}" combined
# SSL Configuration
Define SSLConfigured
SSLCertificateFile {{ parameter_dict['cert-file'] }}
SSLCertificateKeyFile {{ parameter_dict['key-file'] }}
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLRandomSeed startup /dev/urandom 256
SSLRandomSeed connect builtin
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
SSLEngine On
<Directory />
Options FollowSymLinks
AllowOverride None
Allow from all
</Directory>
<VirtualHost *:{{ parameter_dict['port'] }}>
DavLockDB {{ parameter_dict['dav-lock'] }}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
{% if parameter_dict['crl'] -%}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
{%- endif %}
Alias / {{ parameter_dict['private'] }}/
<Directory {{ parameter_dict['private'] }}>
DirectoryIndex disabled
DAV On
Options Indexes FollowSymLinks
Order Allow,Deny
Allow from all
</Directory>
</VirtualHost>
{% if parameter_dict.get('httpd-include-file', '') -%}
# Custom apache configuration here
Include {{ parameter_dict['httpd-include-file'] }}
{% endif -%}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment