325 lines
15 KiB
Diff
325 lines
15 KiB
Diff
|
From b72e8a48be07a1cebce8b2237d7344220678c2ec Mon Sep 17 00:00:00 2001
|
||
|
From: Noriko Hosoi <nhosoi@redhat.com>
|
||
|
Date: Fri, 16 Oct 2020 08:15:11 -0700
|
||
|
Subject: [PATCH 5/7] Logging - support property-based filters in the files and
|
||
|
forwards outputs
|
||
|
|
||
|
Adding property-based filter options to files, forwards and remote_files output.
|
||
|
A test case is added to tests_basics_files2.yml.
|
||
|
|
||
|
In addition, fixing a bug caused by a left over file from the previous tests.
|
||
|
|
||
|
Issue - https://github.com/linux-system-roles/logging/issues/179
|
||
|
|
||
|
(cherry picked from commit 6ac8f9ff680a4b0230446062f5927f5921829f80)
|
||
|
---
|
||
|
README.md | 68 ++++++++++++-------
|
||
|
roles/rsyslog/templates/output_files.j2 | 4 +-
|
||
|
roles/rsyslog/templates/output_forwards.j2 | 4 +-
|
||
|
.../rsyslog/templates/output_remote_files.j2 | 4 +-
|
||
|
tests/tests_basics_files2.yml | 40 +++++++++--
|
||
|
tests/tests_basics_forwards_cert.yml | 8 +++
|
||
|
tests/tests_basics_forwards_cert_missing.yml | 4 ++
|
||
|
tests/tests_server_conflict.yml | 8 +++
|
||
|
8 files changed, 108 insertions(+), 32 deletions(-)
|
||
|
|
||
|
diff --git a/README.md b/README.md
|
||
|
index db29dc5..4352ee7 100644
|
||
|
--- a/README.md
|
||
|
+++ b/README.md
|
||
|
@@ -180,11 +180,16 @@ This is a schematic logging configuration to show log messages from input_nameA
|
||
|
|
||
|
- `files` type - `files` output supports storing logs in the local files usually in /var/log.<br>
|
||
|
**available options**
|
||
|
- - `facility`: Facility; default to `*`.
|
||
|
- - `severity`: Severity; default to `*`.
|
||
|
- - `exclude`: Exclude list; default to none.
|
||
|
+ - `facility`: Facility in selector; default to `*`.
|
||
|
+ - `severity`: Severity in selector; default to `*`.
|
||
|
+ - `exclude`: Exclude list used in selector; default to none.
|
||
|
+ - `property`: Property in property-based filter; no default
|
||
|
+ - `prop_op`: Operation in property-based filter; In case of not `!`, put the `prop_op` value in quotes; default to `contains`
|
||
|
+ - `prop_value`: Value in property-based filter; default to `error`
|
||
|
- `path`: Path to the output file.
|
||
|
|
||
|
+ Selector options and property-based filter options are exclusive. If Property-based filter options are defined, selector options will be ignored.
|
||
|
+
|
||
|
Unless the above options are given, these local file outputs are configured.
|
||
|
```
|
||
|
kern.* /dev/console
|
||
|
@@ -199,8 +204,12 @@ This is a schematic logging configuration to show log messages from input_nameA
|
||
|
|
||
|
- `forwards` type - `forwards` output sends logs to the remote logging system over the network. This is for the client rsyslog.<br>
|
||
|
**available options**
|
||
|
- - `facility`: Facility; default to `*`.
|
||
|
- - `severity`: Severity; default to `*`.
|
||
|
+ - `facility`: Facility in selector; default to `*`.
|
||
|
+ - `severity`: Severity in selector; default to `*`.
|
||
|
+ - `exclude`: Exclude list used in selector; default to none.
|
||
|
+ - `property`: Property in property-based filter; no default
|
||
|
+ - `prop_op`: Operation in property-based filter; In case of not `!`, put the `prop_op` value in quotes; default to `contains`
|
||
|
+ - `prop_value`: Value in property-based filter; default to `error`
|
||
|
- `target`: Target host (fqdn). **Required**.
|
||
|
- `udp_port`: UDP port number. Default to `514`.
|
||
|
- `tcp_port`: TCP port number. Default to `514`.
|
||
|
@@ -208,11 +217,16 @@ This is a schematic logging configuration to show log messages from input_nameA
|
||
|
- `pki_authmode`: Specifying the default network driver authentication mode. `x509/name`, `x509/fingerprint`, `anon` is accepted. Default to `x509/name`.
|
||
|
- `permitted_server`: Hostname, IP address, fingerprint(sha1) or wildcard DNS domain of the server which this client will be allowed to connect and send logs over TLS. Default to `*.{{ logging_domain }}`
|
||
|
|
||
|
+ Selector options and property-based filter options are exclusive. If Property-based filter options are defined, selector options will be ignored.
|
||
|
+
|
||
|
- `remote_files` type - `remote_files` output stores logs to the local files per remote host and program name originated the logs.<br>
|
||
|
**available options**
|
||
|
- - `facility`: Facility; default to `*`.
|
||
|
- - `severity`: Severity; default to `*`.
|
||
|
- - `exclude`: Exclude list; default to none.
|
||
|
+ - `facility`: Facility in selector; default to `*`.
|
||
|
+ - `severity`: Severity in selector; default to `*`.
|
||
|
+ - `exclude`: Exclude list used in selector; default to none.
|
||
|
+ - `property`: Property in property-based filter; no default
|
||
|
+ - `prop_op`: Operation in property-based filter; In case of not `!`, put the `prop_op` value in quotes; default to `contains`
|
||
|
+ - `prop_value`: Value in property-based filter; default to `error`
|
||
|
- `async_writing`: If set to `true`, the files are written asynchronously. Allowed value is `true` or `false`. Default to `false`.
|
||
|
- `client_count`: Count of client logging system supported this rsyslog server. Default to `10`.
|
||
|
- `io_buffer_size`: Buffer size used to write output data. Default to `65536` bytes.
|
||
|
@@ -221,6 +235,8 @@ This is a schematic logging configuration to show log messages from input_nameA
|
||
|
`/path/to/output/dir/%HOSTNAME%/%PROGRAMNAME:::secpath-replace%.log`
|
||
|
- `remote_sub_path`: Relative path to logging_system_log_dir to store the filtered logs.
|
||
|
|
||
|
+ Selector options and property-based filter options are exclusive. If Property-based filter options are defined, selector options will be ignored.
|
||
|
+
|
||
|
if both `remote_log_path` and `remote_sub_path` are _not_ specified, the remote_file output configured with the following settings.
|
||
|
```
|
||
|
template(
|
||
|
@@ -446,32 +462,38 @@ The following playbook generates the same logging configuration files.
|
||
|
outputs: [files_output0, files_output1]
|
||
|
```
|
||
|
|
||
|
-5. Deploying `files input` reading logs from a local file and `elasticsearch output` to store the logs. Assuming the ca_cert, cert and key to connect to Elasticsearch are prepared.
|
||
|
+5. Deploying `files input` reading logs from local files and `files output` to write to the local files based on the property-based filters.
|
||
|
```yaml
|
||
|
---
|
||
|
-- name: Deploying basic input and elasticsearch output
|
||
|
+- name: Deploying files input and configured files output
|
||
|
hosts: all
|
||
|
roles:
|
||
|
- linux-system-roles.logging
|
||
|
vars:
|
||
|
logging_inputs:
|
||
|
- - name: files_input
|
||
|
+ - name: files_input0
|
||
|
type: files
|
||
|
- input_log_path: /var/log/containers/*.log
|
||
|
+ input_log_path: /var/log/containerA/*.log
|
||
|
+ - name: files_input1
|
||
|
+ type: files
|
||
|
+ input_log_path: /var/log/containerB/*.log
|
||
|
logging_outputs:
|
||
|
- - name: elasticsearch_output
|
||
|
- type: elasticsearch
|
||
|
- server_host: your_target_host
|
||
|
- server_port: 9200
|
||
|
- index_prefix: project.
|
||
|
- input_type: ovirt
|
||
|
- ca_cert_src: /local/path/to/ca_cert
|
||
|
- cert_src: /local/path/to/cert
|
||
|
- private_key_src: /local/path/to/key
|
||
|
+ - name: files_output0
|
||
|
+ type: files
|
||
|
+ property: msg
|
||
|
+ prop_op: contains
|
||
|
+ prop_value: error
|
||
|
+ path: /var/log/errors.log
|
||
|
+ - name: files_output1
|
||
|
+ type: files
|
||
|
+ property: msg
|
||
|
+ prop_op: "!contains"
|
||
|
+ prop_value: error
|
||
|
+ path: /var/log/others.log
|
||
|
logging_flows:
|
||
|
- name: flow0
|
||
|
- inputs: [files_input]
|
||
|
- outputs: [elasticsearch_output]
|
||
|
+ inputs: [files_input0, files_input1]
|
||
|
+ outputs: [files_output0, files_output1]
|
||
|
```
|
||
|
|
||
|
### Client configuration
|
||
|
diff --git a/roles/rsyslog/templates/output_files.j2 b/roles/rsyslog/templates/output_files.j2
|
||
|
index d994414..e15e4cd 100644
|
||
|
--- a/roles/rsyslog/templates/output_files.j2
|
||
|
+++ b/roles/rsyslog/templates/output_files.j2
|
||
|
@@ -1,6 +1,8 @@
|
||
|
{% if item.path is defined %}
|
||
|
ruleset(name="{{ item.name }}") {
|
||
|
-{% if item.exclude | d([]) %}
|
||
|
+{% if item.property | d() %}
|
||
|
+ :{{ item.property }}, {{ item.prop_op | d('contains') }}, "{{ item.prop_value | d('error') }}" {{ item.path }}
|
||
|
+{% elif item.exclude | d([]) %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }};{{ item.exclude | join(';') }} {{ item.path }}
|
||
|
{% else %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }} {{ item.path }}
|
||
|
diff --git a/roles/rsyslog/templates/output_forwards.j2 b/roles/rsyslog/templates/output_forwards.j2
|
||
|
index 61254ee..35030b4 100644
|
||
|
--- a/roles/rsyslog/templates/output_forwards.j2
|
||
|
+++ b/roles/rsyslog/templates/output_forwards.j2
|
||
|
@@ -9,7 +9,9 @@
|
||
|
{% set __forwards_protocol = '' %}
|
||
|
{% endif %}
|
||
|
ruleset(name="{{ item.name }}") {
|
||
|
-{% if item.exclude | d([]) %}
|
||
|
+{% if item.property | d() %}
|
||
|
+ :{{ item.property }}, {{ item.prop_op | d('contains') }}, "{{ item.prop_value | d('error') }}" action(name="{{ item.name }}"
|
||
|
+{% elif item.exclude | d([]) %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }};{{ item.exclude | join(';') }} action(name="{{ item.name }}"
|
||
|
{% else %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }} action(name="{{ item.name }}"
|
||
|
diff --git a/roles/rsyslog/templates/output_remote_files.j2 b/roles/rsyslog/templates/output_remote_files.j2
|
||
|
index 3c9339f..aaf547e 100644
|
||
|
--- a/roles/rsyslog/templates/output_remote_files.j2
|
||
|
+++ b/roles/rsyslog/templates/output_remote_files.j2
|
||
|
@@ -17,7 +17,9 @@ ruleset(name="{{ item.name }}"
|
||
|
queue.size="{{ logging_server_queue_size }}"
|
||
|
queue.workerThreads="{{ logging_server_threads }}") {
|
||
|
# Store remote logs in separate logfiles
|
||
|
-{% if item.exclude | d([]) %}
|
||
|
+{% if item.property | d() %}
|
||
|
+ :{{ item.property }}, {{ item.prop_op | d('contains') }}, "{{ item.prop_value | d('error') }}" action(name="{{ item.name }}" type="omfile" DynaFile="{{ item.name }}_template" DynaFileCacheSize="{{ item.client_count | d(10) }}" ioBufferSize="{{ item.io_buffer_size | d('65536') }}" asyncWriting="{{ 'on' if item.async_writing | d(false) | bool else 'off' }}")
|
||
|
+{% elif item.exclude | d([]) %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }};{{ item.exclude | join(';') }} action(name="{{ item.name }}" type="omfile" DynaFile="{{ item.name }}_template" DynaFileCacheSize="{{ item.client_count | d(10) }}" ioBufferSize="{{ item.io_buffer_size | d('65536') }}" asyncWriting="{{ 'on' if item.async_writing | d(false) | bool else 'off' }}")
|
||
|
{% else %}
|
||
|
{{ item.facility | d('*') }}.{{ item.severity | d('*') }} action(name="{{ item.name }}" type="omfile" DynaFile="{{ item.name }}_template" DynaFileCacheSize="{{ item.client_count | d(10) }}" ioBufferSize="{{ item.io_buffer_size | d('65536') }}" asyncWriting="{{ 'on' if item.async_writing | d(false) | bool else 'off' }}")
|
||
|
diff --git a/tests/tests_basics_files2.yml b/tests/tests_basics_files2.yml
|
||
|
index 094b125..b1a0f62 100644
|
||
|
--- a/tests/tests_basics_files2.yml
|
||
|
+++ b/tests/tests_basics_files2.yml
|
||
|
@@ -10,9 +10,9 @@
|
||
|
# If logging role is executed, the file size is about 100 bytes.
|
||
|
# Thus, assert the size is less than 1000.
|
||
|
# 2. Check file count in /etc/rsyslog.d.
|
||
|
-# If logging role is executed, 8 config files are generated.
|
||
|
+# If logging role is executed, 9 config files are generated.
|
||
|
# By setting logging_purge_confs, pre-existing config files are deleted.
|
||
|
-# Thus, assert the the count is equal to 8.
|
||
|
+# Thus, assert the the count is equal to 9.
|
||
|
# 3. Check systemctl status of rsyslog as well as error or specific message in the output.
|
||
|
# 4. To verify the generated filename is correct, check the config file of files output exists.
|
||
|
# 4.1 Check the config file contains the expected filter and the output file as configured.
|
||
|
@@ -24,6 +24,8 @@
|
||
|
vars:
|
||
|
__test_files_conf: /etc/rsyslog.d/30-output-files-files_output1.conf
|
||
|
__default_system_log: /var/log/messages
|
||
|
+ __prop_based_log0: /var/log/property_based_filter_in.log
|
||
|
+ __prop_based_log1: /var/log/property_based_filter_out.log
|
||
|
|
||
|
tasks:
|
||
|
- name: deploy config to output into local files
|
||
|
@@ -49,15 +51,23 @@
|
||
|
path: :omusrmsg:*
|
||
|
- name: files_output3
|
||
|
type: files
|
||
|
- facility: local7
|
||
|
- path: /var/log/boot.log
|
||
|
+ property: msg
|
||
|
+ prop_op: contains
|
||
|
+ prop_value: property_based_filter_test
|
||
|
+ path: "{{ __prop_based_log0 }}"
|
||
|
+ - name: files_output4
|
||
|
+ type: files
|
||
|
+ property: msg
|
||
|
+ prop_op: "!contains"
|
||
|
+ prop_value: property_based_filter_test
|
||
|
+ path: "{{ __prop_based_log1 }}"
|
||
|
logging_inputs:
|
||
|
- name: basic_input
|
||
|
type: basics
|
||
|
logging_flows:
|
||
|
- name: flow_0
|
||
|
inputs: [basic_input]
|
||
|
- outputs: [files_output0, files_output1, files_output2, files_output3]
|
||
|
+ outputs: [files_output0, files_output1, files_output2, files_output3, files_output4]
|
||
|
include_role:
|
||
|
name: linux-system-roles.logging
|
||
|
|
||
|
@@ -74,7 +84,7 @@
|
||
|
|
||
|
- name: Check file counts in rsyslog.d
|
||
|
assert:
|
||
|
- that: rsyslog_d_file_count.matched == 8
|
||
|
+ that: rsyslog_d_file_count.matched == 9
|
||
|
|
||
|
# Checking 'error' in stdout from systemctl status is for detecting the case in which rsyslog is running,
|
||
|
# but some functionality is disabled due to some error, e.g., error: 'tls.cacert' file couldn't be accessed.
|
||
|
@@ -104,3 +114,21 @@
|
||
|
retries: 5
|
||
|
delay: 1
|
||
|
changed_when: false
|
||
|
+
|
||
|
+ - name: Run logger to generate a test log message containing property_based_filter_test
|
||
|
+ command: /bin/logger -i -p local6.info -t testTag1 property_based_filter_test
|
||
|
+ changed_when: false
|
||
|
+
|
||
|
+ - name: Check the test log message in {{ __prop_based_log0 }}
|
||
|
+ command: /bin/grep property_based_filter_test "{{ __prop_based_log0 }}"
|
||
|
+ register: __result
|
||
|
+ until: __result is success
|
||
|
+ retries: 5
|
||
|
+ delay: 1
|
||
|
+ changed_when: false
|
||
|
+
|
||
|
+ - name: Check the test log message not in {{ __prop_based_log1 }}
|
||
|
+ command: /bin/grep property_based_filter_test "{{ __prop_based_log1 }}"
|
||
|
+ register: __result
|
||
|
+ changed_when: false
|
||
|
+ failed_when: "__result is not failed"
|
||
|
diff --git a/tests/tests_basics_forwards_cert.yml b/tests/tests_basics_forwards_cert.yml
|
||
|
index e27e016..48263ae 100644
|
||
|
--- a/tests/tests_basics_forwards_cert.yml
|
||
|
+++ b/tests/tests_basics_forwards_cert.yml
|
||
|
@@ -139,3 +139,11 @@
|
||
|
- /etc/pki/tls/certs/{{ __test_ca_cert_name }}
|
||
|
- /etc/pki/tls/certs/{{ __test_cert_name }}
|
||
|
- /etc/pki/tls/private/{{ __test_key_name }}
|
||
|
+
|
||
|
+ - name: clean up test files
|
||
|
+ file: path="{{ item }}" state=absent
|
||
|
+ loop:
|
||
|
+ - "{{ __test_ca_cert }}"
|
||
|
+ - "{{ __test_cert }}"
|
||
|
+ - "{{ __test_key }}"
|
||
|
+ delegate_to: localhost
|
||
|
diff --git a/tests/tests_basics_forwards_cert_missing.yml b/tests/tests_basics_forwards_cert_missing.yml
|
||
|
index 3e82856..0ad0569 100644
|
||
|
--- a/tests/tests_basics_forwards_cert_missing.yml
|
||
|
+++ b/tests/tests_basics_forwards_cert_missing.yml
|
||
|
@@ -63,6 +63,10 @@
|
||
|
assert:
|
||
|
that: "'{{ ansible_failed_result.results.0.msg }}' is match('{{ __expected_error }}')"
|
||
|
|
||
|
+ - name: clean up test files
|
||
|
+ file: path="{{ __test_key }}" state=absent
|
||
|
+ delegate_to: localhost
|
||
|
+
|
||
|
- name: default run for cleanup
|
||
|
vars:
|
||
|
logging_inputs:
|
||
|
diff --git a/tests/tests_server_conflict.yml b/tests/tests_server_conflict.yml
|
||
|
index 36eeeb7..8c182f6 100644
|
||
|
--- a/tests/tests_server_conflict.yml
|
||
|
+++ b/tests/tests_server_conflict.yml
|
||
|
@@ -76,3 +76,11 @@
|
||
|
- assert:
|
||
|
that: item.msg is not defined or item.msg is defined and item.msg == __expected_error
|
||
|
loop: "{{ ansible_failed_result.results }}"
|
||
|
+
|
||
|
+ - name: clean up test files
|
||
|
+ file: path="{{ item }}" state=absent
|
||
|
+ loop:
|
||
|
+ - "{{ __test_ca_cert }}"
|
||
|
+ - "{{ __test_cert }}"
|
||
|
+ - "{{ __test_key }}"
|
||
|
+ delegate_to: localhost
|
||
|
--
|
||
|
2.26.2
|
||
|
|