merge: testing → main (reconcile 2-week divergence)
This commit is contained in:
44
deploy/decnet-agent.service.j2
Normal file
44
deploy/decnet-agent.service.j2
Normal file
@@ -0,0 +1,44 @@
|
||||
[Unit]
|
||||
Description=DECNET Worker Agent (mTLS)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/SWARM-Mode
|
||||
After=network-online.target docker.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
# docker.sock is group-readable by 'docker'; the agent needs it for compose.
|
||||
SupplementaryGroups=docker
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.agent.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet agent --host 0.0.0.0 --port 8765 --agent-dir /etc/decnet/agent
|
||||
StandardOutput=append:/var/log/decnet/decnet.agent.log
|
||||
StandardError=append:/var/log/decnet/decnet.agent.log
|
||||
|
||||
# MACVLAN/IPVLAN management + scapy raw sockets. Granted via ambient caps so
|
||||
# the process starts unprivileged and keeps only these two bits.
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# {{ install_dir }} holds release slots + state; the agent reads them and writes its PID.
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,29 +0,0 @@
|
||||
[Unit]
|
||||
Description=DECNET API Service
|
||||
After=network.target docker.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=decnet
|
||||
Group=decnet
|
||||
WorkingDirectory=/path/to/DECNET
|
||||
# Ensure environment is loaded from the .env file
|
||||
EnvironmentFile=/path/to/DECNET/.env
|
||||
# Use the virtualenv python to run the decnet api command
|
||||
ExecStart=/path/to/DECNET/.venv/bin/decnet api
|
||||
|
||||
# Capabilities required to manage MACVLAN interfaces and network links without root
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
49
deploy/decnet-api.service.j2
Normal file
49
deploy/decnet-api.service.j2
Normal file
@@ -0,0 +1,49 @@
|
||||
[Unit]
|
||||
Description=DECNET API Service
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/REST-API-Reference
|
||||
After=network-online.target docker.service
|
||||
Wants=network-online.target
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
# docker.sock is group-readable by 'docker'; the API ingester tails container logs.
|
||||
SupplementaryGroups=docker
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.api.log
|
||||
# ProtectHome=read-only (below) makes the user's $HOME read-only inside
|
||||
# the unit's namespace, which breaks `docker compose build` because the
|
||||
# CLI writes ~/.docker/buildx/activity/. Redirect the docker CLI's
|
||||
# config root into install_dir (already in ReadWritePaths) so the
|
||||
# hardening stays on without crippling the build path.
|
||||
Environment=DOCKER_CONFIG={{ install_dir }}/.docker
|
||||
Environment=BUILDX_CONFIG={{ install_dir }}/.docker/buildx
|
||||
ExecStart={{ venv_dir }}/bin/decnet api
|
||||
StandardOutput=append:/var/log/decnet/decnet.api.log
|
||||
StandardError=append:/var/log/decnet/decnet.api.log
|
||||
|
||||
# MACVLAN/IPVLAN setup runs from the API lifespan when the embedded sniffer is on.
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW
|
||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
49
deploy/decnet-bus.service.j2
Normal file
49
deploy/decnet-bus.service.j2
Normal file
@@ -0,0 +1,49 @@
|
||||
[Unit]
|
||||
Description=DECNET Service Bus (host-local UNIX-socket pub/sub)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Service-Bus
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
# /run/decnet is created automatically with the RuntimeDirectory= directive
|
||||
# below (mode 0755, owned by User/Group) and cleaned up on stop. The bus
|
||||
# socket is placed inside it with 0660 perms so only the configured
|
||||
# DECNET group (--group) can connect. That group is rendered here so
|
||||
# `decnet init --group anti` results in a socket every worker running
|
||||
# as anti can actually connect() to — otherwise every worker falls
|
||||
# back to bus=None and the Workers panel sees no heartbeats.
|
||||
RuntimeDirectory=decnet
|
||||
RuntimeDirectoryMode=0755
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.bus.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet bus \
|
||||
--socket /run/decnet/bus.sock \
|
||||
--group {{ group }}
|
||||
StandardOutput=append:/var/log/decnet/decnet.bus.log
|
||||
StandardError=append:/var/log/decnet/decnet.bus.log
|
||||
|
||||
# No privileged network operations — UNIX-domain socket only.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths=/run/decnet /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
52
deploy/decnet-campaign-clusterer.service.j2
Normal file
52
deploy/decnet-campaign-clusterer.service.j2
Normal file
@@ -0,0 +1,52 @@
|
||||
[Unit]
|
||||
Description=DECNET Campaign Clusterer (identities → campaigns / operations)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#campaign-clusterer
|
||||
After=network-online.target decnet-bus.service decnet-clusterer.service
|
||||
Wants=network-online.target decnet-bus.service decnet-clusterer.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.campaign-clusterer.log
|
||||
# Subscribes to identity.>; falls back to a 60s slow-tick poll when
|
||||
# the bus is idle or unavailable. Reads AttackerIdentity rows,
|
||||
# projects them into the campaign-level similarity graph
|
||||
# (phase-handoff / shared-infra / temporal overlap / cohort), runs
|
||||
# union-find, writes campaigns rows + sets
|
||||
# attacker_identities.campaign_id, and publishes campaign.formed /
|
||||
# campaign.identity.assigned / campaign.merged / campaign.unmerged
|
||||
# plus the cross-family identity.campaign.assigned for identity-side
|
||||
# subscribers.
|
||||
#
|
||||
# Master-only: gated via MASTER_ONLY_COMMANDS in decnet/cli/gating.py.
|
||||
# Sits one layer above decnet-clusterer (the After=/Wants= ensures the
|
||||
# identity layer is up first; the campaign clusterer then wakes on
|
||||
# identity.> events fired by it).
|
||||
ExecStart={{ venv_dir }}/bin/decnet campaign-clusterer
|
||||
StandardOutput=append:/var/log/decnet/decnet.campaign-clusterer.log
|
||||
StandardError=append:/var/log/decnet/decnet.campaign-clusterer.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
46
deploy/decnet-canary.service.j2
Normal file
46
deploy/decnet-canary.service.j2
Normal file
@@ -0,0 +1,46 @@
|
||||
[Unit]
|
||||
Description=DECNET Canary Token Callback Receiver (HTTP + DNS)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#canary
|
||||
After=network-online.target decnet-bus.service decnet-api.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.canary.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet canary
|
||||
StandardOutput=append:/var/log/decnet/decnet.canary.log
|
||||
StandardError=append:/var/log/decnet/decnet.canary.log
|
||||
|
||||
# Bind low-numbered DNS port (53) and HTTP port (80/443) requires
|
||||
# CAP_NET_BIND_SERVICE; the default DECNET_CANARY_HTTP_PORT (8088)
|
||||
# and DECNET_CANARY_DNS_PORT (5353) are unprivileged, so the
|
||||
# capability is granted only when an operator overrides those to
|
||||
# privileged values via .env.local.
|
||||
AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
|
||||
# Persist canary blobs (operator uploads) under /var/lib/decnet —
|
||||
# the same posture the rest of the workers use for runtime data.
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet /var/lib/decnet
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
47
deploy/decnet-clusterer.service.j2
Normal file
47
deploy/decnet-clusterer.service.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
[Unit]
|
||||
Description=DECNET Identity Clusterer (per-IP observations → identities)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#identity-clusterer
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.clusterer.log
|
||||
# Subscribes to attacker.observed and attacker.scored; falls back to a
|
||||
# 60s slow-tick poll when the bus is idle or unavailable. Reads
|
||||
# Attacker rows, projects per-IP observations into the similarity
|
||||
# graph (JA3 / HASSH / payload-hash / C2-endpoint), runs union-find,
|
||||
# writes attacker_identities rows + sets attackers.identity_id, and
|
||||
# publishes identity.formed / identity.observation.linked /
|
||||
# identity.merged / identity.unmerged.
|
||||
#
|
||||
# Master-only: gated via MASTER_ONLY_COMMANDS in decnet/cli/gating.py.
|
||||
ExecStart={{ venv_dir }}/bin/decnet clusterer
|
||||
StandardOutput=append:/var/log/decnet/decnet.clusterer.log
|
||||
StandardError=append:/var/log/decnet/decnet.clusterer.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
42
deploy/decnet-collector.service.j2
Normal file
42
deploy/decnet-collector.service.j2
Normal file
@@ -0,0 +1,42 @@
|
||||
[Unit]
|
||||
Description=DECNET Collector (Docker log ingestion)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#collector
|
||||
After=network-online.target docker.service decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
# docker.sock is group-readable by 'docker'; the collector tails container logs.
|
||||
SupplementaryGroups=docker
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.collector.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet collect
|
||||
StandardOutput=append:/var/log/decnet/decnet.collector.log
|
||||
StandardError=append:/var/log/decnet/decnet.collector.log
|
||||
|
||||
# No privileged network operations.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
47
deploy/decnet-enrich.service.j2
Normal file
47
deploy/decnet-enrich.service.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
[Unit]
|
||||
Description=DECNET Threat-Intel Enrichment (GreyNoise + AbuseIPDB + abuse.ch)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#intel-enrichment
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.enrich.log
|
||||
# Subscribes to attacker.observed and attacker.scored; falls back to a 60s
|
||||
# slow-tick poll when the bus is idle or unavailable. Per attacker IP fans
|
||||
# out across the configured intel providers, writes the aggregate verdict
|
||||
# to attacker_intel, and publishes attacker.intel.enriched.
|
||||
#
|
||||
# Free-tier API keys are read from .env.local:
|
||||
# DECNET_GREYNOISE_API_KEY= (optional, lifts rate limit)
|
||||
# DECNET_ABUSEIPDB_API_KEY= (required for AbuseIPDB lookups)
|
||||
# DECNET_THREATFOX_API_KEY= (optional, lifts rate limit)
|
||||
ExecStart={{ venv_dir }}/bin/decnet enrich
|
||||
StandardOutput=append:/var/log/decnet/decnet.enrich.log
|
||||
StandardError=append:/var/log/decnet/decnet.enrich.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
49
deploy/decnet-forwarder.service.j2
Normal file
49
deploy/decnet-forwarder.service.j2
Normal file
@@ -0,0 +1,49 @@
|
||||
[Unit]
|
||||
Description=DECNET Syslog-over-TLS Forwarder (worker, RFC 5425)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Logging-and-Syslog
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# The forwarder can run independently of the agent — it only needs the local
|
||||
# log file to exist and the master to be reachable.
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
# Replace <master-host> with the master's LAN address or hostname. The agent
|
||||
# cert bundle at /etc/decnet/agent is reused — the forwarder presents the same
|
||||
# worker identity when it connects to the master's listener.
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.forwarder.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet forwarder \
|
||||
--log-file /var/log/decnet/decnet.log \
|
||||
--master-host ${DECNET_SWARM_MASTER_HOST} \
|
||||
--master-port 6514 \
|
||||
--agent-dir /etc/decnet/agent
|
||||
StandardOutput=append:/var/log/decnet/decnet.forwarder.log
|
||||
StandardError=append:/var/log/decnet/decnet.forwarder.log
|
||||
|
||||
# TLS client connection; no special capabilities.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# Reads the tailed log; writes a small byte-offset state file alongside it.
|
||||
ReadWritePaths=/var/log/decnet
|
||||
ReadOnlyPaths=/etc/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
46
deploy/decnet-listener.service.j2
Normal file
46
deploy/decnet-listener.service.j2
Normal file
@@ -0,0 +1,46 @@
|
||||
[Unit]
|
||||
Description=DECNET Syslog-over-TLS Listener (master, RFC 5425)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Logging-and-Syslog
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
# Binds 0.0.0.0:6514 so workers across the LAN can connect. 6514 is not a
|
||||
# privileged port (≥1024), so no CAP_NET_BIND_SERVICE is required.
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.listener.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet listener \
|
||||
--host 0.0.0.0 --port 6514 \
|
||||
--ca-dir /etc/decnet/ca \
|
||||
--log-path /var/log/decnet/master.log \
|
||||
--json-path /var/log/decnet/master.json
|
||||
StandardOutput=append:/var/log/decnet/decnet.listener.log
|
||||
StandardError=append:/var/log/decnet/decnet.listener.log
|
||||
|
||||
# Pure TLS server; no privileged network operations.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# Writes forensic .log + parsed .json sinks; CA bundle is read-only.
|
||||
ReadWritePaths=/var/log/decnet
|
||||
ReadOnlyPaths=/etc/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
41
deploy/decnet-mutator.service.j2
Normal file
41
deploy/decnet-mutator.service.j2
Normal file
@@ -0,0 +1,41 @@
|
||||
[Unit]
|
||||
Description=DECNET Mutator (runtime fleet mutation watch loop)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#mutator
|
||||
After=network-online.target docker.service decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
Requires=docker.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
# Mutator recomposes decky services via docker compose.
|
||||
SupplementaryGroups=docker
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.mutator.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet mutate --watch
|
||||
StandardOutput=append:/var/log/decnet/decnet.mutator.log
|
||||
StandardError=append:/var/log/decnet/decnet.mutator.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
50
deploy/decnet-orchestrator.service.j2
Normal file
50
deploy/decnet-orchestrator.service.j2
Normal file
@@ -0,0 +1,50 @@
|
||||
[Unit]
|
||||
Description=DECNET Orchestrator (synthetic life-injection — inter-decky traffic, file plants, email drops)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#orchestrator
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.orchestrator.log
|
||||
# Realism content engine — LLM + persona-pool config used by the
|
||||
# email + (post-stage-6) file-class enrichment paths. See
|
||||
# decnet/realism/llm/factory.py and decnet/realism/personas_pool.py.
|
||||
Environment=DECNET_REALISM_LLM=ollama
|
||||
Environment=DECNET_REALISM_MODEL=llama3.1
|
||||
Environment=DECNET_REALISM_TIMEOUT=60
|
||||
Environment=DECNET_REALISM_PERSONAS=/etc/decnet/email_personas.json
|
||||
ExecStart={{ venv_dir }}/bin/decnet orchestrate
|
||||
StandardOutput=append:/var/log/decnet/decnet.orchestrator.log
|
||||
StandardError=append:/var/log/decnet/decnet.orchestrator.log
|
||||
|
||||
# The orchestrator drives `docker exec` against decky containers, so it
|
||||
# needs membership in the docker group. It does NOT bind to the network,
|
||||
# launch new containers, or write outside its own logs and install dir.
|
||||
SupplementaryGroups=docker
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
39
deploy/decnet-prober.service.j2
Normal file
39
deploy/decnet-prober.service.j2
Normal file
@@ -0,0 +1,39 @@
|
||||
[Unit]
|
||||
Description=DECNET Prober (active realism / attacker fingerprint probes)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#prober
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.prober.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet probe
|
||||
StandardOutput=append:/var/log/decnet/decnet.prober.log
|
||||
StandardError=append:/var/log/decnet/decnet.prober.log
|
||||
|
||||
# TCP connect probes only — no raw sockets required.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
38
deploy/decnet-profiler.service.j2
Normal file
38
deploy/decnet-profiler.service.j2
Normal file
@@ -0,0 +1,38 @@
|
||||
[Unit]
|
||||
Description=DECNET Profiler (attacker profiling and scoring)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#profiler
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.profiler.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet profiler
|
||||
StandardOutput=append:/var/log/decnet/decnet.profiler.log
|
||||
StandardError=append:/var/log/decnet/decnet.profiler.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
47
deploy/decnet-reconciler.service.j2
Normal file
47
deploy/decnet-reconciler.service.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
[Unit]
|
||||
Description=DECNET Fleet Reconciler (converges decnet-state.json ↔ fleet_deckies DB ↔ docker)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#reconciler
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.reconciler.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet reconcile
|
||||
StandardOutput=append:/var/log/decnet/decnet.reconciler.log
|
||||
StandardError=append:/var/log/decnet/decnet.reconciler.log
|
||||
|
||||
# The reconciler queries the docker daemon (via `docker.from_env()`) to
|
||||
# observe per-container state. Membership in the docker group lets it
|
||||
# read /var/run/docker.sock without root. It does NOT exec into
|
||||
# containers, bind to the network, or spawn new containers.
|
||||
SupplementaryGroups=docker
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# Read-only access to /var/lib/decnet so we can read decnet-state.json.
|
||||
# Read-write access only to install_dir + log dir.
|
||||
ReadOnlyPaths=/var/lib/decnet
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
41
deploy/decnet-reuse-correlator.service.j2
Normal file
41
deploy/decnet-reuse-correlator.service.j2
Normal file
@@ -0,0 +1,41 @@
|
||||
[Unit]
|
||||
Description=DECNET Credential-Reuse Correlator (cross-target secret-reuse detection)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#reuse-correlator
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.reuse-correlator.log
|
||||
# Subscribes to credential.captured and attacker.observed; falls back to
|
||||
# a 60s slow-tick poll when the bus is idle or unavailable. Publishes
|
||||
# credential.reuse.detected once per new/grown finding.
|
||||
ExecStart={{ venv_dir }}/bin/decnet reuse-correlate
|
||||
StandardOutput=append:/var/log/decnet/decnet.reuse-correlator.log
|
||||
StandardError=append:/var/log/decnet/decnet.reuse-correlator.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
39
deploy/decnet-sniffer.service.j2
Normal file
39
deploy/decnet-sniffer.service.j2
Normal file
@@ -0,0 +1,39 @@
|
||||
[Unit]
|
||||
Description=DECNET Sniffer (fleet-wide MACVLAN TLS fingerprinting)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#sniffer
|
||||
After=network-online.target decnet-bus.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.sniffer.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet sniffer
|
||||
StandardOutput=append:/var/log/decnet/decnet.sniffer.log
|
||||
StandardError=append:/var/log/decnet/decnet.sniffer.log
|
||||
|
||||
# scapy needs raw packet access on the MACVLAN host interface.
|
||||
CapabilityBoundingSet=CAP_NET_RAW
|
||||
AmbientCapabilities=CAP_NET_RAW
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
43
deploy/decnet-swarmctl.service.j2
Normal file
43
deploy/decnet-swarmctl.service.j2
Normal file
@@ -0,0 +1,43 @@
|
||||
[Unit]
|
||||
Description=DECNET Swarm Controller (master)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/SWARM-Mode
|
||||
After=network-online.target decnet-api.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
# Default bind is loopback — the controller is a master-local orchestrator
|
||||
# reached by the CLI and the web dashboard, not by workers.
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.swarmctl.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet swarmctl --host 127.0.0.1 --port 8770
|
||||
StandardOutput=append:/var/log/decnet/decnet.swarmctl.log
|
||||
StandardError=append:/var/log/decnet/decnet.swarmctl.log
|
||||
|
||||
# No special capabilities — the controller issues mTLS certs and talks to
|
||||
# workers over TCP on unprivileged ports.
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# Reads/writes the CA bundle and the master DB.
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
ReadOnlyPaths=/etc/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
52
deploy/decnet-updater.service.j2
Normal file
52
deploy/decnet-updater.service.j2
Normal file
@@ -0,0 +1,52 @@
|
||||
[Unit]
|
||||
Description=DECNET Self-Updater (mTLS)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Remote-Updates
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
# Deliberately NOT After=decnet-agent.service — the updater must come up even
|
||||
# when the agent is broken, since that is exactly when it is most useful.
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.updater.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet updater \
|
||||
--host 0.0.0.0 --port 8766 \
|
||||
--updater-dir /etc/decnet/updater \
|
||||
--install-dir {{ install_dir }} \
|
||||
--agent-dir /etc/decnet/agent
|
||||
StandardOutput=append:/var/log/decnet/decnet.updater.log
|
||||
StandardError=append:/var/log/decnet/decnet.updater.log
|
||||
|
||||
# The updater SIGTERMs the agent and spawns a new one. Same User=decnet means
|
||||
# signalling is allowed without CAP_KILL. It does not need NET_ADMIN/NET_RAW
|
||||
# itself — the new agent process picks those up from decnet-agent.service when
|
||||
# systemd restarts it (or from the agent's own unit's AmbientCapabilities when
|
||||
# spawned by the updater as a direct child).
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
# Writes release slots, pip installs into venv, manages agent.pid.
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
# Self-update replaces the process image via os.execv; the new binary answers
|
||||
# /health within 30 s. Give it headroom before systemd's own termination.
|
||||
TimeoutStopSec=30
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,30 +0,0 @@
|
||||
[Unit]
|
||||
Description=DECNET Web Dashboard Service
|
||||
After=network.target decnet-api.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=decnet
|
||||
Group=decnet
|
||||
WorkingDirectory=/path/to/DECNET
|
||||
# Ensure environment is loaded from the .env file
|
||||
EnvironmentFile=/path/to/DECNET/.env
|
||||
# Use the virtualenv python to run the decnet web command
|
||||
ExecStart=/path/to/DECNET/.venv/bin/decnet web
|
||||
|
||||
# The Web Dashboard service does not require network administration privileges.
|
||||
# Enable the following lines if you wish to bind the Dashboard to a privileged port (e.g., 80 or 443)
|
||||
# while still running as a non-root user.
|
||||
# CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
# AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
41
deploy/decnet-web.service.j2
Normal file
41
deploy/decnet-web.service.j2
Normal file
@@ -0,0 +1,41 @@
|
||||
[Unit]
|
||||
Description=DECNET Web Dashboard Service
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Web-Dashboard
|
||||
After=network-online.target decnet-api.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.web.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet web
|
||||
StandardOutput=append:/var/log/decnet/decnet.web.log
|
||||
StandardError=append:/var/log/decnet/decnet.web.log
|
||||
|
||||
# Uncomment if you bind the dashboard to a privileged port (80/443):
|
||||
# CapabilityBoundingSet=CAP_NET_BIND_SERVICE
|
||||
# AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
ReadOnlyPaths=/etc/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
38
deploy/decnet-webhook.service.j2
Normal file
38
deploy/decnet-webhook.service.j2
Normal file
@@ -0,0 +1,38 @@
|
||||
[Unit]
|
||||
Description=DECNET Webhook Dispatcher (external SIEM/SOAR egress)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers#webhook
|
||||
After=network-online.target decnet-bus.service decnet-api.service
|
||||
Wants=network-online.target decnet-bus.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User={{ user }}
|
||||
Group={{ group }}
|
||||
WorkingDirectory={{ install_dir }}
|
||||
EnvironmentFile=-{{ install_dir }}/.env.local
|
||||
Environment=DECNET_SYSTEM_LOGS=/var/log/decnet/decnet.webhook.log
|
||||
ExecStart={{ venv_dir }}/bin/decnet webhook
|
||||
StandardOutput=append:/var/log/decnet/decnet.webhook.log
|
||||
StandardError=append:/var/log/decnet/decnet.webhook.log
|
||||
|
||||
CapabilityBoundingSet=
|
||||
AmbientCapabilities=
|
||||
|
||||
# Security Hardening
|
||||
NoNewPrivileges=yes
|
||||
ProtectSystem=full
|
||||
ProtectHome=read-only
|
||||
PrivateTmp=yes
|
||||
ProtectKernelTunables=yes
|
||||
ProtectKernelModules=yes
|
||||
ProtectControlGroups=yes
|
||||
RestrictSUIDSGID=yes
|
||||
LockPersonality=yes
|
||||
ReadWritePaths={{ install_dir }} /var/log/decnet
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
TimeoutStopSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
27
deploy/decnet.target
Normal file
27
deploy/decnet.target
Normal file
@@ -0,0 +1,27 @@
|
||||
[Unit]
|
||||
Description=DECNET honeypot framework (all master-host workers)
|
||||
Documentation=https://git.resacachile.cl/anti/DECNET/wiki/Workers
|
||||
# Bring workers up in dependency order: bus first (everything else publishes
|
||||
# heartbeats to it), then the API + data-plane workers. systemd resolves the
|
||||
# actual ordering via each unit's own After=/Wants= on decnet-bus.service —
|
||||
# this target is a convenience grouping, not an ordering primitive.
|
||||
Wants=decnet-bus.service \
|
||||
decnet-api.service \
|
||||
decnet-web.service \
|
||||
decnet-collector.service \
|
||||
decnet-profiler.service \
|
||||
decnet-sniffer.service \
|
||||
decnet-prober.service \
|
||||
decnet-mutator.service \
|
||||
decnet-reconciler.service \
|
||||
decnet-reuse-correlator.service \
|
||||
decnet-enrich.service \
|
||||
decnet-clusterer.service \
|
||||
decnet-campaign-clusterer.service \
|
||||
decnet-webhook.service \
|
||||
decnet-canary.service \
|
||||
decnet-orchestrator.service
|
||||
After=decnet-bus.service
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
28
deploy/logrotate.d/decnet
Normal file
28
deploy/logrotate.d/decnet
Normal file
@@ -0,0 +1,28 @@
|
||||
# /etc/logrotate.d/decnet — installed by `decnet init`.
|
||||
#
|
||||
# Without this, /var/log/decnet/ grows unbounded — the syslog listener writes
|
||||
# every forwarded worker line, the collector tails every container's stdout,
|
||||
# and a noisy attacker (or an active probe storm) can fill the disk in hours.
|
||||
# Bound to 7 daily rotations + size cap so a single bad day doesn't run away.
|
||||
#
|
||||
# Files we rotate:
|
||||
# - decnet.log: master ingest sink (DECNET_INGEST_LOG_FILE).
|
||||
# - agent.log: per-worker collector sink (DECNET_AGENT_LOG_FILE).
|
||||
# - *.log: any other component sink under /var/log/decnet/.
|
||||
#
|
||||
# `copytruncate` is required: the ingester / forwarder hold the file open via
|
||||
# Python and would otherwise keep writing to the deleted inode after rotation.
|
||||
# `notifempty` avoids spurious .1 files on quiet hosts.
|
||||
|
||||
/var/log/decnet/*.log {
|
||||
daily
|
||||
rotate 7
|
||||
maxsize 100M
|
||||
copytruncate
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
su decnet decnet
|
||||
create 0640 decnet decnet
|
||||
}
|
||||
23
deploy/polkit/50-decnet-workers.rules.j2
Normal file
23
deploy/polkit/50-decnet-workers.rules.j2
Normal file
@@ -0,0 +1,23 @@
|
||||
// Allow members of the '{{ group }}' group to manage DECNET systemd units
|
||||
// (start / stop / restart / reload) without a password prompt.
|
||||
//
|
||||
// Scope is locked to units matching `decnet-<name>.service` or the
|
||||
// `decnet.target` grouping unit. Any other unit is unaffected by this
|
||||
// rule and still goes through the default polkit policy.
|
||||
//
|
||||
// The group name is rendered at `decnet init` time from --group; the
|
||||
// default is `decnet`, but dev boxes that pass --group $USER get a
|
||||
// rule that matches the operator's own login group.
|
||||
//
|
||||
// Install: /etc/polkit-1/rules.d/50-decnet-workers.rules
|
||||
|
||||
polkit.addRule(function(action, subject) {
|
||||
if (action.id == "org.freedesktop.systemd1.manage-units") {
|
||||
var unit = action.lookup("unit");
|
||||
if (unit &&
|
||||
/^decnet-[a-z]+\.service$|^decnet\.target$/.test(unit) &&
|
||||
subject.isInGroup("{{ group }}")) {
|
||||
return polkit.Result.YES;
|
||||
}
|
||||
}
|
||||
});
|
||||
4
deploy/tmpfiles.d/decnet.conf
Normal file
4
deploy/tmpfiles.d/decnet.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
# /run/decnet hosts bus.sock (UDS, 0660, group=decnet).
|
||||
# tmpfiles.d recreates it on every boot before any decnet-*.service starts,
|
||||
# so the bus worker never silently falls back to ~/.decnet/bus.sock.
|
||||
d /run/decnet 0755 root decnet -
|
||||
Reference in New Issue
Block a user