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

This commit is contained in:
2025-12-10 12:29:28 +00:00
parent ee5338d7ca
commit e7b675abf2

View File

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