Commit d1dfde38 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki

Trustable X-Forwarded-For in ERP5 SR

See merge request nexedi/slapos!769
parents d9ca2e38 468d8148
Pipeline #9963 failed with stage
in 0 seconds
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
# # The path given to "SSLSessionCache shmcb:<folder_path>(512000)" # # The path given to "SSLSessionCache shmcb:<folder_path>(512000)"
# "ssl-session-cache": "<folder_path>", # "ssl-session-cache": "<folder_path>",
# #
# # The path given to "SSLCACertificateFile" (can be empty) # # The path given to "SSLCACertificatePath" (can be empty)
# # If this value is not empty, it enables client certificate check. # # If this value is not empty, it enables client certificate check.
# # (Enabling "SSLVerifyClient require") # # (Enabling "SSLVerifyClient require")
# "ca-cert": "<file_path>", # "ca-cert-dir": "<directory_path>",
# #
# # The path given to "SSLCARevocationFile" (used if ca-cert is not # # The path given to "SSLCARevocationPath" (used if ca-cert-dir is not
# # empty) # # empty)
# "crl": "<file_path>", # "crl-dir": "<directory_path>",
# #
# # The path given to "ErrorLog" # # The path given to "ErrorLog"
# "error-log": "<file_path>", # "error-log": "<file_path>",
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
# From to `backend-list`: # From to `backend-list`:
# - 0.0.0.0:8000 redirecting internaly to http://10.0.0.10:8001 and # - 0.0.0.0:8000 redirecting internaly to http://10.0.0.10:8001 and
# - [::1]:8000 redirecting internaly to http://10.0.0.10:8001 # - [::1]:8000 redirecting internaly to http://10.0.0.10:8001
# only accepting requests from clients who provide a valid SSL certificate trusted in `ca-cert`. # only accepting requests from clients who provide a valid SSL certificate trusted in `ca-cert-dir`.
# - 0.0.0.0:8002 redirecting internaly to http://10.0.0.10:8003 # - 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 # - [::1]:8002 redirecting internaly to http://10.0.0.10:8003
# accepting requests from any client. # accepting requests from any client.
...@@ -83,6 +83,8 @@ ...@@ -83,6 +83,8 @@
# For more details, refer to # For more details, refer to
# https://docs.zope.org/zope2/zope2book/VirtualHosting.html#using-virtualhostroot-and-virtualhostbase-together # https://docs.zope.org/zope2/zope2book/VirtualHosting.html#using-virtualhostroot-and-virtualhostbase-together
-#} -#}
{% set ca_cert_dir = parameter_dict.get('ca-cert-dir') -%}
{% set crl_dir = parameter_dict.get('crl-dir') -%}
LoadModule unixd_module modules/mod_unixd.so LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so LoadModule authz_core_module modules/mod_authz_core.so
...@@ -133,15 +135,17 @@ SSLProxyEngine On ...@@ -133,15 +135,17 @@ SSLProxyEngine On
# As backend is trusting Remote-User header unset it always # As backend is trusting Remote-User header unset it always
RequestHeader unset Remote-User RequestHeader unset Remote-User
{% if parameter_dict['ca-cert'] -%} # Drop incoming X-Forwarded-For without valid client authentication
RequestHeader unset X-Forwarded-For "expr=%{SSL_CLIENT_VERIFY} != 'SUCCESS'"
{% if ca_cert_dir -%}
SSLVerifyClient optional SSLVerifyClient optional
RequestHeader set Remote-User %{SSL_CLIENT_S_DN_CN}s RequestHeader set Remote-User %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }} SSLCACertificatePath {{ ca_cert_dir }}
{% if parameter_dict['crl'] -%} {% if crl_dir -%}
SSLCARevocationCheck chain SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }} SSLCARevocationPath {{ crl_dir }}
{%- endif %} {% endif -%}
{%- endif %} {% endif -%}
ErrorLog "{{ parameter_dict['error-log'] }}" ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end # Default apache log format with request time in microsecond at the end
...@@ -161,11 +165,9 @@ Listen {{ ip }}:{{ port }} ...@@ -161,11 +165,9 @@ Listen {{ ip }}:{{ port }}
{% endfor -%} {% endfor -%}
<VirtualHost *:{{ port }}> <VirtualHost *:{{ port }}>
SSLEngine on SSLEngine on
{% if enable_authentication and parameter_dict['ca-cert'] and parameter_dict['crl'] -%} {% if enable_authentication -%}
{% do assert(ca_cert_dir) -%}
SSLVerifyClient require SSLVerifyClient require
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
...@@ -183,11 +185,9 @@ Listen {{ ip }}:{{ port }} ...@@ -183,11 +185,9 @@ Listen {{ ip }}:{{ port }}
<VirtualHost {{ ip }}:{{ port }}> <VirtualHost {{ ip }}:{{ port }}>
SSLEngine on SSLEngine on
Timeout 3600 Timeout 3600
{% if enable_authentication and parameter_dict['ca-cert'] and parameter_dict['crl'] -%} {% if enable_authentication -%}
{% do assert(ca_cert_dir) -%}
SSLVerifyClient require SSLVerifyClient require
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
......
...@@ -14,5 +14,5 @@ ...@@ -14,5 +14,5 @@
# not need these here). # not need these here).
[template-apache-backend-conf] [template-apache-backend-conf]
filename = apache-backend.conf.in filename = apache-backend.conf.in
md5sum = bb8c175a93336f0e1838fd47225426f9 md5sum = 5c6d6aacc092b23a02e1c6f4d51e8127
...@@ -84,7 +84,8 @@ ...@@ -84,7 +84,8 @@
"software-url": { "software-url": {
"description": "Front-end's software type. If this parameter is empty, no front-end instance is requested. Else, sla-dict must specify 'frontend' which is a special value matching all frontends (e.g. {\"instance_guid=bar\": [\"frontend\"]}).", "description": "Front-end's software type. If this parameter is empty, no front-end instance is requested. Else, sla-dict must specify 'frontend' which is a special value matching all frontends (e.g. {\"instance_guid=bar\": [\"frontend\"]}).",
"default": "", "default": "",
"type": "string" "type": "string",
"format": "uri"
}, },
"domain": { "domain": {
"description": "The domain name to request front-end to respond as.", "description": "The domain name to request front-end to respond as.",
...@@ -225,7 +226,8 @@ ...@@ -225,7 +226,8 @@
"cloudooo-url": { "cloudooo-url": {
"description": "Format conversion service URL", "description": "Format conversion service URL",
"pattern": "^https?://", "pattern": "^https?://",
"type": "string" "type": "string",
"format": "uri"
}, },
"cloudooo-retry-count": { "cloudooo-retry-count": {
"description": "Define retry count for cloudooo in network error case in test", "description": "Define retry count for cloudooo in network error case in test",
...@@ -453,10 +455,21 @@ ...@@ -453,10 +455,21 @@
"ssl": { "ssl": {
"description": "HTTPS certificate generation parameters", "description": "HTTPS certificate generation parameters",
"properties": { "properties": {
"frontend-caucase-url-list": {
"title": "Frontend Caucase URL List",
"description": "List of URLs of caucase service of frontend groups to authenticate access from them.",
"type": "array",
"items": {
"type": "string",
"format": "uri"
},
"uniqueItems": true
},
"caucase-url": { "caucase-url": {
"title": "Caucase URL", "title": "Caucase URL",
"description": "URL of caucase service to use. If not set, global setting will be used.", "description": "URL of caucase service to use. If not set, global setting will be used.",
"type": "string" "type": "string",
"format": "uri"
}, },
"csr": { "csr": {
"title": "csr", "title": "csr",
......
This diff is collapsed.
...@@ -23,14 +23,14 @@ ...@@ -23,14 +23,14 @@
# # The path given to "SSLSessionCache shmcb:<folder_path>(512000)" # # The path given to "SSLSessionCache shmcb:<folder_path>(512000)"
# "ssl-session-cache": "<folder_path>", # "ssl-session-cache": "<folder_path>",
# #
# # The path given to "SSLCACertificateFile" (can be empty) # # The path given to "SSLCACertificatePath" (can be empty)
# # If this value is not empty, it enables client certificate check. # # If this value is not empty, it enables client certificate check.
# # (Enabling "SSLVerifyClient require") # # (Enabling "SSLVerifyClient require")
# "ca-cert": "<file_path>", # "ca-cert-dir": "<directory_path>",
# #
# # The path given to "SSLCARevocationFile" (used if ca-cert is not # # The path given to "SSLCARevocationPath" (used if ca-cert-dir is not
# # empty) # # empty)
# "crl": "<file_path>", # "crl-dir": "<directory_path>",
# #
# # The path given to "ErrorLog" # # The path given to "ErrorLog"
# "error-log": "<file_path>", # "error-log": "<file_path>",
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
# From to `backend-list`: # From to `backend-list`:
# - 0.0.0.0:8000 redirecting internaly to http://10.0.0.10:8001 and # - 0.0.0.0:8000 redirecting internaly to http://10.0.0.10:8001 and
# - [::1]:8000 redirecting internaly to http://10.0.0.10:8001 # - [::1]:8000 redirecting internaly to http://10.0.0.10:8001
# only accepting requests from clients who provide a valid SSL certificate trusted in `ca-cert`. # only accepting requests from clients who provide a valid SSL certificate trusted in `ca-cert-dir`.
# - 0.0.0.0:8002 redirecting internaly to http://10.0.0.10:8003 # - 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 # - [::1]:8002 redirecting internaly to http://10.0.0.10:8003
# accepting requests from any client. # accepting requests from any client.
...@@ -83,6 +83,8 @@ ...@@ -83,6 +83,8 @@
# For more details, refer to # For more details, refer to
# https://docs.zope.org/zope2/zope2book/VirtualHosting.html#using-virtualhostroot-and-virtualhostbase-together # https://docs.zope.org/zope2/zope2book/VirtualHosting.html#using-virtualhostroot-and-virtualhostbase-together
-#} -#}
{% set ca_cert_dir = parameter_dict.get('ca-cert-dir') -%}
{% set crl_dir = parameter_dict.get('crl-dir') -%}
LoadModule unixd_module modules/mod_unixd.so LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so LoadModule authz_core_module modules/mod_authz_core.so
...@@ -103,7 +105,7 @@ LoadModule headers_module modules/mod_headers.so ...@@ -103,7 +105,7 @@ LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.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 application/wasm 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 application/javascript image/svg+xml application/x-font-ttf application/font-woff application/font-woff2 application/x-font-opentype application/wasm
PidFile "{{ parameter_dict['pid-file'] }}" PidFile "{{ parameter_dict['pid-file'] }}"
ServerAdmin admin@ ServerAdmin admin@
...@@ -133,17 +135,16 @@ SSLProxyEngine On ...@@ -133,17 +135,16 @@ SSLProxyEngine On
# As backend is trusting Remote-User header unset it always # As backend is trusting Remote-User header unset it always
RequestHeader unset Remote-User RequestHeader unset Remote-User
{% if parameter_dict['ca-cert'] -%} {% if ca_cert_dir -%}
SSLVerifyClient optional SSLVerifyClient optional
RequestHeader set Remote-User %{SSL_CLIENT_S_DN_CN}s RequestHeader set Remote-User %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }} RequestHeader unset X-Forwarded-For "expr=%{SSL_CLIENT_VERIFY} != 'SUCCESS'"
{% if not parameter_dict['shared-ca-cert'] %} SSLCACertificatePath {{ ca_cert_dir }}
{% if parameter_dict['crl'] -%} {% if crl_dir -%}
SSLCARevocationCheck chain SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }} SSLCARevocationPath {{ crl_dir }}
{%- endif %} {% endif -%}
{%- endif %} {% endif -%}
{%- endif %}
ErrorLog "{{ parameter_dict['error-log'] }}" ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end # Default apache log format with request time in microsecond at the end
...@@ -163,12 +164,8 @@ Listen {{ ip }}:{{ port }} ...@@ -163,12 +164,8 @@ Listen {{ ip }}:{{ port }}
{% endfor -%} {% endfor -%}
<VirtualHost *:{{ port }}> <VirtualHost *:{{ port }}>
SSLEngine on SSLEngine on
{% if enable_authentication and parameter_dict['shared-ca-cert'] and parameter_dict['shared-crl'] -%} {% if enable_authentication and ca_cert_dir -%}
SSLVerifyClient require SSLVerifyClient require
# Custom block we use for now different parameters.
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 LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
...@@ -186,11 +183,8 @@ Listen {{ ip }}:{{ port }} ...@@ -186,11 +183,8 @@ Listen {{ ip }}:{{ port }}
<VirtualHost {{ ip }}:{{ port }}> <VirtualHost {{ ip }}:{{ port }}>
SSLEngine on SSLEngine on
Timeout 3600 Timeout 3600
{% if enable_authentication and parameter_dict['ca-cert'] and parameter_dict['crl'] -%} {% if enable_authentication and ca_cert_dir -%}
SSLVerifyClient require SSLVerifyClient require
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined LogFormat "%h %l %{REMOTE_USER}i %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
...@@ -204,4 +198,4 @@ Listen {{ ip }}:{{ port }} ...@@ -204,4 +198,4 @@ Listen {{ ip }}:{{ port }}
RewriteRule ^/{{path}}(.*) {{ backend }}/VirtualHostBase/https/{{ ip }}:{{ port }}/VirtualHostRoot/_vh_{{ path }}$1 [L,P] RewriteRule ^/{{path}}(.*) {{ backend }}/VirtualHostBase/https/{{ ip }}:{{ port }}/VirtualHostRoot/_vh_{{ path }}$1 [L,P]
{% endfor -%} {% endfor -%}
</VirtualHost> </VirtualHost>
{% endfor -%} {% endfor -%}
\ No newline at end of file
...@@ -18,8 +18,8 @@ md5sum = 2ef0ddc206c6b0982a37cfc21f23e423 ...@@ -18,8 +18,8 @@ md5sum = 2ef0ddc206c6b0982a37cfc21f23e423
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
md5sum = ef86e09e44ac67a9b15939df0ab4a466 md5sum = d10a5ddfffa67b8ca01b3e38315bae2f
[template-apache-backend-conf] [template-apache-backend-conf]
filename = apache-backend.conf.in filename = apache-backend.conf.in
md5sum = 48f086ce1acffca7bab942b43d856fb7 md5sum = a169c1d6b0f2636f21f180e8a0b52137
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
{% set part_list = [] -%} {% set part_list = [] -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%} {% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set ssl_parameter_dict = slapparameter_dict['ssl'] -%} {% set ssl_parameter_dict = slapparameter_dict['ssl'] -%}
{% set frontend_caucase_url_list = ssl_parameter_dict.get('frontend_caucase_url_list', []) -%}
{% set shared_ca_path = slapparameter_dict.get('shared-certificate-authority-path') -%} {% set shared_ca_path = slapparameter_dict.get('shared-certificate-authority-path') -%}
{# {#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6 XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
...@@ -28,8 +29,8 @@ mode = 644 ...@@ -28,8 +29,8 @@ mode = 644
url=ssl_parameter_dict['caucase-url'], url=ssl_parameter_dict['caucase-url'],
data_dir='${directory:srv}/caucase-updater', data_dir='${directory:srv}/caucase-updater',
crt_path='${apache-conf-ssl:caucase-cert}', crt_path='${apache-conf-ssl:caucase-cert}',
ca_path='${apache-conf-ssl:ca-cert}', ca_path='${directory:srv}/caucase-updater/ca.crt',
crl_path='${apache-conf-ssl:crl}', crl_path='${directory:srv}/caucase-updater/crl.pem',
key_path='${apache-conf-ssl:caucase-key}', key_path='${apache-conf-ssl:caucase-key}',
on_renew='${apache-graceful:output}', on_renew='${apache-graceful:output}',
max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0), max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0),
...@@ -37,6 +38,69 @@ mode = 644 ...@@ -37,6 +38,69 @@ mode = 644
openssl=parameter_dict['openssl'] ~ '/bin/openssl', openssl=parameter_dict['openssl'] ~ '/bin/openssl',
)}} )}}
{% do section('caucase-updater') -%} {% do section('caucase-updater') -%}
{% do section('caucase-updater-promise') -%}
{% set frontend_caucase_url_hash_list = [] -%}
{% for frontend_caucase_url in frontend_caucase_url_list -%}
{% set hash = hashlib.md5(frontend_caucase_url).hexdigest() -%}
{% do frontend_caucase_url_hash_list.append(hash) -%}
{% set data_dir = '${directory:srv}/client-cert-ca/%s' % hash -%}
{{ caucase.updater(
prefix='caucase-updater-%s' % hash,
buildout_bin_directory=parameter_dict['bin-directory'],
updater_path='${directory:services-on-watch}/caucase-updater-%s' % hash,
url=frontend_caucase_url,
data_dir=data_dir,
ca_path='%s/ca.crt' % data_dir,
crl_path='%s/crl.pem' % data_dir,
on_renew='${caucase-updater-housekeeper:output}; ${apache-graceful:output}',
max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0),
openssl=parameter_dict['openssl'] ~ '/bin/openssl',
)}}
{% do section('caucase-updater-%s' % hash) -%}
{% endfor -%}
{% if frontend_caucase_url_hash_list -%}
[caucase-updater-housekeeper]
recipe = collective.recipe.template
output = ${directory:bin}/caucase-updater-housekeeper
mode = 700
input =
inline:
#!${buildout:executable}
import glob
import os
import subprocess
hash_list = {{ repr(frontend_caucase_url_hash_list) }}
crt_list = ['%s.crt' % e for e in hash_list]
crl_list = ['%s.crl' % e for e in hash_list]
{% if shared_ca_path -%}
crt_list.append('{{ shared_ca_path }}/cacert.pem')
crl_list.append('{{ shared_ca_path }}/crl')
{% endif -%}
for path in glob.glob('${apache-conf-ssl:ca-cert-dir}/*.crt'):
if os.path.basename(path) not in crt_list:
os.unlink(path)
for path in glob.glob('${apache-conf-ssl:crl-dir}/*.crl'):
if os.path.basename(path) not in crl_list:
os.unlink(path)
for hash in hash_list:
crt = '${directory:srv}/client-cert-ca/%s/ca.crt' % hash
crt_link = '${apache-conf-ssl:ca-cert-dir}/%s.crt' % hash
crl = '${directory:srv}/client-cert-ca/%s/crl.pem' % hash
crl_link = '${apache-conf-ssl:crl-dir}/%s.crl' % hash
if os.path.isfile(crt) and not os.path.islink(crt_link):
os.symlink(crt, crt_link)
if os.path.isfile(crl) and not os.path.islink(crl_link):
os.symlink(crl, crl_link)
subprocess.check_call(['{{ parameter_dict["openssl"] }}/bin/c_rehash', '${apache-conf-ssl:ca-cert-dir}'])
subprocess.check_call(['{{ parameter_dict["openssl"] }}/bin/c_rehash', '${apache-conf-ssl:crl-dir}'])
[caucase-updater-housekeeper-run]
recipe = plone.recipe.command
command = ${caucase-updater-housekeeper:output}
update-command = ${:command}
{% endif -%}
{% set haproxy_dict = {} -%} {% set haproxy_dict = {} -%}
{% set apache_dict = {} -%} {% set apache_dict = {} -%}
...@@ -123,8 +187,27 @@ key = ${directory:apache-conf}/apache.pem ...@@ -123,8 +187,27 @@ key = ${directory:apache-conf}/apache.pem
# XXX caucase certificate is not supported by caddy for now # XXX caucase certificate is not supported by caddy for now
caucase-cert = ${directory:apache-conf}/apache-caucase.crt caucase-cert = ${directory:apache-conf}/apache-caucase.crt
caucase-key = ${directory:apache-conf}/apache-caucase.pem caucase-key = ${directory:apache-conf}/apache-caucase.pem
ca-cert = ${directory:apache-conf}/ca.crt {% if frontend_caucase_url_list -%}
crl = ${directory:apache-conf}/crl.pem depends = ${caucase-updater-housekeeper-run:recipe}
ca-cert-dir = ${directory:apache-ca-cert-dir}
crl-dir = ${directory:apache-crl-dir}
{%- endif %}
[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 %}
[apache-ssl] [apache-ssl]
{% if ssl_parameter_dict.get('key') -%} {% if ssl_parameter_dict.get('key') -%}
...@@ -154,13 +237,10 @@ cert = ${apache-ssl:cert} ...@@ -154,13 +237,10 @@ cert = ${apache-ssl:cert}
key = ${apache-ssl:key} key = ${apache-ssl:key}
cipher = cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache ssl-session-cache = ${directory:log}/apache-ssl-session-cache
{% if frontend_caucase_url_list -%}
# Client x509 auth # Client x509 auth
ca-cert = ${apache-conf-ssl:ca-cert} ca-cert-dir = ${apache-conf-ssl:ca-cert-dir}
crl = ${apache-conf-ssl:crl} crl-dir = ${apache-conf-ssl:crl-dir}
{% if shared_ca_path -%}
shared-ca-cert = {{ shared_ca_path }}/cacert.pem
shared-crl = {{ shared_ca_path }}/crl
{%- endif %} {%- endif %}
[apache-conf] [apache-conf]
...@@ -186,8 +266,8 @@ input = inline: ...@@ -186,8 +266,8 @@ input = inline:
kill -USR1 "$(cat '${apache-conf-parameter-dict:pid-file}')" kill -USR1 "$(cat '${apache-conf-parameter-dict:pid-file}')"
[{{ section('apache-promise') }}] [{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
<= monitor-promise-base <= monitor-promise-base
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
module = check_port_listening module = check_port_listening
name = apache.py name = apache.py
config-hostname = {{ ipv4 }} config-hostname = {{ ipv4 }}
...@@ -228,6 +308,10 @@ post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bi ...@@ -228,6 +308,10 @@ post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bi
[directory] [directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache apache-conf = ${:etc}/apache
{% if frontend_caucase_url_list -%}
apache-ca-cert-dir = ${:apache-conf}/ssl.crt
apache-crl-dir = ${:apache-conf}/ssl.crl
{% endif -%}
bin = ${buildout:directory}/bin bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc etc = ${buildout:directory}/etc
services = ${:etc}/run services = ${:etc}/run
......
...@@ -72,7 +72,7 @@ Client ...@@ -72,7 +72,7 @@ Client
This script allows you to re-issue a CSR using a locally-generated private key. 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)`` .. topic:: ``updater(prefix, buildout_bin_directory, updater_path, url, data_dir, ca_path, crl_path, crt_path=None, 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. - ``<prefix>``: Creates ``<updater>`` executable file to start ``caucase-updater``, and ``<data_dir>`` directory for its data storage needs.
......
...@@ -15,4 +15,4 @@ ...@@ -15,4 +15,4 @@
[caucase-jinja2-library] [caucase-jinja2-library]
filename = caucase.jinja2.library filename = caucase.jinja2.library
md5sum = 9a7247cdb2ee1d66c074b0660c54713f md5sum = 2e7e61bb0cf41c28d6d811a0283cf03e
...@@ -43,9 +43,9 @@ config-command = '{{ buildout_bin_directory }}/caucase-probe' 'http://{{ netloc ...@@ -43,9 +43,9 @@ config-command = '{{ buildout_bin_directory }}/caucase-probe' 'http://{{ netloc
updater_path, updater_path,
url, url,
data_dir, data_dir,
crt_path,
ca_path, ca_path,
crl_path, crl_path,
crt_path=None,
key_path=None, key_path=None,
on_renew=None, on_renew=None,
max_sleep=None, max_sleep=None,
...@@ -59,24 +59,25 @@ config-command = '{{ buildout_bin_directory }}/caucase-probe' 'http://{{ netloc ...@@ -59,24 +59,25 @@ config-command = '{{ buildout_bin_directory }}/caucase-probe' 'http://{{ netloc
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
data-dir = {{ data_dir }} data-dir = {{ data_dir }}
{% if template_csr_pem or template_csr -%} {% if crt_path %}
{% if template_csr_pem or template_csr -%}
[{{ prefix }}-provided-csr-content] [{{ prefix }}-provided-csr-content]
{% if template_csr_pem %} {% if template_csr_pem %}
content = {{ dumps(template_csr_pem) }} content = {{ dumps(template_csr_pem) }}
{% elif template_csr %} {% elif template_csr %}
content = {{ template_csr }} content = {{ template_csr }}
{% endif %} {% endif %}
[{{ prefix }}-provided-csr] [{{ prefix }}-provided-csr]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
mode = 644 mode = 644
{% if template_csr_pem %} {% if template_csr_pem %}
template = inline:{{ '{{ content }}' }} template = inline:{{ '{{ content }}' }}
rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem
context = key content {{ prefix }}-provided-csr-content:content context = key content {{ prefix }}-provided-csr-content:content
{% elif template_csr %} {% elif template_csr %}
template = {{ '${' + prefix }}-provided-csr-content:content} template = {{ '${' + prefix }}-provided-csr-content:content}
rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem
{% endif %} {% endif %}
{{ rerequest( {{ rerequest(
prefix=prefix ~ '-csr', prefix=prefix ~ '-csr',
buildout_bin_directory=buildout_bin_directory, buildout_bin_directory=buildout_bin_directory,
...@@ -84,12 +85,13 @@ rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem ...@@ -84,12 +85,13 @@ rendered = ${ {{- prefix }}-directory:data-dir}/provided.csr.pem
csr='${:csr}', csr='${:csr}',
key=key_path, key=key_path,
)}} )}}
{%- else -%} {%- else -%}
[{{ prefix }}-csr] [{{ prefix }}-csr]
recipe = plone.recipe.command 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}' command = '{{ openssl }}' req -newkey rsa:2048 -batch -new -nodes -subj /CN=example.com -keyout '{{ key_path or crt_path }}' -out '${:csr}'
{%- endif %} {%- endif %}
csr = ${ {{- prefix }}-directory:data-dir}/good.csr.pem csr = ${ {{- prefix }}-directory:data-dir}/good.csr.pem
{%- endif %}
[{{ prefix }}] [{{ prefix }}]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
...@@ -98,8 +100,8 @@ command-line = '{{ buildout_bin_directory }}/caucase-updater' ...@@ -98,8 +100,8 @@ command-line = '{{ buildout_bin_directory }}/caucase-updater'
--ca-url '{{ url }}' --ca-url '{{ url }}'
--cas-ca '${ {{- prefix }}-directory:data-dir}/cas.crt.pem' --cas-ca '${ {{- prefix }}-directory:data-dir}/cas.crt.pem'
--mode '{{ mode }}' --mode '{{ mode }}'
--csr '${ {{- prefix }}-csr:csr}' {% if crt_path %}--csr '${ {{- prefix }}-csr:csr}'
--crt '{{ crt_path }}' --crt '{{ crt_path }}' {%- endif %}
--ca '{{ ca_path }}' --ca '{{ ca_path }}'
--crl '{{ crl_path }}' --crl '{{ crl_path }}'
{% if key_path %}--key '{{ key_path }}' {%- endif %} {% if key_path %}--key '{{ key_path }}' {%- endif %}
......
...@@ -70,7 +70,7 @@ md5sum = cc19560b9400cecbd23064d55c501eec ...@@ -70,7 +70,7 @@ md5sum = cc19560b9400cecbd23064d55c501eec
[template] [template]
filename = instance.cfg.in filename = instance.cfg.in
md5sum = f0f3b18f9963b137e366752886591fc3 md5sum = 328ea2bb5f2bff18f8be8c541c01f260
[monitor-template-dummy] [monitor-template-dummy]
filename = dummy.cfg filename = dummy.cfg
...@@ -90,7 +90,7 @@ md5sum = 2f3ddd328ac1c375e483ecb2ef5ffb57 ...@@ -90,7 +90,7 @@ md5sum = 2f3ddd328ac1c375e483ecb2ef5ffb57
[template-balancer] [template-balancer]
filename = instance-balancer.cfg.in filename = instance-balancer.cfg.in
md5sum = 6851e0c28a025bd26a4d3450204ae335 md5sum = 0097e49b5bd7ad4978c722c1cdd27d6c
[template-haproxy-cfg] [template-haproxy-cfg]
filename = haproxy.cfg.in filename = haproxy.cfg.in
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
{% set part_list = [] -%} {% set part_list = [] -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%} {% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set ssl_parameter_dict = slapparameter_dict['ssl'] -%} {% set ssl_parameter_dict = slapparameter_dict['ssl'] -%}
{% set frontend_caucase_url_list = ssl_parameter_dict.get('frontend-caucase-url-list', []) -%}
{# {#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6 XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
per partition. No more (undefined result), no less (IndexError). per partition. No more (undefined result), no less (IndexError).
...@@ -27,8 +28,8 @@ mode = 644 ...@@ -27,8 +28,8 @@ mode = 644
url=ssl_parameter_dict['caucase-url'], url=ssl_parameter_dict['caucase-url'],
data_dir='${directory:srv}/caucase-updater', data_dir='${directory:srv}/caucase-updater',
crt_path='${apache-conf-ssl:caucase-cert}', crt_path='${apache-conf-ssl:caucase-cert}',
ca_path='${apache-conf-ssl:ca-cert}', ca_path='${directory:srv}/caucase-updater/ca.crt',
crl_path='${apache-conf-ssl:crl}', crl_path='${directory:srv}/caucase-updater/crl.pem',
key_path='${apache-conf-ssl:caucase-key}', key_path='${apache-conf-ssl:caucase-key}',
on_renew='${apache-graceful:output}', on_renew='${apache-graceful:output}',
max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0), max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0),
...@@ -38,6 +39,64 @@ mode = 644 ...@@ -38,6 +39,64 @@ mode = 644
{% do section('caucase-updater') -%} {% do section('caucase-updater') -%}
{% do section('caucase-updater-promise') -%} {% do section('caucase-updater-promise') -%}
{% set frontend_caucase_url_hash_list = [] -%}
{% for frontend_caucase_url in frontend_caucase_url_list -%}
{% set hash = hashlib.md5(frontend_caucase_url).hexdigest() -%}
{% do frontend_caucase_url_hash_list.append(hash) -%}
{% set data_dir = '${directory:srv}/client-cert-ca/%s' % hash -%}
{{ caucase.updater(
prefix='caucase-updater-%s' % hash,
buildout_bin_directory=parameter_dict['bin-directory'],
updater_path='${directory:services-on-watch}/caucase-updater-%s' % hash,
url=frontend_caucase_url,
data_dir=data_dir,
ca_path='%s/ca.crt' % data_dir,
crl_path='%s/crl.pem' % data_dir,
on_renew='${caucase-updater-housekeeper:output}; ${apache-graceful:output}',
max_sleep=ssl_parameter_dict.get('max-crl-update-delay', 1.0),
openssl=parameter_dict['openssl'] ~ '/bin/openssl',
)}}
{% do section('caucase-updater-%s' % hash) -%}
{% endfor -%}
{% if frontend_caucase_url_hash_list -%}
[caucase-updater-housekeeper]
recipe = collective.recipe.template
output = ${directory:bin}/caucase-updater-housekeeper
mode = 700
input =
inline:
#!${buildout:executable}
import glob
import os
import subprocess
hash_list = {{ repr(frontend_caucase_url_hash_list) }}
crt_list = ['%s.crt' % e for e in hash_list]
crl_list = ['%s.crl' % e for e in hash_list]
for path in glob.glob('${apache-conf-ssl:ca-cert-dir}/*.crt'):
if os.path.basename(path) not in crt_list:
os.unlink(path)
for path in glob.glob('${apache-conf-ssl:crl-dir}/*.crl'):
if os.path.basename(path) not in crl_list:
os.unlink(path)
for hash in hash_list:
crt = '${directory:srv}/client-cert-ca/%s/ca.crt' % hash
crt_link = '${apache-conf-ssl:ca-cert-dir}/%s.crt' % hash
crl = '${directory:srv}/client-cert-ca/%s/crl.pem' % hash
crl_link = '${apache-conf-ssl:crl-dir}/%s.crl' % hash
if os.path.isfile(crt) and not os.path.islink(crt_link):
os.symlink(crt, crt_link)
if os.path.isfile(crl) and not os.path.islink(crl_link):
os.symlink(crl, crl_link)
subprocess.check_call(['{{ parameter_dict["openssl"] }}/bin/c_rehash', '${apache-conf-ssl:ca-cert-dir}'])
subprocess.check_call(['{{ parameter_dict["openssl"] }}/bin/c_rehash', '${apache-conf-ssl:crl-dir}'])
[caucase-updater-housekeeper-run]
recipe = plone.recipe.command
command = ${caucase-updater-housekeeper:output}
update-command = ${:command}
{% endif -%}
{% set haproxy_dict = {} -%} {% set haproxy_dict = {} -%}
{% set apache_dict = {} -%} {% set apache_dict = {} -%}
{% set zope_virtualhost_monster_backend_dict = {} %} {% set zope_virtualhost_monster_backend_dict = {} %}
...@@ -123,8 +182,27 @@ key = ${directory:apache-conf}/apache.pem ...@@ -123,8 +182,27 @@ key = ${directory:apache-conf}/apache.pem
# XXX caucase certificate is not supported by caddy for now # XXX caucase certificate is not supported by caddy for now
caucase-cert = ${directory:apache-conf}/apache-caucase.crt caucase-cert = ${directory:apache-conf}/apache-caucase.crt
caucase-key = ${directory:apache-conf}/apache-caucase.pem caucase-key = ${directory:apache-conf}/apache-caucase.pem
ca-cert = ${directory:apache-conf}/ca.crt {% if frontend_caucase_url_list -%}
crl = ${directory:apache-conf}/crl.pem depends = ${caucase-updater-housekeeper-run:recipe}
ca-cert-dir = ${directory:apache-ca-cert-dir}
crl-dir = ${directory:apache-crl-dir}
{%- endif %}
[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 %}
[apache-ssl] [apache-ssl]
{% if ssl_parameter_dict.get('key') -%} {% if ssl_parameter_dict.get('key') -%}
...@@ -154,9 +232,11 @@ cert = ${apache-ssl:cert} ...@@ -154,9 +232,11 @@ cert = ${apache-ssl:cert}
key = ${apache-ssl:key} key = ${apache-ssl:key}
cipher = cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache ssl-session-cache = ${directory:log}/apache-ssl-session-cache
{% if frontend_caucase_url_list -%}
# Client x509 auth # Client x509 auth
ca-cert = ${apache-conf-ssl:ca-cert} ca-cert-dir = ${apache-conf-ssl:ca-cert-dir}
crl = ${apache-conf-ssl:crl} crl-dir = ${apache-conf-ssl:crl-dir}
{%- endif %}
[apache-conf] [apache-conf]
< = jinja2-template-base < = jinja2-template-base
...@@ -209,6 +289,10 @@ post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bi ...@@ -209,6 +289,10 @@ post = test ! -s ${apache-conf-parameter-dict:pid-file} || {{ parameter_dict['bi
[directory] [directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache apache-conf = ${:etc}/apache
{% if frontend_caucase_url_list -%}
apache-ca-cert-dir = ${:apache-conf}/ssl.crt
apache-crl-dir = ${:apache-conf}/ssl.crl
{% endif -%}
bin = ${buildout:directory}/bin bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc etc = ${buildout:directory}/etc
services = ${:etc}/run services = ${:etc}/run
......
...@@ -72,6 +72,7 @@ filename = instance-balancer.cfg ...@@ -72,6 +72,7 @@ filename = instance-balancer.cfg
extra-context = extra-context =
section parameter_dict dynamic-template-balancer-parameters section parameter_dict dynamic-template-balancer-parameters
import itertools itertools import itertools itertools
import hashlib hashlib
import-list = import-list =
file caucase context:caucase-jinja2-library file caucase context:caucase-jinja2-library
......
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