예제 #1
0
def test_replace_ipv4_host_where_name_differs(tmpdir):
    """
    Test replacement of an ipv4 entry where just the name differs
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("82.132.132.132\texample.com\texample\n")
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv4', address='82.132.132.132', names=['example2.com', 'example'])
    hosts_entries.add(entries=[new_entry], force=True)
    assert hosts_entries.exists(address='82.132.132.132')
    assert hosts_entries.exists(names=['example2.com', 'example'])
예제 #2
0
def test_addition_of_ipv4_entry_where_matching_exists_and_force_true(tmpdir):
    """
    Test replacement of an ipv4 entry where just the address differs
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("82.132.132.132\texample.com\texample\n")
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv4', address='82.132.132.132', names=['something.com', 'example'])
    hosts_entries.add(entries=[new_entry], force=True)
    assert hosts_entries.exists(address='82.132.132.132')
    assert hosts_entries.exists(names=['something.com', 'example'])
예제 #3
0
 def test_write_hosts_file(self):
     ''' test that adding and removing hosts modifies the hosts file correctly '''
     temp_host_file = Hosts(self.temp_host_file.name)
     self.assertTrue(temp_host_file.exists(names=['hostess']))
     self.assertFalse(temp_host_file.exists(names=['hostess2']))
     watcher = hostess.Watcher(env=self.envvars)
     watcher.hostmap['hostess'] = True
     watcher.remove_host(fqdn='hostess')
     watcher.add_host(fqdn='hostess2', ip_addr='10.0.0.2')
     temp_host_file = Hosts(self.temp_host_file.name)
     self.assertFalse(temp_host_file.exists(names=['hostess']))
     self.assertTrue(temp_host_file.exists(names=['hostess2']))
예제 #4
0
def test_add_adblock_entry_with_force_with_target_having_multiple_names(tmpdir):
    """
    Test that an addition of an adblock entry replaces one with a matching name
    if force is True (multiple names)
    """
    ipv4_line = '0.0.0.0 example.com example2.com'
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write(ipv4_line)
    hosts_entries = Hosts(path=hosts_file.strpath)
    assert hosts_entries.exists(address='0.0.0.0')
    new_entry = HostsEntry.str_to_hostentry('0.0.0.0 example.com example2.com')
    hosts_entries.add(entries=[new_entry], force=True)
    assert hosts_entries.exists(names=['example2.com'])
예제 #5
0
def test_remove_existing_ipv4_address_using_hostsentry(tmpdir):
    """
    Test removal of an existing ip4 address
    """
    ipv4_line = '1.2.3.4 example.com example'
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write(ipv4_line)
    hosts_entries = Hosts(path=hosts_file.strpath)
    assert hosts_entries.exists(address='1.2.3.4')
    assert hosts_entries.exists(names=['example.com'])
    hosts_entries.remove_all_matching(address='1.2.3.4', name='example.com')
    assert not hosts_entries.exists(address='1.2.3.4')
    assert not hosts_entries.exists(names=['example.com'])
예제 #6
0
def update_hosts_file(system_config: Config,
                      warning_callback=lambda msg: None):
    """Update the hosts-file for the current project,
    if any is loaded and updating is enabled in configuration.

    The hosts file is written, if it was changed.
    If it can't be written, warning messages are send to the lambda that outputs
    how to manually change the host file.

    :param warning_callback: Callback that receives strings representing warning messages to output to users.
    :param system_config: System configuration
    """

    if system_config["update_hosts_file"]:
        if "project" in system_config:
            hosts = Hosts()
            new_entries = []
            changes = False

            base_url = system_config["proxy"]["url"]
            if not hosts.exists(names=[base_url]):
                changes = True
                new_entries.append(
                    HostsEntry(entry_type='ipv4',
                               address='127.0.0.1',
                               names=[base_url]))

            if "services" in system_config["project"]["app"]:
                for service in system_config["project"]["app"][
                        "services"].values():
                    domain = service.domain()
                    if not hosts.exists(names=[domain]):
                        changes = True
                        new_entries.append(
                            HostsEntry(entry_type='ipv4',
                                       address='127.0.0.1',
                                       names=[domain]))
            hosts.add(new_entries)
            if changes:
                try:
                    hosts.write()
                except UnableToWriteHosts:
                    entries = "\n".join(
                        [f"{e.address}\t{e.names[0]}" for e in new_entries])
                    warning_callback(
                        f"Could not update the hosts-file ({hosts.hosts_path}) to configure proxy server routing.\n"
                        f"> Give your user permission to edit this file, to remove this warning.\n"
                        f"> If you wish to manually add the entries instead, "
                        f"add the following entries to {hosts.hosts_path}:\n{entries}\n"
                    )
예제 #7
0
def test_addition_of_ipv6_entry_where_matching_name_exists_and_force_false(tmpdir):
    """
    Test no replacement of an ipv6 entry where the address is different
    but there is a matching name and force is false
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("fe80::200:f8ff:fe21:67cf\texample.com\texample\n")
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv6', address='2001:db8:a0b:12f0::1',
                           names=['example.com', 'example'])
    hosts_entries.add(entries=[new_entry], force=False)
    assert not hosts_entries.exists(address='2001:db8:a0b:12f0::1')
    assert hosts_entries.exists(address='fe80::200:f8ff:fe21:67cf')
    assert hosts_entries.exists(names=new_entry.names)
예제 #8
0
    def prepare_hosts(self):
        host = self.host_name
        if host:
            if self.machine_name:
                ip = self.machine.ip(machine=self.machine_name)
            else:
                ip = '127.0.0.1'
            self.logger.debug('Prepare hosts: {name} with {ip}'.format(name=host, ip=ip))
            hosts = Hosts()
            for entry in hosts.entries:
                if entry.address == ip:
                    if host not in entry.names:
                        entry.names.append(host)
                        entry.names = list(set(entry.names))
            if not hosts.exists(names=[host]):
                entry = HostsEntry(entry_type='ipv4', address=ip, names=[host])
                hosts.add(entries=[entry])

            try:
                # make backup
                hosts_path = Hosts.determine_hosts_path()
                hosts_backup_path = hosts_path + '.' + datetime.datetime.today().strftime('%Y%m%d')
                shutil.copy(hosts_path, hosts_backup_path)
            except BaseException:
                pass

            try:
                hosts.write()
            except BaseException:
                self.logger.debug('Unable to write host file, ignored.')
예제 #9
0
def test_replacement_of_ipv4_entry_where_address_differs(tmpdir):
    """
    Test replacement of an ipv4 entry where just the address differs
    Add:
    82.132.132.132 example.com example
    Then add (with force):
    82.132.132.133 example.com example
    The second addition should replace the former as there is an address match
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("82.132.132.132\texample.com\texample\n")
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv4', address='82.132.132.133', names=['example.com', 'example'])
    hosts_entries.add(entries=[new_entry], force=True)
    assert hosts_entries.exists(address='82.132.132.133')
    assert hosts_entries.exists(names=['example.com', 'example'])
예제 #10
0
class HostsFile(object):

    def __init__(self):
        self.hosts = Hosts()

    def verifyentry(self, ip, domains):
        # Check the hosts file for concurrency with the pickle file
        if(self.hosts.exists(address=ip) and self.hosts.exists(names=[domains])):
            return True
        else:
            return False

    def addentry(self, ip, domains):
        # Python-Hosts will support multiple domain entries
        # @ TO-DO add support for multiple domain entries
        new_entry = HostsEntry(entry_type='ipv4', address=ip, names=[domains])
        self.hosts.add(new_entry)
        self.hosts.write()
예제 #11
0
def test_add_single_ipv6_host(tmpdir):
    """
    Test addition of an ipv6 entry
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("127.0.0.1\tlocalhost\n")
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv6', address='::1', names=['localhost6.localdomain6', 'localhost6'])
    hosts_entries.add(entries=[new_entry], force=False)
    assert hosts_entries.exists(address='::1')
예제 #12
0
def test_add_single_ipv4_host(tmpdir):
    """
    Test the addition of an ipv4 host succeeds
    """
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write("127.0.0.1\tlocalhost\n")
    hosts = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry(entry_type='ipv4', address='123.123.123.123', names=['test.example.com'])
    hosts.add(entries=[new_entry])
    assert hosts.exists(address='123.123.123.123')
예제 #13
0
def test_add_adblock_entry_without_force_multiple_names(tmpdir):
    """
    Test that addition of an adblock entry does not succeed if force is not set
    and there is a matching name
    """
    ipv4_line = '0.0.0.0 example2.com example3.com'
    hosts_file = tmpdir.mkdir("etc").join("hosts")
    hosts_file.write(ipv4_line)
    hosts_entries = Hosts(path=hosts_file.strpath)
    new_entry = HostsEntry.str_to_hostentry('0.0.0.0 example.com example3.com')
    hosts_entries.add(entries=[new_entry], force=False)
    assert hosts_entries.exists(names=['example2.com'])
예제 #14
0
def test_write_will_create_path_if_missing():
    """
    Test that the hosts file declared when constructing a Hosts instance will
    be created if it doesn't exist
    """
    now = datetime.datetime.now()
    timestamp = now.strftime('%Y%m%d%H%M%S')
    hosts_path = '/tmp/testwrite.{0}'.format(timestamp)
    hosts = Hosts(path=hosts_path)
    entry = HostsEntry.str_to_hostentry('1.2.3.4 example.com example.org')
    hosts.add(entries=[entry])
    hosts.write()
    hosts2 = Hosts(path=hosts_path)
    os.remove(hosts_path)
    assert hosts2.exists(address='1.2.3.4')
예제 #15
0
    mac = client['mac']

    if ip <> "Unknown":
        ip = IPAddress(ip)

    if ip <> "Unknown" and name <> None:
        name = name.replace(" ", "")
        list[ip] = name
        sorted(list)

for entry in list.items():
    ip = str(entry[0])
    name = entry[1]
    new_entry = HostsEntry(entry_type='ipv4', address=ip, names=[name])

    if hosts.exists(ip):
        hosts.remove_all_matching(ip)

    hosts.add([new_entry])
    if args.verbose:
        print entry[0], '\t', entry[1]

if args.verbose:
    if args.nohosts:
        print "--nohosts specified, not attempting to write to hosts file"

if not args.nohosts:
    try:
        hosts.write()
    except:
        print "You need root permissions to write to /etc/hosts - skipping!"
class HostsHandler():
    ''' handle the Hosts object and the individual HostEntry objects '''

    block_start = '### dnsmasq updater start ###'

    def __init__(self, file_handler, **kwargs):
        self.params = SimpleNamespace(**kwargs)
        self.logger = get_logger(self.__class__.__name__,
                                 self.params.log_level)
        self.file_handler = file_handler
        self.temp_file = file_handler.temp_file
        self.delayed_write = ResettableTimer(self.params.local_write_delay,
                                             self.write_hosts)

        self.get_remote_hosts()

    def get_remote_hosts(self):
        ''' parse remote hosts file into python-hosts '''

        self.hosts = Hosts(path='/dev/null')

        self.logger.debug('Cleaning remote hosts..')

        for line in self.file_handler.hosts:
            if self.block_start in line:
                break

            line_type = HostsEntry.get_entry_type(line)

            if line_type in ['ipv4', 'ipv6']:
                self.hosts.add([HostsEntry.str_to_hostentry(line)])
            elif line_type == 'comment':
                self.hosts.add(
                    [HostsEntry(entry_type='comment', comment=line)])
            elif line_type == 'blank':
                # python_hosts.Hosts.add doesn't seem to work for blank lines.
                # We'll have to use the internal class methods directly.
                self.hosts.entries.append(HostsEntry(entry_type="blank"))
            else:
                self.logger.warning('Unknown line type in hosts file: %s',
                                    line)

        self.hosts.add(
            [HostsEntry(entry_type='comment', comment=self.block_start)])

        if self.params.log_level == logging.DEBUG:
            self.logger.debug('Cleaned remote hosts:')
            for entry in self.hosts.entries:
                print('    ', entry)

    def parse_hostnames(self, hostnames):
        '''
		return dictionary items containing IPs and a list of hostnames

		dict_items([
			('<IP_1>', ['<hostname1>', '<hostname2>', etc..]),
			('<IP_2>', ['<hostname3>', '<hostname4>', etc..]),
			etc..])
		'''

        hostname_dict = defaultdict(set)

        for hostname in hostnames:
            host_ip = self.params.ip

            if ':' in hostname:
                hostname, host_ip = hostname.split(':', 1)

            try:
                hostname = hostname[0:hostname.index('.' + self.params.domain)]
            except ValueError:
                pass

            if not self.hosts.exists(names=[hostname]):
                hostname_dict[host_ip].update(
                    [hostname, hostname + '.' + self.params.domain])

        return dict([key, sorted(value)]
                    for key, value in hostname_dict.items())

    def add_hosts(self, hostnames, do_write=True):
        ''' create HostsEntry for a host and add it to Hosts object, optionally write out '''

        parsed_hostnames = self.parse_hostnames(hostnames)
        parsed_items = parsed_hostnames.items()

        if parsed_items:
            for host_ip, names in parsed_items:
                self.logger.debug('Adding: (%s) %s', host_ip, names)
                hostentry = HostsEntry(entry_type='ipv4',
                                       address=host_ip,
                                       names=names)
                self.hosts.add([hostentry],
                               force=True,
                               allow_address_duplication=True)

            if do_write:
                self.queue_write()

            self.logger.info('Added host(s): %s',
                             sum(parsed_hostnames.values(), []))
        else:
            self.logger.info('Host already exists, nothing to add.')

        return parsed_items

    def del_hosts(self, hostnames):
        ''' delete hostnames, optionally write out '''

        self.logger.debug('Deleting hostnames: %s', hostnames)
        for hostname in hostnames:
            try:
                hostname = hostname[0:hostname.index(':')]
            except ValueError:
                pass

            self.hosts.remove_all_matching(name=hostname)

        self.queue_write()

    def queue_write(self):
        '''
		delayed writing of the local and remote hosts files
		the delay allows for any additional changes in the immediate future,
		such as expected when a container is restarting, for example.
		'''

        self.delayed_write.reset()

    def write_hosts(self):
        ''' write local hosts file, put it on the remote device '''

        if self.params.log_level == logging.DEBUG:
            self.logger.debug('Writing local hosts temp file: %s',
                              self.temp_file.name)
            for entry in self.hosts.entries:
                print('    ', entry)

        self.hosts.write(path=self.temp_file.name)
        self.temp_file.seek(0)
        self.file_handler.queue_put()
예제 #17
0
            ipaddress = nm[host]['addresses']['ipv4']
            macaddress = nm[host]['addresses']['mac']

            if macaddress in addressList:
                etchostname = addressList[macaddress]
                print(
                    f"Device at {ipaddress} ({macaddress}) is in our list as {etchostname}"
                )
            else:
                print(
                    f"Device at {ipaddress} ({macaddress}) is NOT in our list."
                )
                break

            # if neither the hostname or ip address exist in hosts file
            if not hosts.exists(ipaddress, etchostname):
                print(
                    f"Adding hostname: {etchostname} with {ipaddress} to hosts file."
                )
                hosts.remove_all_matching(name=etchostname)
                new_entry = HostsEntry(entry_type='ipv4',
                                       address=ipaddress,
                                       names=[etchostname])
                hosts.add([new_entry])

            # if the hostname exists but ip address in hosts file differs from nmap scan
            for entry in hosts.entries:
                if entry.entry_type in ['ipv4', 'ipv6']:
                    if entry.names[0] == etchostname:
                        if entry.address != ipaddress:
                            print(