From f6d23e0f6636a8870f0b9b02d2e2a1c8f4cb1d5b Mon Sep 17 00:00:00 2001 From: Michael Hinz Date: Thu, 12 Feb 2026 15:18:27 +0100 Subject: [PATCH] feat: first prototype, "works on my machine" edition --- .gitignore | 4 +++ .python-version | 1 + main.py | 46 ++++++++++++++++++++++++++++++++ pyproject.toml | 10 +++++++ uv.lock | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+) create mode 100644 .gitignore create mode 100644 .python-version create mode 100644 main.py create mode 100644 pyproject.toml create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b80815a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.venv +.env +__pycache__ + diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..24ee5b1 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.13 diff --git a/main.py b/main.py new file mode 100644 index 0000000..b571740 --- /dev/null +++ b/main.py @@ -0,0 +1,46 @@ +import datetime +import logging +import MySQLdb as m +import dns.resolver + +def read_config(): + return (['example.com'],'localhost',3306,'test','testpass','pdns','wile') + + +def main(): + (zones, host, port, username, password, database, myname) = read_config() + db = m.connect(host, username, password, database) + for zone in zones: + logging.debug(f"checking zone {zone}") + # try to resolve dnskey.{zone} on all nameservers + # dammit, my testserver is running on a weird port + r = dns.resolver.Resolver() + nsarr = ['127.0.0.1:10053'] + expected = None + for ns in nsarr: + # r.nameservers = [ns] + answer = r.resolve(qname=zone, rdtype='DNSKEY', tcp=False, search=ns) + print(f"{answer=}") + if not expected: + expected = answer.rrset.to_text() + print(f"set {expected=}") + else: + if answer.rrset.to_text() != expected: + print(f"{answer.rrset.to_text()=} differs from {expected=}") + # I'm very confident this is more complicated than it needs to be... + db.query(f"""SELECT id,content FROM records WHERE type='SOA' AND name='{zone}'""") + result = db.store_result() + row = result.fetch_row() + (id,content) = row[0] + carr = content.split() + newdatestr = datetime.datetime.today().strftime("%Y%m%d01") + if newdatestr[:8] == carr[2][:8]: + count = int(carr[2][8:]) + newcount = count + 1 + newdatestr = f"{newdatestr[:8]}{newcount:02d}" + carr[2] = newdatestr + db.query(f"""UPDATE records SET content = '{' '.join(carr)}' WHERE id={id}""") + db.commit() + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..cfebd14 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "dnssec-fix" +version = "0.1.0" +description = "DNSKEY sync via zone update" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "dnstools>=0.0.1", + "mysqlclient>=2.2.8", +] diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..31f0e20 --- /dev/null +++ b/uv.lock @@ -0,0 +1,71 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "click" +version = "8.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "dnssec-fix" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "dnstools" }, + { name = "mysqlclient" }, +] + +[package.metadata] +requires-dist = [ + { name = "dnstools", specifier = ">=0.0.1" }, + { name = "mysqlclient", specifier = ">=2.2.8" }, +] + +[[package]] +name = "dnstools" +version = "0.0.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "dnspython" }, +] +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/90/3bb9dd63613d86bb72e73ce4dcdbd35c99f33c9884b93a4e910a360b346a/dnstools-0.0.1-py2.py3-none-any.whl", hash = "sha256:aa7cbe3ffd3a55b5aa4707a740793890fb49e88998385bf84d901cd072a5ed25", size = 2739, upload-time = "2015-02-23T07:29:47.673Z" }, +] + +[[package]] +name = "mysqlclient" +version = "2.2.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/b0/9df076488cb2e536d40ce6dbd4273c1f20a386e31ffe6e7cb613902b3c2a/mysqlclient-2.2.8.tar.gz", hash = "sha256:8ed20c5615a915da451bb308c7d0306648a4fd9a2809ba95c992690006306199", size = 92287, upload-time = "2026-02-10T10:58:37.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/d5/76e369b0fdccd2eb9ed7d890e4e3e23aa1344fea62f0180d7f1574285e54/mysqlclient-2.2.8-cp313-cp313-win_amd64.whl", hash = "sha256:a81f5e12f8d05439709cb02fba97f9f76d1a6c528164f2260d8798fec969e300", size = 207158, upload-time = "2026-02-10T10:58:38.663Z" }, + { url = "https://files.pythonhosted.org/packages/42/44/6ae21b4e8490eb5167d04fa7452c462ffd72a502b96bf531477ef044a380/mysqlclient-2.2.8-cp314-cp314-win_amd64.whl", hash = "sha256:9bed7c8d3b629bdc09e17fb628d5b3b0a5fd1f12b09432b464b9126c727bedc0", size = 211644, upload-time = "2026-02-10T10:58:45.022Z" }, + { url = "https://files.pythonhosted.org/packages/66/e5/037d55623be9f681236e04abe12e1290847c06bd48270c3f19ac33493cbf/mysqlclient-2.2.8-cp314-cp314t-win_amd64.whl", hash = "sha256:260cce0e81446c83bf0a389e0fae38d68547d9f8fc0833bc733014e10ce28a99", size = 213067, upload-time = "2026-02-10T10:58:43.389Z" }, +]