Обновить playbooks/scan_inventory.yml

This commit is contained in:
2025-12-10 11:08:38 +00:00
parent f4141acaa4
commit fc94c9d6ed

View File

@@ -3,13 +3,13 @@
hosts: localhost hosts: localhost
connection: local connection: local
gather_facts: no gather_facts: no
become: yes # Нужно для сканирования UDP (SNMP) become: yes # Нужно для сканирования UDP (SNMP) и Nmap -O
vars: vars:
# --- SEMAPHORE API --- # --- SEMAPHORE API ---
semaphore_url: "http://192.168.0.198:9999" semaphore_url: "http://192.168.0.198:9999"
semaphore_project_id: 1 semaphore_project_id: 1
semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ=" semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ="
# --- ID КЛЮЧЕЙ ДЛЯ БУДУЩИХ ПОДКЛЮЧЕНИЙ --- # --- ID КЛЮЧЕЙ ДЛЯ БУДУЩИХ ПОДКЛЮЧЕНИЙ ---
key_windows: 7 key_windows: 7
key_linux: 8 key_linux: 8
@@ -32,7 +32,7 @@
- "172.19.56.0/24" - "172.19.56.0/24"
- "172.19.58.0/24" - "172.19.58.0/24"
- "172.19.90.0/24" - "172.19.90.0/24"
# SNMP Community (пароль для чтения) # SNMP Community (пароль для чтения)
snmp_community: "public" snmp_community: "public"
@@ -40,16 +40,20 @@
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 1: Поиск живых хостов (Ping) # ШАГ 1: Поиск живых хостов (Ping)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- name: Ping Sweep - name: Ping Sweep (быстрый поиск)
command: "nmap -sn -n --min-rate 1000 -T4 -oG - {{ subnets | join(' ') }}" command: "nmap -sn -n --min-rate 1000 -T4 -oG - {{ subnets | join(' ') }}"
register: ping_scan register: ping_scan
changed_when: false changed_when: false
- name: Список IP - name: Формирование списка активных IP
set_fact: set_fact:
active_ips: "{{ ping_scan.stdout | regex_findall('Host: ([0-9.]+)') | unique | list }}" active_ips: "{{ ping_scan.stdout | regex_findall('Host: ([0-9.]+)') | unique | list }}"
- fail: msg="Сеть пуста" when: active_ips|length == 0 # ИСПРАВЛЕННАЯ СТРОКА (Теперь это правильный многострочный блок)
- name: Проверка наличия хостов
fail:
msg: "Сеть пуста, активных хостов не найдено."
when: active_ips | length == 0
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 2: Опрос через SNMP + Проверка портов # ШАГ 2: Опрос через SNMP + Проверка портов
@@ -67,24 +71,25 @@
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 3: Классификация на основе ответа SNMP # ШАГ 3: Классификация на основе ответа SNMP
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- name: Анализ устройств - name: Анализ устройств и классификация
set_fact: set_fact:
classified_hosts: "{{ classified_hosts | default([]) + [ host_data ] }}" classified_hosts: "{{ classified_hosts | default([]) + [ host_data ] }}"
vars: vars:
out: "{{ item.stdout }}" out: "{{ item.stdout }}"
ip: "{{ item.item }}" ip: "{{ item.item }}"
# Пытаемся вытащить строку sysDescr # Пытаемся вытащить строку sysDescr
snmp_desc: "{{ out | regex_search('sysDescr\\.0: ([^\\n]+)', '\\1') | first | default('') }}" snmp_desc: "{{ out | regex_search('sysDescr\\.0: ([^\\n]+)', '\\1') | first | default('') }}"
# Определяем тип # Определяем тип (Логика распознавания)
detected_type: >- detected_type: >-
{% if 'Windows' in snmp_desc or '445/tcp open' in out %}windows {% if 'Windows' in snmp_desc or '445/tcp open' in out %}windows
{% elif 'RouterOS' in snmp_desc or 'MikroTik' in snmp_desc or '8291/tcp open' in out %}mikrotik {% elif 'RouterOS' in snmp_desc or 'MikroTik' in snmp_desc or '8291/tcp open' in out %}mikrotik
{% elif 'Linux' in snmp_desc or 'Ubuntu' in snmp_desc or '22/tcp open' in out %}linux {% elif 'Linux' in snmp_desc or 'Ubuntu' in snmp_desc or '22/tcp open' in out %}linux
{% elif 'JetDirect' in snmp_desc or 'LaserJet' in snmp_desc or 'Samsung' in snmp_desc or 'Kyocera' in snmp_desc or '9100/tcp open' in out %}printer {% elif 'JetDirect' in snmp_desc or 'LaserJet' in snmp_desc or 'Samsung' in snmp_desc or 'Kyocera' in snmp_desc or '9100/tcp open' in out %}printer
{% else %}other{% endif %} {% else %}other{% endif %}
# Собираем данные об одном хосте
host_data: host_data:
ip: "{{ ip }}" ip: "{{ ip }}"
type: "{{ detected_type }}" type: "{{ detected_type }}"
@@ -96,7 +101,8 @@
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 4: Разбиение на группы # ШАГ 4: Разбиение на группы
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- set_fact: - name: Группировка хостов
set_fact:
list_win: "{{ classified_hosts | selectattr('type', 'equalto', 'windows') | list }}" list_win: "{{ classified_hosts | selectattr('type', 'equalto', 'windows') | list }}"
list_lin: "{{ classified_hosts | selectattr('type', 'equalto', 'linux') | list }}" list_lin: "{{ classified_hosts | selectattr('type', 'equalto', 'linux') | list }}"
list_tik: "{{ classified_hosts | selectattr('type', 'equalto', 'mikrotik') | list }}" list_tik: "{{ classified_hosts | selectattr('type', 'equalto', 'mikrotik') | list }}"
@@ -106,106 +112,115 @@
# ШАГ 5: Отправка в Semaphore (Windows) # ШАГ 5: Отправка в Semaphore (Windows)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- block: - block:
- set_fact: - name: Генерация текста инвентаря Windows
content_win: | set_fact:
[windows] content_win: |
{% for h in list_win %} [windows]
{{ h.name }} ansible_host={{ h.ip }} # SNMP: {{ h.desc }} {% for h in list_win %}
{% endfor %} {{ h.name }} ansible_host={{ h.ip }} # SNMP: {{ h.desc }}
[windows:vars] {% endfor %}
ansible_connection=ssh [windows:vars]
ansible_shell_type=powershell ansible_connection=ssh
ansible_port=22 ansible_shell_type=powershell
ansible_port=22
- copy: - name: Сохранение JSON для Windows
content: | copy:
{ content: |
"name": "SNMP Windows {{ 1000 | random }}", {
"project_id": {{ semaphore_project_id }}, "name": "SNMP Windows {{ 1000 | random }}",
"type": "static", "project_id": {{ semaphore_project_id }},
"ssh_key_id": {{ key_windows }}, "type": "static",
"become_key_id": null, "ssh_key_id": {{ key_windows }},
"repository_id": null, "become_key_id": null,
"inventory": {{ content_win | to_json }} "repository_id": null,
} "inventory": {{ content_win | to_json }}
dest: /tmp/p_win.json }
dest: /tmp/p_win.json
- command: > - name: Отправка Windows API
curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" command: >
-H "Authorization: Bearer {{ semaphore_api_token }}" curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
-H "Content-Type: application/json" -H "Authorization: Bearer {{ semaphore_api_token }}"
-d @/tmp/p_win.json -H "Content-Type: application/json"
ignore_errors: yes -d @/tmp/p_win.json
ignore_errors: yes
when: list_win | length > 0 when: list_win | length > 0
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 6: Отправка в Semaphore (MikroTik) # ШАГ 6: Отправка в Semaphore (MikroTik)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- block: - block:
- set_fact: - name: Генерация текста инвентаря MikroTik
content_tik: | set_fact:
[routers] content_tik: |
{% for h in list_tik %} [routers]
{{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }} {% for h in list_tik %}
{% endfor %} {{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }}
[routers:vars] {% endfor %}
ansible_connection=network_cli [routers:vars]
ansible_network_os=routeros ansible_connection=network_cli
ansible_network_os=routeros
- copy: - name: Сохранение JSON для MikroTik
content: | copy:
{ content: |
"name": "SNMP MikroTik {{ 1000 | random }}", {
"project_id": {{ semaphore_project_id }}, "name": "SNMP MikroTik {{ 1000 | random }}",
"type": "static", "project_id": {{ semaphore_project_id }},
"ssh_key_id": {{ key_mikrotik }}, "type": "static",
"become_key_id": null, "ssh_key_id": {{ key_mikrotik }},
"repository_id": null, "become_key_id": null,
"inventory": {{ content_tik | to_json }} "repository_id": null,
} "inventory": {{ content_tik | to_json }}
dest: /tmp/p_tik.json }
dest: /tmp/p_tik.json
- command: > - name: Отправка MikroTik API
curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" command: >
-H "Authorization: Bearer {{ semaphore_api_token }}" curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
-H "Content-Type: application/json" -H "Authorization: Bearer {{ semaphore_api_token }}"
-d @/tmp/p_tik.json -H "Content-Type: application/json"
ignore_errors: yes -d @/tmp/p_tik.json
ignore_errors: yes
when: list_tik | length > 0 when: list_tik | length > 0
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# ШАГ 7: Отправка в Semaphore (Принтеры) # ШАГ 7: Отправка в Semaphore (Принтеры)
# ---------------------------------------------------------------- # ----------------------------------------------------------------
- block: - block:
- set_fact: - name: Генерация текста инвентаря Принтеров
content_prn: | set_fact:
[printers] content_prn: |
{% for h in list_prn %} [printers]
{{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }} {% for h in list_prn %}
{% endfor %} {{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }}
[printers:vars] {% endfor %}
ansible_connection=local [printers:vars]
ansible_connection=local
- copy: - name: Сохранение JSON для Принтеров
content: | copy:
{ content: |
"name": "SNMP Printers {{ 1000 | random }}", {
"project_id": {{ semaphore_project_id }}, "name": "SNMP Printers {{ 1000 | random }}",
"type": "static", "project_id": {{ semaphore_project_id }},
"ssh_key_id": {{ key_printers }}, "type": "static",
"become_key_id": null, "ssh_key_id": {{ key_printers }},
"repository_id": null, "become_key_id": null,
"inventory": {{ content_prn | to_json }} "repository_id": null,
} "inventory": {{ content_prn | to_json }}
dest: /tmp/p_prn.json }
dest: /tmp/p_prn.json
- command: > - name: Отправка Принтеров API
curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" command: >
-H "Authorization: Bearer {{ semaphore_api_token }}" curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
-H "Content-Type: application/json" -H "Authorization: Bearer {{ semaphore_api_token }}"
-d @/tmp/p_prn.json -H "Content-Type: application/json"
ignore_errors: yes -d @/tmp/p_prn.json
ignore_errors: yes
when: list_prn | length > 0 when: list_prn | length > 0
- name: Очистка - name: Очистка временных файлов
shell: rm -f /tmp/p_*.json shell: rm -f /tmp/p_*.json