feat: port configure actions (base, ufw, crowdsec, cron, systemd, routing)
This commit is contained in:
1 parent
63c4b6c7eb
commit
05469332e8
7 files changed
+158
No files matched your search
@@ -0,0 +1,31 @@
|
||||
# actions/configure/base.py
|
||||
"""Port of configure/base — base packages + ufw + ufw-docker helper."""
|
||||
import os, shutil, stat, urllib.request
|
||||
from engine.descriptor import Meta
|
||||
|
||||
METADATA = Meta(summary="Configure base system packages (curl, wget, git, rsyslog, ufw, ufw-docker).")
|
||||
UFW_DOCKER_URL = "https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker"
|
||||
|
||||
def run(ctx, args):
|
||||
log, s = ctx.log, ctx.sys
|
||||
log.info("Starting base system initialization...")
|
||||
if not os.path.isfile("/etc/debian_version"):
|
||||
log.error("Requires a Debian-based system (Debian/Ubuntu)."); raise SystemExit(1)
|
||||
log.info("Updating package lists..."); s.sudo(["apt-get", "update", "-y"])
|
||||
log.info("Installing essential packages...")
|
||||
s.sudo(["apt-get", "install", "-y", "curl", "wget", "git", "rsyslog"])
|
||||
s.ensure_running("rsyslog")
|
||||
if not shutil.which("ufw"):
|
||||
log.info("Installing UFW..."); s.sudo(["apt-get", "install", "-y", "ufw"])
|
||||
else:
|
||||
log.info("UFW already installed.")
|
||||
binp = os.path.expanduser("~/.local/bin/ufw-docker")
|
||||
if not (os.path.isfile(binp) and os.access(binp, os.X_OK)):
|
||||
log.info("Downloading ufw-docker helper...")
|
||||
os.makedirs(os.path.dirname(binp), exist_ok=True)
|
||||
urllib.request.urlretrieve(UFW_DOCKER_URL, binp) # stdlib; replaces wget/curl
|
||||
os.chmod(binp, os.stat(binp).st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
log.success(f"ufw-docker downloaded to {binp}.")
|
||||
else:
|
||||
log.info(f"ufw-docker already exists at {binp}.")
|
||||
log.success("Base system initialization completed.")
|
||||
@@ -0,0 +1,14 @@
|
||||
# actions/configure/cron.py
|
||||
"""Port of configure/cron — install crontab from configs/cron/crontab."""
|
||||
import os
|
||||
from engine.descriptor import Meta, Flag
|
||||
|
||||
METADATA = Meta(summary="Install the node crontab from configs/cron/crontab.",
|
||||
args=[Flag("--dry-run", "Render + preview; do not install.")])
|
||||
|
||||
def run(ctx, args):
|
||||
crontab = os.path.join(ctx.paths.configs, "cron", "crontab")
|
||||
if not os.path.isfile(crontab):
|
||||
ctx.log.error(f"Crontab file not found: {crontab}"); raise SystemExit(1)
|
||||
text = ctx.tpl.render(crontab, ctx.vars())
|
||||
ctx.host.install_crontab(text, dry_run=args.dry_run)
|
||||
@@ -0,0 +1,24 @@
|
||||
# actions/configure/crowdsec.py
|
||||
"""Port of configure/crowdsec — install, deploy /etc/crowdsec, collections, bouncer."""
|
||||
import os
|
||||
from engine.descriptor import Meta, Flag
|
||||
|
||||
METADATA = Meta(summary="Install + configure CrowdSec from configs/crowdsec.",
|
||||
args=[Flag("--dry-run", "Render only; do not write/reload.")])
|
||||
|
||||
def run(ctx, args):
|
||||
cfg = os.path.join(ctx.paths.configs, "crowdsec")
|
||||
if not os.path.isdir(cfg):
|
||||
ctx.log.error(f"Config directory not found: {cfg}"); raise SystemExit(1)
|
||||
ctx.log.info("Configuring CrowdSec...")
|
||||
if not args.dry_run:
|
||||
ctx.crowdsec.ensure_installed()
|
||||
ctx.crowdsec.deploy("crowdsec", ctx.vars(), dry_run=args.dry_run)
|
||||
if not args.dry_run:
|
||||
ctx.crowdsec.install_collections(["crowdsecurity/linux", "crowdsecurity/traefik"])
|
||||
bouncer = os.path.join(cfg, "bouncers", "crowdsec-firewall-bouncer.yaml.local")
|
||||
if os.path.isfile(bouncer) and not ctx.sys.ok(
|
||||
["bash", "-c", "dpkg -l | grep -q crowdsec-firewall-bouncer-iptables"]):
|
||||
ctx.log.info("Installing crowdsec-firewall-bouncer-iptables...")
|
||||
ctx.sys.sudo(["apt-get", "install", "-y", "crowdsec-firewall-bouncer-iptables"])
|
||||
ctx.log.success("Configured crowdsec.")
|
||||
@@ -0,0 +1,21 @@
|
||||
# actions/configure/routing.py
|
||||
"""Port of configure/routing — idempotent node routing (ip_forward, fwmark rule, table 100)."""
|
||||
from engine.descriptor import Meta
|
||||
|
||||
METADATA = Meta(summary="Idempotent node-level routing rules and routes.")
|
||||
|
||||
def run(ctx, args):
|
||||
log, s = ctx.log, ctx.sys
|
||||
log.info("Applying persistent node-level routing configuration...")
|
||||
s.sudo(["sysctl", "-w", "net.ipv4.ip_forward=1"])
|
||||
if s.ok(["bash", "-c", "sudo ip rule show | grep -q 'fwmark 0x1 lookup 100'"]):
|
||||
log.info("IP rule for mark 0x1 already exists.")
|
||||
else:
|
||||
s.run(["bash", "-c", "sudo ip rule add fwmark 0x1 lookup 100 priority 100 || true"])
|
||||
log.info("IP rule added for mark 0x1.")
|
||||
if s.ok(["bash", "-c", "sudo ip route show table 100 2>/dev/null | grep -q 'local default dev lo'"]):
|
||||
log.info("Local route in table 100 already exists.")
|
||||
else:
|
||||
s.run(["bash", "-c", "sudo ip route add local 0.0.0.0/0 dev lo table 100 || true"])
|
||||
log.info("Local route added to table 100.")
|
||||
log.success("Routing configuration applied.")
|
||||
@@ -0,0 +1,15 @@
|
||||
# actions/configure/systemd.py
|
||||
"""Port of configure/systemd — deploy + enable units from configs/systemd."""
|
||||
import os
|
||||
from engine.descriptor import Meta, Flag
|
||||
|
||||
METADATA = Meta(summary="Deploy + enable systemd units from configs/systemd.",
|
||||
args=[Flag("--dry-run", "Render only; do not write/enable.")])
|
||||
|
||||
def run(ctx, args):
|
||||
cfg = os.path.join(ctx.paths.configs, "systemd")
|
||||
if not os.path.isdir(cfg):
|
||||
ctx.log.error(f"Config directory not found: {cfg}"); raise SystemExit(1)
|
||||
ctx.log.info("Deploying systemd units...")
|
||||
ctx.systemd.deploy_units("systemd", ctx.vars(), dry_run=args.dry_run)
|
||||
ctx.log.success("Configured systemd.")
|
||||
@@ -0,0 +1,19 @@
|
||||
# actions/configure/ufw.py
|
||||
"""Port of configure/ufw — apply docker + host ufw rules from configs/ufw."""
|
||||
import os
|
||||
from engine.descriptor import Meta, Flag
|
||||
|
||||
METADATA = Meta(summary="Render + apply this node's UFW rules (configs/ufw).",
|
||||
args=[Flag("--dry-run", "Preview; do not apply.")])
|
||||
|
||||
def run(ctx, args):
|
||||
cfg = os.path.join(ctx.paths.configs, "ufw")
|
||||
if not os.path.isdir(cfg):
|
||||
ctx.log.error(f"Config directory not found: {cfg}"); raise SystemExit(1)
|
||||
docker_dir = os.path.join(cfg, "docker")
|
||||
host_dir = os.path.join(cfg, "host")
|
||||
ctx.log.info("Configuring UFW rules...")
|
||||
if not os.path.isdir(docker_dir):
|
||||
ctx.log.warn(f"Docker rules dir not found at {docker_dir}. Skipping ufw-docker rules.")
|
||||
ctx.ufw.apply(docker_dir, host_dir if os.path.isdir(host_dir) else None, dry_run=args.dry_run)
|
||||
ctx.log.success("Configured ufw.")
|
||||
Reference in new issue
Block a user