Files
semaphore/playbooks/scan_inventory.yml

299 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
- name: "Полное сканирование (включая Unknown)"
hosts: localhost
connection: local
gather_facts: no
vars:
# --- SEMAPHORE API ---
semaphore_url: "http://192.168.0.198:9999"
semaphore_project_id: 1
semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ="
# --- ID КЛЮЧЕЙ (ПРОВЕРЬТЕ ИХ В SEMAPHORE!) ---
key_windows: 7
key_linux: 7
key_mikrotik: 7 # <--- Убедитесь, что ключ с ID 9 существует!
key_printers: 7
key_other: 7 # Какой ключ использовать для неизвестных устройств
# --- СЕТИ ---
subnets:
- "192.168.0.0/24"
- "192.168.0.0/23"
- "192.168.2.0/24"
- "192.168.3.0/24"
- "172.19.8.0/24"
- "172.19.9.0/24"
- "172.19.10.0/24"
- "172.19.24.0/24"
- "172.19.26.0/24"
- "172.19.40.0/24"
- "172.19.42.0/24"
- "172.19.56.0/24"
- "172.19.58.0/24"
- "172.19.90.0/24"
tasks:
# ----------------------------------------------------------------
# ШАГ 1: Поиск живых хостов
# ----------------------------------------------------------------
- name: Ping Sweep
command: "nmap -sn -n --min-rate 1000 -T4 -oG - {{ subnets | join(' ') }}"
register: ping_scan
changed_when: false
- name: Формирование списка активных IP
set_fact:
active_ips: "{{ ping_scan.stdout | regex_findall('Host: ([0-9.]+)') | unique | list }}"
- name: Проверка наличия хостов
fail:
msg: "Сеть пуста."
when: active_ips | length == 0
# ----------------------------------------------------------------
# ШАГ 2: Сканирование портов
# ----------------------------------------------------------------
- name: TCP Port Scan & Name Discovery
shell: |
nmap -sT -p 22,445,8291,9100 \
--script smb-os-discovery \
-Pn -n -T4 {{ item }}
loop: "{{ active_ips }}"
register: scan_results
changed_when: false
# ----------------------------------------------------------------
# ШАГ 3: Классификация
# ----------------------------------------------------------------
- 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 '' %}
{% set type = 'other' %}
{% if out | regex_search('445/tcp\s+open') %}
{% set type = 'windows' %}
{% elif out | regex_search('8291/tcp\s+open') %}
{% set type = 'mikrotik' %}
{% elif out | regex_search('9100/tcp\s+open') %}
{% set type = 'printer' %}
{% elif out | regex_search('22/tcp\s+open') %}
{% 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 }}" },
{% endfor %}
]
# ----------------------------------------------------------------
# ШАГ 4: Списки
# ----------------------------------------------------------------
- name: Формирование списков
set_fact:
list_win: "{{ classified_hosts | selectattr('type', 'equalto', 'windows') | list }}"
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: СТАТИСТИКА
debug:
msg:
- "Windows: {{ list_win | length }}"
- "MikroTik: {{ list_tik | length }}"
- "Linux: {{ list_lin | length }}"
- "Printers: {{ list_prn | length }}"
- "Unknown: {{ list_oth | length }}"
# ----------------------------------------------------------------
# ШАГ 5: Отправка Windows
# ----------------------------------------------------------------
- block:
- set_fact:
content_win: |
[windows]
{% for h in list_win %}
{{ h.name }} ansible_host={{ h.ip }}
{% endfor %}
[windows:vars]
ansible_connection=ssh
ansible_shell_type=powershell
ansible_port=22
- copy:
content: |
{
"name": "Auto Windows {{ 1000 | random }}",
"project_id": {{ semaphore_project_id }},
"type": "static",
"ssh_key_id": {{ key_windows }},
"become_key_id": null,
"repository_id": null,
"inventory": {{ content_win | to_json }}
}
dest: /tmp/p_win.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_win.json
ignore_errors: yes
when: list_win | length > 0
# ----------------------------------------------------------------
# ШАГ 6: Отправка MikroTik (С ОТЛАДКОЙ ОШИБОК)
# ----------------------------------------------------------------
- block:
- set_fact:
content_tik: |
[routers]
{% for h in list_tik %}
{{ h.name }} ansible_host={{ h.ip }}
{% endfor %}
[routers:vars]
ansible_connection=network_cli
ansible_network_os=routeros
- copy:
content: |
{
"name": "Auto MikroTik {{ 1000 | random }}",
"project_id": {{ semaphore_project_id }},
"type": "static",
"ssh_key_id": {{ key_mikrotik }},
"become_key_id": null,
"repository_id": null,
"inventory": {{ content_tik | to_json }}
}
dest: /tmp/p_tik.json
- name: Отправка API (MikroTik) - Показать ошибку если упадет
command: >
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
register: tik_result
# ignore_errors: yes <--- УБРАЛИ, ЧТОБЫ УВИДЕТЬ ОШИБКУ, ЕСЛИ ОНА ЕСТЬ
when: list_tik | length > 0
# ----------------------------------------------------------------
# ШАГ 7: Отправка Linux
# ----------------------------------------------------------------
- block:
- set_fact:
content_lin: |
[linux]
{% for h in list_lin %}
{{ h.name }} ansible_host={{ h.ip }}
{% endfor %}
[linux:vars]
ansible_connection=ssh
ansible_user=root
- copy:
content: |
{
"name": "Auto Linux {{ 1000 | random }}",
"project_id": {{ semaphore_project_id }},
"type": "static",
"ssh_key_id": {{ key_linux }},
"become_key_id": null,
"repository_id": null,
"inventory": {{ content_lin | to_json }}
}
dest: /tmp/p_lin.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_lin.json
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