From 9c11b2dc00fc4a488dbdf314542d7b382d3e53ce Mon Sep 17 00:00:00 2001 From: aturenkov Date: Fri, 5 Dec 2025 12:13:19 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=20playbooks/inventory=5Fgenerator.yml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playbooks/inventory_generator.yml | 150 +++++++++++++----------------- 1 file changed, 64 insertions(+), 86 deletions(-) diff --git a/playbooks/inventory_generator.yml b/playbooks/inventory_generator.yml index cf0732f..26bebe6 100644 --- a/playbooks/inventory_generator.yml +++ b/playbooks/inventory_generator.yml @@ -1,5 +1,5 @@ --- -- name: Сбор инвентаря Windows машин (nmap) +- name: Генерация инвентаря Windows PC по DNS hosts: localhost connection: local gather_facts: yes @@ -8,7 +8,7 @@ dns_servers: - "192.168.1.250" - "192.168.1.254" - inventory_file: "/tmp/windows_inventory.ini" + inventory_file: "/tmp/windows_inventory.yml" subnets: - "192.168.0.0/24" - "192.168.1.0/24" @@ -22,113 +22,93 @@ - "172.19.42.0/23" - "172.19.56.0/23" - "172.19.58.0/23" - winrm_ports: - - 5985 - - 5986 tasks: - - name: Проверка установки nmap - command: which nmap - register: nmap_check - failed_when: false - changed_when: false - - - name: Ошибка если nmap не установлен - fail: - msg: "nmap не установлен!" - when: nmap_check.rc != 0 - - - name: Сканирование подсетей - command: "nmap -p {{ winrm_ports | join(',') }} --open -T4 -oG - {{ subnets | join(' ') }}" - register: nmap_result - changed_when: false - - - name: Извлечение IP с WinRM - set_fact: - active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:5985|5986)/open') | unique | list }}" - - - name: Найдено IP - debug: - msg: "Найдено {{ active_ips | length }} IP с WinRM" - - # ИЗМЕНЕНО: Попытка резолва через оба DNS сервера - - name: DNS резолв через корпоративные DNS + - name: Генерация списка всех IP + shell: | + python3 << 'EOF' + import ipaddress + subnets = {{ subnets | to_json }} + for subnet in subnets: + network = ipaddress.ip_network(subnet) + for ip in network.hosts(): + print(ip) + EOF + register: all_ips + changed_when: false + + - name: Парсинг IP адресов + set_fact: + ip_list: "{{ all_ips.stdout_lines }}" + + - name: Информация о сканировании + debug: + msg: "Будет проверено {{ ip_list | length }} IP адресов" + + - name: DNS резолв для всех IP shell: | - # Пробуем первый DNS result=$(nslookup {{ item }} {{ dns_servers[0] }} 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//') - # Если не получилось, пробуем второй DNS if [ -z "$result" ]; then result=$(nslookup {{ item }} {{ dns_servers[1] }} 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//') fi - # Если оба не сработали if [ -z "$result" ]; then echo "NO_DNS" else echo "$result" fi - loop: "{{ active_ips }}" - register: dns_lookup + loop: "{{ ip_list }}" + register: dns_results changed_when: false - when: active_ips | length > 0 + # Выполнение параллельно для ускорения + async: 30 + poll: 0 - - name: Формирование PC хостов + - name: Ожидание завершения DNS запросов + async_status: + jid: "{{ item.ansible_job_id }}" + register: dns_jobs + until: dns_jobs.finished + retries: 60 + delay: 1 + loop: "{{ dns_results.results }}" + + - name: Фильтрация PC хостов set_fact: pc_hosts: "{{ pc_hosts | default([]) + [{'hostname': item.stdout | trim, 'ip': item.item}] }}" - loop: "{{ dns_lookup.results | default([]) }}" + loop: "{{ dns_jobs.results }}" when: - - active_ips | length > 0 - item.stdout is defined - item.stdout != "NO_DNS" - - item.stdout | trim is match('^pc\\d+.*' + domain + '$') + - item.stdout | trim | lower is match('^pc\\d+.*') - - name: Фильтрация PC (pc01-pc500 / pc001-pc500) - set_fact: - filtered_hosts: "{{ pc_hosts | default([]) | selectattr('hostname', 'match', '^pc(\\d{2,3})\\.' + domain + '$') | list }}" - - - name: Неопознанные хосты - set_fact: - unknown_ips: "{{ active_ips | difference(filtered_hosts | default([]) | map(attribute='ip') | list) }}" - - - name: Создание инвентаря + - name: Создание инвентаря YAML copy: content: | # ========================================== # Инвентарь Windows PC - # Дата: {{ ansible_date_time.iso8601 }} + # Сгенерирован: {{ ansible_date_time.iso8601 }} # DNS серверы: {{ dns_servers | join(', ') }} # Подсети: {{ subnets | join(', ') }} - # Найдено IP с WinRM: {{ active_ips | length }} - # PC хостов в домене: {{ filtered_hosts | default([]) | length }} - # Неопознанных: {{ unknown_ips | default([]) | length }} + # Всего IP проверено: {{ ip_list | length }} + # PC хостов найдено: {{ pc_hosts | default([]) | length }} # ========================================== - [windows_pcs] - {% for host in filtered_hosts | default([]) | sort(attribute='hostname') %} - {{ host.hostname | regex_replace('\\.' + domain + '$', '') }} ansible_host={{ host.hostname }} + all: + children: + windows_pcs: + hosts: + {% for host in pc_hosts | default([]) | sort(attribute='hostname') %} + {{ host.hostname | regex_replace('\\.' + domain + '$', '') | regex_replace('\\..*$', '') }}: + ansible_host: {{ host.ip }} {% endfor %} - - {% if unknown_ips | length > 0 %} - # Хосты с WinRM, но без DNS имён или не PC* - [windows_unknown] - {% for ip in unknown_ips %} - unknown_{{ ip | replace('.', '_') }} ansible_host={{ ip }} - {% endfor %} - - [windows:children] - windows_pcs - windows_unknown - {% else %} - [windows:children] - windows_pcs - {% endif %} - - [windows:vars] - ansible_connection=winrm - ansible_winrm_transport=ntlm - ansible_winrm_server_cert_validation=ignore - ansible_port=5985 + vars: + ansible_connection: winrm + ansible_winrm_transport: ntlm + ansible_winrm_server_cert_validation: ignore + ansible_port: 5985 + ansible_winrm_scheme: http dest: "{{ inventory_file }}" - name: Итоговая статистика @@ -136,15 +116,13 @@ msg: - "==========================================" - "Просканировано подсетей: {{ subnets | length }}" - - "Найдено IP с WinRM: {{ active_ips | length }}" - - "PC хостов (pc01-pc500): {{ filtered_hosts | default([]) | length }}" - - "Неопознанных хостов: {{ unknown_ips | default([]) | length }}" - - "Файл: {{ inventory_file }}" + - "Проверено IP адресов: {{ ip_list | length }}" + - "Найдено PC хостов: {{ pc_hosts | default([]) | length }}" + - "Файл инвентаря: {{ inventory_file }}" - "==========================================" - name: Список найденных PC debug: - msg: "{{ filtered_hosts | default([]) | map(attribute='hostname') | list }}" - when: - - filtered_hosts is defined - - filtered_hosts | length > 0 \ No newline at end of file + msg: "{{ item.hostname }} ({{ item.ip }})" + loop: "{{ pc_hosts | default([]) | sort(attribute='hostname') }}" + when: pc_hosts is defined \ No newline at end of file