Changeset 6e63513 for fedd/federation
- Timestamp:
- Nov 23, 2010 6:42:19 PM (14 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master
- Children:
- 25f66c3
- Parents:
- 353db8c
- Location:
- fedd/federation
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/federation/access.py
r353db8c r6e63513 194 194 finally: 195 195 if f: f.close() 196 197 def read_abac_access(self, fn, access_obj=None): 198 """ 199 Read an access DB of the form 200 abac.attribute -> local_auth_data 201 The access dict is filled with mappings from the abac attributes (as 202 strings) to the access objects. The objects are strings by default, 203 but the class constructor is called with the string following the -> 204 and whitespace in the file. 205 """ 206 207 map_re = re.compile("(\S+)\s+->\s+(.*)"); 208 if access_obj is None: 209 access_obj = lambda(x): "%s" % x 210 211 f = open(fn, 'r') 212 try: 213 lineno = 0 214 for line in f: 215 lineno += 1 216 line = line.strip(); 217 if len(line) == 0 or line.startswith('#'): 218 continue 219 m = map_re.match(line) 220 if m != None: 221 self.access[m.group(1)] = access_obj(m.group(2)) 222 continue 223 224 # Nothing matched to here: unknown line - raise exception 225 # (finally will close f) 226 raise self.parse_error( 227 "Unknown statement at line %d of %s" % \ 228 (lineno, fn)) 229 finally: 230 if f: f.close() 231 196 232 197 233 def get_users(self, obj): -
fedd/federation/authorizer.py
r353db8c r6e63513 192 192 bad_name = authorizer_base.bad_name 193 193 attribute_error = authorizer_base.attribute_error 194 class no_file (RuntimeError): pass195 class bad_cert (RuntimeError): pass194 class no_file_error(RuntimeError): pass 195 class bad_cert_error(RuntimeError): pass 196 196 197 197 def __init__(self, certs=None, me=None, key=None, load=None, save=None): … … 203 203 # If the me parameter is a combination certificate, split it into the 204 204 # abac_authorizer save directory (if any) for use with creddy. 205 if abac_pem_type(self.me) == 'both':205 if self.me is not None and abac_pem_type(self.me) == 'both': 206 206 if self.save_dir: 207 207 self.key, self.me = abac_split_cert(self.me, … … 209 209 certfile = "%s/cert.pem" % self.save_dir) 210 210 else: 211 raise abac_authorizer.bad_cert ("Combination certificate" + \212 " and nowhere to split it");211 raise abac_authorizer.bad_cert_error("Combination " + \ 212 "certificate and nowhere to split it"); 213 213 else: 214 214 self.key = key -
fedd/federation/emulab_access.py
r353db8c r6e63513 21 21 from access_project import access_project 22 22 from fedid import fedid, generate_fedid 23 from authorizer import authorizer 23 from authorizer import authorizer, abac_authorizer 24 24 from service_error import service_error 25 25 from remote_service import xmlrpc_handler, soap_handler, service_caller … … 105 105 self.restricted = [ ] 106 106 self.access = { } 107 if config.has_option("access", "accessdb"): 108 self.read_access(config.get("access", "accessdb")) 107 # XXX: this should go? 108 #if config.has_option("access", "accessdb"): 109 # self.read_access(config.get("access", "accessdb")) 109 110 tb = config.get('access', 'testbed') 110 111 if tb: self.testbed = [ t.strip() for t in tb.split(',') ] 111 112 else: self.testbed = [ ] 112 113 113 if config.has_option("access", "accessdb"): 114 self.read_access(config.get("access", "accessdb"), 115 self.make_access_project) 114 # authorization information 115 self.auth_type = config.get('access', 'auth_type') \ 116 or 'legacy' 117 self.auth_dir = config.get('access', 'auth_dir') 118 accessdb = config.get("access", "accessdb") 119 # initialize the authorization system 120 if self.auth_type == 'legacy': 121 if accessdb: 122 self.read_access(accessdb, self.make_access_project) 123 elif self.auth_type == 'abac': 124 self.auth = abac_authorizer(load=self.auth_dir) 125 if accessdb: 126 self.read_abac_access(accessdb, self.make_abac_access_project) 127 else: 128 raise service_error(service_error.internal, 129 "Unknown auth_type: %s" % self.auth_type) 116 130 117 131 # read_state in the base_class … … 124 138 self.keys = self.state['keys'] 125 139 self.types = self.state['types'] 126 # Add the ownership attributes to the authorizer. Note that the 127 # indices of the allocation dict are strings, but the attributes are 128 # fedids, so there is a conversion. 129 for k in self.allocation.keys(): 130 for o in self.allocation[k].get('owners', []): 131 self.auth.set_attribute(o, fedid(hexstr=k)) 132 if self.allocation[k].has_key('userconfig'): 133 sfid = self.allocation[k]['userconfig'] 134 fid = fedid(hexstr=sfid) 135 self.auth.set_attribute(fid, "/%s" % sfid) 140 if self.auth_type == "legacy": 141 # Add the ownership attributes to the authorizer. Note that the 142 # indices of the allocation dict are strings, but the attributes are 143 # fedids, so there is a conversion. 144 for k in self.allocation.keys(): 145 for o in self.allocation[k].get('owners', []): 146 self.auth.set_attribute(o, fedid(hexstr=k)) 147 if self.allocation[k].has_key('userconfig'): 148 sfid = self.allocation[k]['userconfig'] 149 fid = fedid(hexstr=sfid) 150 self.auth.set_attribute(fid, "/%s" % sfid) 136 151 self.state_lock.release() 137 152 self.exports = { … … 220 235 else: 221 236 raise self.parse_error('Bad mapping (unbalanced parens)') 237 238 @staticmethod 239 def make_abac_access_project(str): 240 """ 241 Convert a string of the form (id, id) into an access_project. This is 242 called by read_abac_access to convert to local attributes. It returns 243 a tuple of the form (project, user, user) where the two users are 244 always the same. 245 """ 246 247 str = str.strip() 248 if str.startswith('(') and str.endswith(')') and str.count(',') == 1: 249 proj, user = str.split(',') 250 return ( proj.strip(), user.strip(), user.strip()) 251 else: 252 raise self.parse_error( 253 'Bad mapping (unbalanced parens or more than 1 comma)') 222 254 223 255 … … 296 328 [ fid ] 297 329 330 def lookup_abac_access(self, req, fid): 331 # Import request credentials into this (clone later??) 332 if self.auth.import_credentials(data_list=req.get('abac_credential', [])): 333 self.auth.save() 334 335 # Check every attribute that we know how to map and take the first 336 # success. 337 for attr in (self.access.keys()): 338 if self.auth.check_attribute(fid, attr): 339 # XXX: needs to deal with dynamics 340 return copy.copy(self.access[attr]), (False, False, False), \ 341 [ fid ] 342 else: 343 self.log.debug("Access failed for %s %s" % (attr, fid)) 344 else: 345 raise service_error(service_error.access, "Access denied") 346 347 298 348 def do_project_allocation(self, dyn, project, user): 299 349 """ … … 433 483 434 484 435 found, dyn, owners = self.lookup_access(req, fid) 485 if self.auth_type == "legacy": 486 found, dyn, owners = self.lookup_access(req, fid) 487 elif self.auth_type == 'abac': 488 found, dyn, owners = self.lookup_abac_access(req, fid) 489 else: 490 raise service_error(service_error.internal, 491 'Unknown auth_type: %s' % self.auth_type) 436 492 ap = None 437 493 … … 466 522 for o in owners: 467 523 self.auth.set_attribute(o, allocID) 524 self.auth.save() 468 525 try: 469 526 f = open("%s/%s.pem" % (self.certdir, aid), "w") -
fedd/federation/experiment_control.py
r353db8c r6e63513 1431 1431 allocated[tb] = 1 1432 1432 1433 def get_abac_access_to_testbeds(self, testbeds, fid, allocated, 1434 tbparams, masters, tbmap): 1435 for tb in testbeds: 1436 self.get_abac_access(tb, tbparams, fid, masters, tbmap) 1437 allocated[tb] = 1 1438 1439 def get_abac_access(self, tb, tbparams,fid, masters, tbmap): 1440 """ 1441 Get access to testbed through fedd and set the parameters for that tb 1442 """ 1443 def get_export_project(svcs): 1444 """ 1445 Look through for the list of federated_service for this testbed 1446 objects for a project_export service, and extract the project 1447 parameter. 1448 """ 1449 1450 pe = [s for s in svcs if s.name=='project_export'] 1451 if len(pe) == 1: 1452 return pe[0].params.get('project', None) 1453 elif len(pe) == 0: 1454 return None 1455 else: 1456 raise service_error(service_error.req, 1457 "More than one project export is not supported") 1458 1459 uri = tbmap.get(testbed_base(tb), None) 1460 if not uri: 1461 raise service_error(service_error.server_config, 1462 "Unknown testbed: %s" % tb) 1463 1464 export_svcs = masters.get(tb,[]) 1465 import_svcs = [ s for m in masters.values() \ 1466 for s in m \ 1467 if tb in s.importers ] 1468 1469 export_project = get_export_project(export_svcs) 1470 # Compose the credential list so that IDs come before attributes 1471 creds = set() 1472 keys = set() 1473 for c in self.auth.get_creds_for_principal(fid): 1474 keys.add(c.issuer_cert()) 1475 creds.add(c.attribute_cert()) 1476 creds = list(keys) + list(creds) 1477 1478 # Request credentials 1479 req = { 1480 'abac_credential': creds, 1481 } 1482 # Make the service request from the services we're importing and 1483 # exporting. Keep track of the export request ids so we can 1484 # collect the resulting info from the access response. 1485 e_keys = { } 1486 if import_svcs or export_svcs: 1487 req['service'] = [ ] 1488 1489 for i, s in enumerate(import_svcs): 1490 idx = 'import%d' % i 1491 sr = {'id': idx, 'name': s.name, 'visibility': 'import' } 1492 if s.params: 1493 sr['fedAttr'] = [ { 'attribute': k, 'value': v } \ 1494 for k, v in s.params.items()] 1495 req['service'].append(sr) 1496 1497 for i, s in enumerate(export_svcs): 1498 idx = 'export%d' % i 1499 e_keys[idx] = s 1500 sr = {'id': idx, 'name': s.name, 'visibility': 'export' } 1501 if s.params: 1502 sr['fedAttr'] = [ { 'attribute': k, 'value': v } 1503 for k, v in s.params.items()] 1504 req['service'].append(sr) 1505 1506 1507 if self.local_access.has_key(uri): 1508 # Local access call 1509 req = { 'RequestAccessRequestBody' : req } 1510 r = self.local_access[uri].RequestAccess(req, 1511 fedid(file=self.cert_file)) 1512 r = { 'RequestAccessResponseBody' : r } 1513 else: 1514 r = self.call_RequestAccess(uri, req, 1515 self.cert_file, self.cert_pwd, self.trusted_certs) 1516 1517 tbparam[tb] = { 1518 "allocID" : r['allocID'], 1519 "uri": uri, 1520 } 1521 1522 # Collect the responses corresponding to the services this testbed 1523 # exports. These will be the service requests that we will include in 1524 # the start segment requests (with appropriate visibility values) to 1525 # import and export the segments. 1526 for s in r.get('service', []): 1527 id = s.get('id', None) 1528 if id and id in e_keys: 1529 e_keys[id].reqs.append(s) 1530 1531 # Add attributes to parameter space. We don't allow attributes to 1532 # overlay any parameters already installed. 1533 for a in r.get('fedAttr', []): 1534 try: 1535 if a['attribute'] and \ 1536 isinstance(a['attribute'], basestring)\ 1537 and not tbparam[tb].has_key(a['attribute'].lower()): 1538 tbparam[tb][a['attribute'].lower()] = a['value'] 1539 except KeyError: 1540 self.log.error("Bad attribute in response: %s" % a) 1541 1542 1433 1543 def split_topology(self, top, topo, testbeds): 1434 1544 """ … … 1637 1747 raise service_error(service_error.req, "No request?") 1638 1748 1749 # Import information from the requester 1750 if self.auth.import_credentials(data_list=req.get('credential', [])): 1751 self.auth.save() 1752 1639 1753 self.check_experiment_access(fid, key) 1640 1754 … … 1790 1904 connInfo = { } # Connection information 1791 1905 1792 self.get_access_to_testbeds(testbeds, access_user, allocated, 1793 tbparams, masters, tbmap) 1906 if self.auth_type == 'legacy': 1907 self.get_access_to_testbeds(testbeds, access_user, allocated, 1908 tbparams, masters, tbmap) 1909 elif self.auth_type == 'abac': 1910 self.get_abac_access_to_testbeds(testbeds, fid, allocated, 1911 tbparams, masters, tbmap) 1912 else: 1913 raise service_error(service_error.internal, 1914 "Unknown auth_type %s" % self.auth_type) 1794 1915 1795 1916 self.split_topology(top, topo, testbeds) -
fedd/federation/util.py
r353db8c r6e63513 10 10 11 11 from socket import sslerror 12 from tempfile import mkstemp 12 13 13 14 from M2Crypto import SSL … … 267 268 cert_re = re.compile('\s*-----BEGIN CERTIFICATE-----$') 268 269 type = None 270 print cert 269 271 f = open(cert, 'r') 270 272 for line in f: … … 290 292 ''' 291 293 Wraps up the reqular expression to start and end a diversion, as well as 292 the open file that gets the lines. 294 the open file that gets the lines. If fd is passed in, use that system 295 file (probably from a mkstemp. Otherwise open the given filename. 293 296 ''' 294 def __init__(self, start, end, fn ):297 def __init__(self, start, end, fn=None, fd=None): 295 298 self.start = re.compile(start) 296 299 self.end = re.compile(end) 297 # Open the file securely with minimal permissions. NB file cannot 298 # exist before this call. 299 self.f = os.fdopen(os.open(fn, 300 (os.O_WRONLY | os.O_CREAT | os.O_TRUNC | os.O_EXCL), 0600), 301 'w') 300 301 if not fd: 302 # Open the file securely with minimal permissions. NB file 303 # cannot exist before this call. 304 fd = os.open(fn, 305 (os.O_WRONLY | os.O_CREAT | os.O_TRUNC | os.O_EXCL), 0600) 306 307 self.f = os.fdopen(fd, 'w') 302 308 303 309 def close(self): … … 305 311 306 312 if not keyfile: 307 f, keyfile = mkstemp(suffix=".pem") 308 os.close(f); 313 kf, rkeyfile = mkstemp(suffix=".pem") 314 else: 315 kf, rkeyfile = None, keyfile 316 309 317 if not certfile: 310 f, certfile = mkstemp(suffix=".pem") 311 os.close(f); 318 cf, rcertfile = mkstemp(suffix=".pem") 319 else: 320 cf, rcertfile = None, certfile 312 321 313 322 # Initialize the diversions 314 divs = [diversion(s, e, fn ) for s, e,fnin (323 divs = [diversion(s, e, fn=pfn, fd=pfd ) for s, e, pfn, pfd in ( 315 324 ('\s*-----BEGIN RSA PRIVATE KEY-----$', 316 325 '\s*-----END RSA PRIVATE KEY-----$', 317 keyfile ),326 keyfile, kf), 318 327 ('\s*-----BEGIN CERTIFICATE-----$', 319 328 '\s*-----END CERTIFICATE-----$', 320 certfile ))]329 certfile, cf))] 321 330 322 331 # walk through the file, beginning a diversion when a start regexp … … 340 349 # This is probably unnecessary. Close all the diversion files. 341 350 for d in divs: d.close() 342 return keyfile,certfile351 return rkeyfile, rcertfile 343 352 344 353 def find_pickle_problem(o, st=None):
Note: See TracChangeset
for help on using the changeset viewer.