129 lines
4.6 KiB
YAML
129 lines
4.6 KiB
YAML
---
|
||
- name: Сбор инвентаря Windows (Nmap SMB + DNS)
|
||
hosts: localhost
|
||
connection: local
|
||
gather_facts: yes
|
||
vars:
|
||
inventory_file: "/tmp/windows_inventory.ini"
|
||
|
||
# Список подсетей
|
||
subnets:
|
||
- "192.168.0.0/24"
|
||
- "192.168.1.0/24"
|
||
- "192.168.2.0/24"
|
||
- "192.168.3.0/24"
|
||
- "172.19.8.0/23"
|
||
- "172.19.9.0/23"
|
||
- "172.19.10.0/23"
|
||
- "172.19.24.0/23"
|
||
- "172.19.26.0/23"
|
||
- "172.19.40.0/23"
|
||
- "172.19.42.0/23"
|
||
- "172.19.56.0/23"
|
||
- "172.19.58.0/23"
|
||
|
||
# Порты для проверки доступности (WinRM, SSH, SMB)
|
||
scan_ports:
|
||
- 5985
|
||
- 22
|
||
- 445
|
||
|
||
tasks:
|
||
- name: Сканирование сети (поиск живых IP)
|
||
command: >
|
||
nmap -p {{ scan_ports | join(',') }}
|
||
-Pn -n --open --min-rate 1000 -T4 -oG -
|
||
{{ subnets | join(' ') }}
|
||
register: nmap_result
|
||
changed_when: false
|
||
|
||
- name: Извлечение IP адресов
|
||
set_fact:
|
||
active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}"
|
||
|
||
- name: Статистика
|
||
debug:
|
||
msg: "Найдено активных IP: {{ active_ips | length }}"
|
||
|
||
# ГЛАВНОЕ ИЗМЕНЕНИЕ: Получаем имя через SMB (NetBIOS) или DNS
|
||
- name: Определение имен хостов (SMB Discovery)
|
||
shell: |
|
||
IP="{{ item }}"
|
||
# 1. Пробуем узнать имя через SMB (самый надежный способ для Windows)
|
||
SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}')
|
||
|
||
if [ ! -z "$SMB_NAME" ]; then
|
||
echo "$SMB_NAME" | tr '[:upper:]' '[:lower:]'
|
||
else
|
||
# 2. Если SMB закрыт/не ответил, пробуем DNS (как раньше)
|
||
DNS_NAME=$(nslookup -timeout=1 $IP 192.168.1.250 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//' | head -n 1)
|
||
if [ ! -z "$DNS_NAME" ]; then
|
||
echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]'
|
||
else
|
||
echo "UNKNOWN"
|
||
fi
|
||
fi
|
||
loop: "{{ active_ips }}"
|
||
register: host_names
|
||
changed_when: false
|
||
no_log: true # Чтобы не засорять лог
|
||
|
||
# Фильтруем и готовим списки
|
||
- name: Сортировка хостов
|
||
set_fact:
|
||
# Ищем 'pc' в любом месте имени (было ^pc - только в начале)
|
||
pc_list: >-
|
||
{{ host_names.results
|
||
| selectattr('stdout', 'search', 'pc')
|
||
| map(attribute='item') | list
|
||
| zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
|
||
| list }}
|
||
|
||
# Остальные (сервера, принтеры, неизвестные)
|
||
other_list: >-
|
||
{{ host_names.results
|
||
| rejectattr('stdout', 'search', 'pc')
|
||
| map(attribute='item') | list
|
||
| zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
|
||
| list }}
|
||
|
||
- name: Запись инвентаря
|
||
copy:
|
||
content: |
|
||
# === Найденные PC (по имени содержит 'pc') ===
|
||
[windows_pcs]
|
||
{% for ip, name in pc_list %}
|
||
{{ name }} ansible_host={{ ip }}
|
||
{% endfor %}
|
||
|
||
# === Остальные устройства (Servers, Unknown) ===
|
||
[windows_other]
|
||
{% for ip, name in other_list %}
|
||
{% if name == "UNKNOWN" %}
|
||
unknown_{{ ip | replace('.', '_') }} ansible_host={{ ip }}
|
||
{% else %}
|
||
{{ name }} ansible_host={{ ip }}
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
[windows:children]
|
||
windows_pcs
|
||
windows_other
|
||
|
||
[windows:vars]
|
||
ansible_connection=winrm
|
||
ansible_winrm_transport=ntlm
|
||
ansible_winrm_server_cert_validation=ignore
|
||
ansible_port=5985
|
||
ansible_user=Administrator
|
||
# Пароль лучше задать в Secret Store, не здесь
|
||
dest: "{{ inventory_file }}"
|
||
|
||
- name: ПОКАЗАТЬ РЕЗУЛЬТАТ (Скопируйте это в новый инвентарь)
|
||
command: cat {{ inventory_file }}
|
||
register: cat_inventory
|
||
changed_when: false
|
||
|
||
- name: Вывод в лог
|
||
debug:
|
||
var: cat_inventory.stdout_lines |