mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Run ipaserver under mod_wsgi
This commit is contained in:
@@ -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,7 +11,33 @@ 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
|
||||
|
||||
|
||||
# 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"
|
||||
@@ -24,64 +49,6 @@ AddType application/java-archive jar
|
||||
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>
|
||||
|
||||
|
||||
<Location "/ipa/errors">
|
||||
SetHandler None
|
||||
</Location>
|
||||
|
||||
<Location "/ipa/config">
|
||||
SetHandler None
|
||||
</Location>
|
||||
|
||||
<Location "/ipa/crl">
|
||||
SetHandler None
|
||||
</Location>
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -38,6 +38,7 @@ app_DATA = \
|
||||
unique-attributes.ldif \
|
||||
schema_compat.uldif \
|
||||
ldapi.ldif \
|
||||
wsgi.py \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
|
||||
13
install/share/wsgi.py
Normal file
13
install/share/wsgi.py
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user