2 # GeniAPI authentication
10 from sfa.trust.credential import Credential
11 from sfa.trust.trustedroot import TrustedRootList
12 from sfa.trust.rights import RightList
13 from sfa.util.faults import *
14 from sfa.trust.hierarchy import Hierarchy
15 from sfa.util.config import *
16 from sfa.util.misc import *
17 from sfa.trust.gid import GID
21 Credential based authentication
24 def __init__(self, peer_cert = None, config = None ):
25 self.peer_cert = peer_cert
26 self.hierarchy = Hierarchy()
28 self.config = Config()
29 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
32 def check(self, cred, operation):
34 Check the credential against the peer cert (callerGID included
35 in the credential matches the caller that is connected to the
36 HTTPS connection, check if the credential was signed by a
37 trusted cert and check if the credential is allowd to perform
38 the specified operation.
40 self.client_cred = Credential(string = cred)
41 self.client_gid = self.client_cred.get_gid_caller()
42 self.object_gid = self.client_cred.get_gid_object()
44 # make sure the client_gid is not blank
45 if not self.client_gid:
46 raise MissingCallerGID(self.client_cred.get_subject())
48 # validate the client cert if it exists
50 self.verifyPeerCert(self.peer_cert, self.client_gid)
52 # make sure the client is allowed to perform the operation
54 if not self.client_cred.can_perform(operation):
55 raise InsufficientRights(operation)
57 if self.trusted_cert_list:
58 self.client_cred.verify_chain(self.trusted_cert_list)
60 self.client_gid.verify_chain(self.trusted_cert_list)
62 self.object_gid.verify_chain(self.trusted_cert_list)
64 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
68 def verifyPeerCert(self, cert, gid):
69 # make sure the client_gid matches client's certificate
71 peer_cert = self.peer_cert
76 peer_gid = self.client_gid
79 if not peer_cert.is_pubkey(peer_gid.get_pubkey()):
80 raise ConnectionKeyGIDMismatch(peer_gid.get_subject())
82 def verifyGidRequestHash(self, gid, hash, arglist):
83 key = gid.get_pubkey()
84 if not key.verify_string(str(arglist), hash):
85 raise BadRequestHash(hash)
87 def verifyCredRequestHash(self, cred, hash, arglist):
88 gid = cred.get_gid_caller()
89 self.verifyGidRequestHash(gid, hash, arglist)
91 def validateGid(self, gid):
92 if self.trusted_cert_list:
93 gid.verify_chain(self.trusted_cert_list)
95 def validateCred(self, cred):
96 if self.trusted_cert_list:
97 cred.verify_chain(self.trusted_cert_list)
98 caller_gid = cred.get_gid_caller()
99 object_gid = cred.get_gid_object()
101 caller_gid.verify_chain(self.trusted_cert_list)
103 object_gid.verify_chain(self.trusted_cert_list)
105 def authenticateGid(self, gidStr, argList, requestHash=None):
106 gid = GID(string = gidStr)
107 self.validateGid(gid)
108 # request_hash is optional
110 self.verifyGidRequestHash(gid, requestHash, argList)
113 def authenticateCred(self, credStr, argList, requestHash=None):
114 cred = Credential(string = credStr)
115 self.validateCred(cred)
116 # request hash is optional
118 self.verifyCredRequestHash(cred, requestHash, argList)
121 def authenticateCert(self, certStr, requestHash):
122 cert = Certificate(string=certStr)
123 self.validateCert(self, cert)
125 def gidNoop(self, gidStr, value, requestHash):
126 self.authenticateGid(gidStr, [gidStr, value], requestHash)
129 def credNoop(self, credStr, value, requestHash):
130 self.authenticateCred(credStr, [credStr, value], requestHash)
133 def verify_cred_is_me(self, credential):
135 cred = Credential(string=credential)
136 caller_gid = cred.get_gid_caller()
137 caller_hrn = caller_gid.get_hrn()
138 if caller_hrn != self.config.SFA_INTERFACE_HRN:
139 raise GeniPermissionError(self.config.SFA_INTEFACE_HRN)
143 def get_auth_info(self, auth_hrn):
145 Given an authority name, return the information for that authority.
146 This is basically a stub that calls the hierarchy module.
148 @param auth_hrn human readable name of authority
151 return self.hierarchy.get_auth_info(auth_hrn)
154 def veriry_auth_belongs_to_me(self, name):
156 Verify that an authority belongs to our hierarchy.
157 This is basically left up to the implementation of the hierarchy
158 module. If the specified name does not belong, ane exception is
159 thrown indicating the caller should contact someone else.
161 @param auth_name human readable name of authority
164 # get auth info will throw an exception if the authority doesnt exist
165 self.get_auth_info(name)
168 def verify_object_belongs_to_me(self, name):
170 Verify that an object belongs to our hierarchy. By extension,
171 this implies that the authority that owns the object belongs
172 to our hierarchy. If it does not an exception is thrown.
174 @param name human readable name of object
176 auth_name = self.get_authority(name)
179 if name == self.config.SFA_INTERFACE_HRN:
181 self.verify_auth_belongs_to_me(auth_name)
183 def verify_auth_belongs_to_me(self, name):
184 # get auth info will throw an exception if the authority doesnt exist
185 self.get_auth_info(name)
188 def verify_object_permission(self, name):
190 Verify that the object gid that was specified in the credential
191 allows permission to the object 'name'. This is done by a simple
192 prefix test. For example, an object_gid for plc.arizona would
193 match the objects plc.arizona.slice1 and plc.arizona.
195 @param name human readable name to test
197 object_hrn = self.object_gid.get_hrn()
198 if object_hrn == name:
200 if name.startswith(object_hrn + "."):
202 #if name.startswith(get_authority(name)):
205 raise PermissionError(name)
207 def determine_user_rights(self, caller_hrn, record):
209 Given a user credential and a record, determine what set of rights the
210 user should have to that record.
212 This is intended to replace determine_rights() and
213 verify_cancreate_credential()
217 type = record['type']
220 researchers = record.get("researcher", [])
221 if (caller_hrn in researchers):
228 elif type == "authority":
229 pis = record.get("PI", [])
230 operators = record.get("operator", [])
231 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
232 rl.add("authority,sa,ma",)
233 if (caller_hrn in pis):
234 rl.add("authority,sa")
235 if (caller_hrn in operators):
236 rl.add("authority,ma")
243 elif type == "component":
248 def verify_cancreate_credential(self, src_cred, record):
250 Verify that a user can retrive a particular type of credential.
251 For slices, the user must be on the researcher list. For SA and
252 MA the user must be on the pi and operator lists respectively
255 type = record.get_type()
256 cred_object_hrn = src_cred.get_gid_object().get_hrn()
257 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
260 researchers = record.get("researcher", [])
261 if not (cred_object_hrn in researchers):
262 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
264 pis = record.get("pi", [])
265 if not (cred_object_hrn in pis):
266 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
268 operators = record.get("operator", [])
269 if not (cred_object_hrn in operators):
270 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
272 def get_authority(self, hrn):
273 return get_authority(hrn)