fix ListResources
[sfa.git] / sfa / trust / auth.py
index 218783e..e787fe4 100644 (file)
@@ -3,16 +3,20 @@
 #
 import sys
 
 #
 import sys
 
+from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \
+    BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied
+from sfa.util.sfalogging import logger
+from sfa.util.config import Config
+from sfa.util.xrn import Xrn, get_authority
+
+from sfa.trust.gid import GID
+from sfa.trust.rights import Rights
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
 from sfa.trust.certificate import Keypair, Certificate
 from sfa.trust.credential import Credential
-from sfa.trust.trustedroot import TrustedRootList
-from sfa.util.faults import *
+from sfa.trust.trustedroots import TrustedRoots
 from sfa.trust.hierarchy import Hierarchy
 from sfa.trust.hierarchy import Hierarchy
-from sfa.util.config import *
-from sfa.util.xrn import get_authority
-from sfa.util.sfaticket import *
+from sfa.trust.sfaticket import SfaTicket
 
 
-from sfa.util.sfalogging import sfa_logger
 
 class Auth:
     """
 
 class Auth:
     """
@@ -27,25 +31,31 @@ class Auth:
         self.load_trusted_certs()
 
     def load_trusted_certs(self):
         self.load_trusted_certs()
 
     def load_trusted_certs(self):
-        self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
-        self.trusted_cert_file_list = TrustedRootList(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()
 
         
 
         
-        
-    def checkCredentials(self, creds, operation, hrn = None):
+    def checkCredentials(self, creds, operation, xrns=[]):
+        if not isinstance(xrns, list):
+            xrns = [xrns]
+        hrns = [Xrn(xrn).hrn for xrn in xrns] 
         valid = []
         if not isinstance(creds, list):
             creds = [creds]
         valid = []
         if not isinstance(creds, list):
             creds = [creds]
-        sfa_logger().debug("Auth.checkCredentials with %d creds"%len(creds))
+        logger.debug("Auth.checkCredentials with %d creds on hrns=%s"%(len(creds),hrns))
+        # won't work if either creds or hrns is empty - let's make it more explicit
+        if not creds: raise InsufficientRights("Access denied - no credential provided")
+        if not hrns: hrns = [None]
         for cred in creds:
         for cred in creds:
-            try:
-                self.check(cred, operation, hrn)
-                valid.append(cred)
-            except:
-                cred_obj=Credential(string=cred)
-                sfa_logger().debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
-                error = sys.exc_info()[:2]
-                continue
+            for hrn in hrns:
+                try:
+                    self.check(cred, operation, hrn)
+                    valid.append(cred)
+                except:
+                    cred_obj=Credential(string=cred)
+                    logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
+                    error = sys.exc_info()[:2]
+                    continue
             
         if not len(valid):
             raise InsufficientRights('Access denied: %s -- %s' % (error[0],error[1]))
             
         if not len(valid):
             raise InsufficientRights('Access denied: %s -- %s' % (error[0],error[1]))
@@ -53,7 +63,7 @@ class Auth:
         return valid
         
         
         return valid
         
         
-    def check(self, cred, operation, hrn = None):
+    def check(self, cred_string, operation, hrn = None):
         """
         Check the credential against the peer cert (callerGID included 
         in the credential matches the caller that is connected to the 
         """
         Check the credential against the peer cert (callerGID included 
         in the credential matches the caller that is connected to the 
@@ -61,7 +71,10 @@ class Auth:
         trusted cert and check if the credential is allowed to perform 
         the specified operation.    
         """
         trusted cert and check if the credential is allowed to perform 
         the specified operation.    
         """
-        self.client_cred = Credential(string = cred)
+        cred = Credential(string = cred_string)    
+        self.client_cred = cred
+        logger.debug("Auth.check: handling hrn=%s and credential=%s"%\
+                         (hrn,cred.get_summary_tostring()))
         self.client_gid = self.client_cred.get_gid_caller()
         self.object_gid = self.client_cred.get_gid_object()
         
         self.client_gid = self.client_cred.get_gid_caller()
         self.object_gid = self.client_cred.get_gid_object()
         
@@ -145,7 +158,8 @@ class Auth:
 
     def authenticateCert(self, certStr, requestHash):
         cert = Certificate(string=certStr)
 
     def authenticateCert(self, certStr, requestHash):
         cert = Certificate(string=certStr)
-        self.validateCert(self, cert)   
+        # xxx should be validateCred ??
+        self.validateCred(cert)   
 
     def gidNoop(self, gidStr, value, requestHash):
         self.authenticateGid(gidStr, [gidStr, value], requestHash)
 
     def gidNoop(self, gidStr, value, requestHash):
         self.authenticateGid(gidStr, [gidStr, value], requestHash)
@@ -229,81 +243,64 @@ class Auth:
     
         raise PermissionError(name)
 
     
         raise PermissionError(name)
 
-    def determine_user_rights(self, caller_hrn, record):
+    def determine_user_rights(self, caller_hrn, reg_record):
         """
         Given a user credential and a record, determine what set of rights the
         user should have to that record.
         
         """
         Given a user credential and a record, determine what set of rights the
         user should have to that record.
         
-        This is intended to replace determine_rights() and
+        This is intended to replace determine_user_rights() and
         verify_cancreate_credential()
         """
 
         rl = Rights()
         verify_cancreate_credential()
         """
 
         rl = Rights()
-        type = record['type']
-
-
-        if type=="slice":
-            researchers = record.get("researcher", [])
-            pis = record.get("PI", [])
-            if (caller_hrn in researchers + pis):
-                rl.add("refresh")
-                rl.add("embed")
-                rl.add("bind")
-                rl.add("control")
-                rl.add("info")
-
-        elif type == "authority":
-            pis = record.get("PI", [])
-            operators = record.get("operator", [])
+        type = reg_record.type
+
+        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
+            researcher_hrns = [ user.hrn for user in reg_record.reg_researchers ]
+            # locating PIs attached to that slice
+            slice_pis=reg_record.get_pis()
+            pi_hrns = [ user.hrn for user in slice_pis ]
+            if (caller_hrn in researcher_hrns + pi_hrns):
+                rl.add('refresh')
+                rl.add('embed')
+                rl.add('bind')
+                rl.add('control')
+                rl.add('info')
+
+        elif type == 'authority':
+            pi_hrns = [ user.hrn for user in reg_record.reg_pis ]
             if (caller_hrn == self.config.SFA_INTERFACE_HRN):
             if (caller_hrn == self.config.SFA_INTERFACE_HRN):
-                rl.add("authority")
-                rl.add("sa")
-                rl.add("ma")
-            if (caller_hrn in pis):
-                rl.add("authority")
-                rl.add("sa")
-            if (caller_hrn in operators):
-                rl.add("authority")
-                rl.add("ma")
-
-        elif type == "user":
-            rl.add("refresh")
-            rl.add("resolve")
-            rl.add("info")
-
-        elif type == "node":
-            rl.add("operator")
+                rl.add('authority')
+                rl.add('sa')
+                rl.add('ma')
+            if (caller_hrn in pi_hrns):
+                rl.add('authority')
+                rl.add('sa')
+            # NOTE: for the PL implementation, this 'operators' list 
+            # amounted to users with 'tech' role in that site 
+            # it seems like this is not needed any longer, so for now I just drop that
+            # operator_hrns = reg_record.get('operator',[])
+            # if (caller_hrn in operator_hrns):
+            #    rl.add('authority')
+            #    rl.add('ma')
+
+        elif type == 'user':
+            rl.add('refresh')
+            rl.add('resolve')
+            rl.add('info')
+
+        elif type == 'node':
+            rl.add('operator')
 
         return rl
 
 
         return rl
 
-    def verify_cancreate_credential(self, src_cred, record):
-        """
-        Verify that a user can retrive a particular type of credential.
-        For slices, the user must be on the researcher list. For SA and
-        MA the user must be on the pi and operator lists respectively
-        """
-
-        type = record.get_type()
-        cred_object_hrn = src_cred.get_gid_object().get_hrn()
-        if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
-            return
-        if type=="slice":
-            researchers = record.get("researcher", [])
-            if not (cred_object_hrn in researchers):
-                raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
-        elif type == "sa":
-            pis = record.get("pi", [])
-            if not (cred_object_hrn in pis):
-                raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
-        elif type == "ma":
-            operators = record.get("operator", [])
-            if not (cred_object_hrn in operators):
-                raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
-
     def get_authority(self, hrn):
         return get_authority(hrn)
 
     def get_authority(self, hrn):
         return get_authority(hrn)
 
-    def filter_creds_by_caller(self, creds, caller_hrn):
+    def filter_creds_by_caller(self, creds, caller_hrn_list):
         """
         Returns a list of creds who's gid caller matches the 
         specified caller hrn
         """
         Returns a list of creds who's gid caller matches the 
         specified caller hrn
@@ -311,10 +308,12 @@ class Auth:
         if not isinstance(creds, list):
             creds = [creds]
         creds = []
         if not isinstance(creds, list):
             creds = [creds]
         creds = []
+        if not isinstance(caller_hrn_list, list):
+            caller_hrn_list = [caller_hrn_list]
         for cred in creds:
             try:
                 tmp_cred = Credential(string=cred)
         for cred in creds:
             try:
                 tmp_cred = Credential(string=cred)
-                if tmp_cred.get_gid_caller().get_hrn() == caller_hrn:
+                if tmp_cred.get_gid_caller().get_hrn() in [caller_hrn_list]:
                     creds.append(cred)
             except: pass
         return creds
                     creds.append(cred)
             except: pass
         return creds