Merge branch 'master' of ssh://git.onelab.eu/git/myslice
authorLoic Baron <loic.baron@lip6.fr>
Mon, 10 Feb 2014 17:29:40 +0000 (18:29 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Mon, 10 Feb 2014 17:29:40 +0000 (18:29 +0100)
19 files changed:
README
apache/APACHE.notes
apache/unfold-init-ssl.sh
apache/unfold-ssl.conf [new file with mode: 0644]
apache/unfold.conf
debian/unfold.install
debian/unfold.postinst
manifold/manifoldapi.py
manifold/manifoldproxy.py
myslice/configengine.py [moved from myslice/config.py with 76% similarity]
plugins/scheduler2/asdf.txt [new file with mode: 0644]
portal/django_passresetview.py
portal/forms.py
portal/homeview.py
portal/platformview.py
portal/resourceview.py
portal/sliceview.py
setup.py
unfold/page.py

diff --git a/README b/README
index 69360d3..78ffe6c 100644 (file)
--- a/README
+++ b/README
@@ -16,7 +16,7 @@ $ apt-get install python-django-south
 -- or --
 * git clone ssh://yourlogin@git.onelab.eu/git/myslice.git
 
-* edit myslice/config.py and enter the details of your manifold backend
+* edit/create myslice/myslice.ini and enter the details of your manifold backend
 
 $ apt-get install python-django-south
 * init django
index 7c77e4b..d3c55e0 100644 (file)
@@ -14,7 +14,7 @@ A few notes and caveats must be outlined though below; see also unfold-init-ssl.
 * all the local material for this deployment gets into /etc/unfold/
 
 * I could not find a way to have client-auth without server auth;
-  this is totally weird, and stupid, but just so
+  this is totally weird, and stupid, but that's how it is
   so there is a need to install a (probably self-signed) cert 
   and related key in 
 /etc/unfold/myslice.cert
index 74c1c32..69be328 100755 (executable)
@@ -10,6 +10,8 @@ trusted_roots=/etc/unfold/trusted_roots
 key=/etc/unfold/myslice.key
 cert=/etc/unfold/myslice.cert
 
+# provide a hostname as the first arg to this command 
+# (otherwise we use hostname)
 if [[ -n "$@" ]] ; then hostname=$1; shift; else hostname=$(hostname); fi
 
 function init_trusted_roots () {
diff --git a/apache/unfold-ssl.conf b/apache/unfold-ssl.conf
new file mode 100644 (file)
index 0000000..337ce78
--- /dev/null
@@ -0,0 +1,48 @@
+# see also unfold.conf
+# see also unfold-initi-ssl.sh
+#
+# NOTE on packaging
+# 
+# this is not enabled by default because it would prevent apache from
+# starting up properly when /etc/unfold/trusted_roots is empty
+# 
+# So on debian you would typically need to run
+# a2ensite unfold-ssl.conf
+# unfold-init-ssl.sh
+# service apache2 restart
+#
+# This port is configured with client-certificate *required*
+# corresponding trusted roots (e.g. ple.gid and plc.gid) should be 
+# configured in /etc/unfold/trusted_roots
+# 
+
+<VirtualHost *:443>
+       WSGIDaemonProcess unfold-ssl processes=2 threads=25
+       WSGIProcessGroup  unfold-ssl
+       CustomLog ${APACHE_LOG_DIR}/myslice-ssl-access.log common
+       ErrorLog ${APACHE_LOG_DIR}/myslice-ssl-error.log
+        WSGIScriptAlias / /usr/share/unfold/apache/unfold.wsgi
+        <Directory /usr/share/unfold/apache/>
+        <Files unfold.wsgi>
+        Order deny,allow
+        Allow from all
+        </Files>
+        </Directory>
+        Alias /static/ /usr/share/unfold/static/
+        <Directory /usr/share/unfold/static>
+        Order deny,allow
+        Allow from all
+        </Directory>
+
+       SSLEngine on
+       SSLVerifyClient require
+       SSLVerifyDepth 5
+# make this a symlink to /etc/sfa/trusted_roots if that makes sense in your env.
+       SSLCACertificatePath /etc/unfold/trusted_roots
+# see init-ssl.sh for how to create self-signed stuff in here
+       SSLCertificateFile    /etc/unfold/myslice.cert
+       SSLCertificateKeyFile /etc/unfold/myslice.key
+
+#      SSLOptions +StdEnvVars +ExportCertData
+       SSLOptions +StdEnvVars
+</VirtualHost>
index ff3de7f..357db7e 100644 (file)
@@ -1,3 +1,5 @@
+# see also unfold-ssl.conf
+
 <VirtualHost *:80>
        WSGIDaemonProcess unfold processes=2 threads=25
        WSGIProcessGroup  unfold
         Allow from all
         </Directory>
 </VirtualHost>
-
-# This port (not necessarily well picked) is configured 
-# with client-certificate required
-# corresponding trusted roots (e.g. ple.gid and plc.gid) should be 
-# configured in /etc/unfold/trusted_roots
-# check Jordan's email and pointer to trac, although we do not want 
-# this to be optional on that port
-
-<VirtualHost *:443>
-       WSGIDaemonProcess unfold-ssl processes=2 threads=25
-       WSGIProcessGroup  unfold-ssl
-       CustomLog ${APACHE_LOG_DIR}/myslice-ssl-access.log common
-       ErrorLog ${APACHE_LOG_DIR}/myslice-ssl-error.log
-        WSGIScriptAlias / /usr/share/unfold/apache/unfold.wsgi
-        <Directory /usr/share/unfold/apache/>
-        <Files unfold.wsgi>
-        Order deny,allow
-        Allow from all
-        </Files>
-        </Directory>
-        Alias /static/ /usr/share/unfold/static/
-        <Directory /usr/share/unfold/static>
-        Order deny,allow
-        Allow from all
-        </Directory>
-
-       SSLEngine on
-       SSLVerifyClient require
-       SSLVerifyDepth 5
-# make this a symlink to /etc/sfa/trusted_roots if that makes sense in your env.
-       SSLCACertificatePath /etc/unfold/trusted_roots
-# see init-ssl.sh for how to create self-signed stuff in here
-       SSLCertificateFile    /etc/unfold/myslice.cert
-       SSLCertificateKeyFile /etc/unfold/myslice.key
-
-#      SSLOptions +StdEnvVars +ExportCertData
-       SSLOptions +StdEnvVars
-</VirtualHost>
index 9730d70..fb54250 100644 (file)
@@ -12,3 +12,5 @@ apache/unfold.wsgi /usr/share/unfold/apache/
 apache/unfold.conf /etc/apache2/sites-available
 manage.py usr/share/unfold/
 usr/bin/unfold-init-ssl.sh
+etc/unfold/trusted_roots
+var/unfold
index dd5c680..bdc052c 100644 (file)
@@ -1,15 +1,28 @@
 #!/bin/bash
+# tmp - (or?)
+set -x
 # if this requires a service to be running, add something like this
 # update-rc.d unfold defaults
 [ -d /var/unfold ] || mkdir /var/unfold
 chown -R www-data.www-data /var/unfold
 chmod -R 700 /var/unfold
-# upgrading from older packages -- temporary 
-[ -f /usr/share/unfold/myslice.sqlite3 ] && mv -f /usr/share/unfold/myslice.sqlite3 /var/unfold
-rm -f /etc/apache2/sites*/myslice.conf
 # upgrading end
 /usr/share/unfold/manage.py syncdb
 /usr/share/unfold/manage.py migrate
-a2dissite default
+# be ready, enable ssl
+a2enmod ssl
+# disable defaults; jessie seems to come with 000-default instead of just default
+# not quite sure about ssl, disable every possible combination
+for site in default default-ssl; do 
+    for prefix in "" "000-"; do
+       s=${prefix}${site}
+       a2dissite $s || :
+    done
+done
 a2ensite unfold.conf
+# create a server-side cert/key and passes on gids to rehash them
+# because we do not enable ssl by default it is maybe not quite right to call this
+# at install-time anymore, although it should not hurt either
+unfold-init-ssl.sh
+# restart in any case
 service apache2 restart
index 6639d48..b1a1a0c 100644 (file)
@@ -1,7 +1,7 @@
 # Manifold API Python interface
 import copy, xmlrpclib
 
-from myslice.config import Config
+from myslice.configengine import ConfigEngine
 
 from django.contrib import messages
 from manifoldresult import ManifoldResult, ManifoldCode, ManifoldException
@@ -39,8 +39,7 @@ class ManifoldAPI:
         self.trace = []
         self.calls = {}
         self.multicall = False
-        config = Config()
-        self.url = config.manifold_url()
+        self.url = ConfigEngine().manifold_url()
         self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
 
     def __repr__ (self): return "ManifoldAPI[%s]"%self.url
@@ -158,7 +157,6 @@ def execute_query(request, query):
     return _execute_query(request, query, manifold_api_session_auth)
 
 def execute_admin_query(request, query):
-    config = Config()
-    admin_user, admin_password = config.manifold_admin_user_password()
+    admin_user, admin_password = ConfigEngine().manifold_admin_user_password()
     admin_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
     return _execute_query(request, query, admin_auth)
index debd1f7..d0a8a3e 100644 (file)
@@ -11,7 +11,7 @@ from manifold.core.result_value import ResultValue
 from manifold.manifoldapi       import ManifoldAPI
 from manifold.manifoldresult    import ManifoldException
 from manifold.util.log          import Log
-from myslice.config             import Config
+from myslice.configengine       import ConfigEngine
 
 debug=False
 #debug=True
@@ -52,7 +52,7 @@ with the query passed using POST"""
         # We allow some requests to use the ADMIN user account
         if (manifold_query.get_from() == 'local:user' and manifold_query.get_action() == 'create') \
                 or (manifold_query.get_from() == 'local:platform' and manifold_query.get_action() == 'get'):
-            admin_user, admin_password = Config().manifold_admin_user_password()
+            admin_user, admin_password = ConfigEngine().manifold_admin_user_password()
             manifold_api_session_auth = {'AuthMethod': 'password', 'Username': admin_user, 'AuthString': admin_password}
         else:
             print request.session['manifold']
similarity index 76%
rename from myslice/config.py
rename to myslice/configengine.py
index 908b651..8c98b4c 100644 (file)
@@ -2,18 +2,26 @@ import os.path
 from ConfigParser import RawConfigParser
 from myslice.settings import ROOT
 
-# as this code suggests, you have the option to override these defaults
+#
+# DO NOT EDIT !!!
+#
+# This file does not contain any user-modifiable data
+#
+# te defaults here are, well, only default values, 
+# and, you have the option to override them
 # by writing a file myslice/myslice.ini
 # that looks like this
 #[manifold]
 #url = http://manifold.pl.sophia.inria.fr:7080/
 #admin_user = admin
 #admin_password = admin
+#[googlemap]
+#api_key=theapikeyasprovidedbygoogle
 
 # use a singleton instead of staticmethods
 from manifold.util.singleton    import Singleton
 
-class Config(object):
+class ConfigEngine(object):
     __metaclass__ = Singleton
 
     # the OpenLab-wide backend as managed by UPMC
@@ -30,9 +38,9 @@ class Config(object):
     def __init__ (self):
         parser = RawConfigParser ()
         parser.add_section('manifold')
-        parser.set ('manifold', 'url', Config.default_manifold_url)
-        parser.set ('manifold', 'admin_user', Config.default_manifold_admin_user)
-        parser.set ('manifold', 'admin_password', Config.default_manifold_admin_password)
+        parser.set ('manifold', 'url', ConfigEngine.default_manifold_url)
+        parser.set ('manifold', 'admin_user', ConfigEngine.default_manifold_admin_user)
+        parser.set ('manifold', 'admin_password', ConfigEngine.default_manifold_admin_password)
         parser.add_section('googlemap')
         parser.set ('googlemap','api_key', None)
         parser.read (os.path.join(ROOT,'myslice/myslice.ini'))
diff --git a/plugins/scheduler2/asdf.txt b/plugins/scheduler2/asdf.txt
new file mode 100644 (file)
index 0000000..1050001
--- /dev/null
@@ -0,0 +1 @@
+asd
\ No newline at end of file
index 769e9f5..8e57199 100644 (file)
@@ -34,7 +34,7 @@ If the email address provided does not exist in the system, this view won't send
 This prevents information leaking to potential attackers. If you want to provide an error message in this case, you can subclass PasswordResetForm 
 and use the password_reset_form argument.
 
-Users flagged with an unusable password (see set_unusable_password() aren't allowed to request a password reset to prevent misuse when using an external 
+Users flagged with an unusable password - see set_unusable_password() - aren't allowed to request a password reset to prevent misuse when using an external 
 authentication source like LDAP. Note that they won't receive any error message since this would expose their account's existence but no mail will be sent either.
 
 More Detail: https://docs.djangoproject.com/en/dev/topics/auth/default/#topics-auth-creating-users
@@ -64,7 +64,7 @@ from django.contrib.auth.decorators import login_required
 from portal.forms import PasswordResetForm, SetPasswordForm
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.sites.models import get_current_site
-from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher
+from django.contrib.auth.hashers import identify_hasher
 
 ##
 import os.path, re
index afbf344..61ffb86 100644 (file)
@@ -28,15 +28,26 @@ from portal.models import PendingUser, PendingSlice
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.auth.tokens import default_token_generator
 from django.contrib.auth import authenticate, get_user_model
-# TODO: Remove these automated forms and use html templates and views like any other page !
-# ERROR ImportError: cannot import name UNUSABLE_PASSWORD
-# XXX This is not compatible with Django 1.6.1
-# Ref: https://github.com/dot2code/varnish-bans-manager/issues/8
-from django.contrib.auth.hashers import UNUSABLE_PASSWORD, identify_hasher
 from django.contrib.sites.models import get_current_site
 from django.utils.http import int_to_base36
 from django.template import loader
 
+# TODO: Remove these automated forms and use html templates and views like any other page !
+from django.contrib.auth.hashers import identify_hasher
+# adapted from https://sourcegraph.com/github.com/fusionbox/django-authtools/symbols/python/authtools/forms
+
+def is_password_unusable(pw):
+    # like Django's is_password_usable, but only checks for unusable
+    # passwords, not invalidly encoded passwords too.
+    try:
+        # 1.5
+        from django.contrib.auth.hashers import UNUSABLE_PASSWORD
+        return pw == UNUSABLE_PASSWORD
+    except ImportError:
+        # 1.6
+        from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX
+        return pw.startswith(UNUSABLE_PASSWORD_PREFIX)
+
 
 
 
@@ -146,8 +157,7 @@ class PasswordResetForm(forms.Form):
         if not any(user.is_active for user in self.users_cache):
             # none of the filtered users are active
             raise forms.ValidationError(self.error_messages['unknown'])
-        if any((user.password == UNUSABLE_PASSWORD)
-               for user in self.users_cache):
+        if any(is_password_unusable(user.password) for user in self.users_cache):
             raise forms.ValidationError(self.error_messages['unusable'])
         return email
 
index a665677..c71481a 100644 (file)
@@ -9,15 +9,14 @@ from unfold.loginrequired import FreeAccessView
 
 from manifold.manifoldresult import ManifoldResult
 from ui.topmenu import topmenu_items, the_user
-from myslice.config import Config
+from myslice.configengine import ConfigEngine
 
 class HomeView (FreeAccessView):
 
     # expose this so we can mention the backend URL on the welcome page
     def default_env (self):
-        config=Config()
         return { 
-                 'MANIFOLD_URL':config.manifold_url(),
+                 'MANIFOLD_URL':ConfigEngine().manifold_url(),
                  }
 
     def post (self,request):
index 6f537d0..1b80349 100644 (file)
@@ -14,7 +14,7 @@ from ui.topmenu                  import topmenu_items_live, the_user
 
 from plugins.querytable          import QueryTable
 
-from myslice.config              import Config
+from myslice.configengine        import ConfigEngine
 
 # View for 1 platform and its details
 class PlatformView(FreeAccessView):
index 3ed9dcc..ac1813c 100644 (file)
@@ -9,7 +9,7 @@ from plugins.querytable         import QueryTable
 from plugins.lists.simplelist   import SimpleList
 from plugins.slicestat          import SliceStat
 
-from myslice.config             import Config
+from myslice.configengine       import ConfigEngine
 
 # View for 1 platform and its details
 class ResourceView(FreeAccessView):
@@ -53,7 +53,7 @@ class ResourceView(FreeAccessView):
             togglable  = True,
             query      = resource_query,
             query_all  = resource_query,
-            googlemap_api_key = Config().googlemap_api_key(),
+            googlemap_api_key = ConfigEngine().googlemap_api_key(),
             checkboxes = False,
             # center on Paris
             #latitude   = 49.,
index 0e56cce..eaec3fa 100644 (file)
@@ -29,7 +29,7 @@ from plugins.quickfilter             import QuickFilter
 from plugins.messages                import Messages
 from plugins.slicestat               import SliceStat
 
-from myslice.config                  import Config
+from myslice.configengine            import ConfigEngine
 
 tmp_default_slice='ple.upmc.myslicedemo'
 
@@ -56,8 +56,7 @@ class SliceView (LoginRequiredAutoLogoutView):
         page.add_js_chunks ('$(function() { messages.debug("sliceview: jQuery version " + $.fn.jquery); });')
         page.add_js_chunks ('$(function() { messages.debug("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
         page.add_js_chunks ('$(function() { messages.debug("sliceview: leases turned %s"); });'%("on" if do_query_leases else "off"))
-        config=Config()
-        page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(config.manifold_url()))
+        page.add_js_chunks ('$(function() { messages.debug("manifold URL %s"); });'%(ConfigEngine().manifold_url()))
 
         metadata = page.get_metadata()
         resource_md = metadata.details_by_object('resource')
@@ -199,7 +198,7 @@ class SliceView (LoginRequiredAutoLogoutView):
             query      = sq_resource,
             query_all  = query_resource_all,
             # this key is the one issued by google
-            googlemap_api_key = Config().googlemap_api_key(),
+            googlemap_api_key = ConfigEngine().googlemap_api_key(),
             # the key to use at init-time
             init_key   = main_query_init_key,
             checkboxes = True,
index e7ab6a5..d7008a3 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -16,10 +16,12 @@ setup(packages = packages,
       # xxx somehow this does not seem to show up in debian packaging
       scripts = [ 'apache/unfold-init-ssl.sh' ],
       data_files = [ 
-        ( '/usr/share/unfold/static/js', glob ('static/js/*')),
-        ( '/usr/share/unfold/static/css', glob ('static/css/*')),
-        ( '/usr/share/unfold/static/img', glob ('static/img/*')),
-        ( '/usr/share/unfold/static/fonts', glob ('static/fonts/*')),
-        ( '/usr/share/unfold/templates', glob ('templates/*')),
-        ( 'apache', [ 'apache/unfold.conf', 'apache/unfold.wsgi' ]),
+          ( '/usr/share/unfold/static/js', glob ('static/js/*')),
+          ( '/usr/share/unfold/static/css', glob ('static/css/*')),
+          ( '/usr/share/unfold/static/img', glob ('static/img/*')),
+          ( '/usr/share/unfold/static/fonts', glob ('static/fonts/*')),
+          ( '/usr/share/unfold/templates', glob ('templates/*')),
+          ( 'apache', [ 'apache/unfold.conf', 'apache/unfold-ssl.conf', 'apache/unfold.wsgi' ]),
+          ( '/etc/unfold/trusted_roots', []),
+          ( '/var/unfold', []),
         ])
index 834be7e..9c2fdd7 100644 (file)
@@ -10,7 +10,7 @@ from manifold.metadata import MetaData
 
 from unfold.prelude import Prelude
 
-from myslice.config import Config
+from myslice.configengine import ConfigEngine
 
 # decorator to deflect calls on this Page to its prelude
 def to_prelude (method):
@@ -124,8 +124,7 @@ class Page:
         self.add_js_init_chunks("var MANIFOLD_METADATA =" + self.get_metadata().to_json() + ";\n")
 
     def expose_js_manifold_config (self):
-        config=Config()
-        self.add_js_init_chunks(config.manifold_js_export())
+        self.add_js_init_chunks(ConfigEngine().manifold_js_export())
 
     #################### requirements/prelude management
     # just forward to self.prelude - see decorator above