Skip to content

Commit 3e97f2a

Browse files
committed
adding roles for agents install on clients
1 parent cb58b66 commit 3e97f2a

File tree

6 files changed

+427
-2
lines changed

6 files changed

+427
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,4 @@ rsync*
6363
.rsync-filter
6464
claude-*
6565
.claude/
66+
.opencode/

ansible/README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ This directory contains the Ansible playbooks and roles used to deploy, manage,
88
ansible/
99
├── site.yml # Main installation playbook
1010
├── backup_lme.yml # Backup operations playbook
11-
├── upgrade_lme.yml # Upgrade operations playbook
11+
├── upgrade_lme.yml # Upgrade operations playbook
1212
├── rollback_lme.yml # Rollback operations playbook
1313
├── requirements.yml # Ansible collection dependencies
1414
├── roles/ # Ansible roles for different components
@@ -21,6 +21,7 @@ ansible/
2121
│ ├── nix/ # Nix package manager setup
2222
│ ├── podman/ # Podman container runtime setup
2323
│ └── wazuh/ # Wazuh server configuration
24+
│ └── agents/ # install LME agents onto your ansible client
2425
└── tasks/ # Shared task files
2526
└── load_env.yml # Environment variable loading
2627
```
@@ -110,6 +111,11 @@ ansible/
110111
- Creates backup manifests and metadata
111112
- Supports incremental and full backups
112113

114+
#### Agents Role (`roles/agents/`)
115+
- installs to both linux and windows hosts
116+
- installs elastic agnet and configures it to talk with LME server
117+
- installs wazuh agent and configure it to talk with LME server
118+
113119
## Shared Components
114120

115121
### Tasks (`tasks/`)
@@ -228,4 +234,4 @@ Override default values:
228234
ansible-playbook site.yml -e clone_directory=/custom/path
229235
```
230236

231-
For detailed information about backup, upgrade, and rollback operations, see the respective README files for each operation.
237+
For detailed information about backup, upgrade, and rollback operations, see the respective README files for each operation.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
dependencies: []
3+
4+
galaxy_info:
5+
role_name: lme.agents
6+
author: mreeve
7+
description: An Ansible Role that installs LME agents on linux and windows
8+
company: CISA's LME team
9+
min_ansible_version: "2.19"
10+
platforms:
11+
# Modify the platforms here as required
12+
# This example includes a lot, see https://github.com/ansible/ansible-lint/blob/main/src/ansiblelint/schemas/meta.json for all possibilities
13+
- name: Windows
14+
versions:
15+
- "2012R2"
16+
- "2016"
17+
- "2019"
18+
- "2022"
19+
- name: Debian
20+
versions:
21+
- buster
22+
- bullseye
23+
- bookworm
24+
- name: Ubuntu
25+
versions:
26+
- bionic
27+
- focal
28+
- jammy
29+
galaxy_tags:
30+
- EDR
31+
32+
collections:
33+
[
34+
"ansible.windows",
35+
"ansible.posix",
36+
"ansible.utils",
37+
"community.general",
38+
"community.windows",
39+
"chocolatey.chocolatey",
40+
"microsoft.ad",
41+
"vladgh.samba",
42+
]
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
---
2+
- name: Install Elastic Agent and Monitoring Tools
3+
hosts: win*,lin*
4+
gather_facts: no
5+
vars:
6+
elastic_user: "{{ lookup('env', 'ELASTIC_USER') | default('elastic') }}"
7+
elastic_password: "{{ lookup('env', 'ELASTIC_PASSWORD') }}"
8+
kibana_port: 5601
9+
es_port: 9200
10+
fleet_port: 8220
11+
agent_arch: "x86_64"
12+
temp_dir: "/tmp"
13+
win_temp_dir: "C:\\Temp"
14+
sysmon_url: "https://download.sysinternals.com/files/Sysmon.zip"
15+
sysmon_config_url: "https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml"
16+
audit_rules_url: "https://raw.githubusercontent.com/Neo23x0/auditd/master/audit.rules"
17+
18+
pre_tasks:
19+
- name: Fail if elastic_password is not provided
20+
fail:
21+
msg: "elastic_password must be provided as an environment variable or extra var (e.g., -e elastic_password=yourpass)"
22+
when: elastic_password | length == 0
23+
run_once: true
24+
25+
- name: Set fleet server URL from lme inventory host
26+
set_fact:
27+
fleet_server: "https://{{ hostvars['lme']['ansible_host'] }}:{{ fleet_port }}"
28+
when: fleet_server is not defined
29+
delegate_to: localhost
30+
run_once: true
31+
32+
- name: Fetch Elastic version from Elasticsearch API on lme
33+
when: elastic_version is not defined
34+
block:
35+
- uri:
36+
url: "https://{{ hostvars['lme']['ansible_host'] }}:{{ es_port }}/"
37+
method: GET
38+
user: "{{ elastic_user }}"
39+
password: "{{ elastic_password }}"
40+
force_basic_auth: yes
41+
validate_certs: no
42+
return_content: yes
43+
register: es_response
44+
delegate_to: localhost
45+
run_once: true
46+
47+
- set_fact:
48+
elastic_version: "{{ es_response.json.version.number }}"
49+
delegate_to: localhost
50+
run_once: true
51+
52+
- name: Fetch Fleet enrollment token from Kibana API on lme
53+
when: enrollment_token is not defined
54+
block:
55+
- uri:
56+
url: "https://{{ hostvars['lme']['ansible_host'] }}:{{ kibana_port }}/api/fleet/enrollment_api_keys"
57+
method: GET
58+
user: "{{ elastic_user }}"
59+
password: "{{ elastic_password }}"
60+
force_basic_auth: yes
61+
validate_certs: no
62+
headers:
63+
Content-Type: application/json
64+
kbn-xsrf: true
65+
return_content: yes
66+
register: fleet_response
67+
delegate_to: localhost
68+
run_once: true
69+
70+
- set_fact:
71+
enrollment_token: "{{ fleet_response.json['items'] | selectattr('active') | map(attribute='api_key') | list | first }}"
72+
when: fleet_response.json['items'] | selectattr('active') | list | length > 0
73+
74+
- fail:
75+
msg: "No active Fleet enrollment API keys found. Generate one in Kibana."
76+
when: fleet_response.json['items'] | selectattr('active') | list | length == 0
77+
delegate_to: localhost
78+
run_once: true
79+
80+
tasks:
81+
- name: Set hostname on Linux
82+
when: ansible_system == 'Linux'
83+
become: true
84+
become_method: sudo
85+
hostname:
86+
name: "{{ inventory_hostname }}"
87+
88+
- name: Set hostname on Windows
89+
when: ansible_os_family == 'Windows'
90+
become: true
91+
become_method: runas
92+
become_user: "localuser"
93+
win_hostname:
94+
name: "{{ inventory_hostname }}"
95+
96+
- name: Reboot Windows host
97+
when: ansible_os_family == 'Windows'
98+
win_reboot:
99+
reboot_timeout: 600
100+
post_reboot_delay: 30
101+
102+
- name: Install Elastic Agent on Linux
103+
when: ansible_system == 'Linux'
104+
become: true
105+
become_method: sudo
106+
block:
107+
- name: Gather service facts
108+
service_facts:
109+
110+
#- name: Debug service facts to verify elastic-agent.service presence
111+
# debug:
112+
# var: ansible_facts.services
113+
114+
- name: Skip Elastic Agent installation if already running
115+
meta: end_host
116+
when: "'elastic-agent.service' in ansible_facts.services and ansible_facts.services['elastic-agent.service'].status == 'enabled'"
117+
118+
- name: Download Elastic Agent tar.gz
119+
get_url:
120+
url: "https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-{{ elastic_version }}-linux-{{ agent_arch }}.tar.gz"
121+
dest: "{{ temp_dir }}/elastic-agent-{{ elastic_version }}-linux-{{ agent_arch }}.tar.gz"
122+
validate_certs: yes
123+
124+
- name: Extract Elastic Agent
125+
unarchive:
126+
src: "{{ temp_dir }}/elastic-agent-{{ elastic_version }}-linux-{{ agent_arch }}.tar.gz"
127+
dest: "{{ temp_dir }}"
128+
remote_src: yes
129+
130+
- name: Install Elastic Agent
131+
shell: |
132+
cd {{ temp_dir }}/elastic-agent-{{ elastic_version }}-linux-{{ agent_arch }}
133+
./elastic-agent install --url={{ fleet_server }} --enrollment-token={{ enrollment_token }} --insecure -n
134+
args:
135+
creates: /opt/Elastic/Agent/elastic-agent
136+
137+
- name: Install Elastic Agent on Windows
138+
when: ansible_os_family == 'Windows'
139+
become: true
140+
become_method: runas
141+
become_user: "localuser"
142+
block:
143+
- name: Check if Elastic Agent service is running
144+
win_service:
145+
name: Elastic Agent
146+
register: elastic_service_status
147+
148+
- name: Set fact for skipping installation
149+
set_fact:
150+
skip_elastic_install: "{{ elastic_service_status.exists and elastic_service_status.state == 'running' }}"
151+
152+
- name: Skip Elastic Agent installation if service is running
153+
debug:
154+
msg: "Elastic Agent service is already running, skipping installation."
155+
when: skip_elastic_install
156+
157+
- name: Install Elastic Agent when service is not running
158+
when: not skip_elastic_install
159+
block:
160+
- name: Create temp directory if not exists
161+
win_file:
162+
path: "{{ win_temp_dir }}"
163+
state: directory
164+
165+
- name: Download Elastic Agent ZIP
166+
win_get_url:
167+
url: "https://artifacts.elastic.co/downloads/beats/elastic-agent/elastic-agent-{{ elastic_version }}-windows-{{ agent_arch }}.zip"
168+
dest: "{{ win_temp_dir }}\\elastic-agent-{{ elastic_version }}-windows-{{ agent_arch }}.zip"
169+
170+
- name: Extract Elastic Agent
171+
win_unzip:
172+
src: "{{ win_temp_dir }}\\elastic-agent-{{ elastic_version }}-windows-{{ agent_arch }}.zip"
173+
dest: "{{ win_temp_dir }}"
174+
175+
- name: Install Elastic Agent
176+
win_shell: |
177+
cd {{ win_temp_dir }}\elastic-agent-{{ elastic_version }}-windows-{{ agent_arch }}
178+
.\elastic-agent.exe install --url={{ fleet_server }} --enrollment-token={{ enrollment_token }} --insecure -n
179+
args:
180+
creates: 'C:\Program Files\Elastic\Agent\elastic-agent.exe'
181+
182+
- name: Install auditd on Linux
183+
when: ansible_system == 'Linux'
184+
become: true
185+
become_method: sudo
186+
block:
187+
- name: Gather auditd service facts
188+
service_facts:
189+
190+
- name: Skip auditd installation if already enabled
191+
meta: end_host
192+
when: "'auditd.service' in ansible_facts.services and ansible_facts.services['auditd.service'].status == 'enabled'"
193+
194+
- name: Install auditd package
195+
package:
196+
name:
197+
- auditd
198+
- "{{ 'audispd-plugins' if ansible_distribution in ['Ubuntu', 'Debian'] else omit }}"
199+
state: present
200+
201+
- name: Download audit rules
202+
get_url:
203+
url: "{{ audit_rules_url }}"
204+
dest: /etc/audit/rules.d/audit.rules
205+
mode: "0644"
206+
207+
- name: Load audit rules
208+
shell: augenrules --load
209+
changed_when: false
210+
211+
- name: Restart auditd service
212+
service:
213+
name: auditd
214+
state: restarted
215+
216+
- name: Install Sysmon on Windows
217+
when: ansible_os_family == 'Windows'
218+
become: true
219+
become_method: runas
220+
become_user: "localuser"
221+
block:
222+
- name: Check if Sysmon64 service is running
223+
win_service:
224+
name: Sysmon64
225+
register: sysmon_service_status
226+
227+
- name: Set fact for skipping Sysmon installation
228+
set_fact:
229+
skip_sysmon_install: "{{ sysmon_service_status.exists and sysmon_service_status.state == 'running' }}"
230+
231+
- name: Skip Sysmon installation if service is running
232+
debug:
233+
msg: "Sysmon64 service is already running, skipping installation."
234+
when: skip_sysmon_install
235+
236+
- name: Install Sysmon when service is not running
237+
when: not skip_sysmon_install
238+
block:
239+
- name: Download Sysmon ZIP
240+
win_get_url:
241+
url: "{{ sysmon_url }}"
242+
dest: "{{ win_temp_dir }}\\Sysmon.zip"
243+
244+
- name: Extract Sysmon
245+
win_unzip:
246+
src: "{{ win_temp_dir }}\\Sysmon.zip"
247+
dest: "{{ win_temp_dir }}\\Sysmon"
248+
249+
- name: Download Sysmon config
250+
win_get_url:
251+
url: "{{ sysmon_config_url }}"
252+
dest: "{{ win_temp_dir }}\\Sysmon\\sysmonconfig-export.xml"
253+
254+
- name: Install Sysmon
255+
win_shell: |
256+
cd {{ win_temp_dir }}\Sysmon
257+
.\Sysmon64.exe -accepteula -i sysmonconfig-export.xml
258+
args:
259+
creates: 'HKLM:\SYSTEM\CurrentControlSet\Services\SysmonDrv'
260+
# Restart the Windows host to apply Sysmon configuration
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
- name: Install Elastic Agent (elastic)
3+
ansible.builtin.include_role:
4+
name: agents
5+
tasks_from: elastic
6+
7+
- name: Install Wazuh (wazuh)
8+
ansible.builtin.include_role:
9+
name: agents
10+
tasks_from: wazuh

0 commit comments

Comments
 (0)