From 47f1852c18edc4586a52bf6e9e014fc891edc518 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 8 Sep 2026 03:49:17 +0000 Subject: [PATCH] Install and configure Audita --- README.md | 57 +++++++++++++++++++- ansible.cfg | 3 ++ collections/requirements.yml | 4 ++ defaults/main.yml | 11 ++++ meta/argument_specs.yml | 41 ++++++++++++++ meta/main.yml | 18 +++++++ tasks/main.yml | 101 +++++++++++++++++++++++++++++++++++ tests/converge.yml | 6 +++ tests/integration | 41 ++++++++++++++ tests/inventory | 1 + tests/verify.yml | 85 +++++++++++++++++++++++++++++ 11 files changed, 366 insertions(+), 2 deletions(-) create mode 100644 ansible.cfg create mode 100644 collections/requirements.yml create mode 100644 defaults/main.yml create mode 100644 meta/argument_specs.yml create mode 100644 meta/main.yml create mode 100644 tasks/main.yml create mode 100644 tests/converge.yml create mode 100755 tests/integration create mode 100644 tests/inventory create mode 100644 tests/verify.yml diff --git a/README.md b/README.md index d199d15..e2db79b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,56 @@ -# ansible-role-audita +# Ansible Role: Audita -Ansible role to install the Audita transcript processor. \ No newline at end of file +Installs and configures [Audita](https://gitea.maximumdirect.net/eric/audita) +from source on Ubuntu 26.04 (`x86_64` or `aarch64`). The role requires gathered +facts and uses privilege escalation on tasks that install dependencies or +manage root-owned application state. + +## Variables + +```yaml +audita_version: v0.9.1 +audita_repository_url: https://gitea.maximumdirect.net/eric/audita.git +audita_source_dir: /usr/local/src/audita +audita_binary_path: /usr/local/bin/audita +audita_manage_build_dependencies: true +audita_go_snap_channel: 1.26/stable +audita_go_binary: /snap/bin/go +audita_config_path: /usr/local/etc/audita/config.yml +audita_config: + version: 1 +``` + +When `audita_manage_build_dependencies` is `false`, Git and the executable +selected by `audita_go_binary` must already be available. Otherwise, the role +installs Git with APT and the classic Go Snap from `audita_go_snap_channel`. + +The checkout is authoritative: local source changes are discarded while +selecting `audita_version`. The role builds Audita directly to +`audita_binary_path` using `audita_go_binary`, `CGO_ENABLED=0`, `GOWORK=off`, +`GOTOOLCHAIN=local`, `-trimpath`, and release linker metadata. It rebuilds when +the checkout changes or the binary is absent. The source tree is recursively +owned by `root:root`; the binary is `root:root` mode `0755`. + +`audita_config` is the complete versioned YAML document, not an overlay on +hidden defaults. The role writes it to `audita_config_path` as `root:root` mode +`0644`. The repository-local integration suite validates it with Audita rather +than executing the CLI during production convergence. + +## Example + +```yaml +- hosts: audita_hosts + roles: + - role: ansible-role-audita +``` + +## Validation + +The integration driver installs pinned collection dependencies, runs syntax +checking and ansible-lint, verifies the default release, file ownership and +modes, executable behavior, and native configuration validation, then proves +an immediate repeat is unchanged. It manages the default local installation: + +```sh +tests/integration +``` diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..a876b69 --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +inventory = tests/inventory +localhost_warning = false diff --git a/collections/requirements.yml b/collections/requirements.yml new file mode 100644 index 0000000..22c02b2 --- /dev/null +++ b/collections/requirements.yml @@ -0,0 +1,4 @@ +--- +collections: + - name: community.general + version: 13.3.0 diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..67c968c --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,11 @@ +--- +audita_version: v0.9.1 +audita_repository_url: https://gitea.maximumdirect.net/eric/audita.git +audita_source_dir: /usr/local/src/audita +audita_binary_path: /usr/local/bin/audita +audita_manage_build_dependencies: true +audita_go_snap_channel: 1.26/stable +audita_go_binary: /snap/bin/go +audita_config_path: /usr/local/etc/audita/config.yml +audita_config: + version: 1 diff --git a/meta/argument_specs.yml b/meta/argument_specs.yml new file mode 100644 index 0000000..71ef182 --- /dev/null +++ b/meta/argument_specs.yml @@ -0,0 +1,41 @@ +--- +argument_specs: + main: + short_description: Install and configure Audita from source + options: + audita_version: + type: str + required: true + description: Git revision and version injected into the executable. + audita_repository_url: + type: str + required: true + description: Git repository containing Audita source. + audita_source_dir: + type: path + required: true + description: Fully managed source checkout path. + audita_binary_path: + type: path + required: true + description: Installed executable path. + audita_manage_build_dependencies: + type: bool + required: true + description: Whether to install Git and Go. + audita_go_snap_channel: + type: str + required: true + description: Go Snap channel to install. + audita_go_binary: + type: path + required: true + description: Go executable used to build Audita. + audita_config_path: + type: path + required: true + description: Managed Audita configuration path. + audita_config: + type: dict + required: true + description: Complete versioned Audita configuration mapping. diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..8897b3b --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,18 @@ +--- +galaxy_info: + role_name: audita + namespace: rakestraw + author: Eric Rakestraw + description: Install and configure Audita from source + license: BSD-3-Clause + min_ansible_version: "2.18" + issue_tracker_url: https://gitea.maximumdirect.net/eric/ansible-role-audita/issues + platforms: + - name: Ubuntu + versions: + - resolute + galaxy_tags: + - audita + - transcript + - processing +dependencies: [] diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..a75ba6d --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,101 @@ +--- +- name: Validate the supported platform + ansible.builtin.assert: + that: + - ansible_facts.distribution == "Ubuntu" + - ansible_facts.distribution_version == "26.04" + - ansible_facts.architecture in ["x86_64", "aarch64"] + fail_msg: Audita supports Ubuntu 26.04 on x86_64 or aarch64. + +- name: Install Git + become: true + ansible.builtin.apt: + name: git + state: present + update_cache: true + cache_valid_time: 3600 + when: audita_manage_build_dependencies + +- name: Install Go + become: true + community.general.snap: + name: go + channel: "{{ audita_go_snap_channel }}" + classic: true + state: present + when: audita_manage_build_dependencies + +- name: Create installation parent directories + become: true + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: root + group: root + mode: "0755" + loop: + - "{{ audita_source_dir | dirname }}" + - "{{ audita_binary_path | dirname }}" + - "{{ audita_config_path | dirname }}" + +- name: Check out Audita source + become: true + ansible.builtin.git: + repo: "{{ audita_repository_url }}" + dest: "{{ audita_source_dir }}" + version: "{{ audita_version }}" + force: true + register: audita_checkout + +- name: Inspect the installed binary + ansible.builtin.stat: + path: "{{ audita_binary_path }}" + register: audita_binary + +- name: Build Audita + become: true + ansible.builtin.command: + argv: + - "{{ audita_go_binary }}" + - build + - -trimpath + - -ldflags + - "-s -w -X gitea.maximumdirect.net/eric/audita/internal/buildinfo.Version={{ audita_version }}" + - -o + - "{{ audita_binary_path }}" + - gitea.maximumdirect.net/eric/audita/cmd/audita + chdir: "{{ audita_source_dir }}" + environment: + CGO_ENABLED: "0" + GOTOOLCHAIN: local + GOWORK: "off" + changed_when: true + when: >- + audita_checkout.changed or + not audita_binary.stat.exists + +- name: Converge installed metadata + become: true + ansible.builtin.file: + path: "{{ item.path }}" + state: "{{ item.state }}" + owner: root + group: root + mode: "{{ item.mode | default(omit) }}" + recurse: "{{ item.recurse | default(omit) }}" + loop: + - path: "{{ audita_source_dir }}" + state: directory + recurse: true + - path: "{{ audita_binary_path }}" + state: file + mode: "0755" + +- name: Write Audita configuration + become: true + ansible.builtin.copy: + content: "{{ audita_config | to_nice_yaml }}" + dest: "{{ audita_config_path }}" + owner: root + group: root + mode: "0644" diff --git a/tests/converge.yml b/tests/converge.yml new file mode 100644 index 0000000..5270df6 --- /dev/null +++ b/tests/converge.yml @@ -0,0 +1,6 @@ +--- +- name: Converge + hosts: localhost + gather_facts: true + roles: + - role: ansible-role-audita diff --git a/tests/integration b/tests/integration new file mode 100755 index 0000000..966150e --- /dev/null +++ b/tests/integration @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +repository_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) +workspace_venv="$repository_root/../.venv" +test_tmp=$(mktemp -d) +chmod 0700 "$test_tmp" + +export ANSIBLE_COLLECTIONS_PATH="$test_tmp/collections" +export ANSIBLE_ROLES_PATH="$(dirname "$repository_root")" + +inventory="$repository_root/tests/inventory" +converge="$repository_root/tests/converge.yml" +verify="$repository_root/tests/verify.yml" +ansible_playbook="$workspace_venv/bin/ansible-playbook" +default_commit=a84941d68168a1ed9ea7423b6477ae8218be73f9 + +cleanup() { + rm -rf -- "$test_tmp" +} +trap cleanup EXIT + +require_clean_recap() { + grep -Eq 'changed=0 .*failed=0' "$1" +} + +cd "$repository_root" +"$workspace_venv/bin/ansible-galaxy" collection install \ + -r collections/requirements.yml \ + -p "$ANSIBLE_COLLECTIONS_PATH" +"$ansible_playbook" -i "$inventory" --syntax-check "$converge" +"$workspace_venv/bin/ansible-lint" "$converge" "$verify" + +baseline_log="$test_tmp/baseline.log" +"$ansible_playbook" -i "$inventory" "$converge" | tee "$baseline_log" +"$ansible_playbook" -i "$inventory" \ + -e "audita_expected_commit=$default_commit" \ + "$verify" +baseline_repeat_log="$test_tmp/baseline-repeat.log" +"$ansible_playbook" -i "$inventory" "$converge" | tee "$baseline_repeat_log" +require_clean_recap "$baseline_repeat_log" diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..2302eda --- /dev/null +++ b/tests/inventory @@ -0,0 +1 @@ +localhost ansible_connection=local diff --git a/tests/verify.yml b/tests/verify.yml new file mode 100644 index 0000000..d648216 --- /dev/null +++ b/tests/verify.yml @@ -0,0 +1,85 @@ +--- +- name: Verify Audita installation + hosts: localhost + gather_facts: false + tasks: + - name: Confirm selected source commit + become: true + ansible.builtin.command: + argv: + - git + - -C + - /usr/local/src/audita + - rev-parse + - HEAD + register: audita_commit + changed_when: false + + - name: Check selected source commit + ansible.builtin.assert: + that: + - audita_commit.stdout == audita_expected_commit + + - name: Inspect source ownership + become: true + ansible.builtin.command: + argv: + - find + - /usr/local/src/audita + - -not + - -user + - root + - -o + - -not + - -group + - root + register: audita_source_ownership + changed_when: false + + - name: Check source ownership + ansible.builtin.assert: + that: + - audita_source_ownership.stdout == "" + + - name: Inspect binary metadata + become: true + ansible.builtin.stat: + path: /usr/local/bin/audita + register: audita_binary_metadata + + - name: Check binary metadata + ansible.builtin.assert: + that: + - audita_binary_metadata.stat.pw_name == "root" + - audita_binary_metadata.stat.gr_name == "root" + - audita_binary_metadata.stat.mode == "0755" + - audita_binary_metadata.stat.executable + + - name: Inspect configuration metadata + become: true + ansible.builtin.stat: + path: /usr/local/etc/audita/config.yml + register: audita_config_metadata + + - name: Check configuration metadata + ansible.builtin.assert: + that: + - audita_config_metadata.stat.pw_name == "root" + - audita_config_metadata.stat.gr_name == "root" + - audita_config_metadata.stat.mode == "0644" + + - name: Validate Audita configuration + ansible.builtin.command: + argv: + - /usr/local/bin/audita + - config + - validate + - --config + - /usr/local/etc/audita/config.yml + register: audita_config_validation + changed_when: false + + - name: Check configuration validation output + ansible.builtin.assert: + that: + - audita_config_validation.stdout == "config is valid"