2 # SfaAPI authentication
9 from sfa.trust.certificate import Keypair, Certificate
10 from sfa.trust.credential import Credential
11 from sfa.trust.trustedroot import TrustedRootList
12 from sfa.util.faults import *
13 from sfa.trust.hierarchy import Hierarchy
14 from sfa.util.config import *
15 from sfa.util.namespace import *
16 from sfa.util.sfaticket import *
17 from sfa.util.sfalogging import logger
20 def filter_creds_by_caller(self, creds, caller_hrn):
22 Returns a list of creds who's gid caller matches the
25 if not isinstance(creds, list): creds = [creds]
29 tmp_cred = Credential(string=cred)
30 if tmp_cred.get_gid_caller().get_hrn() == caller_hrn:
31 caller_creds.append(cred)
38 Credential based authentication
41 def __init__(self, peer_cert = None, config = None ):
42 self.peer_cert = peer_cert
43 self.hierarchy = Hierarchy()
45 self.config = Config()
46 self.load_trusted_certs()
48 def load_trusted_certs(self):
49 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
50 self.trusted_cert_file_list = TrustedRootList(self.config.get_trustedroots_dir()).get_file_list()
54 def checkCredentials(self, creds, operation, hrn = None):
56 if not isinstance(creds, list):
60 self.check(cred, operation, hrn)
63 error = sys.exc_info()[:2]
67 raise InsufficientRights('Access denied: %s -- %s' % (error[0],error[1]))
72 def check(self, cred, operation, hrn = None):
74 Check the credential against the peer cert (callerGID included
75 in the credential matches the caller that is connected to the
76 HTTPS connection, check if the credential was signed by a
77 trusted cert and check if the credential is allowd to perform
78 the specified operation.
80 self.client_cred = Credential(string = cred)
81 self.client_gid = self.client_cred.get_gid_caller()
82 self.object_gid = self.client_cred.get_gid_object()
84 # make sure the client_gid is not blank
85 if not self.client_gid:
86 raise MissingCallerGID(self.client_cred.get_subject())
88 # validate the client cert if it exists
90 self.verifyPeerCert(self.peer_cert, self.client_gid)
92 # make sure the client is allowed to perform the operation
94 if not self.client_cred.can_perform(operation):
95 raise InsufficientRights(operation)
97 if self.trusted_cert_list:
98 self.client_cred.verify(self.trusted_cert_file_list)
100 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
102 # Make sure the credential's target matches the specified hrn.
103 # This check does not apply to trusted peers
104 trusted_peers = [gid.get_hrn() for gid in self.trusted_cert_list]
105 if hrn and self.client_gid.get_hrn() not in trusted_peers:
106 target_hrn = self.object_gid.get_hrn()
107 if not hrn == target_hrn:
108 raise PermissionError("Target hrn: %s doesn't match specified hrn: %s " % \
112 def check_ticket(self, ticket):
114 Check if the tickt was signed by a trusted cert
116 if self.trusted_cert_list:
117 client_ticket = SfaTicket(string=ticket)
118 client_ticket.verify_chain(self.trusted_cert_list)
120 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
124 def verifyPeerCert(self, cert, gid):
125 # make sure the client_gid matches client's certificate
126 if not cert.is_pubkey(gid.get_pubkey()):
127 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
129 def verifyGidRequestHash(self, gid, hash, arglist):
130 key = gid.get_pubkey()
131 if not key.verify_string(str(arglist), hash):
132 raise BadRequestHash(hash)
134 def verifyCredRequestHash(self, cred, hash, arglist):
135 gid = cred.get_gid_caller()
136 self.verifyGidRequestHash(gid, hash, arglist)
138 def validateGid(self, gid):
139 if self.trusted_cert_list:
140 gid.verify_chain(self.trusted_cert_list)
142 def validateCred(self, cred):
143 if self.trusted_cert_list:
144 cred.verify(self.trusted_cert_file_list)
146 def authenticateGid(self, gidStr, argList, requestHash=None):
147 gid = GID(string = gidStr)
148 self.validateGid(gid)
149 # request_hash is optional
151 self.verifyGidRequestHash(gid, requestHash, argList)
154 def authenticateCred(self, credStr, argList, requestHash=None):
155 cred = Credential(string = credStr)
156 self.validateCred(cred)
157 # request hash is optional
159 self.verifyCredRequestHash(cred, requestHash, argList)
162 def authenticateCert(self, certStr, requestHash):
163 cert = Certificate(string=certStr)
164 self.validateCert(self, cert)
166 def gidNoop(self, gidStr, value, requestHash):
167 self.authenticateGid(gidStr, [gidStr, value], requestHash)
170 def credNoop(self, credStr, value, requestHash):
171 self.authenticateCred(credStr, [credStr, value], requestHash)
174 def verify_cred_is_me(self, credential):
176 cred = Credential(string=credential)
177 caller_gid = cred.get_gid_caller()
178 caller_hrn = caller_gid.get_hrn()
179 if caller_hrn != self.config.SFA_INTERFACE_HRN:
180 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
184 def get_auth_info(self, auth_hrn):
186 Given an authority name, return the information for that authority.
187 This is basically a stub that calls the hierarchy module.
189 @param auth_hrn human readable name of authority
192 return self.hierarchy.get_auth_info(auth_hrn)
195 def veriry_auth_belongs_to_me(self, name):
197 Verify that an authority belongs to our hierarchy.
198 This is basically left up to the implementation of the hierarchy
199 module. If the specified name does not belong, ane exception is
200 thrown indicating the caller should contact someone else.
202 @param auth_name human readable name of authority
205 # get auth info will throw an exception if the authority doesnt exist
206 self.get_auth_info(name)
209 def verify_object_belongs_to_me(self, name):
211 Verify that an object belongs to our hierarchy. By extension,
212 this implies that the authority that owns the object belongs
213 to our hierarchy. If it does not an exception is thrown.
215 @param name human readable name of object
217 auth_name = self.get_authority(name)
220 if name == self.config.SFA_INTERFACE_HRN:
222 self.verify_auth_belongs_to_me(auth_name)
224 def verify_auth_belongs_to_me(self, name):
225 # get auth info will throw an exception if the authority doesnt exist
226 self.get_auth_info(name)
229 def verify_object_permission(self, name):
231 Verify that the object gid that was specified in the credential
232 allows permission to the object 'name'. This is done by a simple
233 prefix test. For example, an object_gid for plc.arizona would
234 match the objects plc.arizona.slice1 and plc.arizona.
236 @param name human readable name to test
238 object_hrn = self.object_gid.get_hrn()
239 if object_hrn == name:
241 if name.startswith(object_hrn + "."):
243 #if name.startswith(get_authority(name)):
246 raise PermissionError(name)
248 def determine_user_rights(self, caller_hrn, record):
250 Given a user credential and a record, determine what set of rights the
251 user should have to that record.
253 This is intended to replace determine_rights() and
254 verify_cancreate_credential()
258 type = record['type']
262 researchers = record.get("researcher", [])
263 pis = record.get("PI", [])
264 if (caller_hrn in researchers + pis):
271 elif type == "authority":
272 pis = record.get("PI", [])
273 operators = record.get("operator", [])
274 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
278 if (caller_hrn in pis):
281 if (caller_hrn in operators):
295 def verify_cancreate_credential(self, src_cred, record):
297 Verify that a user can retrive a particular type of credential.
298 For slices, the user must be on the researcher list. For SA and
299 MA the user must be on the pi and operator lists respectively
302 type = record.get_type()
303 cred_object_hrn = src_cred.get_gid_object().get_hrn()
304 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
307 researchers = record.get("researcher", [])
308 if not (cred_object_hrn in researchers):
309 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
311 pis = record.get("pi", [])
312 if not (cred_object_hrn in pis):
313 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
315 operators = record.get("operator", [])
316 if not (cred_object_hrn in operators):
317 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
319 def get_authority(self, hrn):
320 return get_authority(hrn)
322 def filter_creds_by_caller(self, creds, caller_hrn):
324 Returns a list of creds who's gid caller matches the
327 if not isinstance(creds, list):
332 tmp_cred = Credential(string=cred)
333 if tmp_cred.get_gid_caller().get_hrn() == caller_hrn: