32ef9eb762d759e7522d2eb4ae89f5c2eabfd73d
[sfa.git] / geni / methods / get_credential.py
1 from geni.util.faults import *
2 from geni.util.excep import *
3 from geni.util.method import Method
4 from geni.util.parameter import Parameter, Mixed
5 from geni.util.auth import Auth
6 from geni.util.record import GeniRecord
7 from geni.util.credential import *
8 from geni.util.rights import *
9 from geni.util.debug import log
10
11 class get_credential(Method):
12     """
13     Retrive a credential for an object
14     If cred == Nonee then the behavior reverts to get_self_credential
15
16     @param cred credential object specifying rights of the caller
17     @param type type of object (user | slice | sa | ma | node)
18     @param hrn human readable name of object
19
20     @return the string representation of a credential object  
21     """
22
23     interfaces = ['registry']
24     
25     accepts = [
26         Mixed(Parameter(str, "credential"),
27               Parameter(None, "No credential")),  
28         Parameter(str, "Human readable name (hrn)")
29         ]
30
31     returns = Parameter(str, "String representation of a credential object")
32     
33     def call(self, cred, type, hrn):
34         if not cred:
35             return self.get_self_credential(type, hrn)
36         
37         self.api.auth.check(cred, 'getcredential')
38         self.api.auth.verify_object_belongs_to_me(hrn)
39         auth_hrn = self.api.auth.get_authority(hrn)
40         if not auth_hrn:
41             auth_hrn = hrn
42         auth_info = self.api.auth.get_auth_info(auth_hrn)
43         table = self.api.auth.get_auth_table(auth_hrn)
44         records = table.resolve('*', hrn)
45         if not records:
46             raise RecordNotFound(hrn)
47         record = records[0]
48         # verify_cancreate_credential requires that the member lists
49         # (researchers, pis, etc) be filled in
50         self.api.fill_record_info(record)
51
52         self.api.auth.verify_cancreate_credential(self.api.auth.client_cred, record)
53
54         # TODO: Check permission that self.client_cred can access the object
55
56         object_gid = record.get_gid_object()
57         new_cred = Credential(subject = object_gid.get_subject())
58         new_cred.set_gid_caller(self.api.auth.client_gid)
59         new_cred.set_gid_object(object_gid)
60         new_cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn)
61         new_cred.set_pubkey(object_gid.get_pubkey())
62
63         rl = determine_rights(type,hrn)
64         new_cred.set_privileges(rl)
65
66         # determine the type of credential that we want to use as a parent for
67         # this credential.
68
69         if (type == "ma") or (type == "node"):
70             auth_kind = "authority,ma"
71         else: # user, slice, sa
72             auth_kind = "authority,sa"
73
74         new_cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind))
75
76         new_cred.encode()
77         new_cred.sign()
78
79         return new_cred.save_to_string(save_parents=True)
80
81     def get_self_credential(self, type, hrn):
82         """
83         get_self_credential a degenerate version of get_credential used by a client
84         to get his initial credential when de doesnt have one. This is the same as 
85         get_credetial(..., cred = None, ...)
86     
87         The registry ensures that the client is the principal that is named by 
88         (type, name) by comparing the public key in the record's  GID to the 
89         private key used to encrypt the client side of the HTTPS connection. Thus
90         it is impossible for one principal to retrive another principal's 
91         credential without having the appropriate private key.    
92
93         @param type type of object (user | slice | sa | ma | node)
94         @param hrn human readable name of authority to list
95         @return string representation of a credential object 
96         """
97         self.api.auth.verify_object_belongs_to_me(hrn)
98
99         auth_hrn = self.api.auth.get_authority(hrn)
100         if not auth_hrn:
101             auth_hrn = hrn
102         auth_info = self.api.auth.get_auth_info(auth_hrn)
103
104         # find a record that matches
105         record = None
106         table = self.api.auth.get_auth_table(auth_hrn)
107         records = table.resolve('*', hrn)
108         for rec in records:
109             if type in ['*'] or rec.get_type() in [type]:
110                 record = rec
111         gid = record.get_gid_object()
112         peer_cert = self.api.auth.peer_cert
113         if not peer_cert.is_pubkey(gid.get_pubkey()):
114            raise ConnectionKeyGIDMismatch(gid.get_subject())
115
116         # create the credential
117         gid = record.get_gid_object()
118         cred = Credential(subject = gid.get_subject())
119         cred.set_gid_caller(gid)
120         cred.set_gid_object(gid)
121         cred.set_issuer(key=auth_info.get_pkey_object(), subject=auth_hrn)
122         cred.set_pubkey(gid.get_pubkey())
123         
124         rl = determine_rights(type, hrn)
125         cred.set_privileges(rl)
126
127         # determine the type of credential that we want to use as a parent for
128         # this credential.
129
130         if (type == "ma") or (type == "node"):
131             auth_kind = "authority,ma"
132         else: # user, slice, sa
133             auth_kind = "authority,sa"
134
135         cred.set_parent(self.api.auth.hierarchy.get_auth_cred(auth_hrn, kind=auth_kind))
136
137         cred.encode()
138         cred.sign()
139
140         return cred.save_to_string(save_parents=True)