Files
semaphore/playbooks/scan_inventory.yml

232 lines
9.0 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: "Сканирование сети через SNMP (Community: public)"
hosts: localhost
connection: local
gather_facts: no
become: yes # МЫ ВЕРНУЛИ ЭТО (нужны права root для nmap -sU / -O)
vars:
# --- SEMAPHORE API ---
semaphore_url: "http://192.168.0.198:9999"
semaphore_project_id: 1
semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ="
# --- ID КЛЮЧЕЙ ---
key_windows: 7
key_linux: 8
key_mikrotik: 9
key_printers: 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"
snmp_community: "public"
tasks:
# ТЕСТ ПРАВ: Проверяем, работает ли become после настройки Environment
- name: Проверка прав root
command: id
register: id_check
changed_when: false
- name: Показать пользователя (должен быть root)
debug:
msg: "Я работаю от имени: {{ id_check.stdout }}"
# ----------------------------------------------------------------
# ШАГ 1: Поиск живых хостов
# ----------------------------------------------------------------
- name: Ping Sweep (быстрый поиск)
# УБРАЛИ 'sudo', ОСТАВИЛИ ТОЛЬКО nmap (права дает become: yes выше)
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: Опрос через SNMP
# ----------------------------------------------------------------
- name: SNMP Discovery
# УБРАЛИ 'sudo'
shell: |
nmap -sU -sS -p U:161,T:22,T:445,T:8291,T:9100 \
--script snmp-sysdescr \
--script-args snmpcommunity={{ snmp_community }} \
-Pn -n -T4 {{ item }}
loop: "{{ active_ips }}"
register: scan_results
changed_when: false
# ----------------------------------------------------------------
# ШАГ 3: Классификация
# ----------------------------------------------------------------
- name: Анализ устройств и классификация
set_fact:
classified_hosts: "{{ classified_hosts | default([]) + [ host_data ] }}"
vars:
out: "{{ item.stdout }}"
ip: "{{ item.item }}"
snmp_desc: "{{ out | regex_search('sysDescr\\.0: ([^\\n]+)', '\\1') | first | default('') }}"
detected_type: >-
{% 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 '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
{% else %}other{% endif %}
host_data:
ip: "{{ ip }}"
type: "{{ detected_type }}"
desc: "{{ snmp_desc | replace('\"', '') | default('No SNMP info') }}"
name: "{{ detected_type }}_{{ ip | replace('.', '_') }}"
loop: "{{ scan_results.results }}"
no_log: true
# ----------------------------------------------------------------
# ШАГ 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 }}"
# ----------------------------------------------------------------
# ШАГ 5: Отправка Windows
# ----------------------------------------------------------------
- block:
- name: Генерация текста инвентаря Windows
set_fact:
content_win: |
[windows]
{% for h in list_win %}
{{ h.name }} ansible_host={{ h.ip }} # SNMP: {{ h.desc }}
{% endfor %}
[windows:vars]
ansible_connection=ssh
ansible_shell_type=powershell
ansible_port=22
- name: Сохранение JSON для Windows
copy:
content: |
{
"name": "SNMP 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
- name: Отправка Windows 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_win.json
ignore_errors: yes
when: list_win | length > 0
# ----------------------------------------------------------------
# ШАГ 6: Отправка MikroTik
# ----------------------------------------------------------------
- block:
- name: Генерация текста инвентаря MikroTik
set_fact:
content_tik: |
[routers]
{% for h in list_tik %}
{{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }}
{% endfor %}
[routers:vars]
ansible_connection=network_cli
ansible_network_os=routeros
- name: Сохранение JSON для MikroTik
copy:
content: |
{
"name": "SNMP 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: Отправка MikroTik 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_tik.json
ignore_errors: yes
when: list_tik | length > 0
# ----------------------------------------------------------------
# ШАГ 7: Отправка Принтеров
# ----------------------------------------------------------------
- block:
- name: Генерация текста инвентаря Принтеров
set_fact:
content_prn: |
[printers]
{% for h in list_prn %}
{{ h.name }} ansible_host={{ h.ip }} # {{ h.desc }}
{% endfor %}
[printers:vars]
ansible_connection=local
- name: Сохранение JSON для Принтеров
copy:
content: |
{
"name": "SNMP 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
- name: Очистка временных файлов
shell: rm -f /tmp/p_*.json