Skip to content

Commit

Permalink
self-signed TLS rsyslog client and server
Browse files Browse the repository at this point in the history
  • Loading branch information
bbaassssiiee committed Mar 8, 2024
1 parent 5ffa9e9 commit 620dae1
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 32 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vscode
molecule/default/files/
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,11 @@
## Ansible role to configure rsyslog in a C2S compliant way.
- Includes CIS benchmark verification with Molecule.
- Includes an end-to-end test with a client and server docker network.
- Configures client and server
- Configures client and server with self-signed
- Logs remote machines in their own directory

## TLS

- the `molecule/default/prepare.yml` playbook generates a self-signed cert for testing.
- define `syslog_cert` as the basename of your certificate, the role assumes `.crt` as file extension.
- place the CA or self-signed certificate in the files directory next to your playbook.
17 changes: 15 additions & 2 deletions defaults/main.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
---

# CIS 4.2.1.6 Ensure remote logging is configured
# Define loghost address and define inventory group
#
# [loghost]
# syslog_host: '127.0.0.1'

# default syslog port
syslog_port: 514
syslog_tls: 'off'
syslog_tls_port: 6514
syslog_tls: 'on'

# other configs will be deleted
rsyslog_allowed_configs:
Expand All @@ -16,4 +17,16 @@ rsyslog_allowed_configs:
- /etc/rsyslog.d/21-cloudinit.conf
- /etc/rsyslog.conf

# See `man 5 journald.conf`
journald_configs:
Compress: 'yes'
ForwardToConsole: 'no'
ForwardToSyslog: 'yes'
MaxFileSec: 1day
MaxLevelStore: notice
MaxLevelSyslog: warning
Storage: persistent
SystemMaxFileSize: 100M
RateLimitBurst: 20000
RateLimitIntervalSec: 10s
...
3 changes: 1 addition & 2 deletions molecule/default/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
hosts: all
vars:
this_role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
syslog_host: '10.16.0.10'
syslog_tls: 'off'
syslog_cert: rsyslog-server

tasks:
- name: "Include {{ this_role }}"
Expand Down
2 changes: 1 addition & 1 deletion molecule/default/molecule.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ platforms:
- name: "syslog"
ipv4_address: '10.16.0.10'
published_ports:
- 127.0.0.1:9514:514
- 127.0.0.1:6514:6514
groups:
- loghost
tmpfs:
Expand Down
49 changes: 49 additions & 0 deletions molecule/default/prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
- name: Prepare directory
hosts: localhost
connection: local
become: false
vars:
out_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/molecule/default/files"
tasks:
- name: Create files directory for testing
ansible.builtin.file:
path: "{{ out_dir }}"
state: directory
mode: '0700'

- name: Prepare TLS certificates
hosts: loghost
vars:
syslog_cert: "{{ inventory_hostname }}"
out_dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/molecule/default/files"
key_dir: /etc/pki/tls/private
crt_dir: /etc/pki/tls/certs
tasks:
- name: Generate certificate
ansible.builtin.command:
argv:
- openssl
- req
- -x509
- -nodes
- -days
- 7
- -newkey
- rsa:4096
- -keyout
- "{{ key_dir }}/{{ syslog_cert }}.key"
- -out
- "{{ crt_dir }}/{{ syslog_cert }}.crt"
- -subj
- "/C=US/ST=Virginia/L=Langley/O=CIA/OU=Wire Tapping/CN={{ inventory_hostname }}"
creates: "{{ crt_dir }}/{{ syslog_cert }}.crt"

- name: Fetch TLS certificate
ansible.builtin.fetch:
src: "{{ crt_dir }}/{{ syslog_cert }}.crt"
flat: true
dest: "{{ out_dir }}/"
mode: '0644'

...
34 changes: 27 additions & 7 deletions molecule/default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,36 @@

- name: Verify E2E result
hosts: rsyslog-server
gather_facts: false

tasks:
- name: Collect the log on server
ansible.builtin.command: cat /var/log/remotes
changed_when: false
register: remote_log
- name: Gather service facts
ansible.builtin.service_facts:

- name: Search the remote log to assert events are logged
- name: Ensure rsyslog service is running
ansible.builtin.assert:
quiet: true
that:
- remote_log.stdout_lines is search('sudo')
- remote_log.stdout_lines is search('useradd')
- ansible_facts.services['rsyslog.service'].state == 'running'

- name: Search for errors on rsyslog server
ansible.builtin.shell: set -o pipefail; grep rsyslog /var/log/messages | grep error | grep -v ansible.legacy.command
changed_when: false
register: remote_log
failed_when: false

- name: Display the errors, fail if any
ansible.builtin.debug:
msg: "{{ remote_log.stdout_lines }}"
failed_when: remote_log.stdout_lines is search('error')

- name: Collect the remote secure log on server
ansible.builtin.command: cat /var/log/remote/rsyslog-client/secure
changed_when: false
register: remote_log

- name: Display the log and assert useradd is logged
ansible.builtin.debug:
msg: "{{ remote_log.stdout_lines }}"
failed_when: remote_log.stdout_lines is not search('useradd')
...
34 changes: 29 additions & 5 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
---
- name: Set the syslog_host if group loghost exists
when:
- groups['loghost'] is defined
ansible.builtin.set_fact:
syslog_host: "{{ groups['loghost'][0] }}"

- name: CIS 4.2.1.1 Ensure rsyslog is installed
ansible.builtin.yum:
Expand Down Expand Up @@ -35,7 +40,7 @@
label: "{{ file.path }}"

- name: CIS 4.2.1.6 Ensure remote logging is configured
when: inventory_hostname not in groups['loghost']
when: groups['loghost'] is not defined or inventory_hostname not in groups['loghost']
ansible.builtin.template:
src: "{{ item | basename }}.j2"
dest: "{{ item }}"
Expand All @@ -46,7 +51,7 @@
notify: Restart rsyslog

- name: CIS 4.2.1.5 Ensure logging is configured
when: inventory_hostname not in groups['loghost']
when: groups['loghost'] is not defined or inventory_hostname not in groups['loghost']
ansible.builtin.template:
src: rsyslog.conf.j2
dest: /etc/rsyslog.conf
Expand Down Expand Up @@ -74,7 +79,9 @@
when: item.path not in rsyslog_allowed_configs

- name: Manage /etc/rsyslog.conf file for remote loghost
when: inventory_hostname in groups['loghost']
when:
- groups['loghost'] is defined
- inventory_hostname in groups['loghost']
ansible.builtin.template:
src: rsyslog.loghost.conf.j2
dest: /etc/rsyslog.conf
Expand All @@ -85,9 +92,9 @@
notify: Restart rsyslog

- name: Update TLS certificate
when: syslog_ca_cert is defined
when: syslog_cert is defined
ansible.builtin.copy:
src: "{{ syslog_ca_cert }}"
src: "{{ syslog_cert }}.crt"
dest: /etc/pki/tls/certs/
owner: root
group: root
Expand All @@ -104,4 +111,21 @@
- system.conf
notify: Reload systemd

# CIS 4.2.1.3 Ensure journald is configured to send logs to rsyslog
- name: Ensure journald is configured to send logs to rsyslog
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: '.*ForwardToSyslog=.*'
line: 'ForwardToSyslog=yes'
state: present
notify: Restart rsyslog

- name: Ensure journald is configured
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: ".*{{ item.key }}=.*"
line: "{{ item.key }}={{ item.value }}"
state: present
with_dict: "{{ journald_configs }}"
notify: Restart rsyslog
...
2 changes: 1 addition & 1 deletion templates/01_modules.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ module(load="imjournal"
)
# provides RELP output module with TLS support
module(load="omrelp"
tls.tlslib="gnutls"
tls.tlslib="openssl"
)
14 changes: 8 additions & 6 deletions templates/02_rules.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,16 @@ ruleset(
local4.*,local5.* -/var/log/localmessages
local6.* -/var/log/localmessages
local7.* /var/log/boot.log
# CIS 4.2.1.6 Ensure rsyslog is configured to send logs to a remote log host
{% if syslog_host is defined %}
auth,authpriv.* action(type="omrelp" target="{{ syslog_host }}" port="{{ syslog_port }}"
{% if syslog_tls is defined and syslog_ca_cert is defined %}
tls="{{ syslog_tls }}"
tls.caCert="/etc/pki/tls/certs/{{ syslog_ca_cert }}"
{% if syslog_tls == 'on' and syslog_cert is defined %}
auth,authpriv.* action(type="omrelp" target="{{ syslog_host }}" port="{{ syslog_tls_port }}"
tls="on"
tls.cacert="/etc/pki/tls/certs/{{ syslog_cert }}.crt"
tls.authMode="fingerprint"
{% endif %}
{% else %}
auth,authpriv.* action(type="omrelp" target="{{ syslog_host }}" port="{{ syslog_port }}"
tls="off"
{% endif %}
template="SecureForwardFormat"
action.resumeRetryCount="-1"
queue.type="linkedList"
Expand Down
Loading

0 comments on commit 620dae1

Please sign in to comment.