[build-system] requires = ["setuptools>=68", "wheel"] build-backend = "setuptools.build_meta" [project] name = "decnet" version = "0.2.0" description = "Deception network: deploy honeypot deckies that appear as real LAN hosts" license = "GPL-3.0-or-later" license-files = ["LICENSE"] requires-python = ">=3.11" classifiers = [ "Programming Language :: Python :: 3.11", "Operating System :: POSIX :: Linux", "Topic :: Security", "Topic :: System :: Networking :: Monitoring", "Development Status :: 4 - Beta", ] dependencies = [ "typer[all]>=0.12", "pydantic>=2.0", "docker>=7.0", "pyyaml>=6.0", "jinja2>=3.1", "fastapi>=0.110.0", "uvicorn>=0.29.0", "aiosqlite>=0.20.0", "asyncmy>=0.2.11", "PyJWT>=2.8.0", "bcrypt>=4.1.0", "psutil>=5.9.0", "python-dotenv>=1.0.0", "sqlmodel>=0.0.16", "scapy>=2.6.1", "orjson>=3.10", "cryptography>=46.0.7", "python-multipart>=0.0.20", "httpx>=0.28.1", "requests>=2.33.1", "slowapi>=0.1.9", "sqlite_vec>=0.1.9", "Pillow>=12.2.0", "lxml>=6.1.0", "pikepdf>=10.5.1", # Linux-only inotify watch for FilesystemRuleStore (decnet/ttp/store). # The store's __init__ refuses to construct on non-Linux, so the # platform-marker keeps macOS/Windows installs from pulling a # never-imported wheel. "asyncinotify>=4.0 ; sys_platform == 'linux'", # BEHAVE — out-of-tree behavioural-observation framework. core ships # the Observation envelope; shell ships the primitive registry + # bus event adapter consumed by decnet/profiler/behave_shell/. Pin # range tracks BEHAVE-INTEGRATION.md §"Versioning". "decnet-behave-core>=0.1.0,<0.2", "decnet-behave-shell>=0.1.0,<0.2", # MITRE ATT&CK: parse the official STIX 2.1 enterprise-attack bundle # instead of hand-maintaining technique/tactic name dicts. stix2 # gives typed parsing; mitreattack-python ships MitreAttackData # query helpers (get_objects_by_external_id, get_parent_technique). # See decnet/ttp/attack_stix.py. "stix2>=3.0", "mitreattack-python>=3.0", ] [project.optional-dependencies] tracing = [ "opentelemetry-api>=1.20.0", "opentelemetry-sdk>=1.20.0", "opentelemetry-exporter-otlp>=1.20.0", "opentelemetry-instrumentation-fastapi>=0.41b0", ] profile = [ "py-spy>=0.4.1", "pyinstrument>=4.7", "pytest-benchmark>=4.0", "memray>=1.14 ; sys_platform == 'linux'", "snakeviz>=2.2", ] dev = [ "decnet[tracing,profile]", "pytest>=9.0.3", "ruff>=0.15.10", "bandit>=1.9.4", "pip>=26.0", "pip-audit>=2.10.0", "httpx>=0.28.1", "hypothesis>=6.151.14", "pytest-cov>=7.1.0", "pytest-asyncio>=1.3.0", "freezegun>=1.5.5", "schemathesis>=4.15.1", "pytest-xdist>=3.8.0", "pytest-timeout>=2.4.0", "flask>=3.1.3", "twisted>=26.4.0rc2", "requests>=2.33.1", "redis>=7.4.0", "pymysql>=1.1.2", "psycopg2-binary>=2.9.11", "paho-mqtt>=2.1.0", "pymongo>=4.16.0", "locust>=2.29", "gevent>=24.0", "pydeps>=3.0.3", "types-PyYAML>=6.0", "types-requests>=2.33", "mypy>=1.16,<1.20" ] [project.scripts] decnet = "decnet.cli:app" [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_debug = "true" asyncio_default_fixture_loop_scope = "module" addopts = "-m 'not fuzz and not live and not stress and not bench and not docker' -v -q -x -n logical --dist loadscope" markers = [ "fuzz: hypothesis-based fuzz tests (slow, run with -m fuzz or -m '' for all)", "live: live subprocess service tests (run with -m live)", "live_docker: live Docker container tests (requires DECNET_LIVE_DOCKER=1)", "stress: locust-based stress tests (run with -m stress)", "bench: pytest-benchmark micro-benchmarks (run with -m bench)", "docker: tests that build and run docker images (run with -m docker)", ] filterwarnings = [ "ignore::pytest.PytestUnhandledThreadExceptionWarning", "ignore::DeprecationWarning", "ignore::RuntimeWarning", ] [tool.coverage.run] source = ["decnet"] omit = ["*/tests/*", "*/templates/*"] parallel = true [tool.coverage.report] show_missing = true skip_covered = false # Run with: pytest --cov --cov-report=term-missing [tool.setuptools.packages.find] where = ["."] include = ["decnet*"] [tool.setuptools.package-data] # Ship docker build contexts + syslog_bridge.py as package data so they land # in site-packages when agents install the bundle via `pip install`. # canary/*.js + canary/package.json ship the Node-side toolchain manifest # so `decnet canary-install-toolchain` can `npm install` post-install. decnet = [ "templates/**/*", "canary/_obfuscate_helper.js", "canary/fingerprint_payload.js", "canary/package.json", ] [tool.bandit] # Docker build contexts — code runs inside decoy containers, not in the # master/agent process. Skipping keeps honeypot service scripts (hashlib.md5 # for JA3, /tmp/build in Dockerfile helpers, etc.) out of the scan. exclude_dirs = [ "decnet/templates", ] [tool.mypy] plugins = [ "pydantic.mypy" ] python_version = "3.11" strict = false ignore_missing_imports = true check_untyped_defs = true warn_redundant_casts = true warn_unused_ignores = true [[tool.mypy.overrides]] # The pydantic plugin types SQLModel class-level field descriptors as their # Python value types (str, bool, …) instead of InstrumentedAttribute. Every # .where(Model.field == value) then becomes where(bool) — a false positive. # Suppressing arg-type here; genuine argument errors are caught by call-arg. module = "decnet.web.db.sqlmodel_repo.*" disable_error_code = ["arg-type"]