172 lines
7.0 KiB
YAML
172 lines
7.0 KiB
YAML
---
|
||
- name: Сбор инвентаря и создание его в Semaphore UI
|
||
hosts: localhost
|
||
connection: local
|
||
gather_facts: no
|
||
vars:
|
||
# --- НАСТРОЙКИ SEMAPHORE ---
|
||
semaphore_url: "http://192.168.0.198:9999" # Укажите ваш URL (или http://localhost:3000)
|
||
semaphore_project_id: 1
|
||
# ID ключа, который будет использоваться для подключения к новым хостам
|
||
semaphore_key_id: 7
|
||
# Токен API (лучше хранить в Secret, но для теста можно тут)
|
||
semaphore_api_token: "9ojexqiwt1xkemig7j1bd1pe-frh7hkre4reryk2occ="
|
||
inventory_name: "Auto Scanned Network"
|
||
|
||
# --- НАСТРОЙКИ СЕТИ ---
|
||
subnets:
|
||
- "192.168.0.0/24"
|
||
- "192.168.1.0/24"
|
||
- "192.168.2.0/24"
|
||
- "192.168.3.0/24"
|
||
- "172.19.8.0/23"
|
||
- "172.19.9.0/23"
|
||
- "172.19.10.0/23"
|
||
- "172.19.24.0/23"
|
||
- "172.19.26.0/23"
|
||
- "172.19.40.0/23"
|
||
- "172.19.42.0/23"
|
||
- "172.19.56.0/23"
|
||
- "172.19.58.0/23"
|
||
- "172.19.90.0/23"
|
||
# - "192.168.1.0/24" # Добавьте нужные подсети
|
||
scan_ports: [5985, 22, 445]
|
||
|
||
tasks:
|
||
# ---------------------------------------------------------
|
||
# ШАГ 1: Сканирование (Nmap)
|
||
# ---------------------------------------------------------
|
||
- name: Сканирование сети (поиск живых IP)
|
||
command: >
|
||
nmap -p {{ scan_ports | join(',') }}
|
||
-Pn -n --open --min-rate 1000 -T4 -oG -
|
||
{{ subnets | join(' ') }}
|
||
register: nmap_result
|
||
changed_when: false
|
||
ignore_errors: yes # Чтобы не падало, если ничего не нашлось
|
||
|
||
- name: Извлечение IP адресов
|
||
set_fact:
|
||
active_ips: "{{ nmap_result.stdout | regex_findall('Host: ([0-9.]+).*Ports:.*(?:' + scan_ports | join('|') + ')/open') | unique | list }}"
|
||
|
||
- name: Проверка, найдены ли IP
|
||
fail:
|
||
msg: "Не найдено ни одного активного IP. Проверьте настройки сети или Nmap."
|
||
when: active_ips | length == 0
|
||
|
||
# ---------------------------------------------------------
|
||
# ШАГ 2: Определение имен
|
||
# ---------------------------------------------------------
|
||
- name: Определение имен хостов (SMB Discovery + DNS)
|
||
shell: |
|
||
IP="{{ item }}"
|
||
SMB_NAME=$(nmap -p 445 --script smb-os-discovery $IP -Pn -n | grep "Computer name:" | awk -F': ' '{print $2}')
|
||
if [ ! -z "$SMB_NAME" ]; then
|
||
echo "$SMB_NAME" | tr '[:upper:]' '[:lower:]'
|
||
else
|
||
DNS_NAME=$(nslookup -timeout=1 $IP 192.168.1.250 2>/dev/null | grep 'name =' | awk '{print $NF}' | sed 's/\.$//' | head -n 1)
|
||
if [ ! -z "$DNS_NAME" ]; then
|
||
echo "$DNS_NAME" | tr '[:upper:]' '[:lower:]'
|
||
else
|
||
echo "UNKNOWN"
|
||
fi
|
||
fi
|
||
loop: "{{ active_ips }}"
|
||
register: host_names
|
||
changed_when: false
|
||
no_log: true
|
||
|
||
# ---------------------------------------------------------
|
||
# ШАГ 3: Сортировка и генерация текста
|
||
# ---------------------------------------------------------
|
||
- name: Сортировка хостов
|
||
set_fact:
|
||
pc_list: >-
|
||
{{ host_names.results | selectattr('stdout', 'search', 'pc')
|
||
| map(attribute='item') | list
|
||
| zip(host_names.results | selectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
|
||
| list }}
|
||
other_list: >-
|
||
{{ host_names.results | rejectattr('stdout', 'search', 'pc')
|
||
| map(attribute='item') | list
|
||
| zip(host_names.results | rejectattr('stdout', 'search', 'pc') | map(attribute='stdout') | list)
|
||
| list }}
|
||
|
||
- name: Генерация текста инвентаря
|
||
set_fact:
|
||
inventory_content: |
|
||
# === Найденные PC ===
|
||
[windows_pcs]
|
||
{% for ip, name in pc_list %}
|
||
{{ name }} ansible_host={{ ip }}
|
||
{% endfor %}
|
||
|
||
# === Остальные устройства ===
|
||
[windows_other]
|
||
{% for ip, name in other_list %}
|
||
{% if name == "UNKNOWN" %}
|
||
unknown_{{ ip | replace('.', '_') }} ansible_host={{ ip }}
|
||
{% else %}
|
||
{{ name }} ansible_host={{ ip }}
|
||
{% endif %}
|
||
{% endfor %}
|
||
|
||
[windows:children]
|
||
windows_pcs
|
||
windows_other
|
||
|
||
[windows:vars]
|
||
ansible_connection=ssh
|
||
ansible_port=22
|
||
ansible_shell_type=powershell
|
||
ansible_user=o.grechko
|
||
|
||
# ---------------------------------------------------------
|
||
# ШАГ 4: Отладка (проверка данных перед отправкой)
|
||
# ---------------------------------------------------------
|
||
- name: Debug Payload (Проверка данных)
|
||
debug:
|
||
msg:
|
||
- "URL: {{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
|
||
- "SSH Key ID: {{ semaphore_key_id }}"
|
||
- "Количество символов в инвентаре: {{ inventory_content | length }}"
|
||
|
||
# ---------------------------------------------------------
|
||
# ШАГ 5: Отправка в API (ИСПРАВЛЕНО ssh_key_id)
|
||
# ---------------------------------------------------------
|
||
- name: Создание инвентаря в Semaphore через API
|
||
uri:
|
||
url: "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
|
||
method: POST
|
||
headers:
|
||
Authorization: "Bearer {{ semaphore_api_token }}"
|
||
Content-Type: "application/json"
|
||
Accept: "application/json"
|
||
body_format: json
|
||
body:
|
||
name: "{{ inventory_name }}"
|
||
project_id: "{{ semaphore_project_id | int }}"
|
||
type: "static"
|
||
ssh_key_id: "{{ semaphore_key_id | int }}"
|
||
become_key_id: null
|
||
inventory: "{{ inventory_content }}"
|
||
status_code: [201, 200]
|
||
register: api_response
|
||
|
||
- name: DEBUG - Попробовать через CURL (чтобы увидеть текст ошибки)
|
||
command: >
|
||
curl -v -X POST "{{ semaphore_url }}/api/project/{{ semaphore_project_id }}/inventory"
|
||
-H "Authorization: Bearer {{ semaphore_api_token }}"
|
||
-H "Content-Type: application/json"
|
||
-d '{"name": "{{ inventory_name }}", "project_id": {{ semaphore_project_id }}, "type": "static", "ssh_key_id": {{ semaphore_key_id }}, "become_key_id": null, "inventory": "localhost ansible_connection=local"}'
|
||
register: curl_output
|
||
ignore_errors: yes
|
||
|
||
- name: Вывод ошибки CURL
|
||
debug:
|
||
var: curl_output.stderr_lines
|
||
|
||
- name: Успех
|
||
debug:
|
||
msg: "Инвентарь создан! ID: {{ api_response.json.id | default('OK') }}"
|