Skip to content

Commit 6abf203

Browse files
authored
Merge pull request #117 from jackby03/feat/109-ansible-role
2 parents 97cbf4f + c7c06b9 commit 6abf203

File tree

17 files changed

+986
-1
lines changed

17 files changed

+986
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
104104
- `cloud-azure` compliance profile — CIS Azure Foundations Benchmark v2.1, OS hardening for Azure VMs with Azure-specific annotations (NSG, Defender for Cloud, Azure Policy, Disk Encryption, AAD login); includes guidance for Defender for Cloud Secure Score validation ([#108](https://github.com/jackby03/hardbox/issues/108))
105105
- cloud-init user-data templates for AWS EC2, GCP Compute Engine, and Azure VMs — each template installs hardbox with checksum verification, applies the provider-matched compliance profile on first boot, uploads the HTML audit report to cloud-native object storage (S3 / GCS / Blob), and configures a daily systemd re-hardening timer ([#111](https://github.com/jackby03/hardbox/issues/111))
106106
- `docs/CLOUD-INIT.md` — usage guide covering quick-start commands, IAM/RBAC requirements, configuration reference, timer management, and troubleshooting for all three cloud-init templates
107+
- Ansible role (`ansible-role/hardbox/`) — Galaxy-compatible role wrapping the hardbox CLI; supports all profiles, audit-only mode, report fetching, rollback on failure, custom profile upload, and systemd re-hardening timer; includes Molecule integration tests for Ubuntu 22.04, Debian 12, and Rocky Linux 9 ([#109](https://github.com/jackby03/hardbox/issues/109))
108+
- `docs/ANSIBLE.md` — Ansible role documentation covering installation, variable reference, example playbooks, CI/CD integration, and Molecule test instructions
107109

108110
### Changed
109111
- `install.sh` now resolves release assets via GitHub API instead of hardcoded filenames, improving compatibility across release archive naming formats.
@@ -117,7 +119,6 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
117119

118120
### Planned for v0.3
119121
- `nist-800-53` profile
120-
- Ansible role integration
121122
- Terraform provisioner plugin
122123
- cloud-init support
123124

ansible-role/hardbox/README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Ansible Role: hardbox
2+
3+
[![Ansible Galaxy](https://img.shields.io/badge/galaxy-jackby03.hardbox-blue)](https://galaxy.ansible.com/jackby03/hardbox)
4+
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](../../LICENSE)
5+
6+
Installs and runs [hardbox](https://github.com/jackby03/hardbox) — a Linux OS hardening tool with built-in compliance profiles.
7+
8+
## Requirements
9+
10+
- Ansible >= 2.14
11+
- Target hosts: Ubuntu 20.04/22.04, Debian 11/12, RHEL/Rocky/AlmaLinux 8/9
12+
- Become (sudo) access on target hosts
13+
14+
## Role Variables
15+
16+
See [`defaults/main.yml`](defaults/main.yml) for the full list with inline documentation.
17+
18+
| Variable | Default | Description |
19+
|---|---|---|
20+
| `hardbox_version` | `"latest"` | Release tag or `"latest"` |
21+
| `hardbox_profile` | `"production"` | Compliance profile to apply |
22+
| `hardbox_apply` | `true` | Apply hardening (`true`) or audit-only (`false`) |
23+
| `hardbox_dry_run` | `false` | Dry-run mode — preview changes without applying |
24+
| `hardbox_report_format` | `"html"` | Report format: `html`, `json`, `text`, `markdown` |
25+
| `hardbox_report_dir` | `/var/lib/hardbox/reports` | Report directory on target host |
26+
| `hardbox_fetch_report` | `false` | Fetch report to Ansible controller |
27+
| `hardbox_fetch_report_dest` | `"{{ playbook_dir }}/hardbox-reports"` | Local report destination |
28+
| `hardbox_rollback_on_failure` | `true` | Roll back on apply failure |
29+
| `hardbox_timer_enabled` | `false` | Install systemd re-hardening timer |
30+
| `hardbox_timer_schedule` | `"daily"` | systemd OnCalendar schedule |
31+
| `hardbox_fail_on_critical` | `true` | Fail play on critical findings |
32+
| `hardbox_fail_on_high` | `true` | Fail play on high findings |
33+
34+
## Example Playbooks
35+
36+
### Minimal — apply CIS Level 1 baseline
37+
38+
```yaml
39+
- hosts: all
40+
become: true
41+
roles:
42+
- role: jackby03.hardbox
43+
vars:
44+
hardbox_profile: cis-level1
45+
```
46+
47+
### Audit-only — check compliance without changing anything
48+
49+
```yaml
50+
- hosts: production
51+
become: true
52+
roles:
53+
- role: jackby03.hardbox
54+
vars:
55+
hardbox_profile: pci-dss
56+
hardbox_apply: false
57+
hardbox_fetch_report: true
58+
hardbox_report_format: html
59+
```
60+
61+
### Cloud AWS — harden and fetch report
62+
63+
```yaml
64+
- hosts: aws_ec2
65+
become: true
66+
roles:
67+
- role: jackby03.hardbox
68+
vars:
69+
hardbox_profile: cloud-aws
70+
hardbox_report_format: json
71+
hardbox_fetch_report: true
72+
hardbox_timer_enabled: true
73+
hardbox_timer_schedule: "daily"
74+
```
75+
76+
### Pin version and use custom profile
77+
78+
```yaml
79+
- hosts: all
80+
become: true
81+
roles:
82+
- role: jackby03.hardbox
83+
vars:
84+
hardbox_version: "v0.3.0"
85+
hardbox_custom_profile_src: files/my-profile.yaml
86+
hardbox_fetch_report: true
87+
```
88+
89+
## Galaxy Installation
90+
91+
```bash
92+
ansible-galaxy role install jackby03.hardbox
93+
```
94+
95+
Or add to `requirements.yml`:
96+
97+
```yaml
98+
roles:
99+
- name: jackby03.hardbox
100+
version: ">=0.3.0"
101+
```
102+
103+
```bash
104+
ansible-galaxy install -r requirements.yml
105+
```
106+
107+
## License
108+
109+
MIT — see [LICENSE](../../LICENSE).
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
# -------------------------------------------------------------------------
3+
# hardbox Ansible role — default variables
4+
# Override any of these in host_vars, group_vars, or the playbook vars block.
5+
# -------------------------------------------------------------------------
6+
7+
# --- Installation ---
8+
# hardbox release to install. Use "latest" to always fetch the newest release,
9+
# or pin to a specific tag (e.g. "v0.3.0") for reproducible deployments.
10+
hardbox_version: "latest"
11+
12+
# Directory where the hardbox binary is installed.
13+
hardbox_install_dir: /usr/local/bin
14+
15+
# Temporary directory used during download and checksum verification.
16+
hardbox_tmp_dir: /tmp
17+
18+
# --- Profile ---
19+
# Compliance profile to apply. Any profile shipped in configs/profiles/ is valid.
20+
# Common values: cis-level1, cis-level2, pci-dss, stig, hipaa, iso27001,
21+
# nist-800-53, cloud-aws, cloud-gcp, cloud-azure,
22+
# production, development
23+
hardbox_profile: production
24+
25+
# Path to a custom profile YAML to copy to the target host.
26+
# When set, this file is uploaded and --profile is pointed at it.
27+
# Leave empty ("") to use one of the built-in profiles.
28+
hardbox_custom_profile_src: ""
29+
30+
# --- Run mode ---
31+
# Whether to actually apply hardening (true) or only run an audit (false).
32+
hardbox_apply: true
33+
34+
# Pass --dry-run to hardbox — show what would change without applying.
35+
hardbox_dry_run: false
36+
37+
# Pass --non-interactive so hardbox never prompts (required in Ansible).
38+
hardbox_non_interactive: true
39+
40+
# --- Reporting ---
41+
# Report output format: html | json | text | markdown
42+
hardbox_report_format: html
43+
44+
# Directory on the target host where reports are stored.
45+
hardbox_report_dir: /var/lib/hardbox/reports
46+
47+
# Fetch the generated report back to the Ansible controller.
48+
hardbox_fetch_report: false
49+
50+
# Local directory on the Ansible controller to store fetched reports.
51+
hardbox_fetch_report_dest: "{{ playbook_dir }}/hardbox-reports"
52+
53+
# --- Audit thresholds ---
54+
# Fail the play if hardbox exits with critical/high findings.
55+
# Mirrors the audit.fail_on_* settings in the profile YAML.
56+
hardbox_fail_on_critical: true
57+
hardbox_fail_on_high: true
58+
hardbox_fail_on_medium: false
59+
60+
# --- Rollback ---
61+
# Run `hardbox rollback apply --last` on failure (via rescue block).
62+
hardbox_rollback_on_failure: true
63+
64+
# --- Periodic re-hardening (systemd timer) ---
65+
# Install a systemd timer that re-runs hardbox apply on a schedule.
66+
hardbox_timer_enabled: false
67+
68+
# OnCalendar value for the systemd timer (systemd time syntax).
69+
hardbox_timer_schedule: "daily"
70+
71+
# OnBootSec — delay after boot before the first run.
72+
hardbox_timer_on_boot_sec: "5min"
73+
74+
# --- Upgrade ---
75+
# Re-install hardbox even if the binary is already present at the target version.
76+
hardbox_force_reinstall: false
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
# hardbox Ansible role — handlers
3+
4+
- name: Verify hardbox installation
5+
ansible.builtin.command: "{{ _hardbox_bin }} version"
6+
changed_when: false
7+
become: true
8+
9+
- name: Reload systemd daemon
10+
ansible.builtin.systemd:
11+
daemon_reload: true
12+
13+
- name: Restart hardbox timer
14+
ansible.builtin.systemd:
15+
name: hardbox-harden.timer
16+
state: restarted
17+
enabled: true

ansible-role/hardbox/meta/main.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
galaxy_info:
3+
role_name: hardbox
4+
author: jackby03
5+
description: >
6+
Ansible role to install, configure, and run hardbox — a Linux system
7+
hardening tool with built-in compliance profiles (CIS, NIST, STIG,
8+
PCI-DSS, HIPAA, ISO 27001, and cloud provider benchmarks).
9+
license: MIT
10+
min_ansible_version: "2.14"
11+
12+
platforms:
13+
- name: Ubuntu
14+
versions:
15+
- jammy # 22.04 LTS
16+
- focal # 20.04 LTS
17+
- name: Debian
18+
versions:
19+
- bullseye # 11
20+
- bookworm # 12
21+
- name: EL
22+
versions:
23+
- "8"
24+
- "9"
25+
26+
galaxy_tags:
27+
- security
28+
- hardening
29+
- compliance
30+
- cis
31+
- nist
32+
- stig
33+
- pci
34+
- hipaa
35+
36+
dependencies: []
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
- name: Converge
3+
hosts: all
4+
become: true
5+
6+
pre_tasks:
7+
- name: Update apt cache (Debian/Ubuntu)
8+
ansible.builtin.apt:
9+
update_cache: true
10+
cache_valid_time: 3600
11+
when: ansible_os_family == "Debian"
12+
13+
roles:
14+
- role: hardbox
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
---
2+
dependency:
3+
name: galaxy
4+
5+
driver:
6+
name: docker
7+
8+
platforms:
9+
- name: hardbox-ubuntu-2204
10+
image: geerlingguy/docker-ubuntu2204-ansible:latest
11+
pre_build_image: true
12+
privileged: true
13+
volumes:
14+
- /sys/fs/cgroup:/sys/fs/cgroup:rw
15+
cgroupns_mode: host
16+
command: /lib/systemd/systemd
17+
18+
- name: hardbox-debian-12
19+
image: geerlingguy/docker-debian12-ansible:latest
20+
pre_build_image: true
21+
privileged: true
22+
volumes:
23+
- /sys/fs/cgroup:/sys/fs/cgroup:rw
24+
cgroupns_mode: host
25+
command: /lib/systemd/systemd
26+
27+
- name: hardbox-rockylinux-9
28+
image: geerlingguy/docker-rockylinux9-ansible:latest
29+
pre_build_image: true
30+
privileged: true
31+
volumes:
32+
- /sys/fs/cgroup:/sys/fs/cgroup:rw
33+
cgroupns_mode: host
34+
command: /lib/systemd/systemd
35+
36+
provisioner:
37+
name: ansible
38+
playbooks:
39+
converge: converge.yml
40+
verify: verify.yml
41+
inventory:
42+
group_vars:
43+
all:
44+
hardbox_profile: cis-level1
45+
hardbox_apply: true
46+
hardbox_dry_run: true # use dry-run in CI to avoid kernel changes in containers
47+
hardbox_fetch_report: false
48+
hardbox_fail_on_critical: false # containers lack some kernel features; relax thresholds
49+
hardbox_fail_on_high: false
50+
51+
verifier:
52+
name: ansible
53+
54+
lint: |
55+
set -e
56+
yamllint .
57+
ansible-lint
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
- name: Verify
3+
hosts: all
4+
become: true
5+
6+
tasks:
7+
- name: Check hardbox binary is installed
8+
ansible.builtin.stat:
9+
path: /usr/local/bin/hardbox
10+
register: _hardbox_bin_stat
11+
12+
- name: Assert hardbox binary exists and is executable
13+
ansible.builtin.assert:
14+
that:
15+
- _hardbox_bin_stat.stat.exists
16+
- _hardbox_bin_stat.stat.executable
17+
fail_msg: "hardbox binary not found or not executable at /usr/local/bin/hardbox"
18+
19+
- name: Run hardbox version
20+
ansible.builtin.command: /usr/local/bin/hardbox version
21+
register: _hardbox_version_output
22+
changed_when: false
23+
24+
- name: Assert hardbox version output is non-empty
25+
ansible.builtin.assert:
26+
that:
27+
- _hardbox_version_output.rc == 0
28+
- _hardbox_version_output.stdout | length > 0
29+
fail_msg: "hardbox version command failed: {{ _hardbox_version_output.stderr }}"
30+
31+
- name: Check report directory exists
32+
ansible.builtin.stat:
33+
path: /var/lib/hardbox/reports
34+
register: _hardbox_report_dir
35+
36+
- name: Assert report directory exists with correct permissions
37+
ansible.builtin.assert:
38+
that:
39+
- _hardbox_report_dir.stat.exists
40+
- _hardbox_report_dir.stat.isdir
41+
- _hardbox_report_dir.stat.mode == "0750"
42+
fail_msg: "Report directory /var/lib/hardbox/reports missing or has wrong permissions"
43+
44+
- name: Find generated report files
45+
ansible.builtin.find:
46+
paths: /var/lib/hardbox/reports
47+
patterns: "hardbox-*.html"
48+
register: _hardbox_reports
49+
50+
- name: Assert at least one report was generated
51+
ansible.builtin.assert:
52+
that: _hardbox_reports.matched >= 1
53+
fail_msg: "No hardbox report files found in /var/lib/hardbox/reports"

0 commit comments

Comments
 (0)