From: Loic Baron Date: Mon, 10 Feb 2014 17:29:40 +0000 (+0100) Subject: Merge branch 'master' of ssh://git.onelab.eu/git/myslice X-Git-Tag: myslice-0.3-0~2 X-Git-Url: http://git.onelab.eu/?p=myslice.git;a=commitdiff_plain;h=ecf7dd5d099c5b94952b6795b748380e2284bc14;hp=cd4ef6cdd7ea6d4ead183970d20d4c3739481251 Merge branch 'master' of ssh://git.onelab.eu/git/myslice --- diff --git a/README b/README index 69360d37..78ffe6c2 100644 --- 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 diff --git a/apache/APACHE.notes b/apache/APACHE.notes index 7c77e4bd..d3c55e0c 100644 --- a/apache/APACHE.notes +++ b/apache/APACHE.notes @@ -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 diff --git a/apache/unfold-init-ssl.sh b/apache/unfold-init-ssl.sh index 74c1c32a..69be3283 100755 --- a/apache/unfold-init-ssl.sh +++ b/apache/unfold-init-ssl.sh @@ -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 index 00000000..337ce787 --- /dev/null +++ b/apache/unfold-ssl.conf @@ -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 +# + + + 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 + + + Order deny,allow + Allow from all + + + Alias /static/ /usr/share/unfold/static/ + + Order deny,allow + Allow from all + + + 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 + diff --git a/apache/unfold.conf b/apache/unfold.conf index ff3de7f0..357db7ee 100644 --- a/apache/unfold.conf +++ b/apache/unfold.conf @@ -1,3 +1,5 @@ +# see also unfold-ssl.conf + WSGIDaemonProcess unfold processes=2 threads=25 WSGIProcessGroup unfold @@ -16,41 +18,3 @@ Allow from all - -# 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 - - - 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 - - - Order deny,allow - Allow from all - - - Alias /static/ /usr/share/unfold/static/ - - Order deny,allow - Allow from all - - - 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 - diff --git a/debian/unfold.install b/debian/unfold.install index 9730d70c..fb542506 100644 --- a/debian/unfold.install +++ b/debian/unfold.install @@ -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 diff --git a/debian/unfold.postinst b/debian/unfold.postinst index dd5c6805..bdc052ca 100644 --- a/debian/unfold.postinst +++ b/debian/unfold.postinst @@ -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 diff --git a/manifold/manifoldapi.py b/manifold/manifoldapi.py index 6639d484..b1a1a0cc 100644 --- a/manifold/manifoldapi.py +++ b/manifold/manifoldapi.py @@ -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) diff --git a/manifold/manifoldproxy.py b/manifold/manifoldproxy.py index debd1f7a..d0a8a3ea 100644 --- a/manifold/manifoldproxy.py +++ b/manifold/manifoldproxy.py @@ -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'] diff --git a/myslice/config.py b/myslice/configengine.py similarity index 76% rename from myslice/config.py rename to myslice/configengine.py index 908b6512..8c98b4c0 100644 --- a/myslice/config.py +++ b/myslice/configengine.py @@ -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 index 00000000..10500012 --- /dev/null +++ b/plugins/scheduler2/asdf.txt @@ -0,0 +1 @@ +asd \ No newline at end of file diff --git a/portal/django_passresetview.py b/portal/django_passresetview.py index 769e9f5a..8e571998 100644 --- a/portal/django_passresetview.py +++ b/portal/django_passresetview.py @@ -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 diff --git a/portal/forms.py b/portal/forms.py index afbf3442..61ffb860 100644 --- a/portal/forms.py +++ b/portal/forms.py @@ -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 diff --git a/portal/homeview.py b/portal/homeview.py index a6656772..c71481ad 100644 --- a/portal/homeview.py +++ b/portal/homeview.py @@ -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): diff --git a/portal/platformview.py b/portal/platformview.py index 6f537d0c..1b80349b 100644 --- a/portal/platformview.py +++ b/portal/platformview.py @@ -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): diff --git a/portal/resourceview.py b/portal/resourceview.py index 3ed9dcca..ac1813c7 100644 --- a/portal/resourceview.py +++ b/portal/resourceview.py @@ -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., diff --git a/portal/sliceview.py b/portal/sliceview.py index 0e56cce7..eaec3faa 100644 --- a/portal/sliceview.py +++ b/portal/sliceview.py @@ -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, diff --git a/setup.py b/setup.py index e7ab6a5b..d7008a38 100644 --- 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', []), ]) diff --git a/unfold/page.py b/unfold/page.py index 834be7e3..9c2fdd7e 100644 --- a/unfold/page.py +++ b/unfold/page.py @@ -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