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
18 from sfa.util.sfaticket import *
22 Credential based authentication
25 def __init__(self, peer_cert = None, config = None ):
26 self.peer_cert = peer_cert
27 self.hierarchy = Hierarchy()
29 self.config = Config()
30 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
33 def check(self, cred, operation):
35 Check the credential against the peer cert (callerGID included
36 in the credential matches the caller that is connected to the
37 HTTPS connection, check if the credential was signed by a
38 trusted cert and check if the credential is allowd to perform
39 the specified operation.
41 self.client_cred = Credential(string = cred)
42 self.client_gid = self.client_cred.get_gid_caller()
43 self.object_gid = self.client_cred.get_gid_object()
45 # make sure the client_gid is not blank
46 if not self.client_gid:
47 raise MissingCallerGID(self.client_cred.get_subject())
49 # validate the client cert if it exists
51 self.verifyPeerCert(self.peer_cert, self.client_gid)
53 # make sure the client is allowed to perform the operation
55 if not self.client_cred.can_perform(operation):
56 raise InsufficientRights(operation)
58 if self.trusted_cert_list:
59 self.client_cred.verify_chain(self.trusted_cert_list)
61 self.client_gid.verify_chain(self.trusted_cert_list)
63 self.object_gid.verify_chain(self.trusted_cert_list)
65 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
69 def check_ticket(self, ticket):
71 Check if the tickt was signed by a trusted cert
73 if self.trusted_cert_list:
74 client_ticket = SfaTicket(string=ticket)
75 client_ticket.verify_chain(self.trusted_cert_list)
77 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
81 def verifyPeerCert(self, cert, gid):
82 # make sure the client_gid matches client's certificate
84 peer_cert = self.peer_cert
89 peer_gid = self.client_gid
92 if not peer_cert.is_pubkey(peer_gid.get_pubkey()):
93 raise ConnectionKeyGIDMismatch(peer_gid.get_subject())
95 def verifyGidRequestHash(self, gid, hash, arglist):
96 key = gid.get_pubkey()
97 if not key.verify_string(str(arglist), hash):
98 raise BadRequestHash(hash)
100 def verifyCredRequestHash(self, cred, hash, arglist):
101 gid = cred.get_gid_caller()
102 self.verifyGidRequestHash(gid, hash, arglist)
104 def validateGid(self, gid):
105 if self.trusted_cert_list:
106 gid.verify_chain(self.trusted_cert_list)
108 def validateCred(self, cred):
109 if self.trusted_cert_list:
110 cred.verify_chain(self.trusted_cert_list)
111 caller_gid = cred.get_gid_caller()
112 object_gid = cred.get_gid_object()
114 caller_gid.verify_chain(self.trusted_cert_list)
116 object_gid.verify_chain(self.trusted_cert_list)
118 def authenticateGid(self, gidStr, argList, requestHash=None):
119 gid = GID(string = gidStr)
120 self.validateGid(gid)
121 # request_hash is optional
123 self.verifyGidRequestHash(gid, requestHash, argList)
126 def authenticateCred(self, credStr, argList, requestHash=None):
127 cred = Credential(string = credStr)
128 self.validateCred(cred)
129 # request hash is optional
131 self.verifyCredRequestHash(cred, requestHash, argList)
134 def authenticateCert(self, certStr, requestHash):
135 cert = Certificate(string=certStr)
136 self.validateCert(self, cert)
138 def gidNoop(self, gidStr, value, requestHash):
139 self.authenticateGid(gidStr, [gidStr, value], requestHash)
142 def credNoop(self, credStr, value, requestHash):
143 self.authenticateCred(credStr, [credStr, value], requestHash)
146 def verify_cred_is_me(self, credential):
148 cred = Credential(string=credential)
149 caller_gid = cred.get_gid_caller()
150 caller_hrn = caller_gid.get_hrn()
151 if caller_hrn != self.config.SFA_INTERFACE_HRN:
152 raise GeniPermissionError(self.config.SFA_INTEFACE_HRN)
156 def get_auth_info(self, auth_hrn):
158 Given an authority name, return the information for that authority.
159 This is basically a stub that calls the hierarchy module.
161 @param auth_hrn human readable name of authority
164 return self.hierarchy.get_auth_info(auth_hrn)
167 def veriry_auth_belongs_to_me(self, name):
169 Verify that an authority belongs to our hierarchy.
170 This is basically left up to the implementation of the hierarchy
171 module. If the specified name does not belong, ane exception is
172 thrown indicating the caller should contact someone else.
174 @param auth_name human readable name of authority
177 # get auth info will throw an exception if the authority doesnt exist
178 self.get_auth_info(name)
181 def verify_object_belongs_to_me(self, name):
183 Verify that an object belongs to our hierarchy. By extension,
184 this implies that the authority that owns the object belongs
185 to our hierarchy. If it does not an exception is thrown.
187 @param name human readable name of object
189 auth_name = self.get_authority(name)
192 if name == self.config.SFA_INTERFACE_HRN:
194 self.verify_auth_belongs_to_me(auth_name)
196 def verify_auth_belongs_to_me(self, name):
197 # get auth info will throw an exception if the authority doesnt exist
198 self.get_auth_info(name)
201 def verify_object_permission(self, name):
203 Verify that the object gid that was specified in the credential
204 allows permission to the object 'name'. This is done by a simple
205 prefix test. For example, an object_gid for plc.arizona would
206 match the objects plc.arizona.slice1 and plc.arizona.
208 @param name human readable name to test
210 object_hrn = self.object_gid.get_hrn()
211 if object_hrn == name:
213 if name.startswith(object_hrn + "."):
215 #if name.startswith(get_authority(name)):
218 raise PermissionError(name)
220 def determine_user_rights(self, caller_hrn, record):
222 Given a user credential and a record, determine what set of rights the
223 user should have to that record.
225 This is intended to replace determine_rights() and
226 verify_cancreate_credential()
230 type = record['type']
233 researchers = record.get("researcher", [])
234 if (caller_hrn in researchers):
241 elif type == "authority":
242 pis = record.get("PI", [])
243 operators = record.get("operator", [])
244 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
245 rl.add("authority,sa,ma",)
246 if (caller_hrn in pis):
247 rl.add("authority,sa")
248 if (caller_hrn in operators):
249 rl.add("authority,ma")
261 def verify_cancreate_credential(self, src_cred, record):
263 Verify that a user can retrive a particular type of credential.
264 For slices, the user must be on the researcher list. For SA and
265 MA the user must be on the pi and operator lists respectively
268 type = record.get_type()
269 cred_object_hrn = src_cred.get_gid_object().get_hrn()
270 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
273 researchers = record.get("researcher", [])
274 if not (cred_object_hrn in researchers):
275 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
277 pis = record.get("pi", [])
278 if not (cred_object_hrn in pis):
279 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
281 operators = record.get("operator", [])
282 if not (cred_object_hrn in operators):
283 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
285 def get_authority(self, hrn):
286 return get_authority(hrn)