summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gerard DeRose <jderose@redhat.com>2010-02-24 11:29:23 -0700
committerJason Gerard DeRose <jderose@redhat.com>2010-03-01 20:22:22 -0700
commit1d529a8d09a2577da9a3883572c2f8ae6dd04d58 (patch)
tree79f3ae824c739232b8c3ac835f04e3799ec4ce60
parent942919bef77030b10a96cab66ab878a8a3d7ef10 (diff)
downloadfreeipa-1d529a8d09a2577da9a3883572c2f8ae6dd04d58.tar.gz
freeipa-1d529a8d09a2577da9a3883572c2f8ae6dd04d58.tar.xz
freeipa-1d529a8d09a2577da9a3883572c2f8ae6dd04d58.zip
Run ipaserver under mod_wsgi
-rw-r--r--install/conf/ipa.conf103
-rw-r--r--install/share/Makefile.am1
-rw-r--r--install/share/wsgi.py13
-rw-r--r--ipa.spec.in5
-rw-r--r--ipaserver/__init__.py206
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)