2 # SfaAPI 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.namespace 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()
31 self.trusted_cert_file_list = TrustedRootList(self.config.get_trustedroots_dir()).get_file_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 self.client_gid.verify_chain(self.trusted_cert_list)
64 self.object_gid.verify_chain(self.trusted_cert_list)
66 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
70 def check_ticket(self, ticket):
72 Check if the tickt was signed by a trusted cert
74 if self.trusted_cert_list:
75 client_ticket = SfaTicket(string=ticket)
76 client_ticket.verify_chain(self.trusted_cert_list)
78 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
82 def verifyPeerCert(self, cert, gid):
83 # make sure the client_gid matches client's certificate
84 if not cert.is_pubkey(gid.get_pubkey()):
85 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
87 def verifyGidRequestHash(self, gid, hash, arglist):
88 key = gid.get_pubkey()
89 if not key.verify_string(str(arglist), hash):
90 raise BadRequestHash(hash)
92 def verifyCredRequestHash(self, cred, hash, arglist):
93 gid = cred.get_gid_caller()
94 self.verifyGidRequestHash(gid, hash, arglist)
96 def validateGid(self, gid):
97 if self.trusted_cert_list:
98 gid.verify_chain(self.trusted_cert_list)
100 def validateCred(self, cred):
101 if self.trusted_cert_list:
102 cred.verify(self.trusted_cert_file_list)
103 caller_gid = cred.get_gid_caller()
104 object_gid = cred.get_gid_object()
106 caller_gid.verify_chain(self.trusted_cert_list)
108 object_gid.verify_chain(self.trusted_cert_list)
110 def authenticateGid(self, gidStr, argList, requestHash=None):
111 gid = GID(string = gidStr)
112 self.validateGid(gid)
113 # request_hash is optional
115 self.verifyGidRequestHash(gid, requestHash, argList)
118 def authenticateCred(self, credStr, argList, requestHash=None):
119 cred = Credential(string = credStr)
120 self.validateCred(cred)
121 # request hash is optional
123 self.verifyCredRequestHash(cred, requestHash, argList)
126 def authenticateCert(self, certStr, requestHash):
127 cert = Certificate(string=certStr)
128 self.validateCert(self, cert)
130 def gidNoop(self, gidStr, value, requestHash):
131 self.authenticateGid(gidStr, [gidStr, value], requestHash)
134 def credNoop(self, credStr, value, requestHash):
135 self.authenticateCred(credStr, [credStr, value], requestHash)
138 def verify_cred_is_me(self, credential):
140 cred = Credential(string=credential)
141 caller_gid = cred.get_gid_caller()
142 caller_hrn = caller_gid.get_hrn()
143 if caller_hrn != self.config.SFA_INTERFACE_HRN:
144 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
148 def get_auth_info(self, auth_hrn):
150 Given an authority name, return the information for that authority.
151 This is basically a stub that calls the hierarchy module.
153 @param auth_hrn human readable name of authority
156 return self.hierarchy.get_auth_info(auth_hrn)
159 def veriry_auth_belongs_to_me(self, name):
161 Verify that an authority belongs to our hierarchy.
162 This is basically left up to the implementation of the hierarchy
163 module. If the specified name does not belong, ane exception is
164 thrown indicating the caller should contact someone else.
166 @param auth_name human readable name of authority
169 # get auth info will throw an exception if the authority doesnt exist
170 self.get_auth_info(name)
173 def verify_object_belongs_to_me(self, name):
175 Verify that an object belongs to our hierarchy. By extension,
176 this implies that the authority that owns the object belongs
177 to our hierarchy. If it does not an exception is thrown.
179 @param name human readable name of object
181 auth_name = self.get_authority(name)
184 if name == self.config.SFA_INTERFACE_HRN:
186 self.verify_auth_belongs_to_me(auth_name)
188 def verify_auth_belongs_to_me(self, name):
189 # get auth info will throw an exception if the authority doesnt exist
190 self.get_auth_info(name)
193 def verify_object_permission(self, name):
195 Verify that the object gid that was specified in the credential
196 allows permission to the object 'name'. This is done by a simple
197 prefix test. For example, an object_gid for plc.arizona would
198 match the objects plc.arizona.slice1 and plc.arizona.
200 @param name human readable name to test
202 object_hrn = self.object_gid.get_hrn()
203 if object_hrn == name:
205 if name.startswith(object_hrn + "."):
207 #if name.startswith(get_authority(name)):
210 raise PermissionError(name)
212 def determine_user_rights(self, caller_hrn, record):
214 Given a user credential and a record, determine what set of rights the
215 user should have to that record.
217 This is intended to replace determine_rights() and
218 verify_cancreate_credential()
222 type = record['type']
225 researchers = record.get("researcher", [])
226 pis = record.get("PI", [])
227 if (caller_hrn in researchers + pis):
234 elif type == "authority":
235 pis = record.get("PI", [])
236 operators = record.get("operator", [])
237 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
238 rl.add("authority,sa,ma",)
239 if (caller_hrn in pis):
240 rl.add("authority,sa")
241 if (caller_hrn in operators):
242 rl.add("authority,ma")
254 def verify_cancreate_credential(self, src_cred, record):
256 Verify that a user can retrive a particular type of credential.
257 For slices, the user must be on the researcher list. For SA and
258 MA the user must be on the pi and operator lists respectively
261 type = record.get_type()
262 cred_object_hrn = src_cred.get_gid_object().get_hrn()
263 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
266 researchers = record.get("researcher", [])
267 if not (cred_object_hrn in researchers):
268 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
270 pis = record.get("pi", [])
271 if not (cred_object_hrn in pis):
272 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
274 operators = record.get("operator", [])
275 if not (cred_object_hrn in operators):
276 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
278 def get_authority(self, hrn):
279 return get_authority(hrn)