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>
This commit is contained in:
2026-04-04 00:57:51 -03:00
parent c9f9e1000e
commit 07c06e3c0a
11 changed files with 394 additions and 53 deletions

View File

@@ -31,11 +31,9 @@ def _is_build_service(name: str) -> bool:
# ---------------------------------------------------------------------------
UPSTREAM_SERVICES = {
"ssh": ("cowrie/cowrie", [22, 2222]),
"telnet": ("cowrie/cowrie", [23]),
"smtp": ("dtagdevsec/mailoney", [25, 587]),
"elasticsearch": ("dtagdevsec/elasticpot", [9200]),
"conpot": ("honeynet/conpot", [502, 161, 80]),
"ssh": ("cowrie/cowrie", [22, 2222]),
"telnet": ("cowrie/cowrie", [23]),
"conpot": ("honeynet/conpot", [502, 161, 80]),
}
# ---------------------------------------------------------------------------
@@ -43,26 +41,28 @@ UPSTREAM_SERVICES = {
# ---------------------------------------------------------------------------
BUILD_SERVICES = {
"http": ([80, 443], "http"),
"rdp": ([3389], "rdp"),
"smb": ([445, 139], "smb"),
"ftp": ([21], "ftp"),
"pop3": ([110, 995], "pop3"),
"imap": ([143, 993], "imap"),
"mysql": ([3306], "mysql"),
"mssql": ([1433], "mssql"),
"redis": ([6379], "redis"),
"mongodb": ([27017], "mongodb"),
"postgres": ([5432], "postgres"),
"ldap": ([389, 636], "ldap"),
"vnc": ([5900], "vnc"),
"docker_api": ([2375, 2376], "docker_api"),
"k8s": ([6443, 8080], "k8s"),
"sip": ([5060], "sip"),
"mqtt": ([1883], "mqtt"),
"llmnr": ([5355, 5353], "llmnr"),
"snmp": ([161], "snmp"),
"tftp": ([69], "tftp"),
"http": ([80, 443], "http"),
"rdp": ([3389], "rdp"),
"smb": ([445, 139], "smb"),
"ftp": ([21], "ftp"),
"smtp": ([25, 587], "smtp"),
"elasticsearch": ([9200], "elasticsearch"),
"pop3": ([110, 995], "pop3"),
"imap": ([143, 993], "imap"),
"mysql": ([3306], "mysql"),
"mssql": ([1433], "mssql"),
"redis": ([6379], "redis"),
"mongodb": ([27017], "mongodb"),
"postgres": ([5432], "postgres"),
"ldap": ([389, 636], "ldap"),
"vnc": ([5900], "vnc"),
"docker_api": ([2375, 2376], "docker_api"),
"k8s": ([6443, 8080], "k8s"),
"sip": ([5060], "sip"),
"mqtt": ([1883], "mqtt"),
"llmnr": ([5355, 5353], "llmnr"),
"snmp": ([161], "snmp"),
"tftp": ([69], "tftp"),
}
ALL_SERVICE_NAMES = list(UPSTREAM_SERVICES) + list(BUILD_SERVICES)