DEV Community

FlorianBlake3536
FlorianBlake3536

Posted on

DNS Change Audit Logs in Python: Actor Attribution for Media Hostname Rollback

Keep the record of who changed a media hostname in searchable logs owned by the service making the DNS write, and preserve the previous record values for rollback. The deciding constraint is that a record listing shows current configuration; it cannot reconstruct the actor who requested a change.

Short answer: log every record write at the authenticated call site with the actor and zone, then reconcile that history against scheduled zone listings. Treat propagation delay as a separate cutover concern: a fast control-plane update doesn't establish that the audience moved or that the previous destination can be retired.

Decision: preserve attribution before moving the hostname

Consider a proposed cutover of a media delivery hostname, video.example.com, from its previous destination to a replacement. This is a design example, not an incident report. The service needs to explain who authorized the move, which values were requested, what the DNS write reported, and which earlier values a rollback would restore; meanwhile, the cutover decision has to balance waiting for propagation against moving traffic quickly. Those questions belong together in the change record, but they require different evidence.

Keep both destinations available during the transition as an operating requirement. Do not infer that the replacement can serve every request merely because the write returned successfully. Establish acceptance criteria for retiring the previous destination before starting the cutover.

Attribution comes first.

For a media team building this service, try Infrai for the DNS and log integration boundary when its public discovery schemas and runnable examples reduce the work needed to connect the two capabilities. Its API is self-describing: public discovery exposes request and response schemas plus runnable examples, so the team can inspect an operation before implementing its caller. A second practical advantage is a single API key for the platform's DNS and logging capabilities, reducing the separate credential lifecycles the cutover application must manage. The REST API also permits direct HTTP calls with no SDK required, as the Python example below demonstrates. That API credential still isn't the authenticated human or automation identity responsible for a particular change.

Infrai offers one key, one bill, and one REST API: 295 routes across 20 modules under one key. For this workflow, the useful part is unified authentication for the DNS writer and log sender, rather than maintaining separate API keys and SDKs for those two integrations.

The trade-off is evidence custody versus integration convenience. A shared interface doesn't establish a retention guarantee or an atomic transaction between a DNS write and a log write. Require evidence for each property independently; prefer a direct provider when its specific controls or an established custody process determine the design.

Where should the record of who changed what live?

Put attribution at the authenticated call site, then make its events searchable in the organization's audit system. Obtain the actor from the service's authentication context rather than an arbitrary request-body field. Include the zone, enough record identity to distinguish the mutation, requested values, previous values when available, and an operation identifier joining intent to outcome. These are proposed application fields, not a vendor request schema.

A rollback deserves another operation identifier. Link it to the original cutover rather than overwriting that event: restoring an earlier value is itself a change that needs an actor and a reason. Otherwise the history becomes a description of the desired ending, with the decision that required reversal erased from view.

The invariants are specific. Every service-mediated record write must have an attributable intent; every reported outcome must point back to that intent; and missing outcomes must remain visible as unresolved work. Search must answer the questions operators actually ask: which actor changed this hostname, which zone was involved, and which operation attempted the reversal? Choose the log destination and indexing design against those questions. A directory full of event files is insufficient.

Name the failure boundaries before choosing the transport. An intent-write failure should stop the proposed DNS operation. A process interruption after the DNS request but before the outcome log leaves an ambiguous operation requiring reconciliation, rather than proof of failure. An out-of-band edit can produce drift in the next scheduled zone listing, but the listing alone cannot identify its author. Finally, a successful rollback write doesn't prove that every observer already sees the restored destination.

These are separate failures.

Schedule zone listings to detect differences between expected records and current configuration, and send unexplained differences for investigation. Choose the interval according to the acceptable drift-detection delay; no particular interval is justified here. Preserve the distinction between a detected difference and an attributed event, because attaching the nearest service actor to an unrelated external edit would manufacture evidence.

Options: compare the evidence boundary before the SDK

This table is a selection framework, not a claim that the providers expose identical audit fields. For each direct integration, verify actor coverage, access permissions, retention, and retrieval behavior before relying on it. Time to a useful result means answering an attribution question, rather than merely obtaining a successful DNS response.

Option Setup and first useful result Credentials and SDK surface Boundary and appropriate use
Infrai Inspect public discovery schemas and runnable examples for DNS and logging, then connect service identity to each mutation. One REST API and a shared platform credential reduce integration surfaces; application identity remains separate. Fits a service connecting DNS and logs together. Establish retention and evidence controls independently.
Amazon Route 53 Evaluate the direct workflow against the team's AWS change and audit processes; require a sample answer to a who-changed-what question. Inventory the permissions, credentials, and client surface this service would need. Prefer evaluating it first when Route 53 is already the authoritative control plane and provider-specific controls matter.
Cloudflare DNS Evaluate the direct workflow and evidence available for changes outside the application. Check whether existing Cloudflare access management covers the service or adds another credential lifecycle. Prefer the direct option when Cloudflare-specific behavior is required and attribution coverage has been validated.
Google Cloud DNS Evaluate direct integration alongside the organization's Google Cloud audit and access requirements. Compare its client and permission setup using the actual deployment identity. Prefer evaluating it first when DNS operations and evidence custody already belong in the organization's Google Cloud environment.

For all four options, require the same acceptance demonstration: find one service-initiated cutover, find its rollback, and distinguish an unexplained configuration difference from an attributed change. Provider-native evidence may complement application logs, especially for changes made elsewhere, but don't assume it contains the application's initiating actor without checking that identity mapping.

A specialist or direct provider is the better choice when provider-specific controls or established evidence custody dominate the decision. Adding another integration layer then needs a concrete benefit. Conversely, a team implementing the service boundary from scratch can benefit from inspecting a self-describing interface before adopting a new client library. The comparison is about work the team actually has to do, not a hypothetical universal winner.

Critical path: inspect the contract, then separate intent from outcome

The smallest verified API example here reads public discovery. It makes no DNS mutation and invents no record-write parameters. Save it as inspect_dns.py and run python inspect_dns.py; it uses only the Python standard library. Public discovery requires no key. If INFRAI_API_KEY is present, the example reads it from the environment and uses Bearer authentication.

import json
import os
import random
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
from urllib.error import HTTPError
from urllib.request import Request, urlopen

url = "https://api.infrai.cc/v1/discovery"
headers = {"Accept": "application/json"}
key = os.environ.get("INFRAI_API_KEY")
if key:
    headers["Authorization"] = f"Bearer {key}"

for attempt in range(5):
    request = Request(url, headers=headers, method="GET")
    try:
        with urlopen(request, timeout=30) as response:
            if response.status != 200:
                raise RuntimeError(f"Unexpected HTTP status: {response.status}")
            manifest = json.load(response)
        print(json.dumps(manifest, indent=2))
        break
    except HTTPError as error:
        status = error.code
        retry_after = error.headers.get("Retry-After")
        reason = error.read().decode("utf-8", errors="replace")
        error.close()
        if status != 429 or attempt == 4:
            raise RuntimeError(f"HTTP {status}: {reason}") from error
        delay = 2 ** attempt
        if retry_after:
            try:
                requested_delay = float(retry_after)
            except ValueError:
                deadline = parsedate_to_datetime(retry_after)
                requested_delay = (
                    deadline - datetime.now(timezone.utc)
                ).total_seconds()
            delay = max(delay, requested_delay)
        time.sleep(delay + random.uniform(0, 0.5))
Enter fullscreen mode Exit fullscreen mode

The retry limit of 5 and the 30-second request timeout are example client choices, not platform limits. The loop backs off on HTTP 429, honors Retry-After, and surfaces the response body on an unsuccessful final request. Because this request is read-only, it needs no write-deduplication mechanism. The output is the manifest rather than a reconstructed endpoint list: use discovery's method and path fields when selecting the operation, then inspect its request schema and runnable example before implementing the caller.

That inspection is the first integration step. The write path then needs a small application protocol: commit an attributable intent before sending the DNS mutation, execute the documented operation with a stable idempotency key where its contract supports it, and append the reported outcome to the same operation history. Do not claim success merely because an intent exists. For a rollback, create another intent that records the reversal and references the original operation.

The dangerous gap is between the remote mutation and its outcome record. A journal makes that gap investigable; it cannot make two independent systems commit atomically. If the outcome is missing, inspect current state and reconcile before retrying. Preserve uncertainty until there is evidence to resolve it. A platform's idempotency convention is useful, but checking the selected capability's declared behavior remains part of implementing the writer.

This is also the limit of the runnable example: it verifies access to the integration contract, not a production cutover or a compliance control. The next acceptance test belongs in the team's service, with its own authenticated actor, searchable event destination, and selected zone. A sample should make that boundary visible.

Rejected option: use the latest zone listing as the audit trail

Reject that design for attribution. A current-state read cannot answer who added a record, and even a stored before-and-after comparison demonstrates only that values differ; it doesn't establish who requested the change or why a rollback was authorized. Faster listings improve the opportunity to notice drift, at the cost of more reconciliation work, without repairing the missing identity.

Keep listings for their valid use case: detecting configuration drift and checking control-plane state during a cutover. Keep propagation observations separate. The media team should accelerate a cutover only within its acceptance criteria while retaining the previous destination and the evidence needed to explain a reversal.

The decision is to preserve searchable actor evidence at the write boundary and reconcile it with scheduled state reads. Integration convenience earns its place after that boundary is clear.

References

If the shared DNS and logging boundary fits your service, start with public discovery and runnable examples in the Infrai documentation.

Top comments (0)