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()
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
83 if not cert.is_pubkey(gid.get_pubkey()):
84 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
86 def verifyGidRequestHash(self, gid, hash, arglist):
87 key = gid.get_pubkey()
88 if not key.verify_string(str(arglist), hash):
89 raise BadRequestHash(hash)
91 def verifyCredRequestHash(self, cred, hash, arglist):
92 gid = cred.get_gid_caller()
93 self.verifyGidRequestHash(gid, hash, arglist)
95 def validateGid(self, gid):
96 if self.trusted_cert_list:
97 gid.verify_chain(self.trusted_cert_list)
99 def validateCred(self, cred):
100 if self.trusted_cert_list:
101 cred.verify_chain(self.trusted_cert_list)
102 caller_gid = cred.get_gid_caller()
103 object_gid = cred.get_gid_object()
105 caller_gid.verify_chain(self.trusted_cert_list)
107 object_gid.verify_chain(self.trusted_cert_list)
109 def authenticateGid(self, gidStr, argList, requestHash=None):
110 gid = GID(string = gidStr)
111 self.validateGid(gid)
112 # request_hash is optional
114 self.verifyGidRequestHash(gid, requestHash, argList)
117 def authenticateCred(self, credStr, argList, requestHash=None):
118 cred = Credential(string = credStr)
119 self.validateCred(cred)
120 # request hash is optional
122 self.verifyCredRequestHash(cred, requestHash, argList)
125 def authenticateCert(self, certStr, requestHash):
126 cert = Certificate(string=certStr)
127 self.validateCert(self, cert)
129 def gidNoop(self, gidStr, value, requestHash):
130 self.authenticateGid(gidStr, [gidStr, value], requestHash)
133 def credNoop(self, credStr, value, requestHash):
134 self.authenticateCred(credStr, [credStr, value], requestHash)
137 def verify_cred_is_me(self, credential):
139 cred = Credential(string=credential)
140 caller_gid = cred.get_gid_caller()
141 caller_hrn = caller_gid.get_hrn()
142 if caller_hrn != self.config.SFA_INTERFACE_HRN:
143 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
147 def get_auth_info(self, auth_hrn):
149 Given an authority name, return the information for that authority.
150 This is basically a stub that calls the hierarchy module.
152 @param auth_hrn human readable name of authority
155 return self.hierarchy.get_auth_info(auth_hrn)
158 def veriry_auth_belongs_to_me(self, name):
160 Verify that an authority belongs to our hierarchy.
161 This is basically left up to the implementation of the hierarchy
162 module. If the specified name does not belong, ane exception is
163 thrown indicating the caller should contact someone else.
165 @param auth_name human readable name of authority
168 # get auth info will throw an exception if the authority doesnt exist
169 self.get_auth_info(name)
172 def verify_object_belongs_to_me(self, name):
174 Verify that an object belongs to our hierarchy. By extension,
175 this implies that the authority that owns the object belongs
176 to our hierarchy. If it does not an exception is thrown.
178 @param name human readable name of object
180 auth_name = self.get_authority(name)
183 if name == self.config.SFA_INTERFACE_HRN:
185 self.verify_auth_belongs_to_me(auth_name)
187 def verify_auth_belongs_to_me(self, name):
188 # get auth info will throw an exception if the authority doesnt exist
189 self.get_auth_info(name)
192 def verify_object_permission(self, name):
194 Verify that the object gid that was specified in the credential
195 allows permission to the object 'name'. This is done by a simple
196 prefix test. For example, an object_gid for plc.arizona would
197 match the objects plc.arizona.slice1 and plc.arizona.
199 @param name human readable name to test
201 object_hrn = self.object_gid.get_hrn()
202 if object_hrn == name:
204 if name.startswith(object_hrn + "."):
206 #if name.startswith(get_authority(name)):
209 raise PermissionError(name)
211 def determine_user_rights(self, caller_hrn, record):
213 Given a user credential and a record, determine what set of rights the
214 user should have to that record.
216 This is intended to replace determine_rights() and
217 verify_cancreate_credential()
221 type = record['type']
224 researchers = record.get("researcher", [])
225 pis = record.get("PI", [])
226 if (caller_hrn in researchers + pis):
233 elif type == "authority":
234 pis = record.get("PI", [])
235 operators = record.get("operator", [])
236 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
237 rl.add("authority,sa,ma",)
238 if (caller_hrn in pis):
239 rl.add("authority,sa")
240 if (caller_hrn in operators):
241 rl.add("authority,ma")
253 def verify_cancreate_credential(self, src_cred, record):
255 Verify that a user can retrive a particular type of credential.
256 For slices, the user must be on the researcher list. For SA and
257 MA the user must be on the pi and operator lists respectively
260 type = record.get_type()
261 cred_object_hrn = src_cred.get_gid_object().get_hrn()
262 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
265 researchers = record.get("researcher", [])
266 if not (cred_object_hrn in researchers):
267 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
269 pis = record.get("pi", [])
270 if not (cred_object_hrn in pis):
271 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
273 operators = record.get("operator", [])
274 if not (cred_object_hrn in operators):
275 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
277 def get_authority(self, hrn):
278 return get_authority(hrn)