2014-10-22

web2py admin behind Apache proxy

So I have this web2py configuration where Apache httpd SSL proxies URLs of the form https://server/web2py/ to http://localhost:8081/web2py (web2py Rocket):
RewriteEngine on

RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !=localhost
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

RewriteRule ^/webpy$ /web2py/ [R,L]

ProxyRequests off
ProxyPass /web2py/ http://localhost:8081/web2py/

<Location /web2py/>
    ProxyPassReverse http://localhost:8081/web2py/
</Location>
This includes a modified global routes.py:
default_application = 'init'    # ordinarily set in base routes.py
default_controller = 'default'  # ordinarily set in app-specific routes.py
default_function = 'index'      # ordinarily set in app-specific routes.py

BASE = '/web2py'

routes_in = (
    # do not reroute admin unless you want to disable it
    (BASE + '/admin', '/admin/default/index'),
    (BASE + '/admin/$anything', '/admin/$anything'),
    # do not reroute appadmin unless you want to disable it
    (BASE + '/$app/appadmin', '/$app/appadmin/index'),
    (BASE + '/$app/appadmin/$anything', '/$app/appadmin/$anything'),
    # do not reroute static files
    (BASE + '/$app/static/$anything', '/$app/static/$anything'),
    # reroute favicon and robots, use exable for lack of better choice
    ('/favicon.ico', '/examples/static/favicon.ico'),
    ('/robots.txt', '/examples/static/robots.txt'),
    # do other stuff
    ((r'.*http://otherdomain\.com.* (?P.*)', r'/app/ctr\g')),
    # remove the BASE prefix
    (BASE + '/$anything', '/$anything'),
)

routes_out = [(x, y) for (y, x) in routes_in]

logging = 'debug'

#fix ticket routing
error_message = '<html><body><h1>%s</h1></body></html>'
error_message_ticket = '<html><body><h1>Internal error</h1>Ticket issued: <a href="' + BASE + '/admin/default/ticket/%(ticket)s" target="_blank">%(ticket)s</a></body></html>'

def __routes_doctest():
    pass

if __name__ == '__main__':
    import doctest
    doctest.testmod()
But if you go to https://hostname/web2py/admin, it returns Admin is disabled because insecure channel. However, the channel IS secure since we are using SSL via the Apache. Offending Lines of code: applications/admin/models/access.py:
if request.is_https:
    session.secure()
elif not request.is_local and not DEMO_MODE:
    raise HTTP(200, T('Admin is disabled because insecure channel'))
According to https://groups.google.com/forum/#!searchin/web2py-developers/request.is_local/web2py-developers/kkBvSzX4wO8/Rjom8huf4yMJ , request.is_local is False behind the Apache proxy, so calling https://server/web2py/admin fails both request.is_https (since the proxy forwards to http://) and request.is_local. Commenting out this block causes login dialog to fail (for the same reasons). Thus the correct modification is to use request.is_local = True

No comments:

Post a Comment