Example #1
0
def auth_as_ansible_host_vars(auth):
    """Get the Ansible host vars that implement an auth.

    :param auth: the auth. A dictionary with fields 'id', 'name',
        'username', 'password', and 'ssh_key_file'.

    :returns: a dict that can be used as the host variables in an
        Ansible inventory.
    """

    username = auth.get('username')
    password = auth.get('password')
    ssh_key_file = auth.get('ssh_key_file')
    sudo_password = auth.get('sudo_password')

    ansible_vars = {}

    ansible_vars['ansible_user'] = str_to_ascii(username)
    if password:
        ansible_vars['ansible_ssh_pass'] = str_to_ascii(password)
    if ssh_key_file:
        ansible_vars['ansible_ssh_private_key_file'] = \
            str_to_ascii(ssh_key_file)
    if sudo_password:
        ansible_vars['ansible_become_pass'] = sudo_password

    return ansible_vars
Example #2
0
def make_inventory_dict(hosts, port_map, auth_map, group_size=10):
    """Make the inventory for the scan, as a dict.

    :param hosts: a list of hosts for the inventory
    :param port_map: mapping from hosts to SSH ports
    :param auth_map: map from host IP to a list of auths it works with
    :param group_size: write hosts in groups of this size

    :returns: a dict with the structure:

        .. code-block:: python

            {'group1':
                 {'hosts':
                     {'IP address 1': {'host-vars-1'},
                      'IP address 2': {'host-vars-2'},
                      # ...
                     }
                 },
             'group2':
                 {'hosts':
                      ....
                 },
             ....
            }
    """

    # Create dict of successfully connected hosts
    host_dict = {}
    for host in hosts:
        ascii_host = str_to_ascii(host)
        ascii_port = str_to_ascii(str(port_map[host]))
        host_vars = {'ansible_host': ascii_host, 'ansible_port': ascii_port}
        host_vars.update(
            ansible_utils.auth_as_ansible_host_vars(auth_map[host][0]))
        host_dict[ascii_host] = host_vars

    result = {}
    keys = sorted(host_dict.keys())
    for group_num in range((len(keys) + group_size - 1) // group_size):
        start = group_num * group_size
        group_name = 'group' + str(group_num)
        result[group_name] = {'hosts': {}}
        for key in keys[start:start + group_size]:
            result[group_name]['hosts'][key] = host_dict[key]

    return result
Example #3
0
def make_inventory_dict(hosts, port_map, auth_map):
    """Make the inventory for the scan, as a dict.

    :param hosts: a list of hosts for the inventory
    :param port_map: mapping from hosts to SSH ports
    :param auth_map: map from host IP to a list of auths it works with

    :returns: a dict with the structure:

        .. code-block:: python

            {'alpha':
                {'hosts':
                    {'IP address 1': {'host-vars-1'},
                     'IP address 2': {'host-vars-2'},
                     # ...
                    }
                }
            }
    """

    yml_dict = {}

    # Create section of successfully connected hosts
    alpha_hosts = {}
    for host in hosts:
        ascii_host = str_to_ascii(host)
        ascii_port = str_to_ascii(str(port_map[host]))
        host_vars = {'ansible_host': ascii_host, 'ansible_port': ascii_port}
        host_vars.update(
            ansible_utils.auth_as_ansible_host_vars(auth_map[host][0]))
        alpha_hosts[ascii_host] = host_vars

    yml_dict['alpha'] = {'hosts': alpha_hosts}

    return yml_dict
Example #4
0
def _create_main_inventory(vault, success_hosts, success_port_map, best_map,
                           profile):
    yml_dict = {}

    # Create section of successfully connected hosts
    alpha_hosts = {}
    for host in success_hosts:
        ascii_host = str_to_ascii(host)
        ascii_port = str_to_ascii(str(success_port_map[host]))
        alpha_host_vars_dict = {
            'ansible_host': ascii_host,
            'ansible_port': ascii_port
        }
        alpha_hosts[ascii_host] = alpha_host_vars_dict

    yml_dict['alpha'] = {'hosts': alpha_hosts}

    for auth in best_map.keys():
        auth_user = auth[2]
        auth_pass = auth[3]
        auth_key = auth[4]

        for host in best_map[auth]:
            ascii_host = str_to_ascii(host)
            if ascii_host in alpha_hosts:
                host_vars_dict = alpha_hosts[ascii_host]
                host_vars_dict['ansible_user'] = str_to_ascii(auth_user)
                if (not auth_pass == '') and auth_pass:
                    host_vars_dict['ansible_ssh_pass'] =\
                        str_to_ascii(auth_pass)
                    if (not auth_key == '') and auth_key:
                        host_vars_dict['ansible_ssh_private_key_file'] = \
                            str_to_ascii(auth_key)
                elif auth_pass == '':
                    if (not auth_key == '') and auth_key:
                        host_vars_dict['ansible_ssh_private_key_file'] = \
                            str_to_ascii(auth_key)

    vault.dump_as_yaml_to_file(yml_dict, 'data/' + profile + '_hosts.yml')
Example #5
0
def _create_ping_inventory(vault, vault_pass, profile_ranges, profile_port,
                           profile_auth_list, forks):
    # pylint: disable=too-many-locals
    success_auths = set()
    success_hosts = set()
    success_port_map = defaultdict()
    success_map = defaultdict(list)
    best_map = defaultdict(list)
    mapped_hosts = set()
    hosts_dict = {}

    for profile_range in profile_ranges:
        # pylint: disable=anomalous-backslash-in-string
        reg = "[0-9]*.[0-9]*.[0-9]*.\[[0-9]*:[0-9]*\]"
        profile_range = profile_range.strip(',').strip()
        hostname = str_to_ascii(profile_range)
        if not re.match(reg, profile_range):
            hosts_dict[profile_range] = {
                'ansible_host': profile_range,
                'ansible_port': profile_port
            }
        else:
            hosts_dict[hostname] = None

    vars_dict = {}
    for cred_item in profile_auth_list:
        cred_pass = cred_item.get('password')
        cred_sshkey = cred_item.get('ssh_key_file')
        auth_item = [
            cred_item.get('id'),
            cred_item.get('name'),
            cred_item.get('username'),
            cred_item.get('password'),
            cred_item.get('ssh_key_file')
        ]

        vars_dict['ansible_user'] = str_to_ascii(cred_item.get('username'))

        if (not cred_pass == '') and cred_pass:
            vars_dict['ansible_ssh_pass'] = str_to_ascii(cred_pass)
            if (not cred_sshkey == '') and cred_sshkey:
                vars_dict['ansible_ssh_private_key_file'] = \
                    str_to_ascii(cred_sshkey)
        elif cred_pass == '':
            if (not cred_sshkey == '') and cred_sshkey:
                vars_dict['ansible_ssh_private_key_file'] = \
                    str_to_ascii(cred_sshkey)

        yml_dict = {'all': {'hosts': hosts_dict, 'vars': vars_dict}}
        vault.dump_as_yaml_to_file(yml_dict, 'data/ping-inventory.yml')

        cmd_string = 'ansible all -m' \
                     ' ping  -i data/ping-inventory.yml --ask-vault-pass -f ' \
                     + forks

        my_env = os.environ.copy()
        my_env["ANSIBLE_HOST_KEY_CHECKING"] = "False"
        with open('data/ping_log', 'w') as ping_log:
            run_ansible_with_vault(cmd_string,
                                   vault_pass,
                                   logfile=ping_log,
                                   env=my_env)

        with open('data/ping_log', 'r') as ping_log:
            out = ping_log.readlines()

        for line, _ in enumerate(out):
            if 'pong' in out[line]:
                tup_auth_item = tuple(auth_item)
                success_auths.add(tup_auth_item)
                host_line = out[line - 2].replace('\x1b[0;32m', '')
                host_ip = host_line.split('|')[0].strip()
                success_hosts.add(host_ip)
                if host_ip not in mapped_hosts:
                    best_map[tup_auth_item].append(host_ip)
                    mapped_hosts.add(host_ip)
                success_map[host_ip].append(tup_auth_item)
                success_port_map[host_ip] = profile_port

    success_auths = list(success_auths)
    success_hosts = list(success_hosts)

    return success_auths, success_hosts, best_map, success_map, \
        success_port_map
Example #6
0
def create_ping_inventory(vault, vault_pass, profile_ranges, profile_port,
                          credential, forks, ansible_verbosity):
    """Find which auths work with which hosts.

    :param vault: a Vault object
    :param vault_pass: password for the Vault?
    :param profile_ranges: hosts for the profile
    :param profile_port: the SSH port to use
    :param credential: auth to use
    :param forks: the number of Ansible forks to use

    :returns: a tuple of
      (list of IP addresses that worked for any auth,
       map from host IPs to SSH ports that worked with them,
       map from host IPs to lists of auths that worked with them
      )
    """

    # pylint: disable=too-many-locals
    success_hosts = set()
    failed_hosts = set()
    success_port_map = defaultdict()
    success_auth_map = defaultdict(list)
    hosts_dict = {}

    for profile_range in profile_ranges:
        # pylint: disable=anomalous-backslash-in-string
        reg = "[0-9]*.[0-9]*.[0-9]*.\[[0-9]*:[0-9]*\]"
        profile_range = profile_range.strip(',').strip()
        hostname = str_to_ascii(profile_range)
        if not re.match(reg, profile_range):
            hosts_dict[profile_range] = {
                'ansible_host': profile_range,
                'ansible_port': profile_port
            }
        else:
            hosts_dict[hostname] = None

    vars_dict = ansible_utils.auth_as_ansible_host_vars(credential)

    yml_dict = {'alpha': {'hosts': hosts_dict, 'vars': vars_dict}}
    vault.dump_as_yaml_to_file(yml_dict, PING_INVENTORY_PATH)
    ansible_utils.log_yaml_inventory('Ping inventory', yml_dict)

    print(
        _('Attempting connection discovery with auth "%s".' %
          (credential.get('name'))))

    cmd_string = 'ansible alpha -m raw' \
                 ' -i ' + PING_INVENTORY_PATH \
                 + ' --ask-vault-pass -f ' + forks \
                 + ' -a \'echo "Hello"\''

    my_env = os.environ.copy()
    my_env["ANSIBLE_HOST_KEY_CHECKING"] = "False"
    my_env["ANSIBLE_NOCOLOR"] = "True"
    # Don't pass ansible_verbosity here as adding too much
    # verbosity can break our parsing of Ansible's output. This is
    # a temporary fix - a better solution would be less-fragile
    # output parsing.
    ansible_utils.run_with_vault(cmd_string,
                                 vault_pass,
                                 log_path=PING_LOG_PATH,
                                 env=my_env,
                                 log_to_stdout=True,
                                 ansible_verbosity=0)

    with open(PING_LOG_PATH, 'r') as ping_log:
        success_hosts, failed_hosts = process_ping_output(ping_log)

    for host in success_hosts:
        success_auth_map[host].append(credential)
        success_port_map[host] = profile_port

    num_success = len(success_hosts)
    num_failed = len(failed_hosts)
    if num_success > 0:
        print(
            _('Connection succeeded with auth "%s" to %d systems.') %
            (credential.get('name'), num_success))
    if num_failed > 0:
        print(
            _('Failed to connect with auth "%s" to %d systems.') %
            (credential.get('name'), num_failed))
    if num_success > 0 or num_failed > 0:
        print()

    return list(success_hosts), success_port_map, success_auth_map, \
        list(failed_hosts)