feat: auditd - new role - initial commit#1
feat: auditd - new role - initial commit#1richm wants to merge 1 commit intolinux-system-roles:mainfrom
Conversation
Reviewer's GuideAdds a new linux-system-roles.auditd Ansible role that manages auditd.conf and custom audit rules, with full CI, validation, rpm-ostree support, documentation, and tests for argument sanity, rules purging, and integration behavior. Sequence diagram for auditd rules purge and retention behaviorsequenceDiagram
actor Admin
participant AnsiblePlay
participant Role_auditd as Role_auditd
participant Tasks_main as Tasks_main_yml
participant Tasks_purge as Tasks_purge_rules_yml
participant Template_custom as Template_custom_rules_j2
participant Handler_augenrules as Handler_Run_augenrules
Admin->>AnsiblePlay: Run play with auditd_purge_rules=true
AnsiblePlay->>Role_auditd: Apply linux_system_roles.auditd
Role_auditd->>Tasks_main: Execute tasks/main.yml
Note over Tasks_main: Earlier tasks validate vars, set facts,
Note over Tasks_main: install packages, create rules.d
alt auditd_purge_rules and auditd_manage_rules are true
Tasks_main->>Tasks_purge: Include purge_rules.yml
Tasks_purge->>Tasks_purge: Find files in rules.d
Tasks_purge->>Tasks_purge: Stat custom.rules
opt custom.rules exists
Tasks_purge->>Tasks_purge: Slurp custom.rules content
Tasks_purge->>Template_custom: Lookup rendered custom.rules
Template_custom-->>Tasks_purge: Rendered rules text
Tasks_purge->>Tasks_purge: Compute expected_sig from rendered body
Tasks_purge->>Tasks_purge: Compute current_sig from file body
alt Signatures equal
Tasks_purge->>Tasks_purge: Set __auditd_purge_keep_custom_rules=true
else Signatures differ
Tasks_purge->>Tasks_purge: Set __auditd_purge_keep_custom_rules=false
end
end
loop For each file in rules.d
alt File is custom.rules and __auditd_purge_keep_custom_rules is true
Tasks_purge-->>Tasks_purge: Skip deletion
else Delete file
Tasks_purge->>Tasks_purge: Remove file
Tasks_purge->>Handler_augenrules: notify Run_augenrules
end
end
else auditd_purge_rules is false or manage_rules is false
Tasks_main-->>Tasks_main: Skip purge_rules.yml
end
Note over Tasks_main,Template_custom: Later, if auditd_manage_rules and not __auditd_purge_keep_custom_rules
Note over Tasks_main,Template_custom: template custom.rules.j2 overwrites custom.rules and notifies Run_augenrules
Handler_augenrules-->>Handler_augenrules: Run augenrules
Handler_augenrules->>Handler_augenrules: Run augenrules --load when allowed
Handler_augenrules-->>Admin: Audit rules updated on target
Class diagram for linux_system_roles_auditd role structureclassDiagram
class Role_linux_system_roles_auditd {
+defaults_main_yml
+vars_main_yml
+tasks_main_yml
+handlers_main_yml
+templates_auditd_conf_j2
+templates_custom_rules_j2
+meta_main_yml
+meta_argument_specs_yml
}
class Defaults_main_yml {
+bool auditd_local_events
+bool auditd_write_logs
+string auditd_log_file
+string auditd_log_format
+string auditd_log_group
+string auditd_flush
+int auditd_freq
+int auditd_num_logs
+string auditd_dispatcher
+string auditd_name_format
+string auditd_name
+string auditd_disp_qos
+int auditd_max_log_file
+string auditd_max_log_file_action
+string auditd_max_log_file_action_exe
+string auditd_space_left
+string auditd_space_left_action
+string auditd_space_left_action_exe
+string auditd_action_mail_acct
+bool auditd_verify_email
+string auditd_admin_space_left
+string auditd_admin_space_left_action
+string auditd_admin_space_left_action_exe
+string auditd_disk_full_action
+string auditd_disk_full_action_exe
+string auditd_disk_error_action
+string auditd_disk_error_action_exe
+int auditd_priority_boost
+int auditd_tcp_listen_port
+int auditd_tcp_listen_queue
+int auditd_tcp_max_per_addr
+bool auditd_use_libwrap
+string auditd_tcp_client_ports
+int auditd_tcp_client_max_idle
+string auditd_transport
+bool auditd_enable_krb5
+string auditd_krb5_principal
+string auditd_krb5_key_file
+bool auditd_distribute_network
+int auditd_q_depth
+string auditd_overflow_action
+int auditd_max_restarts
+string auditd_plugin_dir
+int auditd_end_of_event_timeout
+string auditd_report_interval
+int auditd_buffer_size
+int auditd_fail_mode
+int auditd_maximum_rate
+int auditd_enable_flag
+bool auditd_manage_rules
+bool auditd_purge_rules
+bool auditd_start_service
+string auditd_default_arch
+list auditd_rules
}
class Vars_main_yml {
+map _auditd_packages_map
+string auditd_config_directory
+string auditd_config_file
+string auditd_service
+map _auditd_permissions
+list __auditd_required_facts
+list __auditd_required_facts_subsets
+list __auditd_rh_distros
+list __auditd_rh_distros_fedora
+bool __auditd_is_rh_distro
+bool __auditd_is_rh_distro_fedora
}
class Tasks_main_yml {
+task Validate_role_parameters
+task Include_set_vars
+task Install_audit_packages
+task Deploy_auditd_configuration
+task Ensure_rulesd_directory
+task Purge_rulesd_when_requested
+task Deploy_custom_audit_rules
+task Start_and_enable_auditd_service
}
class Tasks_set_vars_yml {
+task Ensure_required_facts
+task Detect_ostree
+task Include_platform_vars_files
+task Resolve_package_names
+bool __auditd_is_ostree
+list __auditd_required_facts_subsets
+list __auditd_packages
}
class Tasks_assert_yml {
+assert auditd_num_logs_range
+assert auditd_freq_range
+assert_incremental_flush_requires_freq
+assert_priority_boost_range
+assert_q_depth_range
+assert_max_restarts_range
+assert_tcp_ports_ranges
+assert_tcp_client_ports_format
+assert_space_left_action_not_halt
+assert_disk_full_action_not_email
+assert_disk_error_action_not_email_rotate
+assert_exec_actions_have_paths
+assert_name_when_user_format
+assert_auditd_rules_structure
+assert_syscall_rule_keys
+assert_file_rule_permissions
}
class Tasks_purge_rules_yml {
+task Discover_rulesd_files
+task Stat_custom_rules
+task Slurp_custom_rules
+task Compute_expected_signature
+task Compute_current_signature
+task Decide_keep_custom_rules
+task Remove_rulesd_files
+bool __auditd_purge_keep_custom_rules
}
class Handlers_main_yml {
+handler Run_augenrules
+handler Load_audit_rules
+handler Restart_auditd
}
class Template_auditd_conf_j2 {
+macro auditd_yesno
+render auditd_conf_from_variables
}
class Template_custom_rules_j2 {
+render_global_settings
+render_file_watch_rules
+render_syscall_rules
+render_generic_rules
+use _auditd_permissions
}
class Meta_main_yml {
+string namespace
+string role_name
+string author
+string description
+string company
+string license
+string min_ansible_version
+list platforms
+list galaxy_tags
}
Role_linux_system_roles_auditd *-- Defaults_main_yml
Role_linux_system_roles_auditd *-- Vars_main_yml
Role_linux_system_roles_auditd *-- Tasks_main_yml
Role_linux_system_roles_auditd *-- Handlers_main_yml
Role_linux_system_roles_auditd *-- Template_auditd_conf_j2
Role_linux_system_roles_auditd *-- Template_custom_rules_j2
Role_linux_system_roles_auditd *-- Meta_main_yml
Tasks_main_yml --> Tasks_set_vars_yml
Tasks_main_yml --> Tasks_assert_yml
Tasks_main_yml --> Tasks_purge_rules_yml
Tasks_main_yml --> Handlers_main_yml
Tasks_purge_rules_yml --> Template_custom_rules_j2
Template_custom_rules_j2 --> Vars_main_yml
Template_auditd_conf_j2 --> Defaults_main_yml
Tasks_assert_yml --> Vars_main_yml
Tasks_set_vars_yml --> Vars_main_yml
Flow diagram for get_ostree_data_sh package resolution and outputflowchart TD
A[Start get_ostree_data_sh
args category pkgtype distro_ver format] --> B{Args valid?}
B -- no --> Z[Exit with_usage]
B -- yes --> C[Set category
Set pkgtypes
Parse distro and version]
C --> D{category == packages}
D -- no --> Z2[Unsupported_category
exit]
D -- yes --> E[Call get_packages
with ostree_dir]
subgraph get_packages_recursive
E --> F[For each pkgtype in pkgtypes]
F --> G[For each suffix in
"" -distro -distro-major -distro-ver]
G --> H[Check packages-pkgtype-suffix txt]
H --> I{File exists?}
I -- yes --> J[Output package lines]
I -- no --> K[Skip]
F --> L[Check roles-pkgtype txt]
L --> M{roles file exists?}
M -- no --> N[Skip roles]
M -- yes --> O[Read role names]
O --> P[For each role
call get_rolepath]
P --> Q{rolepath found?}
Q -- no --> R[Print error
exit 2]
Q -- yes --> S[Recurse get_packages
on rolepath]
J --> T[Collect all packages]
S --> T
T --> U[Sort -u packages]
end
U --> V{format}
V -- json --> W1[format_packages_json]
V -- yaml --> W2[format_packages_yaml]
V -- raw --> W3[format_packages_raw]
V -- toml --> W4[format_packages_toml]
W1 --> X[Print JSON list]
W2 --> X
W3 --> X
W4 --> X
X --> Y[End]
subgraph get_rolepath_resolution
GR1[Given ostree_dir and role] --> GR2[Check rolesdir under parent collection
role_path role ostree]
GR2 --> GR3{Exists?}
GR3 -- yes --> GR7[Return rolesdir]
GR3 -- no --> GR4[Check legacy role dirs
*-system-roles role
.ostree]
GR4 --> GR5{Exists?}
GR5 -- yes --> GR7
GR5 -- no --> GR6[Search ANSIBLE_COLLECTIONS_PATH
for role .ostree]
GR6 --> GR8{Found?}
GR8 -- yes --> GR7
GR8 -- no --> GR9[Print error
exit 2]
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 6 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path=".github/workflows/build_docs.yml" line_range="99-103" />
<code_context>
+ name: README.html
+ path: ${{ env.RELEASE_VERSION }}/README.html
+
+ - name: Commit changes
+ run: |
+ git config --global user.name "${{ github.actor }}"
+ git config --global user.email "${{ github.actor }}@users.noreply.github.com"
+ git add ${{ env.RELEASE_VERSION }}/README.html docs/index.html
+ git commit -m "Update README.html for ${{ env.RELEASE_VERSION }}"
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard adding docs/index.html so the workflow does not fail when RELEASE_VERSION != 'latest'
`docs/index.html` is only created when `RELEASE_VERSION == 'latest'`, but `git add ... docs/index.html` always runs. For tag-based releases, this file won’t exist and the `git add` will fail. Please either guard `git add docs/index.html` with `RELEASE_VERSION == 'latest'` or move it to a separate, conditional `git add` that matches the copy step’s condition.
</issue_to_address>
### Comment 2
<location path=".github/workflows/tft.yml" line_range="119-120" />
<code_context>
+ ansible_version: "2.17"
+ runs-on: ubuntu-latest
+ env:
+ ARTIFACTS_DIR_NAME: "tf_${{ github.event.repository.name }}-${{ github.event.issue.number }}_\
+ ${{ matrix.platform }}-${{ matrix.ansible_version }}_\
+ ${{ needs.prepare_vars.outputs.datetime }}/artifacts"
+ ARTIFACT_TARGET_DIR: /srv/pub/alt/${{ vars.SR_LSR_USER }}/logs
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid referencing a non-existent datetime output from prepare_vars in ARTIFACTS_DIR_NAME
`ARTIFACTS_DIR_NAME` uses `${{ needs.prepare_vars.outputs.datetime }}`, but `prepare_vars` doesn’t define a `datetime` output. That will leave an empty segment in the path and diverges from the `Set variables with DATETIME` step, which recomputes `DATETIME` and artifact paths. Please either expose `DATETIME` as an output from `prepare_vars` and use it here, or remove this interpolation and rely on the value computed in `set_vars` only.
Suggested implementation:
```
env:
ARTIFACT_TARGET_DIR: /srv/pub/alt/${{ vars.SR_LSR_USER }}/logs
```
If subsequent steps rely on `ARTIFACTS_DIR_NAME` as a job-level environment variable, they should be updated to either:
1. Use the value computed in `set_vars` (e.g., by echoing it to `$GITHUB_OUTPUT` in `set_vars` and then referencing `steps.set_vars.outputs.ARTIFACTS_DIR_NAME`), or
2. Recompute the same value locally in their own `run` sections, mirroring the logic from `set_vars`.
This will ensure there is a single source of truth for the artifacts directory name and no dependency on a non-existent `prepare_vars.outputs.datetime`.
</issue_to_address>
### Comment 3
<location path=".ostree/get_ostree_data.sh" line_range="132" />
<code_context>
+ exit 1
+fi
+
+"get_$category" "$ostree_dir" | "format_${category}_$format"
</code_context>
<issue_to_address>
**suggestion:** Validate category/format values before invoking helper functions to avoid confusing runtime errors
Right now the script assumes any `category`/`format` is valid and directly invokes `get_$category` and `format_${category}_$format`. If a caller passes an unsupported value (e.g., a typo), this will just produce a `command not found` error. Please add explicit validation (e.g., a case statement) for allowed categories and formats, and exit with a clear, actionable error when an invalid value is given.
</issue_to_address>
### Comment 4
<location path="contributing.md" line_range="14-15" />
<code_context>
+* Basic git and github information
+* How to create git commits and submit pull requests
+
+**Bugs and needed implementations** are listed on
+[Github Issues](https://github.com/linux-system-roles/auditd/issues).
+Issues labeled with
+[**help wanted**](https://github.com/linux-system-roles/auditd/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
</code_context>
<issue_to_address>
**nitpick (typo):** Use the correct "GitHub" capitalization in the link text.
Please update the link text to "GitHub Issues" to match the official capitalization and keep the terminology consistent.
Suggested implementation:
```
* Basic git and GitHub information
```
```
[GitHub Issues](https://github.com/linux-system-roles/auditd/issues).
```
```
**Code** is managed on [GitHub](https://github.com/linux-system-roles/auditd), using
```
</issue_to_address>
### Comment 5
<location path="plans/README-plans.md" line_range="3" />
<code_context>
+# Introduction CI Testing Plans
+
+Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) GitHub workflow.
+
+The `plans/test_playbooks_parallel.fmf` plan is a test plan that runs test playbooks in parallel on multiple managed nodes.
</code_context>
<issue_to_address>
**nitpick (typo):** Align "Testing farm" capitalization with the official "Testing Farm" name.
Please update the link text here to "Testing Farm" to match the official name used elsewhere in the docs.
```suggestion
Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing Farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) GitHub workflow.
```
</issue_to_address>
### Comment 6
<location path="plans/README-plans.md" line_range="20" />
<code_context>
+3. For the given role and the given PR, runs the general test from [test.sh](https://github.com/linux-system-roles/tft-tests/blob/main/tests/general/test.sh).
+
+The [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access.
+This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm).
+
+## Running Tests
</code_context>
<issue_to_address>
**nitpick (typo):** Use the proper "GitHub Action" capitalization.
Please update "Github Action" to "GitHub Action" in this sentence for correct branding and consistency with the official name.
```suggestion
This workflow uses Testing Farm's GitHub Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm).
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| - name: Commit changes | ||
| run: | | ||
| git config --global user.name "${{ github.actor }}" | ||
| git config --global user.email "${{ github.actor }}@users.noreply.github.com" | ||
| git add ${{ env.RELEASE_VERSION }}/README.html docs/index.html |
There was a problem hiding this comment.
issue (bug_risk): Guard adding docs/index.html so the workflow does not fail when RELEASE_VERSION != 'latest'
docs/index.html is only created when RELEASE_VERSION == 'latest', but git add ... docs/index.html always runs. For tag-based releases, this file won’t exist and the git add will fail. Please either guard git add docs/index.html with RELEASE_VERSION == 'latest' or move it to a separate, conditional git add that matches the copy step’s condition.
| ARTIFACTS_DIR_NAME: "tf_${{ github.event.repository.name }}-${{ github.event.issue.number }}_\ | ||
| ${{ matrix.platform }}-${{ matrix.ansible_version }}_\ |
There was a problem hiding this comment.
suggestion (bug_risk): Avoid referencing a non-existent datetime output from prepare_vars in ARTIFACTS_DIR_NAME
ARTIFACTS_DIR_NAME uses ${{ needs.prepare_vars.outputs.datetime }}, but prepare_vars doesn’t define a datetime output. That will leave an empty segment in the path and diverges from the Set variables with DATETIME step, which recomputes DATETIME and artifact paths. Please either expose DATETIME as an output from prepare_vars and use it here, or remove this interpolation and rely on the value computed in set_vars only.
Suggested implementation:
env:
ARTIFACT_TARGET_DIR: /srv/pub/alt/${{ vars.SR_LSR_USER }}/logs
If subsequent steps rely on ARTIFACTS_DIR_NAME as a job-level environment variable, they should be updated to either:
- Use the value computed in
set_vars(e.g., by echoing it to$GITHUB_OUTPUTinset_varsand then referencingsteps.set_vars.outputs.ARTIFACTS_DIR_NAME), or - Recompute the same value locally in their own
runsections, mirroring the logic fromset_vars.
This will ensure there is a single source of truth for the artifacts directory name and no dependency on a non-existent prepare_vars.outputs.datetime.
| exit 1 | ||
| fi | ||
|
|
||
| "get_$category" "$ostree_dir" | "format_${category}_$format" |
There was a problem hiding this comment.
suggestion: Validate category/format values before invoking helper functions to avoid confusing runtime errors
Right now the script assumes any category/format is valid and directly invokes get_$category and format_${category}_$format. If a caller passes an unsupported value (e.g., a typo), this will just produce a command not found error. Please add explicit validation (e.g., a case statement) for allowed categories and formats, and exit with a clear, actionable error when an invalid value is given.
| **Bugs and needed implementations** are listed on | ||
| [Github Issues](https://github.com/linux-system-roles/auditd/issues). |
There was a problem hiding this comment.
nitpick (typo): Use the correct "GitHub" capitalization in the link text.
Please update the link text to "GitHub Issues" to match the official capitalization and keep the terminology consistent.
Suggested implementation:
* Basic git and GitHub information
[GitHub Issues](https://github.com/linux-system-roles/auditd/issues).
**Code** is managed on [GitHub](https://github.com/linux-system-roles/auditd), using
| @@ -0,0 +1,55 @@ | |||
| # Introduction CI Testing Plans | |||
|
|
|||
| Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) GitHub workflow. | |||
There was a problem hiding this comment.
nitpick (typo): Align "Testing farm" capitalization with the official "Testing Farm" name.
Please update the link text here to "Testing Farm" to match the official name used elsewhere in the docs.
| Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) GitHub workflow. | |
| Linux System Roles CI runs [tmt](https://tmt.readthedocs.io/en/stable/index.html) test plans in [Testing Farm](https://docs.testing-farm.io/Testing%20Farm/0.1/index.html) with the [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) GitHub workflow. |
| 3. For the given role and the given PR, runs the general test from [test.sh](https://github.com/linux-system-roles/tft-tests/blob/main/tests/general/test.sh). | ||
|
|
||
| The [tft.yml](https://github.com/linux-system-roles/auditd/blob/main/.github/workflows/tft.yml) workflow runs the above plan and uploads the results to our Fedora storage for public access. | ||
| This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm). |
There was a problem hiding this comment.
nitpick (typo): Use the proper "GitHub Action" capitalization.
Please update "Github Action" to "GitHub Action" in this sentence for correct branding and consistency with the official name.
| This workflow uses Testing Farm's Github Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm). | |
| This workflow uses Testing Farm's GitHub Action [Schedule tests on Testing Farm](https://github.com/marketplace/actions/schedule-tests-on-testing-farm). |
This is the initial commit of the new role auditd. Signed-off-by: Rich Megginson <[email protected]>
|
[citest] |
This is the initial commit of the new role auditd.
Signed-off-by: Rich Megginson [email protected]
Summary by Sourcery
Introduce a new linux-system-roles.auditd Ansible role to manage auditd configuration and rules with comprehensive CI, docs, and testing support.
New Features:
Enhancements:
CI:
Documentation:
Tests:
Chores: