dns-monitor
Multi-provider DNS zone guard that detects accidental edits and hijacking across INWX and Cloudflare zones.
USP: the package never calls mutating API methods — drift detection is the compensating control for providers that offer no read-only role.
Installation
pip install dns-monitor # library only
pip install dns-monitor[cli] # + CLI and dotenv support
Providers
| Provider | Auth | Minimum permissions |
|---|---|---|
| INWX | username + password | Domain Management, DNS Management (no read-only role exists) |
| Cloudflare | API token | Zone:Read + DNS:Read |
Set credentials in .env (see .env.example) or export them directly:
export INWX_USERNAME=svc-monitor-inwx
export INWX_PASSWORD=...
export CF_API_TOKEN=...
CLI
dns-monitor zones # list all zones across configured providers
dns-monitor baseline # save current state as drift baseline
dns-monitor check # check guards and detect drift
dns-monitor check --policies my_policies.py # inject custom policies
Exit codes match violation severity: 0 = clean, 1 = MEDIUM, 2 = HIGH, 3 = CRITICAL.
Library usage
from dns_monitor.providers.inwx import InwxProvider
from dns_monitor.guards.policy import Policy
from dns_monitor.guards.predicates import is_address_record, has_public_ip
from dns_monitor.guards.runner import run_policies
from dns_monitor.model.severity import Severity
vpn_policy = Policy(
name="vpn-endpoints-must-be-public",
applies_to=lambda r: is_address_record(r) and r.name in VPN_HOSTNAMES,
require=has_public_ip,
severity=Severity.CRITICAL,
message="{type} {name} → {content} is non-public — VPN tunnel at risk",
)
with InwxProvider(username, password) as p:
for zone in p.list_zones():
records = p.get_records(zone)
violations = run_policies(records, [vpn_policy])
Drift detection
from dns_monitor.model import snapshot
from dns_monitor.guards.runner import run_drift
baseline = snapshot.load(Path("snapshots/latest.json"))
current = p.get_records(zone)
violations = run_drift(baseline.get(f"inwx:{zone}", []), current, zone=zone)
Records exempt from drift detection by default:
- A/AAAA with TTL ≤ 300 (DynDNS — expected to change with WAN IP)
_acme-challenge.*TXT records (transient ACME DNS-01 challenge)
Salt grains
Copy src/dns_monitor/contrib/salt_grains.py to /srv/salt/_grains/. The minion must have dns_monitor[cli] installed and INWX_USERNAME/INWX_PASSWORD in its environment.
Grain returned: dns_monitor.inwx_zones — list of zone names.
License
Apache 2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dns_monitor-0.1.1.tar.gz.
File metadata
- Download URL: dns_monitor-0.1.1.tar.gz
- Upload date:
- Size: 41.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf60c611d5031da2a73ac0fa2899f10b1172d7967f9e3834e3cce05296e10ac6
|
|
| MD5 |
ade9c257b218e11cc92560d94d1c16d2
|
|
| BLAKE2b-256 |
7041f3ad3a5d7549ac4a3d2fe4361fcaa7e039a588c7cdc22e12c5cd64b07c16
|
Provenance
The following attestation bundles were made for dns_monitor-0.1.1.tar.gz:
Publisher:
publish.yml on cprima-integrations/dns-monitor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dns_monitor-0.1.1.tar.gz -
Subject digest:
cf60c611d5031da2a73ac0fa2899f10b1172d7967f9e3834e3cce05296e10ac6 - Sigstore transparency entry: 2294620483
- Sigstore integration time:
-
Permalink:
cprima-integrations/dns-monitor@ce1cbe7b47efd3d44d3979e91173e83854ab18ce -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/cprima-integrations
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ce1cbe7b47efd3d44d3979e91173e83854ab18ce -
Trigger Event:
push
-
Statement type:
File details
Details for the file dns_monitor-0.1.1-py3-none-any.whl.
File metadata
- Download URL: dns_monitor-0.1.1-py3-none-any.whl
- Upload date:
- Size: 21.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
26338a3936c0cbaea5c1e60199665bdc4aff047d247bbc3e2ae6cfb93b3b0cf9
|
|
| MD5 |
d203026326e00fcc38bcc37a04841c73
|
|
| BLAKE2b-256 |
82856706b83255467329e68da734505836c749f0ff17f15279f9fc87c0e175c9
|
Provenance
The following attestation bundles were made for dns_monitor-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on cprima-integrations/dns-monitor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dns_monitor-0.1.1-py3-none-any.whl -
Subject digest:
26338a3936c0cbaea5c1e60199665bdc4aff047d247bbc3e2ae6cfb93b3b0cf9 - Sigstore transparency entry: 2294620539
- Sigstore integration time:
-
Permalink:
cprima-integrations/dns-monitor@ce1cbe7b47efd3d44d3979e91173e83854ab18ce -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/cprima-integrations
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ce1cbe7b47efd3d44d3979e91173e83854ab18ce -
Trigger Event:
push
-
Statement type: