From 035e5b8168eaec3f891ddbf3528bf885e907b920 Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Wed, 8 Apr 2009 01:26:10 +0000 Subject: [PATCH] defining interface methods here --- geni/methods/__init__.py | 5 ++ geni/methods/get_credential.py | 141 +++++++++++++++++++++++++++++++++ geni/methods/list.py | 41 ++++++++++ geni/methods/resolve.py | 64 +++++++++++++++ 4 files changed, 251 insertions(+) create mode 100644 geni/methods/__init__.py create mode 100644 geni/methods/get_credential.py create mode 100644 geni/methods/list.py create mode 100644 geni/methods/resolve.py diff --git a/geni/methods/__init__.py b/geni/methods/__init__.py new file mode 100644 index 00000000..ba307207 --- /dev/null +++ b/geni/methods/__init__.py @@ -0,0 +1,5 @@ +methods=""" +get_credential +list +resolve +""".split() diff --git a/geni/methods/get_credential.py b/geni/methods/get_credential.py new file mode 100644 index 00000000..125bd125 --- /dev/null +++ b/geni/methods/get_credential.py @@ -0,0 +1,141 @@ +from geni.util.faults import * +from geni.util.excep import * +from geni.util.method import Method +from geni.util.parameter import Parameter, Mixed +from geni.util.auth import Auth +from geni.util.record import GeniRecord +from geni.util.credential import * +from geni.util.rights import * +from geni.util.debug import log + +class get_credential(Method): + """ + Retrive a credential for an object + If cred == Nonee then the behavior reverts to get_self_credential + + @param cred credential object specifying rights of the caller + @param type type of object (user | slice | sa | ma | node) + @param hrn human readable name of object + + @return the string representation of a credential object + """ + + interfaces = ['registry'] + + accepts = [ + Mixed(Parameter(str, "credential"), + Parameter(None, "No credential")), + Parameter(str, "Human readable name (hrn)") + ] + + returns = [GeniRecord] + + def call(self, cred, type, hrn): + if not cred: + return self.get_self_credential(type, hrn) + + self.api.auth.check(cred, 'getcredential') + + self.api.auth.verify_object_belongs_to_me(name) + + auth_hrn = self.api.auth.get_authority(hrn) + if not auth_hrn: + auth_hrn = hrn + auth_info = self.api.auth.get_auth_info(auth_hrn) + record = None + table = self.api.auth.get_auth_table(auth_hrn) + records = table.resolve('*', auth_hrn) + + # verify_cancreate_credential requires that the member lists + # (researchers, pis, etc) be filled in + self.api.fill_record_info(record) + + self.api.auth.verify_cancreate_credential(self.client_cred, record) + + # TODO: Check permission that self.client_cred can access the object + + object_gid = record.get_gid_object() + new_cred = Credential(subject = object_gid.get_subject()) + new_cred.set_gid_caller(self.client_gid) + new_cred.set_gid_object(object_gid) + new_cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn) + new_cred.set_pubkey(object_gid.get_pubkey()) + + rl = determine_rights(type, name) + new_cred.set_privileges(rl) + + # determine the type of credential that we want to use as a parent for + # this credential. + + if (type == "ma") or (type == "node"): + auth_kind = "authority,ma" + else: # user, slice, sa + auth_kind = "authority,sa" + + new_cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind)) + + new_cred.encode() + new_cred.sign() + + return new_cred.save_to_string(save_parents=True) + + def get_self_credential(self, type, hrn): + """ + get_self_credential a degenerate version of get_credential used by a client + to get his initial credential when de doesnt have one. This is the same as + get_credetial(..., cred = None, ...) + + The registry ensures that the client is the principal that is named by + (type, name) by comparing the public key in the record's GID to the + private key used to encrypt the client side of the HTTPS connection. Thus + it is impossible for one principal to retrive another principal's + credential without having the appropriate private key. + + @param type type of object (user | slice | sa | ma | node) + @param hrn human readable name of authority to list + @return string representation of a credential object + """ + self.api.auth.verify_object_belongs_to_me(hrn) + + auth_hrn = self.api.auth.get_authority(hrn) + if not auth_hrn: + auth_hrn = hrn + auth_info = self.api.auth.get_auth_info(auth_hrn) + + # find a record that matches + record = None + table = self.api.auth.get_auth_table(auth_hrn) + records = table.resolve('*', hrn) + for rec in records: + if type in ['*'] or rec.get_type() in [type]: + record = rec + gid = record.get_gid_object() + peer_cert = self.api.auth.peer_cert + if not peer_cert.is_pubkey(gid.get_pubkey()): + raise ConnectionKeyGIDMismatch(gid.get_subject()) + + # create the credential + gid = record.get_gid_object() + cred = Credential(subject = gid.get_subject()) + cred.set_gid_caller(gid) + cred.set_gid_object(gid) + cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn) + cred.set_pubkey(gid.get_pubkey()) + + rl = determine_rights(type, hrn) + cred.set_privileges(rl) + + # determine the type of credential that we want to use as a parent for + # this credential. + + if (type == "ma") or (type == "node"): + auth_kind = "authority,ma" + else: # user, slice, sa + auth_kind = "authority,sa" + + cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind)) + + cred.encode() + cred.sign() + + return cred.save_to_string(save_parents=True) diff --git a/geni/methods/list.py b/geni/methods/list.py new file mode 100644 index 00000000..a136abfc --- /dev/null +++ b/geni/methods/list.py @@ -0,0 +1,41 @@ +from geni.util.faults import * +from geni.util.excep import * +from geni.util.method import Method +from geni.util.parameter import Parameter, Mixed +from geni.util.auth import Auth +from geni.util.record import GeniRecord + +class list(Method): + """ + List the records in an authority. + + @param cred credential string specifying the rights of the caller + @param hrn human readable name of authority to list + @return list of record dictionaries + """ + + interfaces = ['registry'] + + accepts = [ + Parameter(str, "credential"), + Parameter(str, "Human readable name (hrn)") + ] + + returns = [GeniRecord] + + def call(self, cred, hrn): + + self.api.auth.check(cred, 'list') + # is this a foreign authority + if not hrn.startswith(self.api.hrn): + for registry in self.api.registries: + if hrn.startswith(registry): + records = self.api.registries[registry].list(self.api.credential, hrn) + return records + + if not self.api.auth.hierarchy.auth_exists(hrn): + raise MissingAuthority(hrn) + table = self.api.auth.get_auth_table(hrn) + records = table.list() + + return records diff --git a/geni/methods/resolve.py b/geni/methods/resolve.py new file mode 100644 index 00000000..3daee240 --- /dev/null +++ b/geni/methods/resolve.py @@ -0,0 +1,64 @@ +from geni.util.faults import * +from geni.util.excep import * +from geni.util.method import Method +from geni.util.parameter import Parameter, Mixed +from geni.util.auth import Auth +from geni.util.record import GeniRecord +from geni.util.debug import log + +class resolve(Method): + """ + Resolve a record. + + @param cred credential string authorizing the caller + @param hrn human readable name to resolve + @return a list of record dictionaries or empty list + """ + + interfaces = ['registry'] + + accepts = [ + Parameter(str, "credential"), + Parameter(str, "Human readable name (hrn)") + ] + + returns = [GeniRecord] + + def call(self, cred, hrn): + + self.api.auth.check(cred, 'resolve') + + # is this a foreign record + if not hrn.startswith(self.api.hrn): + for registry in self.api.registries: + if hrn.startswith(registry): + records = self.api.registries[registry].resolve(self.api.credential, name) + good_records = records + else: + auth_hrn = self.api.auth.get_authority(hrn) + if not auth_hrn: + auth_hrn = hrn + table = self.api.auth.get_auth_table(auth_hrn) + records = table.resolve('*', hrn) + good_records = [] + for record in records: + try: + self.api.fill_record_info(record) + good_records.append(record) + except PlanetLabRecordDoesNotExist: + # silently drop the ones that are missing in PL + print >> log, "ignoring geni record ", record.get_name(), \ + " because pl record does not exist" + table.remove(record) + + dicts = [record.as_dict() for record in good_records] + if not dicts: + raise RecordNotFound(hrn) + + return dicts + + + + + + return records -- 2.43.0