Skip to content

Commit 33ad5a3

Browse files
committed
feat(openbao): Implement OpenBao audit device with log rotation and readiness checks
1 parent 327b772 commit 33ad5a3

10 files changed

Lines changed: 674 additions & 0 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ export ARMORY_LOG_NOLOG=true
169169

170170
Only set `ARMORY_LOG_NOLOG=true` in tightly controlled environments and rotate exposed credentials after use.
171171

172+
### Audit Logging
173+
174+
OpenBao audit logging is enabled with a file audit device by default.
175+
176+
- Audit log path in the OpenBao pod: `/openbao/audit/audit.log`
177+
- Backing storage: dedicated OpenBao audit PVC (separate from data storage)
178+
- Host rotation timer: `openbao-audit-rotate.timer`
179+
180+
Warning: OpenBao blocks requests when no enabled audit device is writable. Keep the audit PVC healthy and sized for retained logs.
181+
172182
## Retrieve Generated Credentials
173183

174184
The deployment uses Keycloak plus OpenBao/VSO. Re-runs reuse existing values unless secrets are intentionally rotated.

ansible/roles/openbao/defaults/main.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,19 @@ openbao_firewall_manage: true
143143
# firewalld zone used when firewall management is enabled.
144144
openbao_firewall_zone: public
145145

146+
# Audit device settings. When enabled, a `file` audit device is mounted on a
147+
# dedicated PVC. WARNING: OpenBao blocks all requests if no enabled audit
148+
# device is writable.
149+
openbao_audit_enabled: true
150+
openbao_audit_device_name: file
151+
openbao_audit_mount_path: /openbao/audit
152+
openbao_audit_log_path: "{{ openbao_audit_mount_path }}/audit.log"
153+
openbao_audit_storage_size: 2Gi
154+
# Host-side rotation (systemd timer; exec + SIGHUP into the pod).
155+
openbao_audit_rotate_enabled: true
156+
openbao_audit_rotate_on_calendar: daily
157+
openbao_audit_rotate_keep: 7
158+
146159

147160
# When true, disables Ansible no_log redaction for sensitive tasks.
148161
# WARNING: Enabling this will print secrets/tokens into logs and output.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
- name: Configure OpenBao audit log rotation timer
3+
when:
4+
- openbao_audit_enabled | bool
5+
- openbao_audit_rotate_enabled | bool
6+
block:
7+
- name: Install OpenBao audit rotation script
8+
ansible.builtin.template:
9+
src: openbao-audit-rotate.sh.j2
10+
dest: "{{ openbao_work_dir }}/openbao-audit-rotate.sh"
11+
mode: "0750"
12+
owner: root
13+
group: root
14+
15+
- name: Install OpenBao audit rotation service unit
16+
ansible.builtin.copy:
17+
dest: /etc/systemd/system/openbao-audit-rotate.service
18+
mode: "0644"
19+
owner: root
20+
group: root
21+
content: |
22+
[Unit]
23+
Description=Rotate OpenBao audit log
24+
Wants=network-online.target
25+
After=network-online.target
26+
27+
[Service]
28+
Type=oneshot
29+
ExecStart={{ openbao_work_dir }}/openbao-audit-rotate.sh
30+
31+
[Install]
32+
WantedBy=multi-user.target
33+
34+
- name: Install OpenBao audit rotation timer unit
35+
ansible.builtin.copy:
36+
dest: /etc/systemd/system/openbao-audit-rotate.timer
37+
mode: "0644"
38+
owner: root
39+
group: root
40+
content: |
41+
[Unit]
42+
Description=Schedule OpenBao audit log rotation
43+
44+
[Timer]
45+
OnCalendar={{ openbao_audit_rotate_on_calendar }}
46+
Persistent=true
47+
48+
[Install]
49+
WantedBy=timers.target
50+
51+
- name: Enable and start OpenBao audit rotation timer
52+
ansible.builtin.systemd_service:
53+
name: openbao-audit-rotate.timer
54+
daemon_reload: true
55+
enabled: true
56+
state: started

ansible/roles/openbao/tasks/main.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,7 @@
3939
- name: OpenBao configuration
4040
ansible.builtin.import_tasks: configure.yml
4141
tags: [openbao, openbao_configure]
42+
43+
- name: OpenBao audit rotation
44+
ansible.builtin.import_tasks: audit_rotate.yml
45+
tags: [openbao, openbao_audit_rotate]

ansible/roles/openbao/tasks/teardown.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,29 @@
1818
register: _openbao_helm_uninstall
1919
changed_when: (_openbao_helm_uninstall.rc | default(1)) == 0
2020
failed_when: false
21+
22+
- name: Stop and disable OpenBao audit rotation timer
23+
ansible.builtin.systemd_service:
24+
name: openbao-audit-rotate.timer
25+
state: stopped
26+
enabled: false
27+
daemon_reload: true
28+
failed_when: false
29+
30+
- name: Remove OpenBao audit rotation service unit
31+
ansible.builtin.file:
32+
path: /etc/systemd/system/openbao-audit-rotate.service
33+
state: absent
34+
failed_when: false
35+
36+
- name: Remove OpenBao audit rotation timer unit
37+
ansible.builtin.file:
38+
path: /etc/systemd/system/openbao-audit-rotate.timer
39+
state: absent
40+
failed_when: false
41+
42+
- name: Remove OpenBao audit rotation script
43+
ansible.builtin.file:
44+
path: "{{ openbao_work_dir }}/openbao-audit-rotate.sh"
45+
state: absent
46+
failed_when: false
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
# Managed by Ansible - do not edit manually
3+
set -euo pipefail
4+
export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
5+
ts=$(date +%Y%m%d%H%M%S)
6+
k3s kubectl exec -n {{ openbao_namespace }} statefulset/{{ openbao_release_name }} -- \
7+
sh -c "mv {{ openbao_audit_log_path }} {{ openbao_audit_log_path }}.${ts} && kill -HUP 1"
8+
# Prune: keep newest {{ openbao_audit_rotate_keep }} rotated files.
9+
k3s kubectl exec -n {{ openbao_namespace }} statefulset/{{ openbao_release_name }} -- \
10+
sh -c "ls -1t {{ openbao_audit_log_path }}.* 2>/dev/null | tail -n +{{ openbao_audit_rotate_keep | int + 1 }} | xargs -r rm --"

ansible/roles/openbao/templates/values.yaml.j2

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ server:
2121
storage "file" {
2222
path = "/openbao/data"
2323
}
24+
{% if openbao_audit_enabled | bool %}
25+
26+
audit "file" "{{ openbao_audit_device_name }}" {
27+
options {
28+
file_path = "{{ openbao_audit_log_path }}"
29+
mode = "0600"
30+
}
31+
}
32+
{% endif %}
2433

2534
service:
2635
enabled: true
@@ -33,6 +42,13 @@ server:
3342
enabled: true
3443
size: 1Gi
3544

45+
{% if openbao_audit_enabled | bool %}
46+
auditStorage:
47+
enabled: true
48+
size: {{ openbao_audit_storage_size }}
49+
mountPath: {{ openbao_audit_mount_path }}
50+
{% endif %}
51+
3652
readinessProbe:
3753
enabled: true
3854
periodSeconds: {{ openbao_readiness_period_seconds }}

ansible/roles/readiness_check/tasks/check_openbao.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,58 @@
115115
'error': ''
116116
}] }}
117117
changed_when: false
118+
119+
- name: Ensure OpenBao root token is available for audit check
120+
ansible.builtin.include_role:
121+
name: common
122+
tasks_from: load_openbao_root_token.yml
123+
when: openbao_audit_enabled | default(true) | bool
124+
125+
- name: Check OpenBao audit devices
126+
ansible.builtin.uri:
127+
url: "{{ _rc_openbao_addr }}/v1/sys/audit"
128+
method: GET
129+
headers:
130+
X-Vault-Token: "{{ openbao_root_token }}"
131+
validate_certs: "{{ readiness_check_openbao_validate_tls }}"
132+
timeout: "{{ readiness_check_openbao_api_timeout }}"
133+
status_code: 200
134+
register: _rc_openbao_audit_devices
135+
changed_when: false
136+
failed_when: false
137+
no_log: "{{ not (armory_log_nolog | default(false) | bool) }}"
138+
when: openbao_audit_enabled | default(true) | bool
139+
140+
- name: Add OpenBao audit enabled check to results
141+
ansible.builtin.set_fact:
142+
_readiness_results: >-
143+
{{ _readiness_results + [{
144+
'component': 'OpenBao',
145+
'check_name': 'Audit device enabled',
146+
'status': (
147+
'pass'
148+
if (((openbao_audit_device_name | default('file')) + '/') in (_rc_openbao_audit_devices.json | default({})))
149+
else 'fail'
150+
),
151+
'detail': (
152+
((openbao_audit_device_name | default('file')) + ' present')
153+
if (((openbao_audit_device_name | default('file')) + '/') in (_rc_openbao_audit_devices.json | default({})))
154+
else ((openbao_audit_device_name | default('file')) + ' not found')
155+
),
156+
'error': _rc_openbao_audit_devices.msg | default('')
157+
}] }}
158+
changed_when: false
159+
when: openbao_audit_enabled | default(true) | bool
160+
161+
- name: Add OpenBao audit disabled warning to results
162+
ansible.builtin.set_fact:
163+
_readiness_results: >-
164+
{{ _readiness_results + [{
165+
'component': 'OpenBao',
166+
'check_name': 'Audit device enabled',
167+
'status': 'warn',
168+
'detail': 'audit disabled by config',
169+
'error': ''
170+
}] }}
171+
changed_when: false
172+
when: not (openbao_audit_enabled | default(true) | bool)

0 commit comments

Comments
 (0)