Commit 4dacf9a8 authored by Alain Takoudjou's avatar Alain Takoudjou

Use certificate authority in erp5 stack, remove custom from slapos-master

This commit allow to use certificate authority stack in erp5 stack to
request apache certificate (in instance-balancer).
if this is enabled (parameter: "certificate-authority": {"enable": true, ...}
instance erp5 will request one more partition containing the CA, then publish the ca-url to balancer
Instead of generated self-signed certificate in balancer, certificate will be signed on CA.

The modification also allow to use the certificate in apache.conf for authentication (SSLVerifyClient require)
by default it True in erp5 stack, the parameter "balancer": {"ssl-client-verify": false} will disable it

- It's also possible to set a custom backend_path for each zope instance.
"zope-partition-dict": {"service": {"backend-path": "/%(site-id)s/portal_slap", ...}}
- If "ssl-client-verify" is false,
it will be possible to add "ssl-authentication": true in zope-dict which will enable authentication on a specific zope service.
Both features was customized in slapos-master sr, and was removed to be reimplemented in erp5 stack.
parent 1a4976ba
......@@ -109,11 +109,13 @@ SSLProxyEngine On
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
{% if parameter_dict['ca-cert'] -%}
SSLVerifyClient require
SSLVerifyClient optional
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 %}
{%- endif %}
ErrorLog "{{ parameter_dict['error-log'] }}"
......@@ -128,12 +130,27 @@ CustomLog "{{ parameter_dict['access-log'] }}" combined
</Directory>
RewriteEngine On
{% for port, _, backend in parameter_dict['backend-list'] -%}
{% for port, _, backend, enable_authentication in parameter_dict['backend-list'] -%}
{% for ip in parameter_dict['ip-list'] -%}
Listen {{ ip }}:{{ port }}
{% endfor -%}
<VirtualHost *:{{ port }}>
SSLEngine on
{% if enable_authentication and parameter_dict['ca-cert'] -%}
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 %}
LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
# We would like to separate the the authentificated logs.
ErrorLog "{{ parameter_dict['log-dir'] }}/apache-service-error.log"
CustomLog "{{ parameter_dict['log-dir'] }}/apache-service-access.log" combined
{% endif -%}
RewriteRule ^/(.*) {{ backend }}/$1 [L,P]
</VirtualHost>
{% endfor -%}
......@@ -190,5 +190,5 @@ make-targets =
[template-apache-backend-conf]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/apache-backend.conf.in
md5sum = feef079241bda3407b7ceed5876cb61f
md5sum = 43a983aa8603a84362f9fc2542f4228d
mode = 640
......@@ -46,6 +46,9 @@ class Recipe(GenericBaseRecipe):
('kumofs_url', 'kumofs-url'),
('smtp_url', 'smtp-url'),
)),
('portal_certificate_authority', (
('certificate_authority_url', 'certificate-authority-url'),
)),
):
promise_parser.add_section(section_name)
for internal_id, option_id in option_id_list:
......
{# This file configures apache to redirect requests from ports to specific urls.
# It provides SSL support for server and optionaly for client.
#
# All parameters are given through the `parameter_dict` variable, see the
# list entries :
#
# parameter_dict = {
# # The path given to "PidFile"
# "pid-file": "<file_path>",
#
# # The number given to "TimeOut"
# "timeout": 300,
#
# # The path given to "SSLCertificateFile"
# "cert": "<file_path>",
#
# # The path given to "SSLCertificateKeyFile"
# "key": "<file_path>",
#
# # The value given to "SSLCipherSuite" (can be empty)
# "cipher": "",
#
# # The path given to "SSLSessionCache shmcb:<folder_path>(512000)"
# "ssl-session-cache": "<folder_path>",
#
# # The path given to "SSLCACertificateFile" (can be empty)
# # If this value is not empty, it enables client certificate check.
# # (Enabling "SSLVerifyClient require")
# "ca-cert": "<file_path>",
#
# # The path given to "SSLCARevocationFile" (used if ca-cert is not
# # empty)
# "crl": "<file_path>",
#
# # The path given to "ErrorLog"
# "error-log": "<file_path>",
#
# # The path given to "AccessLog"
# "access-log": "<file_path>",
#
# # The list of ip which apache will listen to.
# "ip-list": [
# "0.0.0.0",
# "[::1]",
# ],
#
# # The list of backends which apache should redirect to.
# "backend-list": [
# # (port, unused, internal_scheme)
# (8000, _, "http://10.0.0.10:8001"),
# (8002, _, "http://10.0.0.10:8003"),
# ],
# }
#
# This sample of `parameter_dict` will make apache listening to :
# - 0.0.0.0:8000 redirecting internaly to http://10.0.0.10:8001
# - [::1]:8000 redirecting internaly to http://10.0.0.10:8001
# - 0.0.0.0:8002 redirecting internaly to http://10.0.0.10:8003
# - [::1]:8002 redirecting internaly to http://10.0.0.10:8003
-#}
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 log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.so
AddOutputFilterByType DEFLATE text/cache-manifest text/html text/plain text/css application/hal+json application/json application/x-javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml application/x-font-ttf application/font-woff application/font-woff2 application/x-font-opentype
PidFile "{{ parameter_dict['pid-file'] }}"
ServerAdmin admin@
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
TimeOut {{ parameter_dict['timeout'] }}
SSLCertificateFile {{ parameter_dict['cert'] }}
SSLCertificateKeyFile {{ parameter_dict['key'] }}
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
{% if parameter_dict['cipher'] -%}
SSLCipherSuite {{ parameter_dict['cipher'] }}
{% else %}
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
{%- endif %}
SSLSessionCache shmcb:{{ parameter_dict['ssl-session-cache'] }}(512000)
SSLProxyEngine On
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
{% if parameter_dict['ca-cert'] -%}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
{%- endif %}
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
<Directory />
Options FollowSymLinks
AllowOverride None
Allow from all
</Directory>
RewriteEngine On
{% for port, _, backend, enable_authentication in parameter_dict['backend-list'] -%}
{% for ip in parameter_dict['ip-list'] -%}
Listen {{ ip }}:{{ port }}
{% endfor -%}
<VirtualHost *:{{ port }}>
{% if enable_authentication -%}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['shared-ca-cert'] }}
SSLCARevocationPath {{ parameter_dict['shared-crl'] }}
LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
# We would like to separate the the authentificated logs.
ErrorLog "{{ parameter_dict['log-dir'] }}/apache-service-error.log"
CustomLog "{{ parameter_dict['log-dir'] }}/apache-service-access.log" combined
{% endif -%}
SSLEngine on
RewriteRule ^/(.*) {{ backend }}/$1 [L,P]
</VirtualHost>
{% endfor -%}
......@@ -13,17 +13,6 @@
# Substitution (${...:...}), extension ([buildout] extends = ...) and
# section inheritance (< = ...) are NOT supported (but you should really
# not need these here).
[template-erp5]
filename = instance-erp5.cfg.in
md5sum = 1489091851f27c41243eeaa4967cc91c
[template-balancer]
filename = instance-balancer.cfg.in
md5sum = a410f10fe9766c9321ffd7b18ace5a4f
[template-apache-backend-conf]
filename = apache-backend.conf.in
md5sum = ea77222f440bb72fee4939fe1b72976e
[template-create-erp5-site-real]
filename = instance-create-erp5-site-real.cfg.in
......
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{% set shared_ca_path = slapparameter_dict['shared-certificate-authority-path'] -%}
{#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
per partition. No more (undefined result), no less (IndexError).
-#}
# TODO: insert varnish between apache & haproxy.
# And think of a way to specify which urls goe through varnish, which go
# directly to haproxy. (maybe just passing literal configuration file chunk)
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set apache_ip_list = [ipv4] -%}
{% if ipv6_set -%}
{% set ipv6 = (ipv6_set | list)[0] -%}
{% do apache_ip_list.append('[' ~ ipv6 ~ ']') -%}
{% endif -%}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
mode = 644
[simplefile]
< = jinja2-template-base
template = inline:{{ '{{ content }}' }}
{% macro simplefile(section_name, file_path, content, mode='') -%}
{% set content_section_name = section_name ~ '-content' -%}
[{{ content_section_name }}]
content = {{ dumps(content) }}
[{{ section(section_name) }}]
< = simplefile
rendered = {{ file_path }}
context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}
{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
runner-path = ${directory:services}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = {{ ipv4 }}
{% endif -%}
{% set haproxy_dict = {} -%}
{% set apache_dict = {} -%}
{% set next_port = itertools.count(slapparameter_dict['tcpv4-port']).next -%}
{% for family_name, parameter_id_list in sorted(
slapparameter_dict['zope-family-dict'].iteritems()) -%}
{% set zope_family_address_list = [] -%}
{% set has_webdav = [] -%}
{% for parameter_id in parameter_id_list -%}
{% set zope_address_list = slapparameter_dict[parameter_id] -%}
{% for zope_address, maxconn, webdav in zope_address_list -%}
{% if webdav -%}
{% do has_webdav.append(None) %}
{% endif -%}
{% if use_ipv6 -%}
{% set current_port = next_port() -%}
[{{ section('zope-tunnel-' ~ current_port) }}]
< = zope-tunnel-base
base-name = {{ 'zeo-tunnel-' ~ current_port }}
ipv4-port = {{ current_port }}
ipv6-port = {{ zope_address.split(']:')[1] }}
ipv6 = {{ zope_address.split(']:')[0][1:] }}
{% set zope_effective_address = ipv4 ~ ":" ~ current_port -%}
{% else -%}
{% set zope_effective_address = zope_address -%}
{% endif -%}
{% do zope_family_address_list.append((zope_effective_address, maxconn, webdav)) -%}
{% endfor -%}
{% endfor -%}
{# Make rendering fail artificially if any family has no known backend.
# This is useful as haproxy's hot-reconfiguration mechanism is
# supervisord-incompatible.
# As jinja2 postpones KeyError until place-holder value is actually used,
# do a no-op getitem.
-#}
{% do zope_family_address_list[0][0] -%}
{% set haproxy_port = next_port() -%}
{% do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{% if has_webdav -%}
{% set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
{% set external_scheme = 'webdavs' -%}
{% else %}
{% set internal_scheme = 'http' -%}
{% set external_scheme = 'https' -%}
{% endif -%}
{% set backend_path = slapparameter_dict['backend-path-dict'][family_name] -%}
{% set ssl_authentication = slapparameter_dict['ssl-authentication-dict'][family_name] -%}
{% do apache_dict.__setitem__(family_name, (next_port(), external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ backend_path, ssl_authentication)) -%}
{% endfor -%}
[haproxy-cfg-parameter-dict]
socket-path = ${directory:run}/haproxy.sock
server-check-path = {{ dumps(slapparameter_dict['haproxy-server-check-path']) }}
backend-dict = {{ dumps(haproxy_dict) }}
ip = {{ ipv4 }}
[haproxy-cfg]
< = jinja2-template-base
template = {{ parameter_dict['template-haproxy-cfg'] }}
rendered = ${directory:etc}/haproxy.cfg
context = section parameter_dict haproxy-cfg-parameter-dict
extensions = jinja2.ext.do
[{{ section('haproxy') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/haproxy
command-line = "{{ parameter_dict['haproxy'] }}/sbin/haproxy" -f "${haproxy-cfg:rendered}"
{# TODO: build socat and wrap it as "${directory:bin}/haproxy-ctl" to connect to "${haproxy-cfg-parameter-dict:socket-path}" #}
[apache-conf-ssl]
cert = ${directory:apache-conf}/apache.crt
key = ${directory:apache-conf}/apache.pem
ca-cert = ${directory:apache-conf}/ca.crt
crl = ${directory:apache-conf}/crl.pem
[apache-conf-parameter-dict]
backend-list = {{ dumps(apache_dict.values()) }}
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
log-dir = ${directory:log}
# Apache 2.4's default value (60 seconds) can be a bit too short
timeout = 300
# Basic SSL server configuration
cert = ${apache-ssl:cert}
key = ${apache-ssl:key}
cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache
# Client x509 auth
ca-cert = ${apache-ssl-client:cert}
crl = ${apache-ssl-client:crl}
{% if shared_ca_path -%}
shared-ca-cert = {{ shared_ca_path }}/cacert.pem
shared-crl = {{ shared_ca_path }}/crl
{%- endif %}
[apache-conf]
< = jinja2-template-base
template = {{ parameter_dict['template-apache-conf'] }}
rendered = ${directory:apache-conf}/apache.conf
context = section parameter_dict apache-conf-parameter-dict
[{{ section('apache') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND
[{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/apache
hostname = {{ ipv4 }}
port = {{ apache_dict.values()[0][0] }}
[publish]
recipe = slapos.cookbook:publish.serialised
{% for family_name, (apache_port, scheme, _, _) in apache_dict.items() -%}
{{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}
[apache-ssl]
{% if ssl_parameter_dict.get('key') -%}
key = ${apache-ssl-key:rendered}
cert = ${apache-ssl-cert:rendered}
{{ simplefile('apache-ssl-key', '${apache-conf-ssl:key}', ssl_parameter_dict['key']) }}
{{ simplefile('apache-ssl-cert', '${apache-conf-ssl:cert}', ssl_parameter_dict['cert']) }}
{% else %}
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
{%- endif %}
[apache-ssl-client]
{% if ssl_parameter_dict.get('ca-cert') -%}
cert = ${apache-ssl-ca:rendered}
crl = ${apache-ssl-crl:rendered}
{{ simplefile('apache-ssl-ca', '${apache-conf-ssl:ca-cert}', ssl_parameter_dict['ca-cert']) }}
{{ simplefile('apache-ssl-crl', '${apache-conf-ssl:crl}', ssl_parameter_dict['crl']) }}
{% else %}
cert =
crl =
{%- endif %}
{% set apache_service_log_list = {} -%}
{% for family_name, (_, _, _, authentication) in apache_dict.items() -%}
{% if authentication -%}
{% set base_name = 'apache-' ~ family_name -%}
{% do part_list.append('logrotate-' ~ base_name) -%}
{% do apache_service_log_list.__setitem__(family_name, base_name) -%}
[logrotate-{{ base_name }}]
< = logrotate-entry-base
name = {{ base_name }}
log = ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-error.log ${apache-conf-parameter-dict:log-dir}/{{ base_name }}-access.log
post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
{% endif -%}
{% endfor -%}
[logrotate-apache]
< = logrotate-entry-base
name = apache
log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log}
post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
[directory]
recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
promise = ${directory:etc}/promise
services = ${:etc}/run
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
ca-dir = ${buildout:directory}/srv/ssl
requests = ${:ca-dir}/requests
private = ${:ca-dir}/private
certs = ${:ca-dir}/certs
newcerts = ${:ca-dir}/newcerts
crl = ${:ca-dir}/crl
[monitor-instance-parameter]
monitor-httpd-ipv6 = {{ (ipv6_set | list)[0] }}
monitor-httpd-port = {{ next_port() }}
monitor-title = Balancer monitor
[buildout]
extends =
{{ logrotate_cfg }}
{{ parameter_dict['template-monitor'] }}
parts +=
publish
logrotate-apache
{{ part_list | join('\n ') }}
This diff is collapsed.
......@@ -49,18 +49,6 @@ recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:filename}
mode = 644
[template-erp5]
< = download-base-part
filename = instance-erp5.cfg.in
[template-balancer]
< = download-base-part
filename = instance-balancer.cfg.in
[template-apache-backend-conf]
url = ${:_profile_base_location_}/${:filename}
filename = apache-backend.conf.in
[template-create-erp5-site-real]
< = download-base-part
filename = instance-create-erp5-site-real.cfg.in
......
......@@ -59,6 +59,7 @@ extends =
../../component/userhosts/buildout.cfg
../../component/postfix/buildout.cfg
../../software/ipython_notebook/software.cfg
../../software/caucase/software.cfg
../../software/neoppod/software-common.cfg
# keep neoppod extends last
......@@ -140,6 +141,9 @@ parts +=
[instance-jupyter]
rendered = ${buildout:directory}/template-jupyter.cfg
[instance-caucase]
rendered = ${buildout:directory}/instance-caucase.cfg
[download-base]
<= download-base-neo
url = ${:_profile_base_location_}/${:filename}
......@@ -218,6 +222,7 @@ context =
key bin_directory buildout:bin-directory
key buildout_bin_directory buildout:bin-directory
key cairo_location cairo:location
key caucase_template instance-caucase:rendered
key coreutils_location coreutils:location
key cups_location cups:location
key curl_location curl:location
......
......@@ -71,7 +71,7 @@ md5sum = 0969fbb25b05c02ef3c2d437b2f4e1a0
[template]
filename = instance.cfg.in
md5sum = 8ab417cf1ca98d2840c80a266f0e2be7
md5sum = 751f0cab56a8b7484a6cef39856a7f66
[monitor-template-dummy]
filename = dummy.cfg
......@@ -79,7 +79,7 @@ md5sum = d41d8cd98f00b204e9800998ecf8427e
[template-erp5]
filename = instance-erp5.cfg.in
md5sum = 14ec590eaaebc90113f1c589ea8dd444
md5sum = cacaaa4c38bc3b1df5e10b0c1025a7d0
[template-zeo]
filename = instance-zeo.cfg.in
......@@ -87,11 +87,11 @@ md5sum = 7610bafda245c008ccf0b6ea58ce21c2
[template-zope]
filename = instance-zope.cfg.in
md5sum = b7e92234825f9d72ccb9b6c4745b6ce7
md5sum = ed422fc55f1c871c8b5e104d99bbd21b
[template-balancer]
filename = instance-balancer.cfg.in
md5sum = d71c49f91b3455e6866f4b2db591009f
md5sum = 55156630f5f74794fa0f93ff78de51c6
[template-haproxy-cfg]
filename = haproxy.cfg.in
......
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% set caucase_url = slapparameter_dict.get('caucase-url', '') -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{#
......@@ -36,6 +37,35 @@ context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}
[certificate-request-base]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:bin}/request-instance-certificate
parameters-extra = true
command-line = {{ parameter_dict['bin-directory'] }}/caucase-cliweb
--crt-file ${apache-conf-ssl:cert}
--key-file ${apache-conf-ssl:key}
--ca-url {{ caucase_url }}
--ca-crt-file ${apache-conf-ssl:ca-cert}
{% macro request_cert(name, common_name) -%}
[{{ section(name ~ '-certificate-request') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/request-{{ name }}-certificate
command-line =
${certificate-request-base:wrapper-path}
--cn {{ common_name }}
--request
[{{ section(name ~ '-renew-cron-entry') }}]
recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = {{ name }}-certificate-auto-renew
time = weekly
# 2592000 = 30*24*60*60 equivalent to one month in seconds
command = ${certificate-request-base:wrapper-path} --renew --threshold 2592000 --on-renew="${apache-graceful:output}"
{%- endmacro %}
{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
......@@ -81,6 +111,7 @@ ipv6 = {{ zope_address.split(']:')[0][1:] }}
-#}
{% do zope_family_address_list[0][0] -%}
{% set haproxy_port = next_port() -%}
{% set backend_path = slapparameter_dict['backend-path-dict'][family_name] -%}
{% do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{% if has_webdav -%}
{% set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
......@@ -89,7 +120,8 @@ ipv6 = {{ zope_address.split(']:')[0][1:] }}
{% set internal_scheme = 'http' -%}
{% set external_scheme = 'https' -%}
{% endif -%}
{% do apache_dict.__setitem__(family_name, (next_port(), external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ slapparameter_dict['backend-path'])) -%}
{% set ssl_authentication = slapparameter_dict['ssl-authentication-dict'].get(family_name, False) -%}
{% do apache_dict.__setitem__(family_name, (next_port(), external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ backend_path, ssl_authentication)) -%}
{% endfor -%}
[haproxy-cfg-parameter-dict]
......@@ -122,6 +154,7 @@ crl = ${directory:apache-conf}/crl.pem
backend-list = {{ dumps(apache_dict.values()) }}
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
log-dir = ${directory:log}
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
# Apache 2.4's default value (60 seconds) can be a bit too short
......@@ -145,6 +178,18 @@ context = section parameter_dict apache-conf-parameter-dict
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND
wait-for-files =
${apache-conf-ssl:cert}
${apache-conf-ssl:key}
[apache-graceful]
recipe = collective.recipe.template
input = inline:
#!/bin/sh
kill -USR1 "$(cat '${apache-conf-parameter-dict:pid-file}')"
output = ${directory:bin}/apache-httpd-graceful
mode = 700
[{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
......@@ -155,7 +200,7 @@ port = {{ apache_dict.values()[0][0] }}
[publish]
recipe = slapos.cookbook:publish.serialised
{% for family_name, (apache_port, scheme, _) in apache_dict.items() -%}
{% for family_name, (apache_port, scheme, _, _) in apache_dict.items() -%}
{{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}
......@@ -166,6 +211,11 @@ key = ${apache-ssl-key:rendered}
cert = ${apache-ssl-cert:rendered}
{{ simplefile('apache-ssl-key', '${apache-conf-ssl:key}', ssl_parameter_dict['key']) }}
{{ simplefile('apache-ssl-cert', '${apache-conf-ssl:cert}', ssl_parameter_dict['cert']) }}
{% elif caucase_url -%}
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
{{ request_cert('erp5', 'instance.apache@erp5') }}
{% else %}
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
......@@ -179,6 +229,11 @@ cert = ${apache-ssl-ca:rendered}
crl = ${apache-ssl-crl:rendered}
{{ simplefile('apache-ssl-ca', '${apache-conf-ssl:ca-cert}', ssl_parameter_dict['ca-cert']) }}
{{ simplefile('apache-ssl-crl', '${apache-conf-ssl:crl}', ssl_parameter_dict['crl']) }}
{% elif caucase_url -%}
cert = ${apache-conf-ssl:ca-cert}
# Crl URL is present into certificate: see crlDistributionPoints
crl =
{% else %}
cert =
crl =
......
......@@ -8,6 +8,7 @@
{% set jupyter_dict = slapparameter_dict.get('jupyter', {}) -%}
{% set has_jupyter = jupyter_dict.get('enable', jupyter_enable_default.lower() in ('true', 'yes')) -%}
{% set jupyter_zope_family = jupyter_dict.get('zope-family', '') -%}
{% set caucase_url = slapparameter_dict.get('caucase', {}).pop('url', '') -%}
[request-common]
<= request-common-base
config-use-ipv6 = {{ dumps(slapparameter_dict.get('use-ipv6', False)) }}
......@@ -46,6 +47,13 @@ config-{{ k }} = {{ '${' ~ v ~ '}' }}
connection-url = smtp://127.0.0.2:0/
{%- endif %}
{% if caucase_url -%}
[request-caucase]
connection-http-url = {{ caucase_url }}
{%- else %}
{{ request('caucase', 'caucase', 'caucase', {'server-port': 2100, 'server-https-port': 2101}, {'http-url': True, 'https-url': True}) }}
{% endif -%}
{# ZODB -#}
{% set zodb_dict = {} -%}
{% set storage_dict = {} -%}
......@@ -132,6 +140,7 @@ return =
{% endif -%}
config-bt5 = {{ dumps(slapparameter_dict.get('bt5', bt5_default_list)) }}
config-bt5-repository-url = {{ dumps(slapparameter_dict.get('bt5-repository-url', local_bt5_repository)) }}
config-caucase-url = ${request-caucase:connection-http-url}
config-cloudooo-url = ${request-cloudooo:connection-url}
config-deadlock-debugger-password = ${publish-early:deadlock-debugger-password}
config-developer-list = {{ dumps(slapparameter_dict.get('developer-list', [inituser_login])) }}
......@@ -162,17 +171,22 @@ config-tidstorage-port = ${request-zodb:connection-tidstorage-port}
software-type = zope
{% set zope_family_dict = {} -%}
{% set zope_backend_path_dict = {} -%}
{% set ssl_authentication_dict = {} -%}
{% set jupyter_zope_family_default = [] -%}
{% for custom_name, zope_parameter_dict in zope_partition_dict.items() -%}
{% set partition_name = 'zope-' ~ custom_name -%}
{% set section_name = 'request-' ~ partition_name -%}
{% set zope_family = zope_parameter_dict.get('family', 'default') -%}
{% set backend_path = zope_parameter_dict.get('backend-path', '/') % {'site-id': site_id} %}
{# # default jupyter zope family is first zope family. -#}
{# # use list.append() to update it, because in jinja2 set changes only local scope. -#}
{% if not jupyter_zope_family_default -%}
{% do jupyter_zope_family_default.append(zope_family) -%}
{% endif -%}
{% do zope_family_dict.setdefault(zope_family, []).append(section_name) -%}
{% do zope_backend_path_dict.__setitem__(zope_family, backend_path) -%}
{% do ssl_authentication_dict.__setitem__(zope_family, zope_parameter_dict.get('ssl-authentication', False)) -%}
[{{ section_name }}]
<= request-zope-base
name = {{ partition_name }}
......@@ -246,8 +260,10 @@ config-{{ name }} = {{ ' ${' ~ zope_section_id ~ ':connection-zope-address-list}
{% endfor -%}
# XXX: should those really be same for all families ?
config-haproxy-server-check-path = {{ dumps(balancer_dict.get('haproxy-server-check-path', '/') % {'site-id': site_id}) }}
config-backend-path = {{ dumps(balancer_dict.get('apache-backend-path', '/') % {'site-id': site_id}) }}
config-ssl = {{ dumps(balancer_dict.get('ssl', {})) }}
config-caucase-url = ${request-caucase:connection-http-url}
config-backend-path-dict = {{ dumps(zope_backend_path_dict) }}
config-ssl-authentication-dict = {{ dumps(ssl_authentication_dict) }}
[request-frontend-base]
{% if has_frontend -%}
......
......@@ -389,6 +389,9 @@ cloudooo-url = {{ dumps(slapparameter_dict['cloudooo-url']) }}
smtp-url = {{ dumps(slapparameter_dict['smtp-url']) }}
bt5 = {{ dumps(slapparameter_dict['bt5']) }}
bt5-repository-url = {{ dumps(slapparameter_dict['bt5-repository-url']) }}
{% if slapparameter_dict.get('caucase-url', '') -%}
certificate-authority-url = {{ dumps(slapparameter_dict['caucase-url']) }}
{% endif -%}
[monitor-instance-parameter]
monitor-httpd-ipv6 = {{ (ipv6_set | list)[0] }}
......
[buildout]
extends = {{ instance_common_cfg }}
extends =
{{ instance_common_cfg }}
{{ caucase_template }}
[jinja2-template-base]
mode = 644
......@@ -93,6 +95,7 @@ openssl = {{ openssl_location }}
haproxy = {{ haproxy_location }}
bin-directory = {{ bin_directory }}
6tunnel = {{ sixtunnel_location }}
curl-location = {{ curl_location }}
dash = {{ dash_location }}
template-haproxy-cfg = {{ template_haproxy_cfg }}
template-apache-conf = {{ template_apache_conf }}
......@@ -210,6 +213,7 @@ create-erp5-site = dynamic-template-create-erp5-site:rendered
RootSoftwareInstance = ${:default}
# Internal software types
kumofs = dynamic-template-kumofs:rendered
caucase = dynamic-template-caucase:rendered
cloudooo = dynamic-template-cloudooo:rendered
mariadb = dynamic-template-mariadb:rendered
balancer = dynamic-template-balancer:rendered
......
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