diff --git a/playbooks/scan_inventory.yml b/playbooks/scan_inventory.yml index d24056f..d9cad72 100644 --- a/playbooks/scan_inventory.yml +++ b/playbooks/scan_inventory.yml @@ -1,5 +1,5 @@ --- -- name: "Сканирование сети (Jinja2 Logic Fix)" +- name: "Полное сканирование (включая Unknown)" hosts: localhost connection: local gather_facts: no @@ -9,11 +9,12 @@ semaphore_project_id: 1 semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ=" - # --- ID КЛЮЧЕЙ --- + # --- ID КЛЮЧЕЙ (ПРОВЕРЬТЕ ИХ В SEMAPHORE!) --- key_windows: 7 - key_linux: 8 - key_mikrotik: 9 + key_linux: 7 + key_mikrotik: 7 # <--- Убедитесь, что ключ с ID 9 существует! key_printers: 7 + key_other: 7 # Какой ключ использовать для неизвестных устройств # --- СЕТИ --- subnets: @@ -47,11 +48,11 @@ - name: Проверка наличия хостов fail: - msg: "Сеть пуста, активных хостов не найдено." + msg: "Сеть пуста." when: active_ips | length == 0 # ---------------------------------------------------------------- - # ШАГ 2: Сканирование портов (TCP Connect) + # ШАГ 2: Сканирование портов # ---------------------------------------------------------------- - name: TCP Port Scan & Name Discovery shell: | @@ -63,22 +64,18 @@ changed_when: false # ---------------------------------------------------------------- - # ШАГ 3: Классификация (Jinja2 Block - Исправленная логика) - # Мы обрабатываем весь список результатов сразу, а не в цикле задач. + # ШАГ 3: Классификация # ---------------------------------------------------------------- - - name: Обработка результатов сканирования + - name: Обработка результатов set_fact: classified_hosts: >- [ {% for res in scan_results.results %} {% set out = res.stdout %} {% set ip = res.item %} - - {# Поиск имени #} {% set smb_found = out | regex_search('Computer name: ([\\w-]+)', '\\1') %} {% set smb_name = smb_found[0] if smb_found else '' %} - {# Определение типа (Ищем 'порт/tcp' и 'open' с любыми пробелами) #} {% set type = 'other' %} {% if out | regex_search('445/tcp\s+open') %} {% set type = 'windows' %} @@ -90,23 +87,18 @@ {% set type = 'linux' %} {% endif %} - {# Формирование имени #} {% if type == 'windows' and smb_name != '' %} {% set final_name = smb_name | lower %} {% else %} {% set final_name = type + '_' + ip | replace('.', '_') %} {% endif %} - { - "ip": "{{ ip }}", - "type": "{{ type }}", - "name": "{{ final_name }}" - }, + { "ip": "{{ ip }}", "type": "{{ type }}", "name": "{{ final_name }}" }, {% endfor %} ] # ---------------------------------------------------------------- - # ШАГ 4: Разбиение на группы + # ШАГ 4: Списки # ---------------------------------------------------------------- - name: Формирование списков set_fact: @@ -114,22 +106,22 @@ list_lin: "{{ classified_hosts | selectattr('type', 'equalto', 'linux') | list }}" list_tik: "{{ classified_hosts | selectattr('type', 'equalto', 'mikrotik') | list }}" list_prn: "{{ classified_hosts | selectattr('type', 'equalto', 'printer') | list }}" + list_oth: "{{ classified_hosts | selectattr('type', 'equalto', 'other') | list }}" - - name: СТАТИСТИКА (Результат) + - name: СТАТИСТИКА debug: msg: - "Windows: {{ list_win | length }}" - "MikroTik: {{ list_tik | length }}" - "Linux: {{ list_lin | length }}" - "Printers: {{ list_prn | length }}" - - "Other: {{ classified_hosts | length - (list_win|length + list_lin|length + list_tik|length + list_prn|length) }}" + - "Unknown: {{ list_oth | length }}" # ---------------------------------------------------------------- # ШАГ 5: Отправка Windows # ---------------------------------------------------------------- - block: - - name: Генерация инвентаря Windows - set_fact: + - set_fact: content_win: | [windows] {% for h in list_win %} @@ -140,8 +132,7 @@ ansible_shell_type=powershell ansible_port=22 - - name: Сохранение JSON (Windows) - copy: + - copy: content: | { "name": "Auto Windows {{ 1000 | random }}", @@ -154,8 +145,7 @@ } dest: /tmp/p_win.json - - name: Отправка API (Windows) - command: > + - command: > curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" -H "Authorization: Bearer {{ semaphore_api_token }}" -H "Content-Type: application/json" @@ -164,11 +154,10 @@ when: list_win | length > 0 # ---------------------------------------------------------------- - # ШАГ 6: Отправка MikroTik + # ШАГ 6: Отправка MikroTik (С ОТЛАДКОЙ ОШИБОК) # ---------------------------------------------------------------- - block: - - name: Генерация инвентаря MikroTik - set_fact: + - set_fact: content_tik: | [routers] {% for h in list_tik %} @@ -178,8 +167,7 @@ ansible_connection=network_cli ansible_network_os=routeros - - name: Сохранение JSON (MikroTik) - copy: + - copy: content: | { "name": "Auto MikroTik {{ 1000 | random }}", @@ -192,58 +180,21 @@ } dest: /tmp/p_tik.json - - name: Отправка API (MikroTik) + - name: Отправка API (MikroTik) - Показать ошибку если упадет command: > - curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" + curl -f -v -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" -H "Authorization: Bearer {{ semaphore_api_token }}" -H "Content-Type: application/json" -d @/tmp/p_tik.json - ignore_errors: yes + register: tik_result + # ignore_errors: yes <--- УБРАЛИ, ЧТОБЫ УВИДЕТЬ ОШИБКУ, ЕСЛИ ОНА ЕСТЬ when: list_tik | length > 0 # ---------------------------------------------------------------- - # ШАГ 7: Отправка Принтеров + # ШАГ 7: Отправка Linux # ---------------------------------------------------------------- - block: - - name: Генерация инвентаря Принтеров - set_fact: - content_prn: | - [printers] - {% for h in list_prn %} - {{ h.name }} ansible_host={{ h.ip }} - {% endfor %} - [printers:vars] - ansible_connection=local - - - name: Сохранение JSON (Принтеры) - copy: - content: | - { - "name": "Auto Printers {{ 1000 | random }}", - "project_id": {{ semaphore_project_id }}, - "type": "static", - "ssh_key_id": {{ key_printers }}, - "become_key_id": null, - "repository_id": null, - "inventory": {{ content_prn | to_json }} - } - dest: /tmp/p_prn.json - - - name: Отправка API (Принтеры) - command: > - curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" - -H "Authorization: Bearer {{ semaphore_api_token }}" - -H "Content-Type: application/json" - -d @/tmp/p_prn.json - ignore_errors: yes - when: list_prn | length > 0 - - # ---------------------------------------------------------------- - # ШАГ 8: Отправка Linux - # ---------------------------------------------------------------- - - block: - - name: Генерация инвентаря Linux - set_fact: + - set_fact: content_lin: | [linux] {% for h in list_lin %} @@ -253,8 +204,7 @@ ansible_connection=ssh ansible_user=root - - name: Сохранение JSON (Linux) - copy: + - copy: content: | { "name": "Auto Linux {{ 1000 | random }}", @@ -267,8 +217,7 @@ } dest: /tmp/p_lin.json - - name: Отправка API (Linux) - command: > + - command: > curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" -H "Authorization: Bearer {{ semaphore_api_token }}" -H "Content-Type: application/json" @@ -276,5 +225,75 @@ ignore_errors: yes when: list_lin | length > 0 + # ---------------------------------------------------------------- + # ШАГ 8: Отправка Printers + # ---------------------------------------------------------------- + - block: + - set_fact: + content_prn: | + [printers] + {% for h in list_prn %} + {{ h.name }} ansible_host={{ h.ip }} + {% endfor %} + [printers:vars] + ansible_connection=local + + - copy: + content: | + { + "name": "Auto Printers {{ 1000 | random }}", + "project_id": {{ semaphore_project_id }}, + "type": "static", + "ssh_key_id": {{ key_printers }}, + "become_key_id": null, + "repository_id": null, + "inventory": {{ content_prn | to_json }} + } + dest: /tmp/p_prn.json + + - command: > + curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" + -H "Authorization: Bearer {{ semaphore_api_token }}" + -H "Content-Type: application/json" + -d @/tmp/p_prn.json + ignore_errors: yes + when: list_prn | length > 0 + + # ---------------------------------------------------------------- + # ШАГ 9: Отправка UNKNOWN (Other) + # Это добавит те 177 хостов в отдельный инвентарь + # ---------------------------------------------------------------- + - block: + - set_fact: + content_oth: | + [unknown_devices] + {% for h in list_oth %} + {{ h.name }} ansible_host={{ h.ip }} + {% endfor %} + [unknown_devices:vars] + ansible_connection=local + # Мы не знаем, что это, поэтому ставим local или ssh + + - copy: + content: | + { + "name": "Auto Unknown {{ 1000 | random }}", + "project_id": {{ semaphore_project_id }}, + "type": "static", + "ssh_key_id": {{ key_other }}, + "become_key_id": null, + "repository_id": null, + "inventory": {{ content_oth | to_json }} + } + dest: /tmp/p_oth.json + + - command: > + curl -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory" + -H "Authorization: Bearer {{ semaphore_api_token }}" + -H "Content-Type: application/json" + -d @/tmp/p_oth.json + ignore_errors: yes + when: list_oth | length > 0 + - name: Очистка shell: rm -f /tmp/p_*.json \ No newline at end of file