Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the firewall role, the selinux role, and the certificate role from the logging role #293

Merged
merged 4 commits into from Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
72 changes: 66 additions & 6 deletions README.md
Expand Up @@ -36,7 +36,21 @@ To satisfy such requirements, logging role introduced 3 primary variables `loggi

## Requirements

This role is supported on RHEL/CentOS-7, RHEL/CentOS-8 and Fedora distributions.
This role is supported on RHEL-7+, CentOS Stream-8+ and Fedora distributions.

The role requires the `firewall` role and the `selinux` role from the
`fedora.linux_system_roles` collection, if `logging_manage_firewall`
and `logging_manage_selinux` is set to true, respectively.
(Please see also the variables in the [`Other options`](#other-options) section.)

If the `logging` is a role from the `fedora.linux_system_roles`
collection or from the Fedora RPM package, the requirement is already
satisfied.

Otherwise, please run the following command line to install the collection.
```
ansible-galaxy collection install -r meta/collection-requirements.yml
```

## Definitions

Expand Down Expand Up @@ -422,6 +436,34 @@ These variables are set in the same level of the `logging_inputs`, `logging_outp
will be uninstalled and reinstalled in order to revert back to the original
system default configuration.
- `logging_system_log_dir`: Directory where the local log output files are placed. Default to `/var/log`.
- `logging_manage_firewall`: If set to `true` and ports are found in the logging role
parameters, configure the firewall for the ports using the firewall role.
If set to `false`, the `logging role` does not manage the firewall.
Default to `false`.
NOTE: `logging_manage_firewall` is limited to *adding* ports.
It cannot be used for *removing* ports.
If you want to remove ports, you will need to use the firewall system
role directly.
- `logging_manage_selinux`: If set to `true` and ports are found in the logging role
parameters, configure the selinux for the ports using the selinux role.
If set to `false`, the `logging role` does not manage the selinux.
Default to `false`.
NOTE: `logging_manage_selinux` is limited to *adding* policy.
It cannot be used for *removing* policy.
If you want to remove policy, you will need to use the selinux system
role directly.
- `logging_certificates`: This is a `list` of `dict` in the same format as used
by the `fedora.linux_system_roles.certificate` role. Specify this variable if
you want the certificate role to generate the certificates for the logging system
configured by the logging role. With this example, `self-signed` certificate
`logging_cert.crt` is generated in `/etc/pki/tls/certs`.
Default to `[]`.
```yaml
logging_certificates:
- name: logging_cert
dns: ['localhost', 'www.example.com']
ca: self-sign
```

### Update and Delete

Expand Down Expand Up @@ -820,16 +862,34 @@ Deploying `relp input` reading logs from remote rsyslog and `remote_files output
outputs: [remote_files_output]
```

### Port and SELinux
### Port Managed by Firewall and SELinux Role

SELinux is only configured to allow sending and receiving on the following ports by default:
When a port is specified in the logging role configuration,
the firewall role is automatically included and the port
is managed by the firewalld.

The port is then configured by the selinux role and given
an appropriate syslog selinux port type depending upon the
associated TLS value.

You can verify the changes by the following command-line.

For firewall,
```
syslogd_port_t tcp 514, 20514
syslogd_port_t udp 514, 20514
firewall-cmd --list-port
```

If other ports need to be configured, you can use [linux-system-roles/selinux](https://github.com/linux-system-roles/selinux) to manage SELinux contexts.
For selinux,
```
semanage port --list | grep "syslog"
```
The newly specified port will be added to this default set.
```
syslog_tls_port_t tcp 6514, 10514
syslog_tls_port_t udp 6514, 10514
syslogd_port_t tcp 601, 20514
syslogd_port_t udp 514, 601, 20514
```

## Providers

Expand Down
17 changes: 17 additions & 0 deletions defaults/main.yml
Expand Up @@ -90,6 +90,23 @@ logging_files_template_format: ""
# Allowed values: "traditional", "syslog", or "modern"; default to "modern"
logging_forwards_template_format: ""

# If set to `true` and ports are found in the logging role parameters,
# configure the firewall for the ports using the firewall role.
logging_manage_firewall: false

# If set to `true` and ports are found in the logging role parameters,
# configure the selinux for the ports using the selinux role.
logging_manage_selinux: false

# If you want the role to generate the certificates in the logging
# configuration, specify the arguments to pass to the certificate
# system role. Here's an example.
# logging_certificates:
# - name: logging_cert
# dns: ['localhost', 'www.example.com']
# ca: self-sign
logging_certificates: []

# ansible_facts required by the role
__logging_required_facts:
- distribution
Expand Down
3 changes: 3 additions & 0 deletions meta/collection-requirements.yml
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: MIT
collections:
- fedora.linux_system_roles
7 changes: 7 additions & 0 deletions tasks/certificate.yml
@@ -0,0 +1,7 @@
---
- name: Generate certificates
include_role:
name: fedora.linux_system_roles.certificate
vars:
certificate_requests: "{{ logging_certificates }}"
when: logging_certificates | length > 0
33 changes: 33 additions & 0 deletions tasks/firewall.yml
@@ -0,0 +1,33 @@
---
- block:
- name: Initialize logging_firewall_ports
set_fact:
logging_firewall_ports: []

- name: Add tcp ports to logging_firewall_ports
set_fact:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are using set_fact, you'll need to ensure that logging_firewall_ports is empty before this task, either by resetting it before this task, or resetting it after the task that calls the firewall role

logging_firewall_ports: "{{ logging_firewall_ports |
union([{'port': item, 'state': 'enabled'}]) }}"
loop: "{{ (logging_tcp_ports + logging_tls_tcp_ports) |
map('regex_replace', '$', '/tcp') | list }}"
when: (logging_tcp_ports + logging_tls_tcp_ports) | length > 0

- name: Add udp ports to logging_firewall_ports
set_fact:
logging_firewall_ports: "{{ logging_firewall_ports |
union([{'port': item, 'state': 'enabled'}]) }}"
loop: "{{ (logging_udp_ports + logging_tls_udp_ports) |
map('regex_replace', '$', '/udp') | list }}"
when: (logging_udp_ports + logging_tls_udp_ports) | length > 0

- name: Manage firewall for specified ports
include_role:
name: fedora.linux_system_roles.firewall
vars:
firewall: "{{ logging_firewall_ports }}"
when:
- logging_firewall_ports | d([])
when:
- logging_manage_firewall | bool
- logging_tcp_ports or logging_udp_ports or
logging_tls_tcp_ports or logging_tls_udp_ports
183 changes: 183 additions & 0 deletions tasks/gather_ports.yml
@@ -0,0 +1,183 @@
---
# Initialize variables
- name: Initialize logging_tls_tcp_ports
set_fact:
logging_tls_tcp_ports: []

- name: Initialize logging_tcp_ports
set_fact:
logging_tcp_ports: []

- name: Initialize logging_tls_udp_ports
set_fact:
logging_tls_udp_ports: []

- name: Initialize logging_udp_ports
set_fact:
logging_udp_ports: []

# Gather ports configured as logging role parameters
- block:
- name: Parameter 'port' values
set_fact:
logging_tls_tcp_ports: "{{ (logging_inputs + logging_outputs) | d([]) |
selectattr('port', 'defined') |
map(attribute='port') | list }}"

- block:
- name: Parameter 'tcp_port' values (without tls)
set_fact:
logging_tcp_ports: "{{ logging_tcp_ports |
union(__tcp_ports[0] | list) }}"

- name: Parameter 'tcp_port' values (with tls)
set_fact:
logging_tls_tcp_ports: "{{ logging_tls_tcp_ports |
union(__tcp_ports[1] | list) }}"

- name: Parameter 'udp_port' values (without tls)
set_fact:
logging_udp_ports: "{{ logging_udp_ports |
union(__udp_ports[0] | list) }}"

- name: Parameter 'udp_port' values (with tls)
set_fact:
logging_tls_udp_ports: "{{ logging_tls_udp_ports |
union(__udp_ports[1] | list) }}"

- name: Parameter 'server_port' values (without tls)
set_fact:
logging_tcp_ports: "{{ logging_tcp_ports |
union(__server_ports[0] | list) }}"

- name: Parameter 'server_port' values (with tls)
set_fact:
logging_tls_tcp_ports: "{{ logging_tls_tcp_ports |
union(__server_ports[1] | list) }}"
vars:
__tcp_outputs: "{{ logging_outputs | d([]) |
selectattr('tcp_port', 'defined') }}"
__tcp_ports: |
{% set tcp_ports = [] %}
{% set tls_tcp_ports = [] %}
{% for output in __tcp_outputs %}
{% if output.tcp_port is defined %}
{% if output.tls is defined %}
{% if output.tls -%}
{% set _ = tls_tcp_ports.append(output.tcp_port) %}
{% else -%}
{% set _ = tcp_ports.append(output.tcp_port) %}
{%- endif %}
{% else -%}
{% set _ = tcp_ports.append(output.tcp_port) %}
{%- endif %}
{%- endif %}
{% endfor %}
{% set both = [tcp_ports, tls_tcp_ports] %}
{{ both }}
__udp_outputs: "{{ logging_outputs | d([]) |
selectattr('udp_port', 'defined') }}"
__udp_ports: |
{% set udp_ports = [] %}
{% set tls_udp_ports = [] %}
{% for output in __udp_outputs %}
{% if output.udp_port is defined %}
{% if output.tls is defined %}
{% if output.tls -%}
{% set _ = tls_udp_ports.append(output.udp_port) %}
{% else -%}
{% set _ = udp_ports.append(output.udp_port) %}
{%- endif %}
{% else -%}
{% set _ = udp_ports.append(output.udp_port) %}
{%- endif %}
{%- endif %}
{% endfor %}
{% set both = [udp_ports, tls_udp_ports] %}
{{ both }}
__server_outputs: "{{ logging_outputs | d([]) |
selectattr('server_port', 'defined') }}"
__server_ports: |
{% set server_ports = [] %}
{% set server_tls_ports = [] %}
{% for output in __server_outputs %}
{% if output.server_port is defined %}
{% if output.tls is defined %}
{% if output.tls -%}
{% set _ = server_tls_ports.append(output.server_port) %}
{% else -%}
{% set _ = server_ports.append(output.server_port) %}
{%- endif %}
{% else -%}
{% set _ = server_tls_ports.append(output.server_port) %}
{%- endif %}
{%- endif %}
{% endfor %}
{% set both = [server_ports, server_tls_ports] %}
{{ both }}

- block:
- name: Parameter 'tcp_ports' values (without tls)
set_fact:
logging_tcp_ports: "{{ logging_tcp_ports |
union(__tcp_ports[0]) | list | flatten }}"

- name: Parameter 'tcp_ports' values (with tls)
set_fact:
logging_tls_tcp_ports: "{{ logging_tls_tcp_ports |
union(__tcp_ports[1]) |
list | flatten }}"

- name: Parameter 'udp_ports' values (without tls)
set_fact:
logging_udp_ports: "{{ logging_udp_ports |
union(__udp_ports[0])| list | flatten }}"

- name: Parameter 'udp_ports' values (with tls)
set_fact:
logging_tls_udp_ports: "{{ logging_tls_udp_ports |
union(__udp_ports[1]) |
list | flatten }}"
vars:
__tcp_inputs: "{{ logging_inputs | d([]) |
selectattr('tcp_ports', 'defined') }}"
__tcp_ports: |
{% set tcp_ports = [] %}
{% set tls_tcp_ports = [] %}
{% for input in __tcp_inputs %}
{% if input.tcp_ports is defined %}
{% if input.tls is defined %}
{% if input.tls -%}
{% set _ = tls_tcp_ports.append(input.tcp_ports) %}
{% else -%}
{% set _ = tcp_ports.append(input.tcp_ports) %}
{%- endif %}
{% else -%}
{% set _ = tcp_ports.append(input.tcp_ports) %}
{%- endif %}
{%- endif %}
{% endfor %}
{% set both = [tcp_ports, tls_tcp_ports] %}
{{ both }}
__udp_inputs: "{{ logging_inputs | d([]) |
selectattr('udp_port', 'defined') }}"
__udp_ports: |
{% set udp_ports = [] %}
{% set tls_udp_ports = [] %}
{% for input in __udp_inputs %}
{% if input.udp_ports is defined %}
{% if input.tls is defined %}
{% if input.tls -%}
{% set _ = tls_udp_ports.append(input.udp_ports) %}
{% else -%}
{% set _ = udp_ports.append(input.udp_ports) %}
{%- endif %}
{% else -%}
{% set _ = udp_ports.append(input.udp_ports) %}
{%- endif %}
{%- endif %}
{% endfor %}
{% set both = [udp_ports, tls_udp_ports] %}
{{ both }}
when:
- (logging_manage_firewall | bool) or (logging_manage_selinux | bool)
16 changes: 15 additions & 1 deletion tasks/main.yml
Expand Up @@ -47,7 +47,21 @@
length != item.inputs | length
vars:
__logging_input_names: "{{ logging_inputs |
map(attribute='name') | list }}"
map(attribute='name') | list }}"

# Manage firewall for the ports configured as logging role parameters
- name: Gather ports specified in the logging_inputs and outputs vars
include_tasks: gather_ports.yml

- name: Manage firewall on the gathered ports
include_tasks: firewall.yml

- name: Manage selinux on the gathered ports
include_tasks: selinux.yml

# Configure certificates
- name: Generate certificates
include_tasks: certificate.yml

- block:
- name: Re-read facts after adding custom fact
Expand Down