Commit Graph

402 Commits

Author SHA1 Message Date
6ed92d080f fix: invoke uvicorn via sys.executable to handle sudo PATH restrictions 2026-04-07 15:39:32 -04:00
1b593920cd feat: add --api flag to deploy and new web command for dashboard 2026-04-07 15:32:04 -04:00
bad90dfb75 feat: implement background log ingestion from local file 2026-04-07 15:30:44 -04:00
05e71f6d2e feat: frontend support for mandatory password change and react-router integration 2026-04-07 15:16:11 -04:00
52c26a2891 feat: backend support for mandatory password change on first login 2026-04-07 15:15:03 -04:00
81135cb861 fix: switch to direct bcrypt usage for Python 3.14 compatibility 2026-04-07 15:07:46 -04:00
50e53120df feat: initialize React frontend with minimalistic Matrix theme 2026-04-07 15:05:06 -04:00
697929a127 feat: implement Stats endpoints for web dashboard 2026-04-07 14:58:09 -04:00
b46934db46 feat: implement Logs endpoints for web dashboard 2026-04-07 14:56:25 -04:00
5b990743db feat: implement Auth endpoints for web dashboard 2026-04-07 14:54:36 -04:00
fbb16a960c feat: add web dashboard dependencies to support real-time monitoring 2026-04-07 14:51:37 -04:00
c32ad82d0a Modified README: added more examples to the config.ini section and modified instructions for quick setup. 2026-04-06 11:28:29 -04:00
850a6f2ad7 Finished: CI/CD pipeline. 2026-04-06 11:18:10 -04:00
d344e4c8bb revert f8a9f8fc64
revert Added: modified notes. Finished CI/CD pipeline.
2026-04-06 17:17:31 +02:00
f8a9f8fc64 Added: modified notes. Finished CI/CD pipeline.
All checks were successful
PR Gate / Lint (ruff) (pull_request) Successful in 18s
PR Gate / Test (pytest) (3.11) (pull_request) Successful in 20s
PR Gate / Test (pytest) (3.12) (pull_request) Successful in 22s
2026-04-06 11:10:56 -04:00
a428410c8e Modified README.md: added AI disclosure 2026-04-06 11:09:44 -04:00
e5a6c2d9a7 Skip CI on markdown-only changes
All checks were successful
CI / Lint (ruff) (push) Successful in 16s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 20s
CI / SAST (bandit) (push) Successful in 12s
CI / Dependency audit (pip-audit) (push) Successful in 19s
CI / Open PR to main (push) Successful in 6s
PR Gate / Lint (ruff) (pull_request) Successful in 11s
PR Gate / Test (pytest) (3.11) (pull_request) Successful in 18s
PR Gate / Test (pytest) (3.12) (pull_request) Successful in 20s
2026-04-04 23:07:40 -04:00
ea409650fa Trigger CI: token now has repo:write permission
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 18s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 19s
CI / Open PR to main (push) Successful in 5s
PR Gate / Lint (ruff) (pull_request) Successful in 10s
PR Gate / Test (pytest) (3.11) (pull_request) Successful in 17s
PR Gate / Test (pytest) (3.12) (pull_request) Successful in 18s
2026-04-04 17:54:37 -03:00
d92aa99b81 Add DEVELOPMENT.md for CI/CD pipeline test
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 17s
CI / Test (pytest) (3.12) (push) Successful in 19s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 19s
CI / Open PR to main (push) Successful in 4s
2026-04-04 17:51:51 -03:00
fc7fca998f Add API response logging to open-pr step for debugging
All checks were successful
CI / Lint (ruff) (push) Successful in 10s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 18s
CI / SAST (bandit) (push) Successful in 11s
CI / Dependency audit (pip-audit) (push) Successful in 18s
CI / Open PR to main (push) Successful in 3s
2026-04-04 17:47:43 -03:00
ed749a8c31 Merge security jobs into CI workflow so open-pr needs all checks
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 19s
CI / SAST (bandit) (push) Successful in 12s
CI / Dependency audit (pip-audit) (push) Successful in 18s
CI / Open PR to main (push) Successful in 4s
2026-04-04 17:43:55 -03:00
cf36ebcd84 Auto-open PR to main when CI passes on dev
Some checks failed
CI / Lint (ruff) (push) Successful in 13s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 20s
Security / SAST (bandit) (push) Successful in 12s
CI / Open PR to main (push) Has been cancelled
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:42:42 -03:00
6a5c6f098e Remove accidentally committed artifacts and update .gitignore
All checks were successful
CI / Lint (ruff) (push) Successful in 11s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 18s
Security / SAST (bandit) (push) Successful in 12s
Security / Dependency audit (pip-audit) (push) Successful in 19s
2026-04-04 17:36:35 -03:00
988732f4f9 Fix all ruff lint errors across decnet/, templates/, and tests/
Some checks failed
CI / Test (pytest) (3.11) (push) Has been cancelled
CI / Test (pytest) (3.12) (push) Has been cancelled
Security / SAST (bandit) (push) Has been cancelled
Security / Dependency audit (pip-audit) (push) Has been cancelled
CI / Lint (ruff) (push) Has been cancelled
2026-04-04 17:36:16 -03:00
4acfa3f779 Fix pip-audit skipping local editable package
Some checks failed
CI / Lint (ruff) (push) Failing after 10s
CI / Test (pytest) (3.11) (push) Successful in 18s
CI / Test (pytest) (3.12) (push) Successful in 19s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:31:16 -03:00
35c67ec34d Fix registry auto-discovery skipping non-service subclasses (CustomService)
Some checks failed
CI / Lint (ruff) (push) Failing after 11s
CI / Test (pytest) (3.11) (push) Successful in 19s
CI / Test (pytest) (3.12) (push) Successful in 18s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:29:30 -03:00
fe7354554f Add bandit, pip-audit and trivy to CI/CD security pipeline
Some checks failed
CI / Lint (ruff) (push) Failing after 10s
CI / Test (pytest) (3.11) (push) Failing after 39s
CI / Test (pytest) (3.12) (push) Failing after 1m4s
Security / SAST (bandit) (push) Successful in 11s
Security / Dependency audit (pip-audit) (push) Successful in 18s
2026-04-04 17:24:43 -03:00
b3b3597011 Add smoke test: verify all modules import cleanly
Some checks failed
CI / Lint (ruff) (push) Failing after 4s
CI / Test (pytest) (3.11) (push) Failing after 3s
CI / Test (pytest) (3.12) (push) Failing after 4s
2026-04-04 17:18:21 -03:00
38b1efa8c0 Add Gitea Actions CI/CD workflows and ruff dependency
Some checks failed
CI / Test (pytest) (3.11) (push) Failing after 3s
CI / Test (pytest) (3.12) (push) Failing after 3s
CI / Lint (ruff) (push) Failing after 1m49s
2026-04-04 17:16:45 -03:00
d7a6aeff86 dev: add pytest as core dependency 2026-04-04 16:29:17 -03:00
bff03d1198 Add cross-decky correlation engine and decnet correlate command
When the same attacker IP touches multiple deckies, the engine builds a
chronological traversal graph and reports the lateral movement path.

decnet/correlation/
  parser.py   — RFC 5424 line → LogEvent; handles src_ip + src field variants
  graph.py    — AttackerTraversal / TraversalHop data types with path/duration
  engine.py   — CorrelationEngine: ingest(), traversals(), report_table/json,
                traversal_syslog_lines() (emits WARNING-severity RFC 5424)
  __init__.py — public API re-exports

decnet/cli.py — `decnet correlate` command (--log-file, --min-deckies,
                --output table|json|syslog, --emit-syslog)

tests/test_correlation.py — 49 tests: parser, graph, engine, reporting

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:53:30 -03:00
7aff040579 Add deaddeck: real interactive SSH entry-point machine
Introduces the 'real_ssh' service plugin backed by a genuine OpenSSH
server (not cowrie), and the 'deaddeck' archetype that uses it. The
container ships with a lived-in Linux environment and a deliberately
weak root:admin credential to invite exploitation.

- templates/real_ssh/: Dockerfile + entrypoint (configurable via env)
- decnet/services/real_ssh.py: BaseService plugin, service_cfg supports
  password and hostname overrides
- decnet/archetypes.py: deaddeck archetype added
- tests/test_real_ssh.py: 17 tests covering registration, compose
  fragment structure, overrides, and archetype

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:42:19 -03:00
9219bf432b Fix: remove net.core.rmem_default from windows sysctl profile
net.core.rmem_default is a global (non-namespaced) kernel sysctl.
Docker's OCI runtime rejects it at container start with "permission denied"
unless the container runs --privileged. Drop it from the windows profile;
TTL=128 and tcp_syn_retries=2 are sufficient for nmap TTL-based detection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:34:51 -03:00
d75f2afe90 Add comprehensive README.md
Covers how it works, requirements, installation, quick start, full CLI
reference, archetypes table, services table, OS fingerprint spoofing,
distro profiles, INI config file format with field reference, logging,
network drivers (MACVLAN vs IPvlan), architecture overview, plugin
authoring guide, and test suite summary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:29:53 -03:00
086643ef5a Expose nmap_os in INI loader and update test-full.ini
- ini_loader.py: DeckySpec gains nmap_os field; load_ini parses nmap_os=
  (also accepts nmap-os= hyphen alias) and propagates it to amount-expanded deckies
- cli.py: _build_deckies_from_ini resolves nmap_os with priority:
  explicit INI key > archetype default > "linux"
- test-full.ini: every decky now carries nmap_os=; [windows-workstation]
  gains archetype= so its OS family is set correctly; decky-winbox/fileserv/
  ldapdc → windows, decky-iot → embedded, decky-legacy → bsd, rest → linux
- tests/test_ini_loader.py: 7 new tests covering nmap_os parsing, defaults,
  hyphen alias, and amount= expansion propagation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:23:45 -03:00
6610856749 Add nmap OS spoof per decky via TCP/IP stack sysctls
Each decky base container now receives a set of Linux kernel sysctls
(net.ipv4.ip_default_ttl, net.ipv4.tcp_syn_retries, etc.) tuned to
match the claimed OS family, making nmap OS detection return the
expected OS rather than the Linux host.

- decnet/os_fingerprint.py: OS profile table (linux/windows/bsd/embedded/cisco)
  keyed by TTL and TCP tuning knobs
- decnet/archetypes.py: Archetype gains nmap_os field; windows-* → "windows",
  printer/iot/industrial → "embedded", rest → "linux"
- decnet/config.py: DeckyConfig gains nmap_os field (default "linux")
- decnet/cli.py: nmap_os resolved from archetype → DeckyConfig in both CLI
  and INI build paths
- decnet/composer.py: base container gets sysctls + cap_add: [NET_ADMIN];
  service containers inherit via shared network namespace
- tests/test_os_fingerprint.py: 48 new tests covering profiles, compose
  injection, archetype coverage, and CLI propagation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:19:06 -03:00
bbb5fa7a7e Add machine archetypes and amount= expansion
Introduces archetype profiles (windows-workstation, linux-server,
domain-controller, printer, iot-device, etc.) so users get a realistic
service+distro combination without knowing which services to pick.

Adds amount= to INI config (and CLI --archetype) so a single section
can spawn N identical deckies without copy-paste. Per-service subsections
(e.g. [group.ssh]) propagate to all expanded instances automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 13:08:01 -03:00
9f93a8502c Fix Cowrie: install from source to preserve data/honeyfs
pip install cowrie omits the data/ directory (fake filesystem, passwd,
etc.) required at import time. Clone and install from source instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 05:25:16 -03:00
b57269f68a Add --ipvlan flag for WiFi-compatible deployments
MACVLAN assigns unique MACs per container; WiFi APs typically reject
frames from unregistered MACs, making deckies unreachable from other
LAN devices. IPvlan L2 shares the host's MAC, so all traffic passes
through the AP normally.

- network.py: add create_ipvlan_network, setup_host_ipvlan,
  teardown_host_ipvlan, HOST_IPVLAN_IFACE
- config.py: add ipvlan: bool = False to DecnetConfig (persisted to
  state so teardown uses the right driver)
- deployer.py: branch on config.ipvlan for create/setup/teardown
- cli.py: add --ipvlan flag, wire into DecnetConfig
- tests/test_network.py: new test module covering ips_to_range,
  create_macvlan/ipvlan, setup/teardown for both drivers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 05:16:56 -03:00
8276467dbb Fix ips_to_range using XOR instead of subtraction for prefix length
Subtraction underestimates the required prefix when IPs span a CIDR
boundary (e.g. .110–.119 gave /28 covering only .96–.111, leaving
deckies at .112+ unreachable from the host macvlan route).
XOR correctly finds the highest differing bit, yielding /27 (.96–.127).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 05:02:50 -03:00
1b44b30329 Fix docker_api status always showing degraded
deployer.py status lookup used f"{decky.name}-{svc}" verbatim, so
docker_api (underscore) resolved to "decky-devops-docker_api" while the
actual container is named "decky-devops-docker-api" (hyphen). Status
would always report it absent/degraded even when running.

Fix: normalize underscores to hyphens in the container name lookup,
consistent with how all service plugins name their containers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 04:50:29 -03:00
3a6838e5c1 Fix TypeError on Python <3.10: add from __future__ import annotations
dict[str, Any] and X | Y union syntax require Python 3.10+. Containers
running centos7/ubuntu20/rocky9 base images ship Python 3.6-3.9 and
crashed on import. Adding the __future__ import makes all annotations
lazy strings, compatible back to Python 3.7.

Affected: templates/decnet_logging.py (+ all 22 template copies),
decnet/logging/syslog_formatter.py, decnet/logging/file_handler.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 04:46:53 -03:00
24530f94a7 Mount host log directory into containers for on-host syslog file
Previously --log-file only set DECNET_LOG_FILE inside containers with no
volume mount, so logs were lost on container restart and never visible on
the host. Now generate_compose binds the host log dir to
/var/log/decnet inside every service container so the file appears on
the host as expected.

- composer.py: _resolve_log_file() maps host path → container path;
  generate_compose() mkdir's host dir and injects volume + DECNET_LOG_FILE
- tests/test_log_file_mount.py: 9 new tests covering mount format,
  env injection, dir creation, and dedup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 04:39:54 -03:00
55896b0caa Add RFC 5424 syslog logging to all service templates
- decnet/logging/syslog_formatter.py: RFC 5424 formatter (local0 facility,
  decnet@55555 SD element ID, full escaping per §6.3.3)
- decnet/logging/file_handler.py: rotating file handler (10 MB / 5 backups),
  path configurable via DECNET_LOG_FILE env var
- templates/decnet_logging.py: combined syslog_line / write_syslog_file /
  forward_syslog helper distributed to all 22 service template dirs
- All templates/*/server.py: replaced ad-hoc JSON _forward/_log with RFC 5424
  syslog_line + write_syslog_file + forward_syslog
- All templates/*/Dockerfile: COPY decnet_logging.py /opt/
- DecnetConfig: added log_file field; CLI: --log-file flag;
  composer injects DECNET_LOG_FILE env var into service containers
- tests/test_syslog_formatter.py + tests/test_file_handler.py: 25 new tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 04:31:00 -03:00
cf1e00af28 Add per-service customization, stealth hardening, and BYOS support
- HTTP: configurable server_header, response_code, fake_app presets
  (apache/nginx/wordpress/phpmyadmin/iis), extra_headers, custom_body,
  static files directory mount
- SSH/Cowrie: configurable kernel_version, hardware_platform, ssh_banner,
  and users/passwords via COWRIE_USERDB_ENTRIES; switched to build mode
  so cowrie.cfg.j2 persona fields and userdb.txt generation work
- SMTP: configurable banner and MTA hostname
- MySQL: configurable version string in protocol greeting
- Redis: configurable redis_version and os string in INFO response
- BYOS: [custom-*] INI sections define bring-your-own Docker services
- Stealth: rename all *_honeypot.py → server.py; replace HONEYPOT_NAME
  env var with NODE_NAME across all 22+ service templates and plugins;
  strip "honeypot" from all in-container file content
- Config: DeckyConfig.service_config dict; INI [decky-N.svc] subsections;
  composer passes service_cfg to compose_fragment
- 350 tests passing (100%)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 04:08:27 -03:00
07c06e3c0a Replace dead upstream images with custom build services; add retry logic
dtagdevsec/mailoney and dtagdevsec/elasticpot are unavailable on Docker Hub
("manifest unknown"), causing the entire deployment to abort and cascade-
interrupt all other image pulls.

- Convert smtp and elasticsearch to build services with custom Python
  honeypots: smtp emulates Postfix ESMTP (EHLO/AUTH/MAIL/RCPT logging),
  elasticsearch emulates ES 7.17 HTTP API (logs recon probes like /_cat/,
  /_cluster/, /_nodes/, /_security/)
- Both use ARG BASE_IMAGE so they participate in per-decky distro variation
- Add _compose_with_retry() to deployer: 3 attempts with exponential backoff
  (5s → 10s → 20s) for transient network failures; permanent errors
  ("manifest unknown", "pull access denied") are detected and not retried
- Update test_services.py and test_composer.py: smtp/elasticsearch moved
  from UPSTREAM_SERVICES to BUILD_SERVICES (314 tests passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 00:57:51 -03:00
c9f9e1000e Fix SyntaxError in mysql_honeypot.py: replace b"\x00" * 10 with literal bytes
b"\x00" * 10 inside an implicit bytes-literal concatenation block is a
multiplication expression, not a literal. Python's greedy concatenation
absorbs the b"\x00" into the preceding chain, applies * 10 to the whole
thing, then finds the following b"\x21..." literal stranded after an
expression without a comma — SyntaxError.

Fix: inline the 10 null bytes as a literal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 00:51:14 -03:00
ccf62dd925 Fix pip install cross-distro compat: use ENV PIP_BREAK_SYSTEM_PACKAGES=1
--break-system-packages was added in pip 23 (Debian Bookworm). Ubuntu 22.04
ships pip 22 which rejects the flag with exit code 2. Switch to the
PIP_BREAK_SYSTEM_PACKAGES env var instead: recognized by pip>=23, silently
ignored by pip<23 where PEP 668 is not enforced anyway.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 00:31:38 -03:00
7006ed1308 Wire all 25 services into --randomize-services and add heterogeneous OS fingerprints
- Replace hardcoded ALL_SERVICE_NAMES=[5 services] in cli.py with
  _all_service_names() pulling dynamically from the plugin registry;
  randomize-services now draws from all 25 registered honeypots
- Add build_base field to DistroProfile: apt-compatible image for service
  Dockerfiles (ubuntu22/ubuntu20/kali get their own; others fall back to
  debian:bookworm-slim since Dockerfiles use apt-get)
- Add build_base to DeckyConfig; propagate from distro in _build_deckies
  and _build_deckies_from_ini
- Inject BASE_IMAGE build arg in composer.py for every build-based service
  so each decky's containers reflect its assigned distro
- Update all 21 service Dockerfiles: FROM debian:bookworm-slim →
  ARG BASE_IMAGE=debian:bookworm-slim / FROM ${BASE_IMAGE}
- Add tests/test_cli_service_pool.py and tests/test_composer.py (306 total)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 00:18:16 -03:00
e42fcab760 Add 20 honeypot services: email, DB, ICS, cloud, IoT, network protocols
Tier 1 (upstream images): telnet (cowrie), smtp (mailoney),
elasticsearch (elasticpot), conpot (Modbus/S7/SNMP ICS).

Tier 2 (custom asyncio honeypots): pop3, imap, mysql, mssql, redis,
mongodb, postgres, ldap, vnc, docker_api, k8s, sip, mqtt, llmnr, snmp,
tftp — each with Dockerfile, entrypoint, and protocol-accurate
handshake/credential capture.

Adds 256 pytest cases covering registration, compose fragments,
LOG_TARGET propagation, and Dockerfile presence for all 25 services.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 23:07:44 -03:00