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.load_trusted_certs()
32 def load_trusted_certs(self):
33 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
35 def check(self, cred, operation):
37 Check the credential against the peer cert (callerGID included
38 in the credential matches the caller that is connected to the
39 HTTPS connection, check if the credential was signed by a
40 trusted cert and check if the credential is allowd to perform
41 the specified operation.
43 self.client_cred = Credential(string = cred)
44 self.client_gid = self.client_cred.get_gid_caller()
45 self.object_gid = self.client_cred.get_gid_object()
47 # make sure the client_gid is not blank
48 if not self.client_gid:
49 raise MissingCallerGID(self.client_cred.get_subject())
51 # validate the client cert if it exists
53 self.verifyPeerCert(self.peer_cert, self.client_gid)
55 # make sure the client is allowed to perform the operation
57 if not self.client_cred.can_perform(operation):
58 raise InsufficientRights(operation)
60 if self.trusted_cert_list:
61 self.client_cred.verify_chain(self.trusted_cert_list)
63 self.client_gid.verify_chain(self.trusted_cert_list)
65 self.object_gid.verify_chain(self.trusted_cert_list)
67 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
71 def check_ticket(self, ticket):
73 Check if the tickt was signed by a trusted cert
75 if self.trusted_cert_list:
76 client_ticket = SfaTicket(string=ticket)
77 client_ticket.verify_chain(self.trusted_cert_list)
79 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
83 def verifyPeerCert(self, cert, gid):
84 # make sure the client_gid matches client's certificate
85 if not cert.is_pubkey(gid.get_pubkey()):
86 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
88 def verifyGidRequestHash(self, gid, hash, arglist):
89 key = gid.get_pubkey()
90 if not key.verify_string(str(arglist), hash):
91 raise BadRequestHash(hash)
93 def verifyCredRequestHash(self, cred, hash, arglist):
94 gid = cred.get_gid_caller()
95 self.verifyGidRequestHash(gid, hash, arglist)
97 def validateGid(self, gid):
98 if self.trusted_cert_list:
99 gid.verify_chain(self.trusted_cert_list)
101 def validateCred(self, cred):
102 if self.trusted_cert_list:
103 cred.verify_chain(self.trusted_cert_list)
104 caller_gid = cred.get_gid_caller()
105 object_gid = cred.get_gid_object()
107 caller_gid.verify_chain(self.trusted_cert_list)
109 object_gid.verify_chain(self.trusted_cert_list)
111 def authenticateGid(self, gidStr, argList, requestHash=None):
112 gid = GID(string = gidStr)
113 self.validateGid(gid)
114 # request_hash is optional
116 self.verifyGidRequestHash(gid, requestHash, argList)
119 def authenticateCred(self, credStr, argList, requestHash=None):
120 cred = Credential(string = credStr)
121 self.validateCred(cred)
122 # request hash is optional
124 self.verifyCredRequestHash(cred, requestHash, argList)
127 def authenticateCert(self, certStr, requestHash):
128 cert = Certificate(string=certStr)
129 self.validateCert(self, cert)
131 def gidNoop(self, gidStr, value, requestHash):
132 self.authenticateGid(gidStr, [gidStr, value], requestHash)
135 def credNoop(self, credStr, value, requestHash):
136 self.authenticateCred(credStr, [credStr, value], requestHash)
139 def verify_cred_is_me(self, credential):
141 cred = Credential(string=credential)
142 caller_gid = cred.get_gid_caller()
143 caller_hrn = caller_gid.get_hrn()
144 if caller_hrn != self.config.SFA_INTERFACE_HRN:
145 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
149 def get_auth_info(self, auth_hrn):
151 Given an authority name, return the information for that authority.
152 This is basically a stub that calls the hierarchy module.
154 @param auth_hrn human readable name of authority
157 return self.hierarchy.get_auth_info(auth_hrn)
160 def veriry_auth_belongs_to_me(self, name):
162 Verify that an authority belongs to our hierarchy.
163 This is basically left up to the implementation of the hierarchy
164 module. If the specified name does not belong, ane exception is
165 thrown indicating the caller should contact someone else.
167 @param auth_name human readable name of authority
170 # get auth info will throw an exception if the authority doesnt exist
171 self.get_auth_info(name)
174 def verify_object_belongs_to_me(self, name):
176 Verify that an object belongs to our hierarchy. By extension,
177 this implies that the authority that owns the object belongs
178 to our hierarchy. If it does not an exception is thrown.
180 @param name human readable name of object
182 auth_name = self.get_authority(name)
185 if name == self.config.SFA_INTERFACE_HRN:
187 self.verify_auth_belongs_to_me(auth_name)
189 def verify_auth_belongs_to_me(self, name):
190 # get auth info will throw an exception if the authority doesnt exist
191 self.get_auth_info(name)
194 def verify_object_permission(self, name):
196 Verify that the object gid that was specified in the credential
197 allows permission to the object 'name'. This is done by a simple
198 prefix test. For example, an object_gid for plc.arizona would
199 match the objects plc.arizona.slice1 and plc.arizona.
201 @param name human readable name to test
203 object_hrn = self.object_gid.get_hrn()
204 if object_hrn == name:
206 if name.startswith(object_hrn + "."):
208 #if name.startswith(get_authority(name)):
211 raise PermissionError(name)
213 def determine_user_rights(self, caller_hrn, record):
215 Given a user credential and a record, determine what set of rights the
216 user should have to that record.
218 This is intended to replace determine_rights() and
219 verify_cancreate_credential()
223 type = record['type']
226 researchers = record.get("researcher", [])
227 pis = record.get("PI", [])
228 if (caller_hrn in researchers + pis):
235 elif type == "authority":
236 pis = record.get("PI", [])
237 operators = record.get("operator", [])
238 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
239 rl.add("authority,sa,ma",)
240 if (caller_hrn in pis):
241 rl.add("authority,sa")
242 if (caller_hrn in operators):
243 rl.add("authority,ma")
255 def verify_cancreate_credential(self, src_cred, record):
257 Verify that a user can retrive a particular type of credential.
258 For slices, the user must be on the researcher list. For SA and
259 MA the user must be on the pi and operator lists respectively
262 type = record.get_type()
263 cred_object_hrn = src_cred.get_gid_object().get_hrn()
264 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
267 researchers = record.get("researcher", [])
268 if not (cred_object_hrn in researchers):
269 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
271 pis = record.get("pi", [])
272 if not (cred_object_hrn in pis):
273 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
275 operators = record.get("operator", [])
276 if not (cred_object_hrn in operators):
277 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
279 def get_authority(self, hrn):
280 return get_authority(hrn)