Changeset 0a49bd7 for fedd/federation/access.py
- Timestamp:
- Jan 15, 2011 5:52:15 PM (14 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master
- Children:
- aaf7f41
- Parents:
- ac15159 (diff), 944b746 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - git-author:
- Ted Faber <faber@…> (01/15/11 17:51:40)
- git-committer:
- Ted Faber <faber@…> (01/15/11 17:52:15)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/federation/access.py
rac15159 r0a49bd7 234 234 "Unpickling failed: %s") % e) 235 235 236 def append_allocation_authorization(self, aid, attrs, 237 need_state_lock=False, write_state_file=False, state_attr='state'): 238 """ 239 Append the authorization information to system state. By default we 240 assume this is called with the state lock and with a write of the state 241 file in the near future, need_state_lock and write_state_file can 242 override this. The state_attr is the attribute in the access class 243 that holds the per allocation information. Some complex classes use 244 different names for the dict. 245 """ 246 247 for p, a in attrs: 248 self.auth.set_attribute(p, a) 249 self.auth.save() 250 251 if need_state_lock: self.state_lock.acquire() 252 d = getattr(self, state_attr) 253 if aid in d and 'auth' in d[aid]: 254 d[aid]['auth'].update(attrs) 255 if write_state_file: self.write_state() 256 if need_state_lock: self.state_lock.release() 257 258 def clear_allocation_authorization(self, aid, need_state_lock=False, 259 write_state_file=False, state_attr='state'): 260 """ 261 Attrs is a set of attribute principal pairs that need to be removed 262 from the authenticator. Remove them and save the authenticator. See 263 append_allocation_authorization for the various overrides. 264 """ 265 266 if need_state_lock: self.state_lock.acquire() 267 d = getattr(self, state_attr) 268 if aid in d and 'auth' in d[aid]: 269 for p, a in d[aid]['auth']: 270 self.auth.unset_attribute(p, a) 271 d[aid]['auth'] = set() 272 if write_state_file: self.write_state() 273 if need_state_lock: self.state_lock.release() 274 self.auth.save() 275 236 276 def lookup_access(self, req, fid, filter=None, compare=None): 237 277 """ … … 261 301 # Check every attribute that we know how to map and take the first 262 302 # success. 303 fail_proofs = [ ] 263 304 for attr in check: 264 if self.auth.check_attribute(fid, attr.attr): 305 access_ok, proof = self.auth.check_attribute(fid, attr.attr, 306 with_proof=True) 307 if access_ok: 265 308 self.log.debug("Access succeeded for %s %s" % (attr.attr, fid)) 266 309 # XXX: needs to deal with dynamics 267 310 return copy.copy(attr.value), (False, False, False), \ 268 [ fid ] 311 [ fid ], proof 269 312 else: 313 fail_proofs.append(proof) 270 314 self.log.debug("Access failed for %s %s" % (attr.attr, fid)) 271 315 else: 272 raise service_error(service_error.access, "Access denied") 316 raise service_error(service_error.access, "Access denied", 317 proof=fail_proofs) 273 318 274 319 … … 408 453 return (exp, state) 409 454 410 def build_access_response(self, alloc_id, ap, services ):455 def build_access_response(self, alloc_id, ap, services, proof): 411 456 """ 412 457 Create the SOAP response. … … 421 466 msg = { 422 467 'allocID': alloc_id, 468 'proof': proof.to_dict(), 423 469 'fedAttr': [ 424 470 { 'attribute': 'domain', 'value': self.domain } , … … 730 776 except EnvironmentError, e: 731 777 self.log.error("Error deleting directory tree in %s" % e); 778 779 def RequestAccess(self, req, fid): 780 """ 781 Handle an access request. Success here maps the requester into the 782 local access control space and establishes state about that user keyed 783 to a fedid. We also save a copy of the certificate underlying that 784 fedid so this allocation can access configuration information and 785 shared parameters on the experiment controller. 786 """ 787 788 # The dance to get into the request body 789 if req.has_key('RequestAccessRequestBody'): 790 req = req['RequestAccessRequestBody'] 791 else: 792 raise service_error(service_error.req, "No request!?") 793 794 # Base class lookup routine. If this fails, it throws a service 795 # exception denying access that triggers a fault response back to the 796 # caller. 797 found, match, owners, proof = self.lookup_access(req, fid) 798 self.log.info( 799 "[RequestAccess] Access granted to %s with local creds %s" % \ 800 (match, found)) 801 # Make a fedid for this allocation 802 allocID, alloc_cert = generate_fedid(subj="alloc", log=self.log) 803 aid = unicode(allocID) 804 805 # Store the data about this allocation: 806 self.state_lock.acquire() 807 self.state[aid] = { } 808 self.state[aid]['user'] = found 809 self.state[aid]['owners'] = owners 810 self.state[aid]['auth'] = set() 811 # Authorize the creating fedid and the principal representing the 812 # allocation to manipulate it. 813 self.append_allocation_authorization(aid, 814 ((fid, allocID), (allocID, allocID))) 815 self.write_state() 816 self.state_lock.release() 817 818 # Create a directory to stash the certificate in, ans stash it. 819 try: 820 f = open("%s/%s.pem" % (self.certdir, aid), "w") 821 print >>f, alloc_cert 822 f.close() 823 except EnvironmentError, e: 824 raise service_error(service_error.internal, 825 "Can't open %s/%s : %s" % (self.certdir, aid, e)) 826 self.log.debug('[RequestAccess] Returning allocation ID: %s' % allocID) 827 return { 'allocID': { 'fedid': allocID }, 'proof': proof.to_dict() } 828 829 def ReleaseAccess(self, req, fid): 830 """ 831 Release the allocation granted earlier. Access to the allocation is 832 checked and if valid, the state and cached certificate are destroyed. 833 """ 834 # The dance to get into the request body 835 if req.has_key('ReleaseAccessRequestBody'): 836 req = req['ReleaseAccessRequestBody'] 837 else: 838 raise service_error(service_error.req, "No request!?") 839 840 # Pull a key out of the request. One can request to delete an 841 # allocation by a local human readable name or by a fedid. This finds 842 # both choices. 843 try: 844 if 'localname' in req['allocID']: 845 auth_attr = aid = req['allocID']['localname'] 846 elif 'fedid' in req['allocID']: 847 aid = unicode(req['allocID']['fedid']) 848 auth_attr = req['allocID']['fedid'] 849 else: 850 raise service_error(service_error.req, 851 "Only localnames and fedids are understood") 852 except KeyError: 853 raise service_error(service_error.req, "Badly formed request") 854 855 self.log.debug("[ReleaseAccess] deallocation requested for %s", aid) 856 # Confirm access 857 access_ok, proof = self.auth.check_attribute(fid, auth_attr, 858 with_proof=True) 859 if not access_ok: 860 self.log.debug("[ReleaseAccess] deallocation denied for %s", aid) 861 raise service_error(service_error.access, "Access Denied", 862 proof=proof) 863 864 # If there is an allocation in the state, delete it. Note the locking. 865 self.state_lock.acquire() 866 if aid in self.state: 867 self.log.debug("[ReleaseAccess] Found allocation for %s" %aid) 868 self.clear_allocation_authorization(aid) 869 del self.state[aid] 870 self.write_state() 871 self.state_lock.release() 872 # And remove the access cert 873 cf = "%s/%s.pem" % (self.certdir, aid) 874 self.log.debug("[ReleaseAccess] Removing %s" % cf) 875 os.remove(cf) 876 return { 'allocID': req['allocID'], 'proof': proof.to_dict() } 877 else: 878 self.state_lock.release() 879 raise service_error(service_error.req, "No such allocation")
Note: See TracChangeset
for help on using the changeset viewer.