Merge branch 'geni-v3' of ssh://git.onelab.eu/git/sfa into geni-v3
authorLoic Baron <loic.baron@lip6.fr>
Wed, 4 Mar 2015 12:51:58 +0000 (13:51 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Wed, 4 Mar 2015 12:51:58 +0000 (13:51 +0100)
12 files changed:
init.d/functions.sfa
sfa.spec
sfa/client/sfaclientlib.py
sfa/client/sfi.py
sfa/importer/iotlabimporter.py
sfa/iotlab/LDAPapi.py
sfa/iotlab/iotlabslices.py
sfa/planetlab/plaggregate.py
sfa/planetlab/pldriver.py
sfa/server/threadedserver.py
sfa/trust/auth.py
sfa/trust/credential.py

index 010ab41..038adc9 100644 (file)
@@ -32,6 +32,10 @@ if [ $PPID -ne 1 -a -z "$SYSTEMCTL_SKIP_REDIRECT" ] && \
        esac
 fi
 
+# ubuntu does not have /bin/systemctl
+[ -f /bin/systemctl ] || _use_systemctl=0
+
+
 systemctl_redirect () {
        local s
        local prog=${1##*/}
index e1da07b..ac2cb5e 100644 (file)
--- a/sfa.spec
+++ b/sfa.spec
@@ -1,6 +1,6 @@
 %define name sfa
 %define version 3.1
-%define taglevel 12
+%define taglevel 13
 
 %define release %{taglevel}%{?pldistro:.%{pldistro}}%{?date:.%{date}}
 %global python_sitearch        %( python -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)" )
@@ -264,6 +264,9 @@ fi
 #[ "$1" -ge "1" ] && service sfa-cm restart || :
 
 %changelog
+* Mon Dec 01 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-13
+- bugfix - was adding extraneous backslashes in email address when attempting to AddPerson
+
 * Mon Sep 15 2014 Thierry Parmentelat <thierry.parmentelat@sophia.inria.fr> - sfa-3.1-12
 - getting closer with the pip/pypi packaging
 
index 78f6f48..bc4a1d1 100644 (file)
@@ -121,7 +121,7 @@ class SfaClientBootstrap:
     ######################################## *_produce methods
     ### step1
     # unconditionnally create a self-signed certificate
-    def self_signed_cert_produce (self,output):
+    def self_signed_cert_produce (self, output):
         self.assert_private_key()
         private_key_filename = self.private_key_filename()
         keypair=Keypair(filename=private_key_filename)
@@ -131,7 +131,7 @@ class SfaClientBootstrap:
         self_signed.sign ()
         self_signed.save_to_file (output)
         self.logger.debug("SfaClientBootstrap: Created self-signed certificate for %s in %s"%\
-                              (self.hrn,output))
+                              (self.hrn, output))
         return output
 
     ### step2 
@@ -142,7 +142,8 @@ class SfaClientBootstrap:
         certificate_filename = self.self_signed_cert_filename()
         certificate_string = self.plain_read (certificate_filename)
         self.assert_private_key()
-        registry_proxy = SfaServerProxy (self.registry_url, self.private_key_filename(),
+        registry_proxy = SfaServerProxy (self.registry_url,
+                                         self.private_key_filename(),
                                          certificate_filename)
         try:
             credential_string=registry_proxy.GetSelfCredential (certificate_string, self.hrn, "user")
@@ -316,10 +317,14 @@ class SfaClientBootstrap:
             raise IOError,"Missing %s file %s"%(kind,filename)
         return True
         
-    def assert_private_key (self): return self.assert_filename (self.private_key_filename(),"private key")
-    def assert_self_signed_cert (self): return self.assert_filename (self.self_signed_cert_filename(),"self-signed certificate")
-    def assert_my_credential (self): return self.assert_filename (self.my_credential_filename(),"user's credential")
-    def assert_my_gid (self): return self.assert_filename (self.my_gid_filename(),"user's GID")
+    def assert_private_key (self):
+        return self.assert_filename (self.private_key_filename(),"private key")
+    def assert_self_signed_cert (self):
+        return self.assert_filename (self.self_signed_cert_filename(),"self-signed certificate")
+    def assert_my_credential (self):
+        return self.assert_filename (self.my_credential_filename(),"user's credential")
+    def assert_my_gid (self):
+        return self.assert_filename (self.my_gid_filename(),"user's GID")
 
 
     # decorator to make up the other methods
index dcad9da..6f5f64d 100644 (file)
@@ -674,6 +674,8 @@ use this if you mean an authority instead""")
     
     # init self-signed cert, user credentials and gid
     def bootstrap (self):
+        if self.options.verbose:
+            self.logger.info("Initializing SfaClientBootstrap with {}".format(self.reg_url))
         client_bootstrap = SfaClientBootstrap (self.user, self.reg_url, self.options.sfi_dir,
                                                logger=self.logger)
         # if -k is provided, use this to initialize private key
index 3528db4..25427d1 100644 (file)
@@ -552,7 +552,7 @@ class IotlabImporter:
         # import site and node records in site into the SFA db.
         self.import_sites_and_nodes(testbed_shell)
         #import users and slice into the SFA DB.
-        self.import_persons_and_slices(testbed_shell)
+        #self.import_persons_and_slices(testbed_shell)
 
          ### remove stale records
         # special records must be preserved
index 217e200..4fea094 100644 (file)
@@ -589,51 +589,28 @@ class LDAPapi:
         .. seealso:: make_ldap_filters_from_record
 
         """
-        logger.debug(" \r\n \t LDAP LdapAddUser \r\n\r\n ================\r\n ")
-        user_ldap_attrs = self.make_ldap_attributes_from_record(record)
-        logger.debug("JORDAN LdapAddUser (ctd) user_ldap_attrs=%r" % user_ldap_attrs)
-
-        #Check if user already in LDAP wih email, first name and last name
-        filter_by = self.make_ldap_filters_from_record(user_ldap_attrs)
-        logger.debug("JORDAN LdapAddUser (ctd) filter_by = %r" % filter_by)
-        user_exist = self.LdapSearch(filter_by)
-        logger.debug("JORDAN LdapAddUser (ctd) user_exist = %r" % user_exist)
-        if user_exist:
-            logger.warning(" \r\n \t LDAP LdapAddUser user %s %s \
-                        already exists" % (user_ldap_attrs['sn'],
-                           user_ldap_attrs['mail']))
-            return {'bool': False}
-
-        #Bind to the server
-        result = self.conn.connect()
-        logger.debug("JORDAN LdapAddUser (ctd) result = %r" % result)
-
-        if(result['bool']):
-
-            # A dict to help build the "body" of the object
-            logger.debug(" \r\n \t LDAP LdapAddUser attrs %s "
-                         % user_ldap_attrs)
-
+        filter_by = self.make_ldap_filters_from_record({'email' : record['email']})
+        user = self.LdapSearch(filter_by)
+        if user:
+            logger.debug("LDAPapi.py user ldap exist \t%s" % user)
+            # user = [('uid=saint,ou=People,dc=senslab,dc=info', {'uid': ['saint'], 'givenName': ['Fred'], ...})]
+            return {'bool': True, 'uid': user[0][1]['uid'][0]}
+        else:
+            self.conn.connect()
+            user_ldap_attrs = self.make_ldap_attributes_from_record(record)
+            logger.debug("LDAPapi.py user ldap doesn't exist \t%s" % user_ldap_attrs)
             # The dn of our new entry/object
             dn = 'uid=' + user_ldap_attrs['uid'] + "," + self.baseDN
-
             try:
                 ldif = modlist.addModlist(user_ldap_attrs)
-                logger.debug("LDAPapi.py add attrs %s \r\n  ldif %s"
-                             % (user_ldap_attrs, ldif))
                 self.conn.ldapserv.add_s(dn, ldif)
-
-                logger.info("Adding user %s login %s in LDAP"
-                            % (user_ldap_attrs['cn'], user_ldap_attrs['uid']))
             except ldap.LDAPError, error:
                 logger.log_exc("LDAP Add Error %s" % error)
                 return {'bool': False, 'message': error}
-
             self.conn.close()
             return {'bool': True, 'uid': user_ldap_attrs['uid']}
-        else:
-            return result
-
+        
+        
     def LdapDelete(self, person_dn):
         """Deletes a person in LDAP. Uses the dn of the user.
 
index 7206c92..e24560c 100644 (file)
@@ -359,7 +359,7 @@ class IotlabSlices:
                 logger.debug(" IOTLABSLICES \tverify_slice hrn %s USER %s"
                              % (hrn, user))
 
-                 # add the external slice to the local SFA iotlab DB
+                # add the external slice to the local SFA iotlab DB
                 if sfa_slice:
                     self.driver.AddSlice(sfa_slice, user)
 
@@ -390,222 +390,36 @@ class IotlabSlices:
 
         .. seealso:: AddPerson
         .. note:: Removed unused peer and sfa_peer parameters. SA 18/07/13.
-
-
         """
-        slice_user = slice_record['user']['hrn']
-
         if options is None: options={}
-        logger.debug("IOTLABSLICES \tverify_persons \tslice_hrn  %s  \
-                    \t slice_record %s\r\n users %s \t  "
-                     % (slice_hrn, slice_record, users))
-
-        users_by_email = {}
-        #users_dict : dict whose keys can either be the user's hrn or its id.
-        #Values contains only id and hrn
-        users_dict = {}
-        
-        # XXX LOIC !!! Fix: Only 1 user per slice in iotlab
-        users = [slice_record['user']]
-        #First create dicts by hrn and id for each user in the user record list:
-        for info in users:
-            # if 'slice_record' in info:
-            #     slice_rec = info['slice_record']
-                # if 'user' in slice_rec :
-                #     user = slice_rec['user']
-
-            if 'email' in info:
-                users_by_email[info['email']] = info
-                users_dict[info['email']] = info
-
-        #logger.debug("IOTLABSLICES.PY \t verify_person  \
-        #                users_dict %s \r\n user_by_email %s \r\n  "
-        #             % (users_dict, users_by_email))
-
-        existing_user_ids = []
-        existing_users_by_email = dict()
-        existing_users = []
-        # Check if user is in Iotlab LDAP using its hrn.
-        # Assuming Iotlab is centralised :  one LDAP for all sites,
-        # user's record_id unknown from LDAP
-        # LDAP does not provide users id, therefore we rely on email to find the
-        # user in LDAP
-
-        if users_by_email:
-            #Construct the list of filters (list of dicts) for GetPersons
-            filter_user = [users_by_email[email] for email in users_by_email]
-            #Check user i in LDAP with GetPersons
-            #Needed because what if the user has been deleted in LDAP but
-            #is still in SFA?
-            # GetPersons -> LdapFindUser -> _process_ldap_info_for_one_user
-            # XXX LOIC Fix in _process_ldap_info_for_one_user not to update user with hrn=None
-            existing_users = self.driver.testbed_shell.GetPersons(filter_user)
-            logger.debug(" \r\n IOTLABSLICES.PY \tverify_person  filter_user %s\
-                       existing_users %s  "
-                        % (filter_user, existing_users))
-            #User is in iotlab LDAP
-            if existing_users:
-                for user in existing_users:
-                    user['login'] = user['uid']
-                    # XXX LOIC Fix we already have all informations comming from Allocate
-                    #users_dict[user['email']].update(user)
-                    existing_users_by_email[user['email']] = user
-                logger.debug("User is in iotlab LDAP slice_record[user] = %s" % slice_user)
-
-            # User from another known trusted federated site. Check
-            # if a iotlab account matching the email has already been created.
-            else:
-                req = 'mail='
-                if isinstance(users, list):
-                    req += users[0]['email']
-                else:
-                    req += users['email']
-                ldap_reslt = self.driver.testbed_shell.ldap.LdapSearch(req)
-                logger.debug("LdapSearch slice_record[user] = %s" % slice_user)
-                if ldap_reslt:
-                    logger.debug(" IOTLABSLICES.PY \tverify_person users \
-                                USER already in Iotlab \t ldap_reslt %s \
-                                " % (ldap_reslt))
-                    existing_users.append(ldap_reslt[1])
-                    logger.debug("ldap_reslt slice_record[user] = %s" % slice_user)
-                else:
-                    #User not existing in LDAP
-                    logger.debug("IOTLABSLICES.PY \tverify_person users \
-                                not in ldap ...NEW ACCOUNT NEEDED %s \r\n \t \
-                                ldap_reslt %s " % (users, ldap_reslt))
-
-        requested_user_emails = users_by_email.keys()
-        # requested_user_hrns = \
-        #     [users_by_email[user]['hrn'] for user in users_by_email]
-        # logger.debug("IOTLABSLICES.PY \tverify_person  \
-        #                users_by_email  %s " % (users_by_email))
-
-        # #Check that the user of the slice in the slice record
-        # #matches one of the existing users
-        # try:
-        #     if slice_record['reg-researchers'][0] in requested_user_hrns:
-        #         logger.debug(" IOTLABSLICES  \tverify_person ['PI']\
-        #                         slice_record %s" % (slice_record))
-
-        # except KeyError:
-        #     pass
-
-        # The function returns a list of added persons (to the LDAP ?)
-        added_persons = list()
-
-        # We go though each requested user and make sure it exists both in the
-        # LDAP and in the local DB
-        for user_email in requested_user_emails:
-            user = users_by_email[user_email]
-
-            person = {
+        user = slice_record['user']
+        logger.debug("IOTLABSLICES \tverify_persons \tuser  %s " % user)
+        person = {
                 'peer_person_id': None,
                 'mail'      : user['email'],
                 'email'     : user['email'],
                 'key_ids'   : user.get('key_ids', []),
-                'hrn'       : users_by_email[user['email']]['hrn'],
-            }
-            if 'first_name' in user:
-                person['first_name'] = user['first_name']
-            if 'last_name' in user:
-                person['last_name'] = user['last_name']
-            if 'person_id' in user:
-                person['person_id'] = user['person_id']
-            if user['keys']:
-                # XXX Only one key is kept for IoTLAB
-                person['pkey'] = user['keys'][0]
-
-            # LDAP 
-            if users_by_email not in existing_users_by_email.keys():
-                ret = self.driver.AddPerson(person)
-                if 'uid' in ret:
-                    person['uid'] = ret['uid']
-                    added_persons.append(person)
-                else:
-                    logger.debug(" IOTLABSLICES ret message %s" %(ret))
-            else:
-                person['uid'] = existing_users_by_email[user['email']]['uid']
-
-            # Local DB
-            self.driver.add_person_to_db(person)
-
-            
-        # Set the login in the slice_record XXX
-        slice_record['login'] = existing_users[0]['uid']
-
-        return added_persons
-
-#DEPRECATED|        # users to be added, removed or updated
-#DEPRECATED|        #One user in one iotlab slice : there should be no need
-#DEPRECATED|        #to remove/ add any user from/to a slice.
-#DEPRECATED|        #However a user from SFA which is not registered in Iotlab yet
-#DEPRECATED|        #should be added to the LDAP.
-#DEPRECATED|        added_user_emails = set(requested_user_emails).\
-#DEPRECATED|                                        difference(set(existing_user_emails))
-#DEPRECATED|
-#DEPRECATED|
-#DEPRECATED|        #self.verify_keys(existing_slice_users, updated_users_list, \
-#DEPRECATED|                                                            #peer, append)
-#DEPRECATED|
-#DEPRECATED|        # XXX JORDAN the uid of the user is put in slice_record['login']
-#DEPRECATED|        added_persons = []
-#DEPRECATED|        # add new users
-#DEPRECATED|        #requested_user_email is in existing_user_emails
-#DEPRECATED|        if len(added_user_emails) == 0:
-#DEPRECATED|            slice_record['login'] = existing_users[0]['uid']
-#DEPRECATED|            #slice_record['login'] = users_dict[requested_user_emails[0]]['uid']
-#DEPRECATED|            logger.debug(" IOTLABSLICES  \tverify_person QUICK DIRTY %s"
-#DEPRECATED|                         % (slice_record))
-#DEPRECATED|            # XXX JORDAN uid == 'register'
-#DEPRECATED|        logger.debug("JORDAN USERS BY EMAIL: %r" % users_by_email)
-#DEPRECATED|
-#DEPRECATED|        # XXX JORDAN i have no added_user_emails
-#DEPRECATED|        logger.debug("JORDAN: added_user_emails: %r" % added_user_emails)
-#DEPRECATED|        for added_user_email in added_user_emails:
-#DEPRECATED|            added_user = users_dict[added_user_email]
-#DEPRECATED|            logger.debug(" IOTLABSLICES \r\n \r\n  \t  verify_person \
-#DEPRECATED|                         added_user %s" % (added_user))
-#DEPRECATED|            person = {}
-#DEPRECATED|            person['peer_person_id'] = None
-#DEPRECATED|            k_list = ['first_name', 'last_name', 'person_id']
-#DEPRECATED|            for k in k_list:
-#DEPRECATED|                if k in added_user:
-#DEPRECATED|                    person[k] = added_user[k]
-#DEPRECATED|            # bug user without key
-#DEPRECATED|            if added_user['keys']:
-#DEPRECATED|                person['pkey'] = added_user['keys'][0]
-#DEPRECATED|            person['mail'] = added_user['email']
-#DEPRECATED|            person['email'] = added_user['email']
-#DEPRECATED|            person['key_ids'] = added_user.get('key_ids', [])
-#DEPRECATED|
-#DEPRECATED|            # JORDAN
-#DEPRECATED|            # This is the only call to AddPerson. We need to be sure to provide
-#DEPRECATED|            # the right hrn, by default it used to be done in the function like
-#DEPRECATED|            # this:
-#DEPRECATED|            # person['hrn'] = self.testbed_shell.root_auth + '.' + ret['uid']
-#DEPRECATED|            person['hrn'] = users_by_email[added_user['email']]['hrn']
-#DEPRECATED|
-#DEPRECATED|            # This only deals with the LDAP (now)
-#DEPRECATED|            ret = self.driver.AddPerson(person)
-#DEPRECATED|            # This will check if we have a record in the local DB and add it if necessary
-#DEPRECATED|            self.__add_person_to_db(person)
-#DEPRECATED|
-#DEPRECATED|            if 'uid' in ret:
-#DEPRECATED|                # meaning bool is True and the AddPerson was successful
-#DEPRECATED|                person['uid'] = ret['uid']
-#DEPRECATED|                slice_record['login'] = person['uid']
-#DEPRECATED|            else:
-#DEPRECATED|                # error message in ret
-#DEPRECATED|                logger.debug(" IOTLABSLICES ret message %s" %(ret))
-#DEPRECATED|
-#DEPRECATED|            logger.debug(" IOTLABSLICES \r\n \r\n  \t THE SECOND verify_person\
-#DEPRECATED|                           person %s" % (person))
-#DEPRECATED|            #Update slice_Record with the id now known to LDAP
-#DEPRECATED|
-#DEPRECATED|
-#DEPRECATED|            added_persons.append(person)
-#DEPRECATED|        return added_persons
-
+                'hrn'       : user['hrn'],
+        }
+        if 'first_name' in user:
+            person['first_name'] = user['first_name']
+        if 'last_name' in user:
+            person['last_name'] = user['last_name']
+        if 'person_id' in user:
+            person['person_id'] = user['person_id']
+        if user['keys']:
+            # Only one key is kept for IoTLAB
+            person['pkey'] = user['keys'][0]
+        # SFA DB (if user already exist we do nothing)
+        self.driver.add_person_to_db(person)
+        # Iot-LAB LDAP (if user already exist we do nothing)
+        ret = self.driver.AddPerson(person)
+        # user uid information is only in LDAP
+        # Be carreful : global scope of dict slice_record in driver
+        slice_record['login'] = ret['uid']
+        return person
+
+       
 
     def verify_keys(self, persons, users, peer, options=None):
         """
index 2876694..9ab8c6d 100644 (file)
@@ -18,7 +18,7 @@ from sfa.rspecs.elements.lease import Lease
 from sfa.rspecs.elements.granularity import Granularity
 from sfa.rspecs.version_manager import VersionManager
 
-from sfa.planetlab.plxrn import PlXrn, hostname_to_urn, hrn_to_pl_slicename, slicename_to_hrn, top_auth, hash_loginbase
+from sfa.planetlab.plxrn import PlXrn, hostname_to_urn
 from sfa.planetlab.vlink import get_tc_rate
 from sfa.planetlab.topology import Topology
 from sfa.storage.model import SliverAllocation
index 88c41fe..d16b23a 100644 (file)
@@ -23,7 +23,7 @@ from sfa.managers.driver import Driver
 from sfa.planetlab.plshell import PlShell
 from sfa.planetlab.plaggregate import PlAggregate
 from sfa.planetlab.plslices import PlSlices
-from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, xrn_to_hostname, top_auth, hash_loginbase
+from sfa.planetlab.plxrn import PlXrn, slicename_to_hrn, hostname_to_hrn, hrn_to_pl_slicename, top_auth, hash_loginbase
 
 
 def list_to_dict(recs, key):
index dbdde3f..7dfac7d 100644 (file)
@@ -145,11 +145,13 @@ class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
 class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
 
     def __init__(self, server_address, HandlerClass, key_file, cert_file, logRequests=True):
-        """Secure XML-RPC server.
+        """
+        Secure XML-RPC server.
 
         It it very similar to SimpleXMLRPCServer but it uses HTTPS for transporting XML data.
         """
-        logger.debug("SecureXMLRPCServer.__init__, server_address=%s, cert_file=%s, key_file=%s"%(server_address,cert_file,key_file))
+        logger.debug("SecureXMLRPCServer.__init__, server_address=%s, " 
+                     "cert_file=%s, key_file=%s"%(server_address,cert_file,key_file))
         self.logRequests = logRequests
         self.interface = None
         self.key_file = key_file
index 59ca4c2..2120a80 100644 (file)
@@ -4,9 +4,10 @@
 import sys
 from types import StringTypes
 
-from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \
-    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden, \
-    BadArgs
+from sfa.util.faults import InsufficientRights, MissingCallerGID, \
+    MissingTrustedRoots, PermissionError, BadRequestHash, \
+    ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, \
+    Forbidden, BadArgs
 from sfa.util.sfalogging import logger
 from sfa.util.config import Config
 from sfa.util.xrn import Xrn, get_authority
@@ -34,10 +35,13 @@ class Auth:
         self.load_trusted_certs()
 
     def load_trusted_certs(self):
-        self.trusted_cert_list = TrustedRoots(self.config.get_trustedroots_dir()).get_list()
-        self.trusted_cert_file_list = TrustedRoots(self.config.get_trustedroots_dir()).get_file_list()
+        self.trusted_cert_list = \
+            TrustedRoots(self.config.get_trustedroots_dir()).get_list()
+        self.trusted_cert_file_list = \
+            TrustedRoots(self.config.get_trustedroots_dir()).get_file_list()
 
-    # this convenience methods extracts speaking_for_xrn from the passed options using 'geni_speaking_for'
+    # this convenience methods extracts speaking_for_xrn
+    # from the passed options using 'geni_speaking_for'
     def checkCredentialsSpeaksFor (self, *args, **kwds):
         if 'options' not in kwds:
             logger.error ("checkCredentialsSpeaksFor was not passed options=options")
@@ -62,7 +66,8 @@ class Auth:
                 error="checkCredentials: expected a string, received %s"%(type(cred))
             else:
                 cred_obj=Credential(string=cred)
-                logger.info("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
+                logger.info("failed to validate credential - dump=%s"%\
+                            cred_obj.dump_string(dump_parents=True))
                 error = sys.exc_info()[:2]
             return error
 
@@ -76,7 +81,7 @@ class Auth:
         if not isinstance(xrns, list):
             xrns = [xrns]
 
-        slice_xrns = Xrn.filter_type(xrns, 'slice')
+        slice_xrns  = Xrn.filter_type(xrns, 'slice')
         sliver_xrns = Xrn.filter_type(xrns, 'sliver')
 
         # we are not able to validate slivers in the traditional way so 
@@ -122,7 +127,7 @@ class Auth:
         
     def check(self, credential, operation, hrn = None):
         """
-        Check the credential against the peer cert (callerGID included 
+        Check the credential against the peer cert (callerGID) included 
         in the credential matches the caller that is connected to the 
         HTTPS connection, check if the credential was signed by a 
         trusted cert and check if the credential is allowed to perform 
@@ -152,7 +157,8 @@ class Auth:
                 raise InsufficientRights(operation)
 
         if self.trusted_cert_list:
-            self.client_cred.verify(self.trusted_cert_file_list, self.config.SFA_CREDENTIAL_SCHEMA)
+            self.client_cred.verify(self.trusted_cert_file_list,
+                                    self.config.SFA_CREDENTIAL_SCHEMA)
         else:
            raise MissingTrustedRoots(self.config.get_trustedroots_dir())
        
@@ -168,7 +174,7 @@ class Auth:
 
     def check_ticket(self, ticket):
         """
-        Check if the tickt was signed by a trusted cert
+        Check if the ticket was signed by a trusted cert
         """
         if self.trusted_cert_list:
             client_ticket = SfaTicket(string=ticket)
@@ -315,7 +321,8 @@ class Auth:
         rl = Rights()
         type = reg_record.type
 
-        logger.debug("entering determine_user_rights with record %s and caller_hrn %s"%(reg_record, caller_hrn))
+        logger.debug("entering determine_user_rights with record %s and caller_hrn %s"%\
+                     (reg_record, caller_hrn))
 
         if type == 'slice':
             # researchers in the slice are in the DB as-is
index 9d0fd28..109a529 100644 (file)
@@ -26,7 +26,8 @@
 # Credentials are signed XML files that assign a subject gid privileges to an object gid
 ##
 
-import os
+import os, os.path
+import subprocess
 from types import StringTypes
 import datetime
 from StringIO import StringIO
@@ -512,7 +513,8 @@ class Credential(object):
                     # Below throws InUse exception if we forgot to clone the attribute first
                     oldAttr = signed_cred.setAttributeNode(attr.cloneNode(True))
                     if oldAttr and oldAttr.value != attr.value:
-                        msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value)
+                        msg = "Delegating cred from owner %s to %s over %s:\n - Replaced attribute %s value '%s' with '%s'" % \
+                              (self.parent.gidCaller.get_urn(), self.gidCaller.get_urn(), self.gidObject.get_urn(), oldAttr.name, oldAttr.value, attr.value)
                         logger.warn(msg)
                         #raise CredentialNotVerifiable("Can't encode new valid delegated credential: %s" % msg)
 
@@ -798,12 +800,12 @@ class Credential(object):
 
         # make sure it is not expired
         if self.get_expiration() < datetime.datetime.utcnow():
-            raise CredentialNotVerifiable("Credential %s expired at %s" % (self.get_summary_tostring(), self.expiration.strftime(SFATIME_FORMAT)))
+            raise CredentialNotVerifiable("Credential %s expired at %s" % \
+                                          (self.get_summary_tostring(),
+                                           self.expiration.strftime(SFATIME_FORMAT)))
 
         # Verify the signatures
         filename = self.save_to_random_tmp_file()
-        if trusted_certs is not None:
-            cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs])
 
         # If caller explicitly passed in None that means skip cert chain validation.
         # - Strange and not typical
@@ -826,11 +828,25 @@ class Credential(object):
             if trusted_certs is None:
                 break
 
-#            print "Doing %s --verify --node-id '%s' %s %s 2>&1" % \
-#                (self.xmlsec_path, ref, cert_args, filename)
-            verified = os.popen('%s --verify --node-id "%s" %s %s 2>&1' \
-                            % (self.xmlsec_path, ref, cert_args, filename)).read()
-            if not verified.strip().startswith("OK"):
+            # Thierry - jan 2015
+            # up to fedora20 we used os.popen and checked that the output begins with OK
+            # turns out, with fedora21, there is extra input before this 'OK' thing
+            # looks like we're better off just using the exit code - that's what it is made for
+            #cert_args = " ".join(['--trusted-pem %s' % x for x in trusted_certs])
+            #command = '{} --verify --node-id "{}" {} {} 2>&1'.\
+            #          format(self.xmlsec_path, ref, cert_args, filename)
+            command = [ self.xmlsec_path, '--verify', '--node-id', ref ]
+            for trusted in trusted_certs:
+                command += ["--trusted-pem", trusted ]
+            command += [ filename ]
+            logger.debug("Running " + " ".join(command))
+            try:
+                verified = subprocess.check_output(command, stderr=subprocess.STDOUT)
+                logger.debug("xmlsec command returned {}".format(verified))
+                if "OK\n" not in verified:
+                    logger.warning("WARNING: xmlsec1 seemed to return fine but without a OK in its output")
+            except subprocess.CalledProcessError as e:
+                verified = e.output
                 # xmlsec errors have a msg= which is the interesting bit.
                 mstart = verified.find("msg=")
                 msg = ""
@@ -838,7 +854,9 @@ class Credential(object):
                     mstart = mstart + 4
                     mend = verified.find('\\', mstart)
                     msg = verified[mstart:mend]
-                raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s %s" % (self.get_summary_tostring(), ref, msg, verified.strip()))
+                logger.warning("Credential.verify - failed - xmlsec1 returned {}".format(verified.strip()))
+                raise CredentialNotVerifiable("xmlsec1 error verifying cred %s using Signature ID %s: %s" % \
+                                              (self.get_summary_tostring(), ref, msg))
         os.remove(filename)
 
         # Verify the parents (delegation)
@@ -936,7 +954,8 @@ class Credential(object):
 
         # Give up, credential does not pass issuer verification
 
-        raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
+        raise CredentialNotVerifiable("Could not verify credential owned by %s for object %s. Cred signer %s not the trusted authority for Cred target %s" % \
+                                      (self.gidCaller.get_urn(), self.gidObject.get_urn(), root_cred_signer.get_hrn(), root_target_gid.get_hrn()))
 
 
     ##
@@ -951,22 +970,26 @@ class Credential(object):
         # parents rights (and check delegate bits)
         if not parent_cred.get_privileges().is_superset(self.get_privileges()):
             raise ChildRightsNotSubsetOfParent(("Parent cred ref %s rights " % parent_cred.get_refid()) +
-                self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % (self.get_summary_tostring(), self.get_refid())) +
+                self.parent.get_privileges().save_to_string() + (" not superset of delegated cred %s ref %s rights " % \
+                                                                 (self.get_summary_tostring(), self.get_refid())) +
                 self.get_privileges().save_to_string())
 
         # make sure my target gid is the same as the parent's
         if not parent_cred.get_gid_object().save_to_string() == \
            self.get_gid_object().save_to_string():
-            raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+            raise CredentialNotVerifiable("Delegated cred %s: Target gid not equal between parent and child. Parent %s" % \
+                                          (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
 
         # make sure my expiry time is <= my parent's
         if not parent_cred.get_expiration() >= self.get_expiration():
-            raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+            raise CredentialNotVerifiable("Delegated credential %s expires after parent %s" % \
+                                          (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
 
         # make sure my signer is the parent's caller
         if not parent_cred.get_gid_caller().save_to_string(False) == \
            self.get_signature().get_issuer_gid().save_to_string(False):
-            raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
+            raise CredentialNotVerifiable("Delegated credential %s not signed by parent %s's caller" % \
+                                          (self.get_summary_tostring(), parent_cred.get_summary_tostring()))
                 
         # Recurse
         if parent_cred.parent: