def write_named_conf_includes(self, db_session, op_exc): """ Write the bits of named configuration. Seperated so that it is callable from recovery script """ def open_tmp_file(prefix): (fd, tmp_filename) = mkstemp( dir=tmp_dir, prefix=prefix) include_file = io.open(fd, mode='wt') return (include_file, tmp_filename) def clean_up_rename(include_file, tmp_filename, config_file_name): include_file.close() # Rename tmp file into place so that replacement is atomic run_as_user = settings['run_as_user'] try: run_as_user_pwd = pwd.getpwnam(run_as_user) except KeyError as exc: msg = ("Could not find user '%s' in passwd database - %s" % (run_as_user, str(exc))) raise op_exc(msg) uid = run_as_user_pwd.pw_uid gid = run_as_user_pwd.pw_gid os.chown(tmp_filename, uid, gid) os.chmod(tmp_filename, int(settings['zone_file_mode'],8)) # Rename tmp file into place so that replacement is atomic os.chmod(tmp_filename, int(settings['config_file_mode'],8)) os.rename(tmp_filename, config_file_name) db_query_slice = get_numeric_setting('db_query_slice', int) # Clear template cache. This forces a re read of all templates clear_template_cache() # Rewrite include and global server ACL file if required. # Trap file IO errors as event queue can't handle them. try: tmp_dir = settings['master_config_dir'] # master server ACL file acl_prefix = ('.' + basename(settings['master_server_acl_file']) + '-') acl_file, tmp_filename = open_tmp_file(acl_prefix) # Create Master ACL file server_acl_template = read_template( settings['master_template_dir'] + '/' + settings[MASTER_SERVER_ACL_TEMPLATE]) server_acls = {} ServerGroup = sql_types['ServerGroup'] query = db_session.query(ServerGroup) for sg in query: # Each SG gets its own ACL to prevent cross SG # domain discovery if a server is compromised. sg_acl_name = sg.name + settings['acl_name_extension'] server_acls[sg.name] = {'acl_name': sg_acl_name, 'servers': ''} for server_sm in sg.servers: # include disabled server, as access can be shut off # in IPSEC and firewall! server_acls[sg.name]['servers'] += ("%s;\n" % server_sm.address) del server_sm if not server_acls[sg.name]['servers']: server_acls[sg.name]['servers'] = 'none;\n' # Stop memory leaks del sg for sg_name in server_acls: acl_file.write(server_acl_template % server_acls[sg_name]) clean_up_rename(acl_file, tmp_filename, settings['master_server_acl_file']) # include file include_prefix = ('.' + basename(settings['master_include_file']) + '-') include_file, tmp_filename = open_tmp_file(include_prefix) # Get list of zones from zone_sm, and write out each # config file section ZoneSM = sql_types['ZoneSM'] query = ZoneSM.query_is_configured( db_session.query(ZoneSM)).yield_per(db_query_slice) for zone_sm in query: zone_sm.write_config(include_file, db_session, server_acls, self.replica_sg) del zone_sm clean_up_rename(include_file, tmp_filename, settings['master_include_file']) except (IOError, OSError) as exc: msg = ( "Could not access/write file '%s' - %s." % (exc.filename, exc.strerror)) raise op_exc(msg) except KeyError as exc: msg = ("Invalid template key in template dir %s - %s" % (settings['master_template_dir'], str(exc))) raise op_exc(msg) finally: # clean up if possible try: os.unlink(tmp_filename) except: pass
def write_config(self, db_session, op_exc): """ Write out all configuration files needed for a server group. """ def write_zone_include(zone_sm): # Remove dot at end of zone name as this gives more # human literate filenames filler_name = zone_sm.name[:-1] \ if zone_sm.name.endswith('.') \ else zone_sm.name filler = {'name': filler_name, 'master': master_address} tmp_file.write(template % filler) replica_sg = (True if hasattr(self, 'master_sm') and self.master_sm else False) # Calculate master addresses if (self.master_address and self.master_address in settings['this_servers_addresses']): master_address = self.master_address elif (self.master_alt_address and self.master_alt_address in settings['this_servers_addresses']): master_address = self.master_alt_address else: master_address = settings['master_dns_server'] # Get list of server types in SG ServerSM = sql_types['ServerSM'] server_types = [s.server_type for s in self.servers] # sort|uniq the types list server_types = list(set(sorted(server_types))) if replica_sg: server_types = [ st + settings['server_replica_suffix'] for st in server_types ] db_query_slice = get_numeric_setting('db_query_slice', int) for server_type in server_types: include_dir = self.get_include_dir() include_file = self.get_include_file(server_type) if self.config_dir: # This allows us to override default template configuration # for say internal domains which IPV6 ULA/ # IPV4 RFC1918 addressing template_file = (self.config_dir + '/' + server_type + '.conf') else: template_file = (settings['server_config_dir'] + '/' + server_type + '.conf') try: # Make directory if it already does not exist # This is in here to avoid try: verbosity if not os.path.isdir(include_dir): os.mkdir(include_dir) template = read_template(template_file) (fd, tmp_filename) = tempfile.mkstemp( dir=include_dir, prefix='.' + basename(include_file) + '-') tmp_file = io.open(fd, mode='wt') zone_sm_type = sql_types['ZoneSM'] zone_count = 0 if replica_sg: # Master SG - include all zones query = db_session.query(zone_sm_type) query = zone_sm_type.query_sg_is_configured(query)\ .yield_per(db_query_slice) for zone_sm in query: write_zone_include(zone_sm) zone_count += 1 # Prevent Memory leaks... del zone_sm else: query = zone_sm_type.query_sg_is_configured(self.zones)\ .yield_per(db_query_slice) for zone_sm in query: write_zone_include(zone_sm) zone_count += 1 # Prevent Memory leaks... del zone_sm query = zone_sm_type.query_sg_is_configured( self.alt_zones)\ .yield_per(db_query_slice) for zone_sm in query: write_zone_include(zone_sm) zone_count += 1 # Prevent Memory leaks... del zone_sm tmp_file.close() # Rename tmp file into place so that replacement is atomic os.chmod(tmp_filename, int(settings['config_file_mode'],8)) os.rename(tmp_filename, include_file) # Store zone_count for monitoring data input self.zone_count = zone_count except (IOError, OSError) as exc: msg = ( "SG %s - '%s' - %s." % (self.name, exc.filename, exc.strerror)) if exc.errno in (errno.ENOENT, errno.EPERM, errno.EACCES): raise op_exc(msg) else: raise exc except KeyError as exc: msg = ("SG %s - Invalid template key in template file %s - %s" % (self.name, template_file, str(exc))) raise op_exc(msg) finally: # clean up if possible try: os.unlink(tmp_filename) except: pass return
def write_named_conf_includes(self, db_session, op_exc): """ Write the bits of named configuration. Seperated so that it is callable from recovery script """ def open_tmp_file(prefix): (fd, tmp_filename) = mkstemp(dir=tmp_dir, prefix=prefix) include_file = io.open(fd, mode='wt') return (include_file, tmp_filename) def clean_up_rename(include_file, tmp_filename, config_file_name): include_file.close() # Rename tmp file into place so that replacement is atomic run_as_user = settings['run_as_user'] try: run_as_user_pwd = pwd.getpwnam(run_as_user) except KeyError as exc: msg = ("Could not find user '%s' in passwd database - %s" % (run_as_user, str(exc))) raise op_exc(msg) uid = run_as_user_pwd.pw_uid gid = run_as_user_pwd.pw_gid os.chown(tmp_filename, uid, gid) os.chmod(tmp_filename, int(settings['zone_file_mode'], 8)) # Rename tmp file into place so that replacement is atomic os.chmod(tmp_filename, int(settings['config_file_mode'], 8)) os.rename(tmp_filename, config_file_name) db_query_slice = get_numeric_setting('db_query_slice', int) # Clear template cache. This forces a re read of all templates clear_template_cache() # Rewrite include and global server ACL file if required. # Trap file IO errors as event queue can't handle them. try: tmp_dir = settings['master_config_dir'] # master server ACL file acl_prefix = ('.' + basename(settings['master_server_acl_file']) + '-') acl_file, tmp_filename = open_tmp_file(acl_prefix) # Create Master ACL file server_acl_template = read_template( settings['master_template_dir'] + '/' + settings[MASTER_SERVER_ACL_TEMPLATE]) server_acls = {} ServerGroup = sql_types['ServerGroup'] query = db_session.query(ServerGroup) for sg in query: # Each SG gets its own ACL to prevent cross SG # domain discovery if a server is compromised. sg_acl_name = sg.name + settings['acl_name_extension'] server_acls[sg.name] = {'acl_name': sg_acl_name, 'servers': ''} for server_sm in sg.servers: # include disabled server, as access can be shut off # in IPSEC and firewall! server_acls[sg.name]['servers'] += ("%s;\n" % server_sm.address) del server_sm if not server_acls[sg.name]['servers']: server_acls[sg.name]['servers'] = 'none;\n' # Stop memory leaks del sg for sg_name in server_acls: acl_file.write(server_acl_template % server_acls[sg_name]) clean_up_rename(acl_file, tmp_filename, settings['master_server_acl_file']) # include file include_prefix = ('.' + basename(settings['master_include_file']) + '-') include_file, tmp_filename = open_tmp_file(include_prefix) # Get list of zones from zone_sm, and write out each # config file section ZoneSM = sql_types['ZoneSM'] query = ZoneSM.query_is_configured( db_session.query(ZoneSM)).yield_per(db_query_slice) for zone_sm in query: zone_sm.write_config(include_file, db_session, server_acls, self.replica_sg) del zone_sm clean_up_rename(include_file, tmp_filename, settings['master_include_file']) except (IOError, OSError) as exc: msg = ("Could not access/write file '%s' - %s." % (exc.filename, exc.strerror)) raise op_exc(msg) except KeyError as exc: msg = ("Invalid template key in template dir %s - %s" % (settings['master_template_dir'], str(exc))) raise op_exc(msg) finally: # clean up if possible try: os.unlink(tmp_filename) except: pass