diff options
-rw-r--r-- | install/conf/ipa.conf | 103 | ||||
-rw-r--r-- | install/share/Makefile.am | 1 | ||||
-rw-r--r-- | install/share/wsgi.py | 13 | ||||
-rw-r--r-- | ipa.spec.in | 5 | ||||
-rw-r--r-- | ipaserver/__init__.py | 206 |
5 files changed, 59 insertions, 269 deletions
diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf index f5987fbea..dba47c5a4 100644 --- a/install/conf/ipa.conf +++ b/install/conf/ipa.conf @@ -4,7 +4,6 @@ # LoadModule auth_kerb_module modules/mod_auth_kerb.so ProxyRequests Off -PythonImport ipaserver main_interpreter # ipa-rewrite.conf is loaded separately @@ -12,79 +11,47 @@ PythonImport ipaserver main_interpreter AddType application/java-archive jar +# FIXME: WSGISocketPrefix is a server-scope directive. The mod_wsgi package +# should really be fixed by adding this its /etc/httpd/conf.d/wsgi.conf: +WSGISocketPrefix /var/run/httpd/wsgi -<Location "/ipa"> - AuthType Kerberos - AuthName "Kerberos Login" - KrbMethodNegotiate on - KrbMethodK5Passwd off - KrbServiceName HTTP - KrbAuthRealms $REALM - Krb5KeyTab /etc/httpd/conf/ipa.keytab - KrbSaveCredentials on - Require valid-user - ErrorDocument 401 /ipa/errors/unauthorized.html - - SetHandler python-program - PythonInterpreter main_interpreter - PythonHandler ipaserver::handler - PythonDebug Off - PythonOption SCRIPT_NAME /ipa - PythonAutoReload Off - -</Location> - -#<Location "/ipa/xml"> -# SetHandler python-program -# PythonInterpreter main_interpreter -# PythonHandler ipaserver::xmlrpc -# PythonDebug Off -# PythonOption SCRIPT_NAME /ipa/xml -# PythonAutoReload Off -#</Location> - -#<Location "/ipa/json"> -# SetHandler python-program -# PythonInterpreter main_interpreter -# PythonHandler ipaserver::jsonrpc -# PythonDebug Off -# PythonOption SCRIPT_NAME /ipa/json -# PythonAutoReload Off -#</Location> - -#<Location "/ipa/ui"> -# SetHandler python-program -# PythonInterpreter main_interpreter -# PythonHandler ipaserver::webui -# PythonDebug Off -# PythonOption SCRIPT_NAME /ipa/ui -# PythonAutoReload Off -#</Location> -Alias /ipa-assets/ "/var/cache/ipa/assets/" -<Directory "/var/cache/ipa/assets"> - Allow from all - AllowOverride None - # add Indexes to Options to allow browsing - Options FollowSymLinks - ExpiresActive On - ExpiresDefault A31536000 -</Directory> +# Configure mod_wsgi handler for /ipa +WSGIDaemonProcess ipa processes=2 threads=1 maximum-requests=500 +WSGIProcessGroup ipa +WSGIApplicationGroup ipa +WSGIImportScript /usr/share/ipa/wsgi.py process-group=ipa application-group=ipa +WSGIScriptAlias /ipa /usr/share/ipa/wsgi.py +WSGIScriptReloading Off +# Turn off mod_msgi handler for errors, config, crl: <Location "/ipa/errors"> SetHandler None </Location> - <Location "/ipa/config"> SetHandler None </Location> - <Location "/ipa/crl"> SetHandler None </Location> +# Protect /ipa with Kerberos +<Location "/ipa"> + AuthType Kerberos + AuthName "Kerberos Login" + KrbMethodNegotiate on + KrbMethodK5Passwd off + KrbServiceName HTTP + KrbAuthRealms $REALM + Krb5KeyTab /etc/httpd/conf/ipa.keytab + KrbSaveCredentials on + Require valid-user + ErrorDocument 401 /ipa/errors/unauthorized.html +</Location> + + # This is where we redirect on failed auth Alias /ipa/errors "/usr/share/ipa/html" @@ -102,7 +69,6 @@ Alias /ipa/config "/usr/share/ipa/html" # For CRL publishing Alias /ipa/crl "/var/lib/pki-ca/publish" - <Directory "/var/lib/pki-ca/publish"> SetHandler None AllowOverride None @@ -111,6 +77,18 @@ Alias /ipa/crl "/var/lib/pki-ca/publish" Allow from all </Directory> + +# WebUI assets +Alias /ipa-assets/ "/var/cache/ipa/assets/" +<Directory "/var/cache/ipa/assets"> + Allow from all + AllowOverride None + Options FollowSymLinks + ExpiresActive On + ExpiresDefault A31536000 +</Directory> + + # Protect our CGIs <Directory /var/www/cgi-bin> AuthType Kerberos @@ -125,20 +103,19 @@ Alias /ipa/crl "/var/lib/pki-ca/publish" ErrorDocument 401 /ipa/errors/unauthorized.html </Directory> + # migration related pages Alias /ipa/migration "/usr/share/ipa/migration" - <Directory "/usr/share/ipa/migration"> AllowOverride None Satisfy Any Allow from all - AddHandler mod_python .py PythonHandler mod_python.publisher </Directory> -#Alias /ipatest "/usr/share/ipa/ipatest" +#Alias /ipatest "/usr/share/ipa/ipatest" #<Directory "/usr/share/ipa/ipatest"> # AuthType Kerberos # AuthName "Kerberos Login" diff --git a/install/share/Makefile.am b/install/share/Makefile.am index e3e7cf606..92d50775f 100644 --- a/install/share/Makefile.am +++ b/install/share/Makefile.am @@ -38,6 +38,7 @@ app_DATA = \ unique-attributes.ldif \ schema_compat.uldif \ ldapi.ldif \ + wsgi.py \ $(NULL) EXTRA_DIST = \ diff --git a/install/share/wsgi.py b/install/share/wsgi.py new file mode 100644 index 000000000..457d8e024 --- /dev/null +++ b/install/share/wsgi.py @@ -0,0 +1,13 @@ +""" +WSGI appliction for IPA server. +""" + +from ipalib import api +api.bootstrap(context='server', debug=True, log=None) +api.finalize() +api.log.info('*** PROCESS START ***') +import ipawebui +ui = ipawebui.create_wsgi_app(api) + +# This is the WSGI callable: +application = api.Backend.session diff --git a/ipa.spec.in b/ipa.spec.in index 0607dd76d..f7f3a2903 100644 --- a/ipa.spec.in +++ b/ipa.spec.in @@ -75,6 +75,7 @@ Requires: cyrus-sasl-gssapi Requires: ntp Requires: httpd Requires: mod_python +Requires: mod_wsgi Requires: mod_auth_kerb %{?fc8:Requires: mod_nss >= 1.0.7-2} %{?fc9:Requires: mod_nss >= 1.0.7-5} @@ -383,6 +384,7 @@ fi %{python_sitelib}/ipaserver/* %{python_sitelib}/ipawebui/* %dir %{_usr}/share/ipa +%{_usr}/share/ipa/wsgi.py %{_usr}/share/ipa/*.ldif %{_usr}/share/ipa/*.uldif %{_usr}/share/ipa/*.template @@ -497,6 +499,9 @@ fi %endif %changelog +* Wed Feb 24 2010 Jason Gerard DeRose <jderose@redhat.com> - 1.99-17 +- Added Require mod_wsgi, added share/ipa/wsgi.py + * Thu Feb 11 2010 Jason Gerard DeRose <jderose@redhat.com> - 1.99-16 - Require python-wehjit >= 0.2.2 diff --git a/ipaserver/__init__.py b/ipaserver/__init__.py index 874ac3e24..b0be96bd2 100644 --- a/ipaserver/__init__.py +++ b/ipaserver/__init__.py @@ -20,209 +20,3 @@ """ Package containing server backend. """ - -import traceback -from xmlrpclib import dumps, Fault -from ipalib import api - - -# This is a simple way to ensure that ipalib.api is only initialized -# when ipaserver is imported from within the Apache process: -try: - from mod_python import apache - api.bootstrap(context='server', debug=True, log=None) - api.finalize() - api.log.info('*** PROCESS START ***') - import ipawebui - ui = ipawebui.create_wsgi_app(api) -except ImportError: - pass - - -# START code from paste -# Red Hat does not hold the copyright to the following code. The following code -# is from paste: -# http://pythonpaste.org/ -# Which in turn was based on Robert Brewer's modpython_gateway: -# http://projects.amor.org/misc/svn/modpython_gateway.py - -class InputWrapper(object): - - def __init__(self, req): - self.req = req - - def close(self): - pass - - def read(self, size=-1): - return self.req.read(size) - - def readline(self, size=-1): - return self.req.readline(size) - - def readlines(self, hint=-1): - return self.req.readlines(hint) - - def __iter__(self): - line = self.readline() - while line: - yield line - # Notice this won't prefetch the next line; it only - # gets called if the generator is resumed. - line = self.readline() - - -class ErrorWrapper(object): - - def __init__(self, req): - self.req = req - - def flush(self): - pass - - def write(self, msg): - self.req.log_error(msg) - - def writelines(self, seq): - self.write(''.join(seq)) - - -bad_value = ("You must provide a PythonOption '%s', either 'on' or 'off', " - "when running a version of mod_python < 3.1") - - -class Handler(object): - - def __init__(self, req): - self.started = False - - options = req.get_options() - - # Threading and forking - try: - q = apache.mpm_query - threaded = q(apache.AP_MPMQ_IS_THREADED) - forked = q(apache.AP_MPMQ_IS_FORKED) - except AttributeError: - threaded = options.get('multithread', '').lower() - if threaded == 'on': - threaded = True - elif threaded == 'off': - threaded = False - else: - raise ValueError(bad_value % "multithread") - - forked = options.get('multiprocess', '').lower() - if forked == 'on': - forked = True - elif forked == 'off': - forked = False - else: - raise ValueError(bad_value % "multiprocess") - - env = self.environ = dict(apache.build_cgi_env(req)) - - if 'SCRIPT_NAME' in options: - # Override SCRIPT_NAME and PATH_INFO if requested. - env['SCRIPT_NAME'] = options['SCRIPT_NAME'] - env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):] - else: - env['SCRIPT_NAME'] = '' - env['PATH_INFO'] = req.uri - - env['wsgi.input'] = InputWrapper(req) - env['wsgi.errors'] = ErrorWrapper(req) - env['wsgi.version'] = (1, 0) - env['wsgi.run_once'] = False - if env.get("HTTPS") in ('yes', 'on', '1'): - env['wsgi.url_scheme'] = 'https' - else: - env['wsgi.url_scheme'] = 'http' - env['wsgi.multithread'] = threaded - env['wsgi.multiprocess'] = forked - - self.request = req - - def run(self, application): - try: - result = application(self.environ, self.start_response) - for data in result: - self.write(data) - if not self.started: - self.request.set_content_length(0) - if hasattr(result, 'close'): - result.close() - except: - traceback.print_exc(None, self.environ['wsgi.errors']) - if not self.started: - self.request.status = 500 - self.request.content_type = 'text/plain' - data = "A server error occurred. Please contact the administrator." - self.request.set_content_length(len(data)) - self.request.write(data) - - def start_response(self, status, headers, exc_info=None): - if exc_info: - try: - if self.started: - raise exc_info[0], exc_info[1], exc_info[2] - finally: - exc_info = None - - self.request.status = int(status[:3]) - - for key, val in headers: - if key.lower() == 'content-length': - self.request.set_content_length(int(val)) - elif key.lower() == 'content-type': - self.request.content_type = val - else: - self.request.headers_out.add(key, val) - - return self.write - - def write(self, data): - if not self.started: - self.started = True - self.request.write(data) - -# END code from paste - - -def adapter(req, app): - if apache.mpm_query(apache.AP_MPMQ_IS_THREADED): - response = dumps( - Fault(3, 'Apache must use the forked model'), - methodresponse=True, - ) - req.content_type = 'text/xml' - req.set_content_length(len(response)) - req.write(response) - else: - Handler(req).run(app) - return apache.OK - - -def xmlrpc(req): - """ - mod_python handler for XML-RPC requests. - """ - return adapter(req, api.Backend.xmlserver) - - -def jsonrpc(req): - """ - mod_python handler for JSON-RPC requests (place holder). - """ - return adapter(req, api.Backend.jsonserver) - - -def webui(req): - """ - mod_python handler for web-UI requests (place holder). - """ - return adapter(req, ui) - - -def handler(req): - return adapter(req, api.Backend.session) |