defining interface methods here
authorTony Mack <tmack@cs.princeton.edu>
Wed, 8 Apr 2009 01:26:10 +0000 (01:26 +0000)
committerTony Mack <tmack@cs.princeton.edu>
Wed, 8 Apr 2009 01:26:10 +0000 (01:26 +0000)
geni/methods/__init__.py [new file with mode: 0644]
geni/methods/get_credential.py [new file with mode: 0644]
geni/methods/list.py [new file with mode: 0644]
geni/methods/resolve.py [new file with mode: 0644]

diff --git a/geni/methods/__init__.py b/geni/methods/__init__.py
new file mode 100644 (file)
index 0000000..ba30720
--- /dev/null
@@ -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 (file)
index 0000000..125bd12
--- /dev/null
@@ -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 (file)
index 0000000..a136abf
--- /dev/null
@@ -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 (file)
index 0000000..3daee24
--- /dev/null
@@ -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