2 # GeniAPI 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.misc import *
17 from sfa.trust.gid import GID
21 Credential based authentication
24 def __init__(self, peer_cert = None, config = None ):
25 self.peer_cert = peer_cert
26 self.hierarchy = Hierarchy()
28 self.config = Config()
29 self.trusted_cert_list = TrustedRootList(self.config.get_trustedroots_dir()).get_list()
32 def check(self, cred, operation):
34 Check the credential against the peer cert (callerGID included
35 in the credential matches the caller that is connected to the
36 HTTPS connection, check if the credential was signed by a
37 trusted cert and check if the credential is allowd to perform
38 the specified operation.
40 self.client_cred = Credential(string = cred)
41 self.client_gid = self.client_cred.get_gid_caller()
42 self.object_gid = self.client_cred.get_gid_object()
44 # make sure the client_gid is not blank
45 if not self.client_gid:
46 raise MissingCallerGID(self.client_cred.get_subject())
48 # validate the client cert if it exists
50 self.verifyPeerCert(self.peer_cert, self.client_gid)
52 # make sure the client is allowed to perform the operation
54 if not self.client_cred.can_perform(operation):
55 raise InsufficientRights(operation)
57 if self.trusted_cert_list:
58 self.client_cred.verify_chain(self.trusted_cert_list)
60 self.client_gid.verify_chain(self.trusted_cert_list)
62 self.object_gid.verify_chain(self.trusted_cert_list)
66 def verifyPeerCert(self, cert, gid):
67 # make sure the client_gid matches client's certificate
69 peer_cert = self.peer_cert
74 peer_gid = self.client_gid
77 if not peer_cert.is_pubkey(peer_gid.get_pubkey()):
78 raise ConnectionKeyGIDMismatch(peer_gid.get_subject())
80 def verifyGidRequestHash(self, gid, hash, arglist):
81 key = gid.get_pubkey()
82 if not key.verify_string(str(arglist), hash):
83 raise BadRequestHash(hash)
85 def verifyCredRequestHash(self, cred, hash, arglist):
86 gid = cred.get_gid_caller()
87 self.verifyGidRequestHash(gid, hash, arglist)
89 def validateGid(self, gid):
90 if self.trusted_cert_list:
91 gid.verify_chain(self.trusted_cert_list)
93 def validateCred(self, cred):
94 if self.trusted_cert_list:
95 cred.verify_chain(self.trusted_cert_list)
96 caller_gid = cred.get_gid_caller()
97 object_gid = cred.get_gid_object()
99 caller_gid.verify_chain(self.trusted_cert_list)
101 object_gid.verify_chain(self.trusted_cert_list)
103 def authenticateGid(self, gidStr, argList, requestHash=None):
104 gid = GID(string = gidStr)
105 self.validateGid(gid)
106 # request_hash is optional
108 self.verifyGidRequestHash(gid, requestHash, argList)
111 def authenticateCred(self, credStr, argList, requestHash=None):
112 cred = Credential(string = credStr)
113 self.validateCred(cred)
114 # request hash is optional
116 self.verifyCredRequestHash(cred, requestHash, argList)
119 def authenticateCert(self, certStr, requestHash):
120 cert = Certificate(string=certStr)
121 self.validateCert(self, cert)
123 def gidNoop(self, gidStr, value, requestHash):
124 self.authenticateGid(gidStr, [gidStr, value], requestHash)
127 def credNoop(self, credStr, value, requestHash):
128 self.authenticateCred(credStr, [credStr, value], requestHash)
131 def verify_cred_is_me(self, credential):
133 cred = Credential(string=credential)
134 caller_gid = cred.get_gid_caller()
135 caller_hrn = caller_gid.get_hrn()
136 if caller_hrn != self.config.SFA_INTERFACE_HRN:
137 raise GeniPermissionError(self.config.SFA_INTEFACE_HRN)
141 def get_auth_info(self, auth_hrn):
143 Given an authority name, return the information for that authority.
144 This is basically a stub that calls the hierarchy module.
146 @param auth_hrn human readable name of authority
149 return self.hierarchy.get_auth_info(auth_hrn)
152 def veriry_auth_belongs_to_me(self, name):
154 Verify that an authority belongs to our hierarchy.
155 This is basically left up to the implementation of the hierarchy
156 module. If the specified name does not belong, ane exception is
157 thrown indicating the caller should contact someone else.
159 @param auth_name human readable name of authority
162 # get auth info will throw an exception if the authority doesnt exist
163 self.get_auth_info(name)
166 def verify_object_belongs_to_me(self, name):
168 Verify that an object belongs to our hierarchy. By extension,
169 this implies that the authority that owns the object belongs
170 to our hierarchy. If it does not an exception is thrown.
172 @param name human readable name of object
174 auth_name = self.get_authority(name)
177 if name == self.config.SFA_INTERFACE_HRN:
179 self.verify_auth_belongs_to_me(auth_name)
181 def verify_auth_belongs_to_me(self, name):
182 # get auth info will throw an exception if the authority doesnt exist
183 self.get_auth_info(name)
186 def verify_object_permission(self, name):
188 Verify that the object gid that was specified in the credential
189 allows permission to the object 'name'. This is done by a simple
190 prefix test. For example, an object_gid for plc.arizona would
191 match the objects plc.arizona.slice1 and plc.arizona.
193 @param name human readable name to test
195 object_hrn = self.object_gid.get_hrn()
196 if object_hrn == name:
198 if name.startswith(object_hrn + "."):
200 #if name.startswith(get_authority(name)):
203 raise PermissionError(name)
205 def determine_user_rights(self, caller_hrn, record):
207 Given a user credential and a record, determine what set of rights the
208 user should have to that record.
210 This is intended to replace determine_rights() and
211 verify_cancreate_credential()
215 type = record['type']
218 researchers = record.get("researcher", [])
219 if (caller_hrn in researchers):
226 elif type == "authority":
227 pis = record.get("PI", [])
228 operators = record.get("operator", [])
229 if (caller_hrn == self.config.SFA_INTERFACE_HRN):
230 rl.add("authority,sa,ma",)
231 if (caller_hrn in pis):
232 rl.add("authority,sa")
233 if (caller_hrn in operators):
234 rl.add("authority,ma")
243 def verify_cancreate_credential(self, src_cred, record):
245 Verify that a user can retrive a particular type of credential.
246 For slices, the user must be on the researcher list. For SA and
247 MA the user must be on the pi and operator lists respectively
250 type = record.get_type()
251 cred_object_hrn = src_cred.get_gid_object().get_hrn()
252 if cred_object_hrn in [self.config.SFA_REGISTRY_ROOT_AUTH]:
255 researchers = record.get("researcher", [])
256 if not (cred_object_hrn in researchers):
257 raise PermissionError(cred_object_hrn + " is not in researcher list for " + record.get_name())
259 pis = record.get("pi", [])
260 if not (cred_object_hrn in pis):
261 raise PermissionError(cred_object_hrn + " is not in pi list for " + record.get_name())
263 operators = record.get("operator", [])
264 if not (cred_object_hrn in operators):
265 raise PermissionError(cred_object_hrn + " is not in operator list for " + record.get_name())
267 def get_authority(self, hrn):
268 return get_authority(hrn)