adding support for geni_speaking_for option
authorTony Mack <tmack@paris.CS.Princeton.EDU>
Wed, 22 Jan 2014 03:03:23 +0000 (22:03 -0500)
committerTony Mack <tmack@paris.CS.Princeton.EDU>
Wed, 22 Jan 2014 03:03:23 +0000 (22:03 -0500)
sfa/managers/aggregate_manager.py
sfa/methods/Allocate.py
sfa/methods/Delete.py
sfa/methods/Describe.py
sfa/methods/ListResources.py
sfa/methods/PerformOperationalAction.py
sfa/methods/Provision.py
sfa/methods/Renew.py
sfa/methods/Status.py
sfa/trust/auth.py

index 5108c4f..b10e441 100644 (file)
@@ -63,6 +63,7 @@ class AggregateManager:
             'geni_single_allocation': 0, # Accept operations that act on as subset of slivers in a given state.
             'geni_allocate': 'geni_many',# Multiple slivers can exist and be incrementally added, including those which connect or overlap in some way.
             'geni_credential_types': cred_types,
+            'geni_handles_speaksfor': True,     # supports 'speaks for' credentials
         }
         version.update(version_generic)
         version.update(self.rspec_versions())
index 4105f31..a9dac0d 100644 (file)
@@ -37,9 +37,10 @@ class Allocate(Method):
     def call(self, xrn, creds, rspec, options):
         xrn = Xrn(xrn, type='slice')
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, xrn.get_hrn(), self.name))
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
 
         # Find the valid credentials
-        valid_creds = self.api.auth.checkCredentials(creds, 'createsliver', xrn.get_hrn())
+        valid_creds = self.api.auth.checkCredentials(creds, 'createsliver', xrn.get_hrn(), speaking_for_hrn=speaking_for)
         # use the expiration from the first valid credential to determine when 
         # the slivers should expire.
         expiration = datetime_to_string(Credential(cred=valid_creds[0]).expiration)
index 94684b9..eed8a39 100644 (file)
@@ -24,8 +24,10 @@ class Delete(Method):
     returns = Parameter(int, "1 if successful")
     
     def call(self, xrns, creds, options):
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
         valid_creds = self.api.auth.checkCredentials(creds, 'deletesliver', xrns,
-                      check_sliver_callback = self.api.driver.check_sliver_credentials)
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for)
 
         #log the call
         origin_hrn = Credential(cred=valid_creds[0]).get_gid_caller().get_hrn()
index 8485f79..ec60489 100644 (file)
@@ -36,9 +36,10 @@ class Describe(Method):
                 options['geni_rspec_version'] = options['rspec_version']
             else:
                 raise SfaInvalidArgument('Must specify an rspec version option. geni_rspec_version cannot be null')
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
         valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', urns, \
-                      check_sliver_callback = self.api.driver.check_sliver_credentials)
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for)
 
         # get hrn of the original caller 
         origin_hrn = options.get('origin_hrn', None)
index b7ac0b7..a9ffe76 100644 (file)
@@ -32,9 +32,11 @@ class ListResources(Method):
                 options['geni_rspec_version'] = options['rspec_version']
             else:
                 raise SfaInvalidArgument('Must specify an rspec version option. geni_rspec_version cannot be null')
+
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
  
         # Find the valid credentials
-        valid_creds = self.api.auth.checkCredentials(creds, 'listnodes')
+        valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', speaking_for_hrn=speaking_for)
 
         # get hrn of the original caller 
         origin_hrn = options.get('origin_hrn', None)
index 01d853d..a263514 100644 (file)
@@ -31,9 +31,12 @@ class PerformOperationalAction(Method):
     def call(self, xrns, creds, action, options):
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, xrns, self.name))
 
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
+        
         # Find the valid credentials
         valid_creds = self.api.auth.checkCredentials(creds, 'createsliver', xrns,
-                      check_sliver_callback = self.api.driver.check_sliver_credentials) 
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for) 
         origin_hrn = Credential(cred=valid_creds[0]).get_gid_caller().get_hrn()
         self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, xrns, self.name))
         result = self.api.manager.PerformOperationalAction(self.api, xrns, creds, action, options)
index a94c1bc..a3fd0fe 100644 (file)
@@ -31,9 +31,12 @@ class Provision(Method):
     def call(self, xrns, creds, options):
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, xrns, self.name))
 
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
+        
         # Find the valid credentials
         valid_creds = self.api.auth.checkCredentials(creds, 'createsliver', xrns,
-                      check_sliver_callback = self.api.driver.check_sliver_credentials) 
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for) 
         origin_hrn = Credential(cred=valid_creds[0]).get_gid_caller().get_hrn()
         self.api.logger.info("interface: %s\tcaller-hrn: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, origin_hrn, xrns, self.name))
         result = self.api.manager.Provision(self.api, xrns, creds, options)
index 8f31786..7b470f1 100644 (file)
@@ -32,9 +32,12 @@ class Renew(Method):
 
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tcaller-creds: %s\tmethod-name: %s"%(self.api.interface, urns, creds, self.name))
 
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
+    
         # Find the valid credentials
         valid_creds = self.api.auth.checkCredentials(creds, 'renewsliver', urns,
-                      check_sliver_callback = self.api.driver.check_sliver_credentials)
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for)
 
         # Validate that the time does not go beyond the credential's expiration time
         requested_time = utcparse(expiration_time)
index 164093e..36da58e 100644 (file)
@@ -19,8 +19,10 @@ class Status(Method):
     returns = Parameter(dict, "Status details")
 
     def call(self, xrns, creds, options):
+        (speaking_for, _) = urn_to_hrn(options.get('geni_speaking_for'))
         valid_creds = self.api.auth.checkCredentials(creds, 'sliverstatus', xrns,
-                      check_sliver_callback = self.api.driver.check_sliver_credentials)
+                      check_sliver_callback = self.api.driver.check_sliver_credentials,
+                      speaking_for_hrn=speaking_for)
 
         self.api.logger.info("interface: %s\ttarget-hrn: %s\tmethod-name: %s"%(self.api.interface, xrns, self.name))
         return self.api.manager.Status(self.api, xrns, creds, options)
index d217b1c..35c76b7 100644 (file)
@@ -35,7 +35,14 @@ class Auth:
         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, xrns=[], check_sliver_callback=None):
+    def checkCredentials(self, creds, operation, xrns=[], check_sliver_callback=None, speaking_for_hrn=None):
+
+        def log_invalid_cred(cred):
+            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]
+            return error
+
         # if xrns are specified they cannot be None or empty string
         if xrns:
             for xrn in xrns:
@@ -53,6 +60,7 @@ class Auth:
         # we make sure not to include sliver urns/hrns in the core validation loop
         hrns = [Xrn(xrn).hrn for xrn in xrns if xrn not in sliver_xrns] 
         valid = []
+        speaks_for_cred = None
         if not isinstance(creds, list):
             creds = [creds]
         logger.debug("Auth.checkCredentials with %d creds on hrns=%s"%(len(creds),hrns))
@@ -65,10 +73,16 @@ class Auth:
                     self.check(cred, operation, hrn)
                     valid.append(cred)
                 except:
-                    cred_obj=Credential(cred=cred)
-                    logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True))
-                    error = sys.exc_info()[:2]
-                    continue
+                    if speaking_for_hrn:
+                    try:
+                        self.check(cred, operation, speaking_for_hrn)
+                        speaks_for_cred = cred
+                        valid.append(cred)
+                    except:
+                        error = log_invalid_cred(cred)
+                else:
+                    error = log_invalid_cred(cred)
+                continue
         
         # make sure all sliver xrns are validated against the valid credentials
         if sliver_xrns:
@@ -81,6 +95,9 @@ class Auth:
         if not len(valid):
             raise Forbidden("Invalid credential")
         
+        if speaking_for_hrn and not speaks_for_cred:
+            raise InsufficientRights('Access denied: "geni_speaking_for" option specified but no valid speaks for credential found: %s -- %s' % (error[0],error[1]))
+        
         return valid