Skip to content

Commit

Permalink
Creates "ossec-register" common workflow
Browse files Browse the repository at this point in the history
In order to support cross-host variable delegation, we'll need the play
to target *both* the Application and Monitor servers. We can then
dynamically open ports on the firewall as necessary in order to support
registration.

Reuses @msheiny's `iptables` Ansible module implementation, which is
remarkably clean. Love the state=absent functionality.

Rather than use `delegate_to`, we target both hosts and use the boolean
vars `ossec_is_server` and `ossec_is_client` (both defaulting to False)
in order to determine which host the task should execute on. For some
tasks, we want both hosts to execute, thus the combined play target.

Uses a rather gnarly hostvars-based retrieval to map a registered var
result across both hosts, ensuring the same value is accessible to both
play hosts, to coordinate the firewall rule management. Left an in-line
comment to guide future maintainers.

Removes most tags because we can better handle tasks at the import task
level now, which was difficult to do before because the logic was so
spaghetti.
  • Loading branch information
Conor Schaefer authored and emkll committed Jan 22, 2018
1 parent d1b0c31 commit 58b29c8
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ authd_iprules:
match: state
cstate: "ESTABLISHED,RELATED"
jump: ACCEPT

# Declare Application Server as OSSEC agent role.
ossec_is_client: yes
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@ authd_iprules:
match: state
cstate: "ESTABLISHED,RELATED"
jump: ACCEPT

# Declare Monitor Server as OSSEC server role.
ossec_is_server: yes
Original file line number Diff line number Diff line change
Expand Up @@ -6,59 +6,3 @@
when: not install_local_packages
tags:
- apt

- name: Add firewall exemption for OSSEC agent registration (both servers)
iptables:
chain: "{{ item[0].chain }}"
destination: "{{ item[0].dest|default(omit) }}"
destination_port: "{{ item[0].dest_port|default(omit) }}"
protocol: "{{ item[0].proto }}"
ctstate: "{{ item[0].cstate }}"
jump: "{{ item[0].jump }}"
match: "{{ item[0].match }}"
source: "{{ item[0].source|default(omit) }}"
source_port: "{{ item[0].source_port|default(omit) }}"
state: present
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ authd_iprules }}"
- "{{ groups['all'] }}"
when: not ossec_agent_already_registered
tags:
- iptables
- ossec_auth

- debug: var="{{ groups['securedrop_monitor_server'] + groups['securedrop_application_server'] }}"

- name: Register OSSEC agent.
command: /var/ossec/bin/agent-auth -m {{ monitor_ip }} -p 1515 -A {{ app_hostname }}
when: not ossec_agent_already_registered
tags:
- ossec_auth

# If the OSSEC agent auth iptable rule exemptions are in place remove them and
# restart OSSEC. This order does matter. The app server's
# ossec agent needs to restart to load the imported cert from authd and
# connect to the ossec server. The monitor server's OSSEC server needs to
# restart after the agent connects to correctly display the agent status.
- name: Remove firewall exemption for OSSEC agent registration.
iptables:
chain: "{{ item[0].chain }}"
destination: "{{ item[0].dest|default(omit) }}"
destination_port: "{{ item[0].dest_port|default(omit) }}"
protocol: "{{ item[0].proto }}"
ctstate: "{{ item[0].cstate }}"
jump: "{{ item[0].jump }}"
match: "{{ item[0].match }}"
source: "{{ item[0].source|default(omit) }}"
source_port: "{{ item[0].source_port|default(omit) }}"
state: present
delegate_to: "{{ item[1] }}"
with_nested:
- "{{ authd_iprules }}"
- "{{ groups['securedrop_monitor_server'] + groups['securedrop_application_server'] }}"
when: not ossec_agent_already_registered
notify: restart ossec
tags:
- iptables
- ossec_auth

This file was deleted.

2 changes: 0 additions & 2 deletions install_files/ansible-base/roles/ossec-agent/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
---
- include: agent_config.yml

- include: cleanup_authd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
# By default, no roles are assigned. Via group_vars or otherwise,
# identify which hosts should act as server or client. The role
# will execute tasks conditionally based on the var values.
ossec_is_server: False
ossec_is_client: False
98 changes: 98 additions & 0 deletions install_files/ansible-base/roles/ossec-register/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
- name: Check whether Application Server is registered as OSSEC agent.
command: /var/ossec/bin/list_agents -a
register: ossec_list_agents_result
# Read-only task, so don't report changed
when: ossec_is_server
changed_when: false

# Gnarly vars retrieval logic in this task. The "register" action above applies
# only to the Monitor Server, so the Application Server won't be able to access
# the value (and the play will fail as a result). So on both hosts, let's look up
# the registered value by referencing the hostvars for the Monitor Server, then
# copy the result to a more conveniently named fact on both hosts.
- name: Set host fact for OSSEC registration state.
set_fact:
ossec_agent_already_registered: "{{ hostvars[groups.securedrop_monitor_server.0].ossec_list_agents_result.stdout == app_hostname +'-'+app_ip+' is available.' }}"
# No "delegate_to", so that *both* hosts are aware of registration stauts via set_fact.

- name: Start authd.
shell: /var/ossec/bin/ossec-authd -i {{ app_ip }} -p 1515 >/dev/null 2>&1 &
async: 0
poll: 0
when:
- ossec_is_server
- not ossec_agent_already_registered
notify: restart ossec-server

- name: Add firewall exemption for OSSEC agent registration (both servers)
iptables:
chain: "{{ item.chain }}"
destination: "{{ item.dest|default(omit) }}"
destination_port: "{{ item.dest_port|default(omit) }}"
protocol: "{{ item.proto }}"
ctstate: "{{ item.cstate }}"
jump: "{{ item.jump }}"
match: "{{ item.match }}"
source: "{{ item.source|default(omit) }}"
source_port: "{{ item.source_port|default(omit) }}"
state: present
# No "delegate_to", since servers will have different group_vars.
with_items: "{{ authd_iprules }}"
when: not ossec_agent_already_registered

- name: Register OSSEC agent.
command: /var/ossec/bin/agent-auth -m {{ monitor_ip }} -p 1515 -A {{ app_hostname }}
when: not ossec_agent_already_registered

# If the OSSEC agent auth iptable rule exemptions are in place remove them and
# restart OSSEC. This order does matter. The app server's
# ossec agent needs to restart to load the imported cert from authd and
# connect to the ossec server. The monitor server's OSSEC server needs to
# restart after the agent connects to correctly display the agent status.
- name: Remove firewall exemption for OSSEC agent registration.
iptables:
chain: "{{ item.chain }}"
destination: "{{ item.dest|default(omit) }}"
destination_port: "{{ item.dest_port|default(omit) }}"
protocol: "{{ item.proto }}"
ctstate: "{{ item.cstate }}"
jump: "{{ item.jump }}"
match: "{{ item.match }}"
source: "{{ item.source|default(omit) }}"
source_port: "{{ item.source_port|default(omit) }}"
state: absent
with_items: "{{ authd_iprules }}"
# No conditional, to force state=absent in all cases.
notify: restart ossec

# Contact the OSSEC server and ensure that the authd process
# is not running. Declaring these as tasks rather than handlers
# to ensure that the the cleanup happens every time, in case
# authd was somehow left running, e.g. if playbook was interrupted.
- name: Check if authd process is running on Monitor Server.
command: pgrep ossec-authd
# pgrep returns 1 if no process is found, so ignore that error.
# This is essentially a read-only task, with the subsequent task
# potentially making changes
failed_when: false
changed_when: false
register: ossec_authd_running_check
when: ossec_is_server

- name: Kill authd process (if running) on Monitor Server.
# This should work using the pattern to grep for in the output of ps per
# http://docs.ansible.com/service_module.html
# Currently getting an error saying
# failed: [mon-staging] => {"failed": true}
# msg: service not found: ossec-authd
# service: name=ossec-authd pattern=/var/ossec/bin/ossec-authd state=started
command: kill {{ item }}
# It's technically possible that pgrep will return more than one PID.
# Let's be careful and kill each process, even though in most cases there
# will be only one, if any.
with_items: "{{ ossec_authd_running_check.stdout_lines }}"
when:
- ossec_is_server
- ossec_authd_running_check.rc == 0
- ossec_authd_running_check.stdout != ""
43 changes: 0 additions & 43 deletions install_files/ansible-base/roles/ossec-server/tasks/authd.yml

This file was deleted.

63 changes: 58 additions & 5 deletions install_files/ansible-base/roles/ossec-server/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,60 @@
---
# This needs to be run after seting the etc hosts or else will get a hostname
# error change these to lineinfile module to work with the exemptions
- include: mon_configure_ossec_gpg_alerts.yml
- name: Install OSSEC manager package.
apt:
name: securedrop-ossec-server
state: present
update_cache: yes
cache_valid_time: 3600
when: not install_local_packages
tags:
- apt

- include: authd.yml
tags: authd
- name: Copy the OSSEC GPG public key for sending encrypted alerts.
copy:
src: "{{ ossec_alert_gpg_public_key }}"
dest: /var/ossec
tags:
- gpg

- name: Add the OSSEC GPG public key to the OSSEC manager keyring.
# multiline format for command module, since this is a long command
command: >
gpg
--homedir /var/ossec/.gnupg
--import /var/ossec/{{ ossec_alert_gpg_public_key }}
become: yes
become_user: "{{ ossec_group }}"
register: add_ossec_gpg_key_result
changed_when: "'imported: 1' in add_ossec_gpg_key_result.stderr"
tags:
- gpg

- name: Copy script for sending GPG-encrypted OSSEC alerts.
template:
src: send_encrypted_alarm.sh
dest: /var/ossec/send_encrypted_alarm.sh
mode: "0550"
owner: root
group: ossec
tags:
- procmail
- permissions

- name: Create OSSEC manager SSL key.
command: openssl genrsa -out /var/ossec/etc/sslmanager.key 4096
args:
creates: /var/ossec/etc/sslmanager.key
when: ossec_agent_already_registered == false
tags:
- ossec_auth

- name: Create OSSEC manager SSL certificate.
command: >
openssl req -new -x509 -batch
-subj "/CA=AU/ST=Some-State/locality=city/O=Internet Widgits Pty Ltd/commonName=mon/organizationUnitName=section/emailAddress=admin@localhost"
-key /var/ossec/etc/sslmanager.key -out /var/ossec/etc/sslmanager.cert -days 365
args:
creates: /var/ossec/etc/sslmanager.cert
when: ossec_agent_already_registered == false
tags:
- ossec_auth

This file was deleted.

0 comments on commit 58b29c8

Please sign in to comment.