Added draft for CSP health checker

This commit is contained in:
2025-05-13 09:10:20 +02:00
parent 72baa9ea28
commit 23496f2fab
18 changed files with 424 additions and 0 deletions

View File

View File

@@ -0,0 +1,43 @@
const puppeteer = require('puppeteer');
const domains = process.argv.slice(2);
(async () => {
let errorCounter = 0;
const browser = await puppeteer.launch({ headless: 'new' });
for (const domain of domains) {
const page = await browser.newPage();
const blockedResources = [];
page.on('requestfailed', request => {
const reason = request.failure()?.errorText || '';
if (reason.includes('blocked')) {
blockedResources.push({ url: request.url(), reason });
}
});
try {
const url = `https://${domain}`;
await page.goto(url, { waitUntil: 'networkidle2', timeout: 20000 });
} catch (e) {
console.error(`${domain}: ERROR visiting site - ${e.message}`);
errorCounter++;
continue;
}
if (blockedResources.length > 0) {
console.warn(`${domain}: Blocked resources detected:`);
blockedResources.forEach(r =>
console.log(` BLOCKED by CSP: ${r.url} (${r.reason})`)
);
errorCounter++;
} else {
console.log(`${domain}: ✅ No CSP blocks detected.`);
}
await page.close();
}
await browser.close();
process.exit(errorCounter);
})();

View File

@@ -0,0 +1,66 @@
#!/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$')
domains = []
try:
for filename in os.listdir(config_path):
if filename.endswith(".conf") and domain_pattern.match(filename):
domain = filename[:-5] # Remove ".conf"
domains.append(domain)
except FileNotFoundError:
print(f"Directory {config_path} not found.", file=sys.stderr)
return None
return domains
def run_node_checker(script_path, domains):
"""
Executes the Node.js CSP checker script with the given domains.
"""
try:
result = subprocess.run(
["/usr/bin/node", script_path] + domains,
check=True
)
return result.returncode
except subprocess.CalledProcessError as e:
print(f"{os.path.basename(script_path)} reported issues (exit code {e.returncode})")
return e.returncode
except Exception as e:
print(f"Unexpected error: {e}", file=sys.stderr)
return 1
def main():
parser = argparse.ArgumentParser(description="Check CSP-blocked resources via Puppeteer")
parser.add_argument("--nginx-config-dir", required=True, help="Directory containing NGINX .conf files")
parser.add_argument("--script", required=True, help="Path to Node.js CSP checker script")
args = parser.parse_args()
domains = extract_domains(args.nginx_config_dir)
if domains is None:
return 1
if not domains:
print("No domains found to check.")
return 0
return run_node_checker(args.script, domains)
if __name__ == "__main__":
sys.exit(main())