2 # SfaAPI authentication
9 from sfa.trust.credential import Credential
10 from sfa.trust.trustedroot import TrustedRootList
11 from sfa.util.faults import *
12 from sfa.trust.hierarchy import Hierarchy
13 from sfa.util.config import *
14 from sfa.util.namespace import *
15 from sfa.util.sfaticket import *
16 from sfa.util.sfalogging import logger
20 Credential based authentication
23 def __init__(self, peer_cert = None, config = None ):
24 self.peer_cert = peer_cert
25 self.hierarchy = Hierarchy()
27 self.config = Config()
28 self.load_trusted_certs()
29 self.trusted_cert_file_list = TrustedRootList(self.config.get_trustedroots_dir()).get_file_list()
31 def load_trusted_certs(self):
32 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
34 def check(self, cred, operation):
36 Check the credential against the peer cert (callerGID included
37 in the credential matches the caller that is connected to the
38 HTTPS connection, check if the credential was signed by a
39 trusted cert and check if the credential is allowd to perform
40 the specified operation.
42 self.client_cred = Credential(string = cred)
43 self.client_gid = self.client_cred.get_gid_caller()
44 self.object_gid = self.client_cred.get_gid_object()
46 # make sure the client_gid is not blank
47 if not self.client_gid:
48 raise MissingCallerGID(self.client_cred.get_subject())
50 # validate the client cert if it exists
52 self.verifyPeerCert(self.peer_cert, self.client_gid)
54 # make sure the client is allowed to perform the operation
56 if not self.client_cred.can_perform(operation):
57 raise InsufficientRights(operation)
59 if self.trusted_cert_list:
60 self.client_cred.verify(self.trusted_cert_file_list)
62 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
66 def check_ticket(self, ticket):
68 Check if the tickt was signed by a trusted cert
70 if self.trusted_cert_list:
71 client_ticket = SfaTicket(string=ticket)
72 client_ticket.verify_chain(self.trusted_cert_list)
74 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
78 def verifyPeerCert(self, cert, gid):
79 # make sure the client_gid matches client's certificate
80 if not cert.is_pubkey(gid.get_pubkey()):
81 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
83 def verifyGidRequestHash(self, gid, hash, arglist):
84 key = gid.get_pubkey()
85 if not key.verify_string(str(arglist), hash):
86 raise BadRequestHash(hash)
88 def verifyCredRequestHash(self, cred, hash, arglist):
89 gid = cred.get_gid_caller()
90 self.verifyGidRequestHash(gid, hash, arglist)
92 def validateGid(self, gid):
93 if self.trusted_cert_list:
94 gid.verify_chain(self.trusted_cert_list)
96 def validateCred(self, cred):
97 if self.trusted_cert_list:
98 cred.verify(self.trusted_cert_file_list)
100 def authenticateGid(self, gidStr, argList, requestHash=None):
101 gid = GID(string = gidStr)
102 self.validateGid(gid)
103 # request_hash is optional
105 self.verifyGidRequestHash(gid, requestHash, argList)
108 def authenticateCred(self, credStr, argList, requestHash=None):
109 cred = Credential(string = credStr)
110 self.validateCred(cred)
111 # request hash is optional
113 self.verifyCredRequestHash(cred, requestHash, argList)
116 def authenticateCert(self, certStr, requestHash):
117 cert = Certificate(string=certStr)
118 self.validateCert(self, cert)
120 def gidNoop(self, gidStr, value, requestHash):
121 self.authenticateGid(gidStr, [gidStr, value], requestHash)
124 def credNoop(self, credStr, value, requestHash):
125 self.authenticateCred(credStr, [credStr, value], requestHash)
128 def verify_cred_is_me(self, credential):
130 cred = Credential(string=credential)
131 caller_gid = cred.get_gid_caller()
132 caller_hrn = caller_gid.get_hrn()
133 if caller_hrn != self.config.SFA_INTERFACE_HRN:
134 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
138 def get_auth_info(self, auth_hrn):
140 Given an authority name, return the information for that authority.
141 This is basically a stub that calls the hierarchy module.
143 @param auth_hrn human readable name of authority
146 return self.hierarchy.get_auth_info(auth_hrn)
149 def veriry_auth_belongs_to_me(self, name):
151 Verify that an authority belongs to our hierarchy.
152 This is basically left up to the implementation of the hierarchy
153 module. If the specified name does not belong, ane exception is
154 thrown indicating the caller should contact someone else.
156 @param auth_name human readable name of authority
159 # get auth info will throw an exception if the authority doesnt exist
160 self.get_auth_info(name)
163 def verify_object_belongs_to_me(self, name):
165 Verify that an object belongs to our hierarchy. By extension,
166 this implies that the authority that owns the object belongs
167 to our hierarchy. If it does not an exception is thrown.
169 @param name human readable name of object
171 auth_name = self.get_authority(name)
174 if name == self.config.SFA_INTERFACE_HRN:
176 self.verify_auth_belongs_to_me(auth_name)
178 def verify_auth_belongs_to_me(self, name):
179 # get auth info will throw an exception if the authority doesnt exist
180 self.get_auth_info(name)
183 def verify_object_permission(self, name):
185 Verify that the object gid that was specified in the credential
186 allows permission to the object 'name'. This is done by a simple
187 prefix test. For example, an object_gid for plc.arizona would
188 match the objects plc.arizona.slice1 and plc.arizona.
190 @param name human readable name to test
192 object_hrn = self.object_gid.get_hrn()
193 if object_hrn == name:
195 if name.startswith(object_hrn + "."):
197 #if name.startswith(get_authority(name)):
200 raise PermissionError(name)
202 def determine_user_rights(self, caller_hrn, record):
204 Given a user credential and a record, determine what set of rights the
205 user should have to that record.
207 This is intended to replace determine_rights() and
208 verify_cancreate_credential()
212 type = record['type']
215 researchers = record.get("researcher", [])
216 pis = record.get("PI", [])
217 if (caller_hrn in researchers + pis):
224 elif type == "authority":
225 pis = record.get("PI", [])
226 operators = record.get("operator", [])
227 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
231 if (caller_hrn in pis):
234 if (caller_hrn in operators):
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)