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()
31 self.trusted_cert_file_list = TrustedRootList(self.config.get_trustedroots_dir()).get_file_list()
33 def load_trusted_certs(self):
34 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
36 def check(self, cred, operation):
38 Check the credential against the peer cert (callerGID included
39 in the credential matches the caller that is connected to the
40 HTTPS connection, check if the credential was signed by a
41 trusted cert and check if the credential is allowd to perform
42 the specified operation.
44 self.client_cred = Credential(string = cred)
45 self.client_gid = self.client_cred.get_gid_caller()
46 self.object_gid = self.client_cred.get_gid_object()
48 # make sure the client_gid is not blank
49 if not self.client_gid:
50 raise MissingCallerGID(self.client_cred.get_subject())
52 # validate the client cert if it exists
54 self.verifyPeerCert(self.peer_cert, self.client_gid)
56 # make sure the client is allowed to perform the operation
58 if not self.client_cred.can_perform(operation):
59 raise InsufficientRights(operation)
61 if self.trusted_cert_list:
62 self.client_cred.verify(self.trusted_cert_file_list)
64 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
68 def check_ticket(self, ticket):
70 Check if the tickt was signed by a trusted cert
72 if self.trusted_cert_list:
73 client_ticket = SfaTicket(string=ticket)
74 client_ticket.verify_chain(self.trusted_cert_list)
76 raise MissingTrustedRoots(self.config.get_trustedroots_dir())
80 def verifyPeerCert(self, cert, gid):
81 # make sure the client_gid matches client's certificate
82 if not cert.is_pubkey(gid.get_pubkey()):
83 raise ConnectionKeyGIDMismatch(gid.get_subject()+":"+cert.get_subject())
85 def verifyGidRequestHash(self, gid, hash, arglist):
86 key = gid.get_pubkey()
87 if not key.verify_string(str(arglist), hash):
88 raise BadRequestHash(hash)
90 def verifyCredRequestHash(self, cred, hash, arglist):
91 gid = cred.get_gid_caller()
92 self.verifyGidRequestHash(gid, hash, arglist)
94 def validateGid(self, gid):
95 if self.trusted_cert_list:
96 gid.verify_chain(self.trusted_cert_list)
98 def validateCred(self, cred):
99 if self.trusted_cert_list:
100 cred.verify(self.trusted_cert_file_list)
102 def authenticateGid(self, gidStr, argList, requestHash=None):
103 gid = GID(string = gidStr)
104 self.validateGid(gid)
105 # request_hash is optional
107 self.verifyGidRequestHash(gid, requestHash, argList)
110 def authenticateCred(self, credStr, argList, requestHash=None):
111 cred = Credential(string = credStr)
112 self.validateCred(cred)
113 # request hash is optional
115 self.verifyCredRequestHash(cred, requestHash, argList)
118 def authenticateCert(self, certStr, requestHash):
119 cert = Certificate(string=certStr)
120 self.validateCert(self, cert)
122 def gidNoop(self, gidStr, value, requestHash):
123 self.authenticateGid(gidStr, [gidStr, value], requestHash)
126 def credNoop(self, credStr, value, requestHash):
127 self.authenticateCred(credStr, [credStr, value], requestHash)
130 def verify_cred_is_me(self, credential):
132 cred = Credential(string=credential)
133 caller_gid = cred.get_gid_caller()
134 caller_hrn = caller_gid.get_hrn()
135 if caller_hrn != self.config.SFA_INTERFACE_HRN:
136 raise SfaPermissionDenied(self.config.SFA_INTEFACE_HRN)
140 def get_auth_info(self, auth_hrn):
142 Given an authority name, return the information for that authority.
143 This is basically a stub that calls the hierarchy module.
145 @param auth_hrn human readable name of authority
148 return self.hierarchy.get_auth_info(auth_hrn)
151 def veriry_auth_belongs_to_me(self, name):
153 Verify that an authority belongs to our hierarchy.
154 This is basically left up to the implementation of the hierarchy
155 module. If the specified name does not belong, ane exception is
156 thrown indicating the caller should contact someone else.
158 @param auth_name human readable name of authority
161 # get auth info will throw an exception if the authority doesnt exist
162 self.get_auth_info(name)
165 def verify_object_belongs_to_me(self, name):
167 Verify that an object belongs to our hierarchy. By extension,
168 this implies that the authority that owns the object belongs
169 to our hierarchy. If it does not an exception is thrown.
171 @param name human readable name of object
173 auth_name = self.get_authority(name)
176 if name == self.config.SFA_INTERFACE_HRN:
178 self.verify_auth_belongs_to_me(auth_name)
180 def verify_auth_belongs_to_me(self, name):
181 # get auth info will throw an exception if the authority doesnt exist
182 self.get_auth_info(name)
185 def verify_object_permission(self, name):
187 Verify that the object gid that was specified in the credential
188 allows permission to the object 'name'. This is done by a simple
189 prefix test. For example, an object_gid for plc.arizona would
190 match the objects plc.arizona.slice1 and plc.arizona.
192 @param name human readable name to test
194 object_hrn = self.object_gid.get_hrn()
195 if object_hrn == name:
197 if name.startswith(object_hrn + "."):
199 #if name.startswith(get_authority(name)):
202 raise PermissionError(name)
204 def determine_user_rights(self, caller_hrn, record):
206 Given a user credential and a record, determine what set of rights the
207 user should have to that record.
209 This is intended to replace determine_rights() and
210 verify_cancreate_credential()
214 type = record['type']
217 researchers = record.get("researcher", [])
218 pis = record.get("PI", [])
219 if (caller_hrn in researchers + pis):
226 elif type == "authority":
227 pis = record.get("PI", [])
228 operators = record.get("operator", [])
229 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
233 if (caller_hrn in pis):
236 if (caller_hrn in operators):
250 def verify_cancreate_credential(self, src_cred, record):
252 Verify that a user can retrive a particular type of credential.
253 For slices, the user must be on the researcher list. For SA and
254 MA the user must be on the pi and operator lists respectively
257 type = record.get_type()
258 cred_object_hrn = src_cred.get_gid_object().get_hrn()
259 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
262 researchers = record.get("researcher", [])
263 if not (cred_object_hrn in researchers):
264 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
266 pis = record.get("pi", [])
267 if not (cred_object_hrn in pis):
268 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
270 operators = record.get("operator", [])
271 if not (cred_object_hrn in operators):
272 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
274 def get_authority(self, hrn):
275 return get_authority(hrn)