How to deploy wazuh-agent with Ansible

Note: For windows ports 5986 and 1515 must be open along with configureansiblescript.ps(powershell script) must have been setup for ansible to be able to communicate and deploy the wazuh-agent to windows machines.

In order to deploy the wazuh-agent to a large group of servers that span windows, ubuntu, centos type distros with ansible. Some tweaks need to be made on the wazuh manager and ansible server

This is done on the wazuh-manager server

/var/ossec/etc/ossec.conf – inside this file the following need to be edited for registrations to have the proper ip of the hosts being registered

<auth>
<disabled>no</disabled>
<port>1515</port>
<use_source_ip>yes</use_source_ip>
<force_insert>yes</force_insert>
<force_time>0</force_time>
<purge>yes</purge>
<use_password>yes</use_password>
<limit_maxagents>no</limit_maxagents>
<ciphers>HIGH:!ADH:!EXP:!MD5:RC4:3DES:!CAMELLIA:@STRENGTH</ciphers>
<!– <ssl_agent_ca></ssl_agent_ca> –>
<ssl_verify_host>no</ssl_verify_host>
<ssl_manager_cert>/var/ossec/etc/sslmanager.cert</ssl_manager_cert>
<ssl_manager_key>/var/ossec/etc/sslmanager.key</ssl_manager_key>
<ssl_auto_negotiate>yes</ssl_auto_negotiate>
</auth>

To enable authd on wazuh-manager

  • /var/ossec/bin/ossec-control enable authd

Now on your ansible server

  1. You need to download the git repository with ansible playbooks for wazuh
  2. git clone https://github.com/wazuh/wazuh-ansible <–do this in home directory /home/nicktailor
  3. Next you will see them setup as roles that you would call in your playbook

  • drwxr-x— 7 root root 97 Sep 21 13:45 ansible-role-elasticsearch
  • drwxr-x— 8 root root 110 Sep 21 13:45 ansible-role-filebeat
  • drwxr-x— 7 root root 97 Sep 21 13:45 ansible-role-kibana
  • drwxr-x— 7 root root 97 Sep 21 13:45 ansible-role-logstash
  • drwxr-x— 8 root root 109 Sep 21 13:45 ansible-wazuh-agent<– this is the role one you want to copy to /etc/ansible/roles
  • drwxr-x— 8 root root 167 Sep 21 13:45 ansible-wazuh-manager
  • drwxr-x— 8 root root 163 Sep 21 13:45 .git
  • -rw-r—– 1 root root 163 Sep 21 13:45 .gitignore
  • drwxr-x— 2 root root 22 Sep 21 13:45 meta
  • -rw-r—– 1 root root 1060 Sep 21 13:45 README.md
  • -rw-r—– 1 root root 350 Sep 21 13:45 wazuh-agent.yml<–this is the playbook you want to copy to /etc/ansible/playbooks
  • -rw-r—– 1 root root 460 Sep 21 13:45 wazuh-elastic_stack-distributed.yml
  • -rw-r—– 1 root root 322 Sep 21 13:45 wazuh-elastic_stack-single.yml
  • -rw-r—– 1 root root 121 Sep 21 13:45 wazuh-elastic.yml
  • -rw-r—– 1 root root 107 Sep 21 13:45 wazuh-kibana.yml
  • -rw-r—– 1 root root 106 Sep 21 13:45 wazuh-logstash.yml
  • -rw-r—– 1 root root 159 Sep 21 13:45 wazuh-manager.yml
  1. You need to copy the role over to your ansible roles directory
    1. cp -r ansible-wazuh-manger /etc/ansible/roles
  2. next copy the playbook to your playbook directory
    1. cp wazuh-agent.yml /etc/ansible/playbooks
  3. Next you need to update the following file with the ip address of the wazuh-manager
    1. /etc/ansible/roles/ansible-wazuh-agent/defaults# cat main.yml

wazuh_managers:
– address: 127.0.0.1<—-update with manager ip
port: 1514
protocol: tcp
api_port: 55000
api_proto: ‘http’
api_user: null
wazuh_profile: null
wazuh_auto_restart: ‘yes’
wazuh_agent_authd:
enable: true
port: 1515
Next section in main.yml
openscap:
disable: ‘no’
timeout: 1800
interval: ‘1d’
scan_on_start: ‘yes’

  1. d the password you setup on the wazuh-manager for the api user to the ansible authd section:
    1. /etc/ansible/roles/ansible-wazuh-agent/vars# cat authd_pass.yml

# We recommend the use of Ansible Vault to protect Wazuh, api, agentless and authd credentials.

authd_pass: ‘password’

  1. Save the file authd_pass.yml
  2. Next you need to have the hosts listed in your hosts file in ansible /etc/ansible/hosts-whatever
    1. Not that for windows machines you will need to ensure the are also listed in /etc/hosts. The reason is authd using Kerberos has issues sometimes with dns resolution when attempting open a connection via winrm on port 5986.
  3. Next you must list your hosts in the ansible host file as such
    1. /etc/ansible/hosts-linux
      1. [linux]
      2. Server1.mcs.local
  • Server2.mcs.local
  1. /etc/ansible/hosts-windows
    1. [windows]
    2. Server1.mcs.local
  • Server2.mcs.local

Test communication to windows machines via ansible run the following from /etc/ansible

  • ansible windows -i /etc/ansible/hosts-windows -m ping
  • ansible gsdprdint -i /etc/ansible/hosts-linux -m ping –vault-password-file /etc/ansible/vaultpw.txt -u ansible-nickt -k -K

How to run he playbook on linux machines, run from /etc/ansible/playbook/

  • ansible-playbook linux -i /etc/ansible/hosts–linux /etc/ansible/playbooks/wazuh-agent.yml –vault-password-file /etc/ansible/vaultpw.txt -u ansible-nickt -k -K

How to run playbook on windows

  • ansible-playbook -i /etc/ansible/hosts-windows /etc/ansible/playbooks/wazuh-agent.yml –vault-password-file /etc/ansible/vaultpw.txt -u ansible-nickt -k -K

Ansible playbook-roles-tasks breakdown

:/etc/ansible/playbooks# cat wazuh-agent.ymlplaybook file
– hosts: all:!wazuh-manager
roles:
– ansible-wazuh-agentroles that is called
vars:
wazuh_managers:
– address: 127.0.0.1
port: 1514
protocol: udp
api_port: 55000
api_proto: ‘http’
api_user: ansible
wazuh_agent_authd:
enable: true
port: 1515
ssl_agent_ca: null
ssl_auto_negotiate: ‘no

Roles: ansible-wazuh-agent
:/etc/ansible/roles/ansible-wazuh-agent/tasks#
cat Linux.yml

– import_tasks: “RedHat.yml”
when: ansible_os_family == “RedHat”

– import_tasks: “Debian.yml”
when: ansible_os_family == “Debian”

– name: Linux | Install wazuh-agent
become: yes
package: name=wazuh-agent state=present
async: 90
poll: 15
tags:
– init

– name: Linux | Check if client.keys exists
become: yes
stat: path=/var/ossec/etc/client.keys
register: check_keys
tags:
– config

This task I added. If the client.keys file exists the registration on linux simply skips over when the playbook runs. You may want to disable this later, however when deploying to new machines probably best to have it active

– name: empty client key file
become: yes
command: rm -f /var/ossec/etc/client.keys
command: touch /var/ossec/etc/client.keys

– name: Linux | Agent registration via authd
block:
– name: Retrieving authd Credentials
include_vars: authd_pass.yml
tags:
– config
– authd

– name: Copy CA, SSL key and cert for authd
copy:
src: “{{ item }}”
dest: “/var/ossec/etc/{{ item | basename }}”
mode: 0644
with_items:
– “{{ wazuh_agent_authd.ssl_agent_ca }}”
– “{{ wazuh_agent_authd.ssl_agent_cert }}”
– “{{ wazuh_agent_authd.ssl_agent_key }}”
tags:
– config
– authd
when:
– wazuh_agent_authd.ssl_agent_ca is not none

This section below is the most important section as this what registers the machine to wazuh, if this section is skipped its usually due to client.keys file. I have made adjustments from the original git repository as I found it had some issues.

– name: Linux | Register agent (via authd)
shell: >
/var/ossec/bin/agent-auth
-m {{ wazuh_managers.0.address }}
-p {{ wazuh_agent_authd.port }}
{% if authd_pass is defined %}-P {{ authd_pass }}{% endif %}
{% if wazuh_agent_authd.ssl_agent_ca is not none %}
-v “/var/ossec/etc/{{ wazuh_agent_authd.ssl_agent_ca | basename }}”
-x “/var/ossec/etc/{{ wazuh_agent_authd.ssl_agent_cert | basename }}”
-k “/var/ossec/etc/{{ wazuh_agent_authd.ssl_agent_key | basename }}”
{% endif %}
{% if wazuh_agent_authd.ssl_auto_negotiate == ‘yes’ %}-a{% endif %}
become: yes
register: agent_auth_output
when:
– check_keys.stat.size == 0
– wazuh_managers.0.address is not none
tags:
– config
– authd

– name: Linux | Verify agent registration
shell: echo {{ agent_auth_output }} | grep “Valid key created”
when:
– check_keys.stat.size == 0
– wazuh_managers.0.address is not none
tags:
– config
– authd

when: wazuh_agent_authd.enable == true

– name: Linux | Agent registration via rest-API
block:

– name: Retrieving rest-API Credentials
include_vars: api_pass.yml
tags:
– config
– api

– name: Linux | Create the agent key via rest-API
uri:
url: “{{ wazuh_managers.0.api_proto }}://{{ wazuh_managers.0.address }}:{{ wazuh_managers.0.api_port }}/agents/”
validate_certs: no
method: POST
body: {“name”:”{{ inventory_hostname }}”}
body_format: json
status_code: 200
headers:
Content-Type: “application/json”
user: “{{ wazuh_managers.0.api_user }}”
password: “{{ api_pass }}”
register: newagent_api
changed_when: newagent_api.json.error == 0
when:
– check_keys.stat.size == 0
– wazuh_managers.0.address is not none
become: no
tags:
– config
– api

– name: Linux | Retieve new agent data via rest-API
uri:
url: “{{ wazuh_managers.0.api_proto }}://{{ wazuh_managers.0.address }}:{{ wazuh_managers.0.api_port }}/agents/{{ newagent_api.json.data.id }}”
validate_certs: no
method: GET
return_content: yes
user: “{{ wazuh_managers.0.api_user }}”
password: “{{ api_pass }}”
when:
– check_keys.stat.size == 0
– wazuh_managers.0.address is not none
– newagent_api.json.error == 0
register: newagentdata_api
delegate_to: localhost
become: no
tags:
– config
– api

– name: Linux | Register agent (via rest-API)
command: /var/ossec/bin/manage_agents
environment:
OSSEC_ACTION: i
OSSEC_AGENT_NAME: ‘{{ newagentdata_api.json.data.name }}’
OSSEC_AGENT_IP: ‘{{ newagentdata_api.json.data.ip }}’
OSSEC_AGENT_ID: ‘{{ newagent_api.json.data.id }}’
OSSEC_AGENT_KEY: ‘{{ newagent_api.json.data.key }}’
OSSEC_ACTION_CONFIRMED: y
register: manage_agents_output
when:
– check_keys.stat.size == 0
– wazuh_managers.0.address is not none
– newagent_api.changed
tags:
– config
– api
notify: restart wazuh-agent

when: wazuh_agent_authd.enable == false

– name: Linux | Vuls integration deploy (runs in background, can take a while)
command: /var/ossec/wodles/vuls/deploy_vuls.sh {{ ansible_distribution|lower }} {{ ansible_distribution_major_version|int }}
args:
creates: /var/ossec/wodles/vuls/config.toml
async: 3600
poll: 0
when:
– wazuh_agent_config.vuls.disable != ‘yes’
– ansible_distribution == ‘Redhat’ or ansible_distribution == ‘CentOS’ or ansible_distribution == ‘Ubuntu’ or ansible_distribution == ‘Debian’ or ansible_distribution == ‘Oracle’
tags:
– init

– name: Linux | Installing agent configuration (ossec.conf)
become: yes
template: src=var-ossec-etc-ossec-agent.conf.j2
dest=/var/ossec/etc/ossec.conf
owner=root
group=ossec
mode=0644
notify: restart wazuh-agent
tags:
– init
– config

– name: Linux | Ensure Wazuh Agent service is restarted and enabled
become: yes
service:
name: wazuh-agent
enabled: yes
state: restarted

– import_tasks: “RMRedHat.yml”
when: ansible_os_family == “RedHat”

– import_tasks: “RMDebian.yml”
when: ansible_os_family == “Debian”
Windows- tasks
Note: This section only works if your ansible is configured to communicate with Windows machines. It requires that port 5986 from ansible to windows is open and then port 1515 from the window machine to the wazuh-manager is open.

Problems: When using authd and Kerberos for windows ensure you have the host name listed in /etc/hosts on the ansible server to help alleviate agent deployment issues. Its script does not seem to handle well when you have more than 5 or 6 clients at a time at least in my experience.

Either I had to rejoin the windows machines to the domain or remove the client.keys file. I have updated this task to include the task to remove the client.keys file before it check to see if it exists. You do need to play with it a bit sometimes. I have also added a section that adds the wazuh-agent as a service and restarts it upon deployment as I found it sometimes skipped this entirely.

:/etc/ansible/roles/ansible-wazuh-agent/tasks# cat Windows.yml

– name: Windows | Get current installed version
win_shell: “{{ wazuh_winagent_config.install_dir }}ossec-agent.exe -h”
args:
removes: “{{ wazuh_winagent_config.install_dir }}ossec-agent.exe”
register: agent_version
failed_when: False
changed_when: False

– name: Windows | Check Wazuh agent version installed
set_fact: correct_version=true
when:
– agent_version.stdout is defined
– wazuh_winagent_config.version in agent_version.stdout

– name: Windows | Downloading windows Wazuh agent installer
win_get_url:
dest: C:\wazuh-agent-installer.msi
url: “{{ wazuh_winagent_config.repo }}wazuh-agent-{{ wazuh_winagent_config.version }}-{{ wazuh_winagent_config.revision }}.msi”
when:
– correct_version is not defined

– name: Windows | Verify the downloaded Wazuh agent installer
win_stat:
path: C:\wazuh-agent-installer.msi
get_checksum: yes
checksum_algorithm: md5
register: installer_md5
when:
– correct_version is not defined
failed_when:
– installer_md5.stat.checksum != wazuh_winagent_config.md5

– name: Windows | Install Wazuh agent
win_package:
path: C:\wazuh-agent-installer.msi
arguments: APPLICATIONFOLDER={{ wazuh_winagent_config.install_dir }}
when:
– correct_version is not defined

This section was added. If it was present registrations would skip
– name: Remove a file, if present
win_file:
path: C:\wazuh-agent\client.keys
state: absent

This section was added for troubleshooting purposes
#- name: Touch a file (creates if not present, updates modification time if present)
# win_file:
# path: C:\wazuh-agent\client.keys
# state: touch

– name: Windows | Check if client.keys exists
win_stat: path=”{{ wazuh_winagent_config.install_dir }}client.keys”
register: check_windows_key
notify: restart wazuh-agent windows
tags:
– config

– name: Retrieving authd Credentials
include_vars: authd_pass.yml
tags:
– config

– name: Windows | Register agent
win_shell: >
{{ wazuh_winagent_config.install_dir }}agent-auth.exe
-m {{ wazuh_managers.0.address }}
-p {{ wazuh_agent_authd.port }}
{% if authd_pass is defined %}-P {{ authd_pass }}{% endif %}
args:
chdir: “{{ wazuh_winagent_config.install_dir }}”
register: agent_auth_output
notify: restart wazuh-agent windows
when:
– wazuh_agent_authd.enable == true
– check_windows_key.stat.exists == false
– wazuh_managers.0.address is not none
tags:
– config

– name: Windows | Installing agent configuration (ossec.conf)
win_template:
src: var-ossec-etc-ossec-agent.conf.j2
dest: “{{ wazuh_winagent_config.install_dir }}ossec.conf”
notify: restart wazuh-agent windows
tags:
– config

– name: Windows | Delete downloaded Wazuh agent installer file
win_file:
path: C:\wazuh-agent-installer.msi
state: absent

These section was added as the service sometimes was not created and the agent was not restarted upon deployment which resulted in a non active client In kibana
– name: Create a new service
win_service:
name: wazuh-agent
path: C:\wazuh-agent\ossec-agent.exe

– name: Windows | Wazuh-agent Restart
win_service:
name: wazuh-agent
state: restarted

Leave a Reply

Your email address will not be published. Required fields are marked *