Refactor systemctl services and categories due to alarm bugs

This commit restructures systemctl service definitions and category mappings.

Motivation: Alarm-related bugs revealed inconsistencies in service and role handling.

Preparation step: lays the groundwork for fixing the alarm issues by aligning categories, roles, and service templates.
This commit is contained in:
2025-08-18 13:35:43 +02:00
parent 29f50da226
commit 3a839cfe37
289 changed files with 975 additions and 948 deletions

View File

@@ -0,0 +1,27 @@
# Health CSP Crawler
## Description
This Ansible role automates the validation of [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP) enforcement for all configured domains by crawling them using a [CSP Checker](https://github.com/kevinveenbirkenbach/csp-checker).
## Overview
Designed for Archlinux systems, this role periodically checks whether web resources (JavaScript, fonts, images, etc.) are blocked by CSP headers. It integrates Python and Node.js tooling and installs a systemd service with timer support.
## Features
- **CSP Resource Validation:** Uses Puppeteer to simulate browser requests and detect blocked resources.
- **Domain Extraction:** Parses all `.conf` files in the NGINX config folder to determine the list of domains to check.
- **Automated Execution:** Registers a systemd service and timer for recurring health checks.
- **Error Notification:** Integrates with `sys-ctl-alm-compose` for alerting on failure.
## License
Infinito.Nexus NonCommercial License
[https://s.infinito.nexus/license](https://s.infinito.nexus/license)
## Author
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
[https://www.veen.world](https://www.veen.world)

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
import argparse
def extract_domains(config_path):
"""
Extracts domain names from .conf filenames in the given directory.
"""
domain_pattern = re.compile(r'^([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\.conf$')
try:
return [
fn[:-5]
for fn in os.listdir(config_path)
if fn.endswith(".conf") and domain_pattern.match(fn)
]
except FileNotFoundError:
print(f"Directory {config_path} not found.", file=sys.stderr)
return None
def run_checkcsp(domains):
"""
Executes the 'checkcsp' command with the given domains.
"""
cmd = ["checkcsp", "start", "--short"] + domains
try:
result = subprocess.run(cmd, check=True)
return result.returncode
except subprocess.CalledProcessError as e:
print(f"'checkcsp' reported issues (exit code {e.returncode})", file=sys.stderr)
return e.returncode
except Exception as e:
print(f"Unexpected error: {e}", file=sys.stderr)
return 1
def main():
parser = argparse.ArgumentParser(
description="Extract domains from NGINX and run checkcsp against them"
)
parser.add_argument(
"--nginx-config-dir",
required=True,
help="Directory containing NGINX .conf files"
)
args = parser.parse_args()
domains = extract_domains(args.nginx_config_dir)
if domains is None:
sys.exit(1)
if not domains:
print("No domains found to check.")
sys.exit(0)
rc = run_checkcsp(domains)
sys.exit(rc)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,12 @@
- name: "reload sys-ctl-hlth-csp service"
systemd:
name: sys-ctl-hlth-csp{{ SYS_SERVICE_SUFFIX }}
enabled: yes
daemon_reload: yes
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"
- name: rebuild checkcsp docker image
shell: checkcsp build
async: "{{ ASYNC_TIME if ASYNC_ENABLED | bool else omit }}"
poll: "{{ ASYNC_POLL if ASYNC_ENABLED | bool else omit }}"

View File

@@ -0,0 +1,25 @@
galaxy_info:
author: "Kevin Veen-Birkenbach"
description: "Checks for CSP-blocked resources via Puppeteer-based Node.js crawler"
license: "Infinito.Nexus NonCommercial License"
license_url: "https://s.infinito.nexus/license"
company: |
Kevin Veen-Birkenbach
Consulting & Coaching Solutions
https://www.veen.world
min_ansible_version: "2.9"
platforms:
- name: Archlinux
versions:
- rolling
galaxy_tags:
- csp
- puppeteer
- health
- browser
- nodejs
- monitoring
- systemd
repository: "https://s.infinito.nexus/code"
issue_tracker_url: "https://s.infinito.nexus/issues"
documentation: "https://docs.infinito.nexus"

View File

@@ -0,0 +1,39 @@
- name: Include dependency 'sys-ctl-alm-compose'
include_role:
name: sys-ctl-alm-compose
when: run_once_sys_ctl_alm_compose is not defined
- name: "pkgmgr install"
include_role:
name: pkgmgr-install
vars:
package_name: checkcsp
package_notify: rebuild checkcsp docker image
- name: "create {{ health_csp_crawler_folder }}"
file:
path: "{{ health_csp_crawler_folder }}"
state: directory
mode: "0755"
- name: copy sys-ctl-hlth-csp.py
copy:
src: sys-ctl-hlth-csp.py
dest: "{{ health_csp_crawler_script }}"
mode: "0755"
- name: create sys-ctl-hlth-csp{{ SYS_SERVICE_SUFFIX }}
template:
src: sys-ctl-hlth-csp.service.j2
dest: /etc/systemd/system/sys-ctl-hlth-csp{{ SYS_SERVICE_SUFFIX }}
notify: reload sys-ctl-hlth-csp service
- name: set service_name to role_name
set_fact:
service_name: "{{ role_name }}"
- name: include systemd timer role
include_role:
name: sys-timer
vars:
on_calendar: "{{ SYS_SCHEDULE_HEALTH_CSP_CRAWLER }}"

View File

@@ -0,0 +1,4 @@
- block:
- include_tasks: 01_core.yml
- include_tasks: utils/run_once.yml
when: run_once_sys_ctl_hlth_csp is not defined

View File

@@ -0,0 +1,8 @@
[Unit]
Description=Check for CSP-blocked resources via Puppeteer
OnFailure=sys-ctl-alm-compose.{{ SOFTWARE_NAME }}@%n.service
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 {{ health_csp_crawler_script }} \
--nginx-config-dir={{ NGINX.DIRECTORIES.HTTP.SERVERS }}

View File

@@ -0,0 +1,3 @@
health_csp_crawler_folder: '{{ PATH_ADMINISTRATOR_SCRIPTS }}sys-ctl-hlth-csp/'
health_csp_crawler_script: '{{ health_csp_crawler_folder }}sys-ctl-hlth-csp.py'