X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=geni%2Fregistry.py;h=574f8f7163a79b2004e6876b11895e3e9f211f10;hb=2c81e48358ed74f551169df4e00d6fc5dae5a9c0;hp=c4de3e6246a1310b94f79c516db1f36a4fece95b;hpb=b2344721149cb64667c88b63cdc3adb62ccf3530;p=sfa.git diff --git a/geni/registry.py b/geni/registry.py index c4de3e62..574f8f71 100644 --- a/geni/registry.py +++ b/geni/registry.py @@ -12,6 +12,7 @@ from geni.util.trustedroot import TrustedRootList from geni.util.cert import Keypair, Certificate from geni.util.gid import GID, create_uuid from geni.util.geniserver import GeniServer +from geni.util.geniclient import GeniClient from geni.util.record import GeniRecord from geni.util.rights import RightList from geni.util.genitable import GeniTable @@ -19,6 +20,7 @@ from geni.util.geniticket import Ticket from geni.util.excep import * from geni.util.misc import * from geni.util.config import * +from geni.util.storage import * ## # Convert geni fields to PLC fields for use when registering up updating @@ -86,7 +88,7 @@ class Registry(GeniServer): # @param key_file private key filename of registry # @param cert_file certificate filename containing public key (could be a GID file) - def __init__(self, ip, port, key_file, cert_file): + def __init__(self, ip, port, key_file, cert_file, config = '/usr/share/geniwrapper/geni/util/geni_config'): GeniServer.__init__(self, ip, port, key_file, cert_file) # get PL account settings from config module @@ -98,6 +100,22 @@ class Registry(GeniServer): else: self.connect_local_shell() + self.key_file = key_file + self.cert_file = cert_file + self.config = Config(config) + self.basedir = self.config.GENI_BASE_DIR + os.sep + self.server_basedir = self.basedir + os.sep + "geni" + os.sep + self.hrn = self.config.GENI_INTERFACE_HRN + + # get peer registry information + registries_file = self.server_basedir + os.sep + 'registries.xml' + connection_dict = {'hrn': '', 'addr': '', 'port': ''} + self.registry_info = XmlStorage(registries_file, {'registries': {'registry': [connection_dict]}}) + self.registry_info.load() + self.connectRegistry() + self.connectRegistries() + + ## # Connect to a remote shell via XMLRPC @@ -129,6 +147,63 @@ class Registry(GeniServer): self.server.register_function(self.list) self.server.register_function(self.resolve) + + def loadCredential(self): + """ + Attempt to load credential from file if it exists. If it doesnt get + credential from registry. + """ + + # see if this file exists + # XX This is really the aggregate's credential. Using this is easier than getting + # the registry's credential from iteslf (ssl errors). + ma_cred_filename = self.server_basedir + os.sep + "agg." + self.hrn + ".ma.cred" + try: + self.credential = Credential(filename = ma_cred_filename) + except IOError: + self.credential = self.getCredentialFromRegistry() + + def getCredentialFromRegistry(self): + """ + Get our current credential from the registry. + """ + # get self credential + self_cred_filename = self.server_basedir + os.sep + "smgr." + self.hrn + ".cred" + self_cred = self.registry.get_credential(None, 'ma', self.hrn) + self_cred.save_to_file(self_cred_filename, save_parents=True) + + # get ma credential + ma_cred_filename = self.server_basedir + os.sep + "smgr." + self.hrn + ".sa.cred" + ma_cred = self.registry.get_credential(self_cred, 'sa', self.hrn) + ma_cred.save_to_file(ma_cred_filename, save_parents=True) + return ma_cred + + def connectRegistry(self): + """ + Connect to the registry + """ + # connect to registry using GeniClient + address = self.config.GENI_REGISTRY_HOSTNAME + port = self.config.GENI_REGISTRY_PORT + url = 'http://%(address)s:%(port)s' % locals() + self.registry = GeniClient(url, self.key_file, self.cert_file) + + def connectRegistries(self): + """ + Get connection details for the trusted peer registries from file and + create an GeniClient connection to each. + """ + self.registries= {} + registries = self.registry_info['registries']['registry'] + if isinstance(registries, dict): + registries = [registries] + if isinstance(registries, list): + for registry in registries: + # create xmlrpc connection using GeniClient + hrn, address, port = registry['hrn'], registry['addr'], registry['port'] + url = 'http://%(address)s:%(port)s' % locals() + self.registries[hrn] = GeniClient(url, self.key_file, self.cert_file) + ## # Given an authority name, return the information for that authority. This # is basically a stub that calls the hierarchy module. @@ -557,14 +632,22 @@ class Registry(GeniServer): self.verify_object_permission(record.get_name()) auth_name = get_authority(record.get_name()) + if not auth_name: + auth_name = record.get_name() table = self.get_auth_table(auth_name) # make sure the record exists existing_record_list = table.resolve(type, record.get_name()) if not existing_record_list: raise RecordNotFound(record.get_name()) - existing_record = existing_record_list[0] + + # Update_membership needs the membership lists in the existing record + # filled in, so it can see if members were added or removed + self.fill_record_info(existing_record) + + # Use the pointer from the existing record, not the one that the user + # gave us. This prevents the user from inserting a forged pointer pointer = existing_record.get_pointer() # update the PLC information that was specified with the record @@ -650,11 +733,10 @@ class Registry(GeniServer): def resolve_raw(self, type, name, must_exist=True): auth_name = get_authority(name) - + if not auth_name: + auth_name = name table = self.get_auth_table(auth_name) - records = table.resolve(type, name) - if (not records) and must_exist: raise RecordNotFound(name) @@ -684,8 +766,16 @@ class Registry(GeniServer): def resolve(self, cred, name): self.decode_authentication(cred, "resolve") + + try: + records = self.resolve_raw("*", name) + except: + records = [] + for registry in self.registries: + if name.startswith(registry): + records = self.registries[registry].resolve(self.credential, name) + - records = self.resolve_raw("*", name) dicts = [] for record in records: dicts.append(record.as_dict()) @@ -708,7 +798,7 @@ class Registry(GeniServer): records = self.resolve_raw("*", name) gid_string_list = [] for record in records: - gid = record.get_gid() + gid = record.get_gid_object() gid_string_list.append(gid.save_to_string(save_parents=True)) return gid_string_list @@ -771,8 +861,9 @@ class Registry(GeniServer): self.verify_object_belongs_to_me(name) auth_hrn = get_authority(name) + if not auth_hrn: + auth_hrn = name auth_info = self.get_auth_info(auth_hrn) - # find a record that matches records = self.resolve_raw(type, name, must_exist=True) record = records[0] @@ -808,6 +899,32 @@ class Registry(GeniServer): return cred.save_to_string(save_parents=True) + ## + # verify_cancreate_credential + # + # Verify that a user can retrieve 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. + + def verify_cancreate_credential(self, src_cred, record): + type = record.get_type() + cred_object_hrn = src_cred.get_gid_object().get_hrn() + config = Config() + if cred_object_hrn in [config.GENI_REGISTRY_ROOT_AUTH]: + return + if type=="slice": + researchers = record.get_geni_info().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_geni_info().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_geni_info().get("operator", []) + if not (cred_object_hrn in operators): + raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name()) + ## # GENI API: Get_credential # @@ -823,18 +940,26 @@ class Registry(GeniServer): def get_credential(self, cred, type, name): if not cred: - return get_self_credential(self, type, name) + return self.get_self_credential(type, name) self.decode_authentication(cred, "getcredential") self.verify_object_belongs_to_me(name) auth_hrn = get_authority(name) + if not auth_hrn: + auth_hrn = name auth_info = self.get_auth_info(auth_hrn) records = self.resolve_raw(type, name, must_exist=True) record = records[0] + # verify_cancreate_credential requires that the member lists + # (researchers, pis, etc) be filled in + self.fill_record_info(record) + + self.verify_cancreate_credential(self.client_cred, record) + # TODO: Check permission that self.client_cred can access the object object_gid = record.get_gid_object() @@ -890,6 +1015,8 @@ class Registry(GeniServer): # that they should be combined? auth_hrn = get_authority(name) + if not auth_hrn: + auth_hrn = name auth_info = self.get_auth_info(auth_hrn) records = self.resolve_raw("slice", name, must_exist=True)