-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwazuh_agent_deploy.yml
More file actions
249 lines (213 loc) · 9.34 KB
/
Copy pathwazuh_agent_deploy.yml
File metadata and controls
249 lines (213 loc) · 9.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
---
# wazuh_agent_deploy.yml
# Installs and configures the Wazuh 4.x agent on all apt-based hosts.
# Registers each agent with the Wazuh manager defined in wazuh_manager_ip.
# Alpine and other non-apt hosts are skipped automatically.
#
# Prerequisites
# 1. Wazuh server (lxc-wazuh, 192.168.0.243) must be up and running.
# 2. ansibleuser must already be bootstrapped on each target host.
# For a new host (e.g. lxc-wazuh itself), bootstrap it first:
# ansible-playbook setup-ansibleuser.yml --limit <host> -u root --ask-pass
# Note: setup-ansibleuser.yml uses gather_facts: false, so ansible_os_family
# is not available — the shell variable falls back via | default('') filter.
# 3. host_vars/<host>/vault.yml must exist and be encrypted with ansible-vault.
# For lxc-wazuh: host_vars/lxc-wazuh/vault.yml (vault_become_password)
# ansible-vault encrypt host_vars/lxc-wazuh/vault.yml
#
# Usage:
# ansible-playbook wazuh_agent_deploy.yml # all vms + lxcs
# ansible-playbook wazuh_agent_deploy.yml --limit vms
# ansible-playbook wazuh_agent_deploy.yml --limit lxcs:!lxc-wazuh # recommended: skips wazuh server
# ansible-playbook wazuh_agent_deploy.yml --limit vm-debian-dev.server.wow
#
# Testing (runs against already-deployed agents — no install steps):
# ansible-playbook wazuh_agent_deploy.yml --tags test
# ansible-playbook wazuh_agent_deploy.yml --tags test --limit lxcs:!lxc-wazuh
#
# IP check only (no remote tasks beyond fact gathering):
# ansible-playbook wazuh_agent_deploy.yml --tags always --limit lxcs:!lxc-wazuh
#
# The [always]-tagged task prints each host's IP (parsed from hosts.ini via
# ansible_host) so you can confirm inventory resolution before any work runs.
#
# NOTE: lxc-wazuh must be excluded from --limit lxcs runs. Although this playbook
# skips lxc-wazuh via meta: end_host, gather_facts fires over SSH first and
# will fail with "Permission denied" if ansibleuser is not bootstrapped there.
# Use lxcs:!lxc-wazuh to avoid the confusing (but harmless) unreachable error.
#
# lxc-wazuh server-side services (run on the LXC directly if services need re-enabling):
# systemctl enable wazuh-dashboard.service wazuh-indexer.service \
# wazuh-indexer-performance-analyzer.service wazuh-manager.service
# systemctl start wazuh-dashboard.service wazuh-indexer.service \
# wazuh-indexer-performance-analyzer.service wazuh-manager.service
#
# WARNING: Do NOT run this playbook against lxc-wazuh — installing wazuh-agent on the
# manager host replaces the wazuh-manager systemd unit and breaks the server.
# lxc-wazuh is automatically skipped by this playbook.
- name: Deploy Wazuh agent on apt-based Linux hosts
hosts: all
gather_facts: true
become: true
ignore_unreachable: true
vars:
wazuh_manager_ip: "192.168.0.243"
wazuh_agent_name: "{{ inventory_hostname }}"
tasks:
# Inventory — show the IP parsed from hosts.ini
- name: "[wazuh] Show inventory host details"
ansible.builtin.debug:
msg: "Host: {{ inventory_hostname }} → IP (ansible_host): {{ ansible_host }}"
tags: [ always ]
- name: Skip non-apt hosts (Alpine, etc.)
when: ansible_pkg_mgr != 'apt'
block:
- name: "[wazuh] NOTICE — Alpine Linux has no official Wazuh package (skipping)"
ansible.builtin.debug:
msg: >-
{{ inventory_hostname }} uses {{ ansible_pkg_mgr }} ({{ ansible_distribution }}). Wazuh does not publish an official Alpine APK package. This host is SKIPPED — install manually from source if needed.
- name: End host — non-apt system
ansible.builtin.meta: end_host
- name: Skip the Wazuh manager host (never touch the server with this playbook)
ansible.builtin.meta: end_host
when: inventory_hostname == 'lxc-wazuh'
# Repository setup
- name: "[wazuh] Install prerequisite packages"
ansible.builtin.apt:
name:
- gnupg
- gpg
- apt-transport-https
- curl
state: present
update_cache: true
- name: "[wazuh] Import Wazuh GPG key"
ansible.builtin.shell:
cmd: "curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import && chmod 644 /usr/share/keyrings/wazuh.gpg"
creates: /usr/share/keyrings/wazuh.gpg
- name: "[wazuh] Add Wazuh APT repository"
ansible.builtin.apt_repository:
repo: "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main"
filename: wazuh
state: present
update_cache: true
# Firewall — open outbound ports to Wazuh manager if UFW is active
- name: "[ufw] Check if UFW is active"
ansible.builtin.command:
cmd: ufw status
register: ufw_status
changed_when: false
failed_when: false
- name: "[ufw] Allow outbound to Wazuh manager — port 1514 (agent comms)"
community.general.ufw:
rule: allow
direction: out
dest: "{{ wazuh_manager_ip }}"
port: "1514"
proto: tcp
when: "'Status: active' in ufw_status.stdout"
- name: "[ufw] Allow outbound to Wazuh manager — port 1515 (agent enrollment)"
community.general.ufw:
rule: allow
direction: out
dest: "{{ wazuh_manager_ip }}"
port: "1515"
proto: tcp
when: "'Status: active' in ufw_status.stdout"
# Install
- name: "[wazuh] Check if wazuh-agent is already installed"
ansible.builtin.command:
cmd: dpkg-query -W -f='${Status}' wazuh-agent
register: wazuh_pkg_status
failed_when: false
changed_when: false
- name: "[wazuh] Install wazuh-agent and enroll with manager"
ansible.builtin.command:
cmd: apt-get install -y wazuh-agent
environment:
DEBIAN_FRONTEND: noninteractive
WAZUH_MANAGER: "{{ wazuh_manager_ip }}"
WAZUH_AGENT_NAME: "{{ wazuh_agent_name }}"
when: "'install ok installed' not in wazuh_pkg_status.stdout"
# Configure — ensure manager IP is correct on every run
- name: "[wazuh] Ensure manager address in ossec.conf"
ansible.builtin.lineinfile:
path: /var/ossec/etc/ossec.conf
regexp: '^\s*<address>.*</address>'
line: " <address>{{ wazuh_manager_ip }}</address>"
backrefs: true
notify: Restart wazuh-agent
# Service
- name: "[wazuh] Reload systemd daemon"
ansible.builtin.systemd:
daemon_reload: true
- name: "[wazuh] Enable and start wazuh-agent"
ansible.builtin.systemd:
name: wazuh-agent
enabled: true
state: started
# Pin package version to prevent accidental upgrades
- name: "[wazuh] Hold wazuh-agent package (prevent auto-upgrade)"
ansible.builtin.dpkg_selections:
name: wazuh-agent
selection: hold
# Test / Verify — run with:
# ansible-playbook wazuh_agent_deploy.yml --tags test
# lxc-wazuh is always excluded — it runs the manager, not the agent.
- name: "[wazuh][test] Run agent checks (skipped on lxc-wazuh)"
when: inventory_hostname != 'lxc-wazuh'
tags: [ test ]
block:
- name: "[wazuh][test] Verify wazuh-agent service is running"
ansible.builtin.systemd:
name: wazuh-agent
register: wazuh_service_state
changed_when: false
- name: "[wazuh][test] Assert wazuh-agent is active"
ansible.builtin.assert:
that:
- wazuh_service_state.status is defined
- wazuh_service_state.status.ActiveState == 'active'
fail_msg: "wazuh-agent is NOT running on {{ inventory_hostname }} ({{ ansible_host }})"
success_msg: "wazuh-agent is running on {{ inventory_hostname }} ({{ ansible_host }})"
- name: "[wazuh][test] Verify manager address in ossec.conf matches wazuh_manager_ip"
ansible.builtin.command:
cmd: grep -E '<address>' /var/ossec/etc/ossec.conf
register: ossec_address
changed_when: false
failed_when: wazuh_manager_ip not in ossec_address.stdout
- name: "[wazuh][test] Show ossec.conf manager address"
ansible.builtin.debug:
msg: "ossec.conf manager entry: {{ ossec_address.stdout | trim }} (expected: {{ wazuh_manager_ip }})"
- name: "[wazuh][test] Check TCP reachability to manager port 1514 (agent comms)"
ansible.builtin.wait_for:
host: "{{ wazuh_manager_ip }}"
port: 1514
timeout: 5
state: started
ignore_errors: true
register: port_1514_check
- name: "[wazuh][test] Check TCP reachability to manager port 1515 (enrollment)"
ansible.builtin.wait_for:
host: "{{ wazuh_manager_ip }}"
port: 1515
timeout: 5
state: started
ignore_errors: true
register: port_1515_check
- name: "[wazuh][test] Report connectivity results"
ansible.builtin.debug:
msg:
- "Host: {{ inventory_hostname }} IP: {{ ansible_host }}"
- "Port 1514 → {{ 'OPEN' if not port_1514_check.failed else 'UNREACHABLE' }}"
- "Port 1515 → {{ 'OPEN' if not port_1515_check.failed else 'UNREACHABLE' }}"
rescue:
- name: "[wazuh][test] NOTICE — host unreachable or agent not yet installed"
ansible.builtin.debug:
msg: >-
SKIPPED: {{ inventory_hostname }} ({{ ansible_host }}) was unreachable or has no wazuh-agent installed yet. Bootstrap the host first, then re-run --tags test.
handlers:
- name: Restart wazuh-agent
ansible.builtin.systemd:
name: wazuh-agent
state: restarted