Install and configure Audita

This commit is contained in:
2026-09-08 03:49:17 +00:00
parent 793e6d3ea6
commit 47f1852c18
11 changed files with 366 additions and 2 deletions

View File

@@ -1,3 +1,56 @@
# ansible-role-audita
# Ansible Role: Audita
Ansible role to install the Audita transcript processor.
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
```

3
ansible.cfg Normal file
View File

@@ -0,0 +1,3 @@
[defaults]
inventory = tests/inventory
localhost_warning = false

View File

@@ -0,0 +1,4 @@
---
collections:
- name: community.general
version: 13.3.0

11
defaults/main.yml Normal file
View File

@@ -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

41
meta/argument_specs.yml Normal file
View File

@@ -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.

18
meta/main.yml Normal file
View File

@@ -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: []

101
tasks/main.yml Normal file
View File

@@ -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"

6
tests/converge.yml Normal file
View File

@@ -0,0 +1,6 @@
---
- name: Converge
hosts: localhost
gather_facts: true
roles:
- role: ansible-role-audita

41
tests/integration Executable file
View File

@@ -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"

1
tests/inventory Normal file
View File

@@ -0,0 +1 @@
localhost ansible_connection=local

85
tests/verify.yml Normal file
View File

@@ -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"