From efd75ef27955b8a1d3bfecccdf90b8bc767b4f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Nowak?= <luke@nexedi.com> Date: Tue, 18 Oct 2011 11:45:15 +0200 Subject: [PATCH] Add apache backend for zope. --- setup.py | 1 + slapos/recipe/apache_zope_backend/__init__.py | 68 +++++++++++++++++++ slapos/recipe/apache_zope_backend/apache.py | 22 ++++++ .../template/apache.zope.conf.in | 63 +++++++++++++++++ slapos/recipe/erp5/__init__.py | 30 +------- software/erp5/instance-zope.cfg | 66 +++++++++++++++++- software/erp5/software.cfg | 2 +- 7 files changed, 221 insertions(+), 31 deletions(-) create mode 100644 slapos/recipe/apache_zope_backend/__init__.py create mode 100644 slapos/recipe/apache_zope_backend/apache.py create mode 100644 slapos/recipe/apache_zope_backend/template/apache.zope.conf.in diff --git a/setup.py b/setup.py index ea975bf5d..9891107e3 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ setup(name=name, zip_safe=True, entry_points={ 'zc.buildout': [ + 'apache.zope.backend = slapos.recipe.apache_zope_backend:Recipe', 'certificate_authority = slapos.recipe.certificate_authority:Recipe', 'certificate_authority.request = slapos.recipe.certificate_authority:Request', 'cron = slapos.recipe.dcron:Recipe', diff --git a/slapos/recipe/apache_zope_backend/__init__.py b/slapos/recipe/apache_zope_backend/__init__.py new file mode 100644 index 000000000..034b30031 --- /dev/null +++ b/slapos/recipe/apache_zope_backend/__init__.py @@ -0,0 +1,68 @@ +############################################################################## +# +# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved. +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsibility of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# guarantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## +from slapos.recipe.librecipe import GenericBaseRecipe + +import pkg_resources + +class Recipe(GenericBaseRecipe): + def install(self): + path_list = [] + ip = self.options['ip'] + port = self.options['port'] + backend = self.options['backend'] + key = self.options['key-file'] + certificate = self.options['cert-file'] + access_control_string = self.options['access-control-string'] + apache_conf = dict() + apache_conf['pid_file'] = self.options['pid-file'] + apache_conf['lock_file'] = self.options['lock-file'] + apache_conf['ip'] = ip + apache_conf['port'] = port + apache_conf['server_admin'] = 'admin@' + apache_conf['error_log'] = self.options['error-log'] + apache_conf['access_log'] = self.options['access-log'] + apache_conf['server_name'] = '%s' % apache_conf['ip'] + apache_conf['certificate'] = certificate + apache_conf['key'] = key + apache_conf['path'] = '/' + apache_conf['access_control_string'] = access_control_string + apache_conf['rewrite_rule'] = "RewriteRule (.*) http://%s$1 [L,P]" % backend + apache_conf_string = pkg_resources.resource_string(__name__, + 'template/apache.zope.conf.in') % apache_conf + apache_config_file = self.createFile(self.options['configuration-file'], + apache_conf_string) + path_list.append(apache_config_file) + wrapper = self.createPythonScript(self.options['wrapper'], __name__ + + '.apache.runApache', [ + dict( + required_path_list=[key, certificate], + binary=self.options['apache-binary'], + config=apache_config_file + ) + ]) + path_list.append(wrapper) + return path_list diff --git a/slapos/recipe/apache_zope_backend/apache.py b/slapos/recipe/apache_zope_backend/apache.py new file mode 100644 index 000000000..861f787d0 --- /dev/null +++ b/slapos/recipe/apache_zope_backend/apache.py @@ -0,0 +1,22 @@ +import os +import sys +import time + + +def runApache(args): + sleep = 60 + conf = args[0] + while True: + ready = True + for f in conf.get('required_path_list', []): + if not os.path.exists(f): + print 'File %r does not exists, sleeping for %s' % (f, sleep) + ready = False + if ready: + break + time.sleep(sleep) + apache_wrapper_list = [conf['binary'], '-f', conf['config'], '-DFOREGROUND'] + apache_wrapper_list.extend(sys.argv[1:]) + sys.stdout.flush() + sys.stderr.flush() + os.execl(apache_wrapper_list[0], *apache_wrapper_list) diff --git a/slapos/recipe/apache_zope_backend/template/apache.zope.conf.in b/slapos/recipe/apache_zope_backend/template/apache.zope.conf.in new file mode 100644 index 000000000..ac689e15f --- /dev/null +++ b/slapos/recipe/apache_zope_backend/template/apache.zope.conf.in @@ -0,0 +1,63 @@ +# Apache configuration file for Zope +# Automatically generated + +# List of modules +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 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 + +# Basic server configuration +PidFile "%(pid_file)s" +LockFile "%(lock_file)s" +Listen %(ip)s:%(port)s +ServerAdmin %(server_admin)s +TypesConfig conf/mime.types +AddType application/x-compress .Z +AddType application/x-gzip .gz .tgz + +# As backend is trusting REMOTE_USER header unset it always +RequestHeader unset REMOTE_USER + +# SSL Configuration +SSLEngine on +SSLCertificateFile %(certificate)s +SSLCertificateKeyFile %(key)s +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin + +SSLProxyEngine On + +# Log configuration +ErrorLog "%(error_log)s" +# 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 "%(access_log)s" combined + +# Directory protection +<Directory /> + Options FollowSymLinks + AllowOverride None + Order deny,allow + Deny from all +</Directory> + +# Path protected +<Location %(path)s> + Order Deny,Allow + Deny from all + Allow from %(access_control_string)s +</Location> + +# Magic of Zope related rewrite +RewriteEngine On +%(rewrite_rule)s diff --git a/slapos/recipe/erp5/__init__.py b/slapos/recipe/erp5/__init__.py index 53ac57a02..94790fa6e 100644 --- a/slapos/recipe/erp5/__init__.py +++ b/slapos/recipe/erp5/__init__.py @@ -68,9 +68,9 @@ class Recipe(BaseSlapRecipe): key_access = None key, certificate = self.requestCertificate('Login Based Access') - apache_conf = dict( - apache_login=self.installBackendApache(ip=self.getGlobalIPv6Address(), - port=13000, backend=site_access, key=key, certificate=certificate)) +# apache_conf = dict( +# apache_login=self.installBackendApache(ip=self.getGlobalIPv6Address(), +# port=13000, backend=site_access, key=key, certificate=certificate)) connection_dict = dict(site_url=apache_conf['apache_login']) @@ -824,27 +824,3 @@ SSLCARevocationPath %(ca_crl)s""" ])) # Note: IPv6 is assumed always return 'https://%(server_name)s:%(port)s%(frontend_path)s' % (apache_conf) - - def installBackendApache(self, ip, port, backend, key, certificate, - suffix='', access_control_string=None): - apache_conf = self._getApacheConfigurationDict('backend_apache'+suffix, ip, - port) - apache_conf['server_name'] = '%s' % apache_conf['ip'] - apache_conf['ssl_snippet'] = pkg_resources.resource_string(__name__, - 'template/apache.ssl-snippet.conf.in') % dict( - login_certificate=certificate, login_key=key) - apache_config_file = self._writeApacheConfiguration('backend_apache'+suffix, - apache_conf, backend, access_control_string) - self.path_list.append(apache_config_file) - self.path_list.extend(zc.buildout.easy_install.scripts([( - 'backend_apache'+suffix, - __name__ + '.apache', 'runApache')], self.ws, - sys.executable, self.wrapper_directory, arguments=[ - dict( - required_path_list=[key, certificate], - binary=self.options['httpd_binary'], - config=apache_config_file - ) - ])) - # Note: IPv6 is assumed always - return 'https://[%(ip)s]:%(port)s' % apache_conf diff --git a/software/erp5/instance-zope.cfg b/software/erp5/instance-zope.cfg index 15d2d8eef..6759c24d7 100644 --- a/software/erp5/instance-zope.cfg +++ b/software/erp5/instance-zope.cfg @@ -1,7 +1,10 @@ [buildout] parts = - publish-zope-connection-string + certificate-authority + publish-apache-zope-backend-connection-string zope-instance + apache-zope-backend-instance + ca-apache-zope-backend logrotate logrotate-entry-zope cron @@ -13,11 +16,35 @@ eggs-directory = ${buildout:eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory} offline = true -[publish-zope-connection-string] +[publish-apache-zope-backend-connection-string] recipe = slapos.cookbook:publishurl -url = http://$${zope-instance:user}:$${zope-instance:password}@$${zope-instance:ip}:$${zope-instance:port} +url = https://$${zope-instance:user}:$${zope-instance:password}@[$${apache-zope-backend-instance:ip}]:$${apache-zope-backend-instance:port} deadlock-url = $${:url}/$${zope-instance:deadlock-path}?$${zope-instance:deadlock-password} +[apache-zope-backend-instance] +recipe = slapos.cookbook:apache.zope.backend +backend = http://$${zope-instance:ip}:$${zope-instance:port}/ +ip = $${slap-network-information:global-ipv6} +port = 16001 +wrapper = $${rootdirectory:bin}/apache +key-file = $${directory:apache-conf}/apache.key +cert-file = $${directory:apache-conf}/apache.crt +configuration-file = $${directory:apache-conf}/apache.conf +access-control-string = $${slap-parameter:access-control-string} +pid-file = $${basedirectory:run}/apache.pid +lock-file = $${basedirectory:run}/apache.lock +error-log = $${basedirectory:log}/apache-error.log +access-log = $${basedirectory:log}/apache-access.log +apache-binary = ${apache:location}/bin/httpd + +[ca-apache-zope-backend] +<= certificate-authority +recipe = slapos.cookbook:certificate_authority.request +key-file = $${apache-zope-backend-instance:key-file} +cert-file = $${apache-zope-backend-instance:cert-file} +executable = $${apache-zope-backend-instance:wrapper} +wrapper = $${basedirectory:services}/apache + [zope-instance] recipe = slapos.cookbook:generic.zope @@ -79,6 +106,18 @@ sharedscripts = true notifempty = true create = true +[logrotate-entry-apache-zope-backend] +<= logrotate +recipe = slapos.cookbook:logrotate.d +name = zope +log = $${apache-zope-backend-instance:error-log} $${apache-zope-backend-instance:access-log} +frequency = daily +rotate-num = 30 +post = ${buildout:bin-directory}/killpidfromfile $${apache-zope-backend-instance:pid-file} SIGUSR1 +sharedscripts = true +notifempty = true +create = true + [cron] recipe = slapos.cookbook:cron dcrond-binary = ${dcron:location}/sbin/crond @@ -100,6 +139,25 @@ name = logrotate frequency = 0 0 * * * command = $${logrotate:wrapper} +[certificate-authority] +recipe = slapos.cookbook:certificate_authority +openssl-binary = ${openssl:location}/bin/openssl +ca-dir = $${directory:ca-dir} +requests-directory = $${cadirectory:requests} +wrapper = $${basedirectory:services}/ca +ca-private = $${cadirectory:private} +ca-certs = $${cadirectory:certs} +ca-newcerts = $${cadirectory:newcerts} +ca-crl = $${cadirectory:crl} + +[cadirectory] +recipe = slapos.cookbook:mkdirectory +requests = $${directory:ca-dir}/requests/ +private = $${directory:ca-dir}/private/ +certs = $${directory:ca-dir}/certs/ +newcerts = $${directory:ca-dir}/newcerts/ +crl = $${directory:ca-dir}/crl/ + [rootdirectory] recipe = slapos.cookbook:mkdirectory etc = $${buildout:directory}/etc/ @@ -120,6 +178,7 @@ recipe = slapos.cookbook:mkdirectory zodb = $${rootdirectory:srv}/zodb/ instance = $${rootdirectory:srv}/erp5shared/ instance-etc = $${:instance}/etc +apache-conf = $${rootdirectory:etc}/apache instance-etc-package-include = $${:instance}/etc/package-include # because of bug in slapos.recipe.template keys are lowercased instance-document = $${:instance}/Document @@ -130,6 +189,7 @@ instance-constraint = $${:instance}/Constraint instance-import = $${:instance}/import instance-lib = $${:instance}/lib instance-tests = $${:instance}/tests +ca-dir = $${rootdirectory:srv}/ssl/ cron-entries = $${rootdirectory:etc}/cron.d/ crontabs = $${rootdirectory:etc}/crontabs/ cronstamps = $${rootdirectory:etc}/cronstamps/ diff --git a/software/erp5/software.cfg b/software/erp5/software.cfg index 7bd83c551..9f288d619 100644 --- a/software/erp5/software.cfg +++ b/software/erp5/software.cfg @@ -32,7 +32,7 @@ mode = 0644 [template-zope] recipe = slapos.recipe.template url = ${:_profile_base_location_}/instance-zope.cfg -md5sum = 1b6613da7980e0dd9f9290d3e30e8eef +md5sum = 3b5ba87a44f172c8afc14ed57736949f output = ${buildout:directory}/template-zope.cfg mode = 0644 -- 2.30.9