From 8f367b9457f47ba1e3b8a56eea8ed5c9b1e52eed Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Tue, 8 Jan 2013 13:35:20 -0500 Subject: [PATCH] working toward full support for sliver urns in the aggregate and registry --- sfa/managers/aggregate_manager.py | 1 - sfa/managers/registry_manager.py | 8 ++++++- sfa/methods/Describe.py | 4 ++-- sfa/openstack/nova_driver.py | 7 ++++++ sfa/planetlab/plaggregate.py | 8 +++---- sfa/planetlab/pldriver.py | 36 ++++++++++++++++++++++++++++++- sfa/trust/auth.py | 30 ++++++++++++++++++++------ sfa/util/xrn.py | 29 +++++++++++++++++++++++++ 8 files changed, 106 insertions(+), 17 deletions(-) diff --git a/sfa/managers/aggregate_manager.py b/sfa/managers/aggregate_manager.py index c0a8b656..0bf5d9f2 100644 --- a/sfa/managers/aggregate_manager.py +++ b/sfa/managers/aggregate_manager.py @@ -58,7 +58,6 @@ class AggregateManager: 'geni_api_versions': {'3': 'http://%s:%s' % (socket.gethostname(), api.config.sfa_aggregate_port)}, '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_best_effort': 'true', 'geni_credential_types': cred_types, } version.update(version_generic) diff --git a/sfa/managers/registry_manager.py b/sfa/managers/registry_manager.py index f3f75f79..f6277ed2 100644 --- a/sfa/managers/registry_manager.py +++ b/sfa/managers/registry_manager.py @@ -42,7 +42,13 @@ class RegistryManager: hrn = urn_to_hrn(xrn)[0] else: hrn, type = urn_to_hrn(xrn) - + + # Slivers don't have credentials but users should be able to + # specify a sliver xrn and receive the slice's credential + if type == 'sliver' or '-' in Xrn(hrn).leaf: + slice_xrn = self.driver.sliver_to_slice_xrn(hrn) + hrn = slice_xrn.hrn + # Is this a root or sub authority auth_hrn = api.auth.get_authority(hrn) if not auth_hrn or hrn == api.config.SFA_INTERFACE_HRN: diff --git a/sfa/methods/Describe.py b/sfa/methods/Describe.py index ff3765d3..b66780a4 100644 --- a/sfa/methods/Describe.py +++ b/sfa/methods/Describe.py @@ -37,8 +37,8 @@ class Describe(Method): else: raise SfaInvalidArgument('Must specify an rspec version option. geni_rspec_version cannot be null') - # Find the valid credentials - valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', urns) + valid_creds = self.api.auth.checkCredentials(creds, 'listnodes', urns, \ + check_sliver_callback = self.api.manager.driver.check_sliver_credentials) # get hrn of the original caller origin_hrn = options.get('origin_hrn', None) diff --git a/sfa/openstack/nova_driver.py b/sfa/openstack/nova_driver.py index c3c9f54c..da06c842 100644 --- a/sfa/openstack/nova_driver.py +++ b/sfa/openstack/nova_driver.py @@ -49,6 +49,13 @@ class NovaDriver(Driver): if NovaDriver.cache is None: NovaDriver.cache = Cache() self.cache = NovaDriver.cache + + def sliver_to_slice_xrn(self, xrn): + return xrn + + def check_sliver_credentials(self, creds, urns): + #TODO: Implement + return ######################################## ########## registry oriented diff --git a/sfa/planetlab/plaggregate.py b/sfa/planetlab/plaggregate.py index ef1a5bb9..0e32d8f7 100644 --- a/sfa/planetlab/plaggregate.py +++ b/sfa/planetlab/plaggregate.py @@ -120,13 +120,11 @@ class PlAggregate: xrn = PlXrn(xrn=urn) if xrn.type == 'sliver': # id: slice_id-node_id - id_parts = xrn.leaf.split('-') - slice_ids.add(id_parts[0]) - node_ids.append(id_parts[1]) + sliver_id_parts = xrn.get_sliver_id_parts() + slice_ids.add(sliver_id_parts[0]) + node_ids.append(sliver_id_parts[1]) else: names.add(xrn.pl_slicename()) - if xrn.id: - ids.add(xrn.id) filter = {} if names: diff --git a/sfa/planetlab/pldriver.py b/sfa/planetlab/pldriver.py index c47d170c..93949f5b 100644 --- a/sfa/planetlab/pldriver.py +++ b/sfa/planetlab/pldriver.py @@ -2,7 +2,7 @@ import datetime # from sfa.util.faults import MissingSfaInfo, UnknownSfaType, \ RecordNotFound, SfaNotImplemented, SliverDoesNotExist, SearchFailed, \ - UnsupportedOperation + UnsupportedOperation, Forbidden from sfa.util.sfalogging import logger from sfa.util.defaultdict import defaultdict from sfa.util.sfatime import utcparse, datetime_to_string, datetime_to_epoch @@ -52,7 +52,41 @@ class PlDriver (Driver): if PlDriver.cache is None: PlDriver.cache = Cache() self.cache = PlDriver.cache + + def sliver_to_slice_xrn(self, xrn): + sliver_id_parts = Xrn(xrn).get_sliver_id_parts() + slices = self.shell.GetSlices(sliver_id_parts[0]) + if not slices: + raise Forbidden("Unable to locate slice record for sliver: %s" % xrn) + slice = slices[0] + slice_xrn = Xrn(auth=self.hrn, slicename=slice['name']) + return slice_xrn + def check_sliver_credentials(self, creds, urns): + # build list of cred object hrns + slice_cred_names = [] + for cred in creds: + slice_cred_hrn = Credential(cred=cred).get_gid_object().get_hrn() + slice_cred_names.append(PlXrn(xrn=slice_cred_hrn).pl_slicename()) + + # look slice names of slivers listed in urns arg + slice_ids = [] + for urn in urns: + sliver_id_parts = Xrn(xrn=urn).get_sliver_id_parts() + slice_ids.append(sliver_id_parts[0]) + + if not slice_ids: + raise Forbidden("sliver urn not provided") + + slices = self.shell.GetSlices(slice_ids) + sliver_names = [slice['name'] for slice in slices] + + # make sure we have a credential for every specified sliver ierd + for sliver_name in sliver_names: + if sliver_name not in slice_cred_names: + msg = "Valid credential not found for target: %s" % sliver_name + raise Forbidden(msg) + ######################################## ########## registry oriented ######################################## diff --git a/sfa/trust/auth.py b/sfa/trust/auth.py index 4a2fd62b..d72c3f81 100644 --- a/sfa/trust/auth.py +++ b/sfa/trust/auth.py @@ -4,7 +4,7 @@ import sys from sfa.util.faults import InsufficientRights, MissingCallerGID, MissingTrustedRoots, PermissionError, \ - BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable + BadRequestHash, ConnectionKeyGIDMismatch, SfaPermissionDenied, CredentialNotVerifiable, Forbidden from sfa.util.sfalogging import logger from sfa.util.config import Config from sfa.util.xrn import Xrn, get_authority @@ -34,17 +34,22 @@ 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=[]): + def checkCredentials(self, creds, operation, xrns=[], check_sliver_callback=None): if not isinstance(xrns, list): xrns = [xrns] - hrns = [Xrn(xrn).hrn for xrn in xrns] + + 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 + # 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 = [] if not isinstance(creds, list): creds = [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 creds: raise Forbidden("no credential provided") if not hrns: hrns = [None] for cred in creds: for hrn in hrns: @@ -56,9 +61,20 @@ class Auth: logger.debug("failed to validate credential - dump=%s"%cred_obj.dump_string(dump_parents=True)) error = sys.exc_info()[:2] continue - + + # make sure all sliver xrns are validated against the valid credentials + if sliver_xrns: + if not check_sliver_callback: + msg = "sliver verification callback method not found." + msg += " Unable to validate sliver xrns: %s" % sliver_xrns + raise Forbidden(msg) + check_sliver_callback(valid, sliver_xrns) + if not len(valid): - raise InsufficientRights('Access denied: %s -- %s' % (error[0],error[1])) + msg = "Valid credential not found for method: %s" % operation + if xrns: + msg += " target: %s" % xrns + raise Forbidden(msg) return valid diff --git a/sfa/util/xrn.py b/sfa/util/xrn.py index ee587a7a..dfcf3e5b 100644 --- a/sfa/util/xrn.py +++ b/sfa/util/xrn.py @@ -109,6 +109,26 @@ class Xrn: def urn_split (urn): return Xrn.urn_meaningful(urn).split('+') + @staticmethod + def filter_type(urns=[], type=None): + urn_list = [] + if not type: + return urns + + for urn in urns: + xrn = Xrn(xrn=urn) + if not xrn.type: + # If an xrn doesn't have a type its probably a hrn. + # We have to make some assumptions on the hrn's type + # based on the contents of the hrn. + if type == 'sliver' and '-' in xrn.leaf: + urn_list.append(urn) + elif type != 'sliver' and not '-' in xrn.leaf: + urn_list.append(urn) + elif (xrn.type == type): + # Xrn is probably a urn so we can just compare types + urn_list.append(urn) + return urn_list #################### # the local fields that are kept consistent # self.urn @@ -181,6 +201,15 @@ class Xrn: self.hrn = hrn self.hrn_to_urn() self._normalize() + + # sliver_id_parts is list that contains the sliver's + # slice id and node id + def get_sliver_id_parts(self): + sliver_id_parts = [] + if self.type == 'sliver' or '-' in self.leaf: + sliver_id_parts = self.leaf.split('-') + return sliver_id_parts + def urn_to_hrn(self): """ -- 2.43.0