Skip to content

2.4 Audit log, Trash and change safety

Part 2 · AdministrationAdministrator⏱ ~25 min▶ Narrated video🖱 Interactive walkthrough🧪 Lab 9 (auto-checked)✓ Knowledge check

Mistakes happen, even to careful admins: the wrong subnet selected, a script with a bad filter, a colleague who thought a zone was unused. SpatiumDDI gives you three safety nets: confirmations that slow you down before a risky change, Trash to undo a deletion afterwards, and an audit log that records every change and can prove it hasn’t been altered.

This module covers all three, and their limits, which matter as much: a subnet in Trash takes its DNS names offline until a superadmin restores it, and forwarding to a SIEM is best-effort.

  • Delete through the two-step Danger zone, and restore a whole batch from Trash
  • Know what Trash covers, what happens to DNS while something sits there, and how long it keeps things
  • Read the audit log, refusals included, and prove that nobody has altered it
  • Forward audit events to a SIEM, and know what “best-effort” means there
  • Use change-safety habits: previews, typed confirmations, two-person approval and maintenance mode

The video deletes a scratch subnet through the Danger zone, restores it from Trash, and then follows the whole story, including a refused request, in the audit log. The walkthrough repeats the clicks.

▶ Audit log, Trash and change safety · 2:14 · narrated, captions on (CC) · recorded on SpatiumDDI 1.0.0-beta.3
Chapters
Transcript

0:00Module 2.4: the audit log, Trash, and change safety. Mistakes happen, even to careful admins. You'll delete something on purpose, bring it back, and then see how the audit log tells the whole story.

0:14Start with something that's safe to break: a scratch subnet in the campus block, 10.20.99.0/24, named Scratch.

0:25Now delete it, the way you'd delete anything important. Deleting lives on the “Danger zone” tab, behind two confirmations. The second one spells out exactly what happens: the subnet, its DHCP scopes and its reverse zone move to Trash, its DNS records stop resolving, and a superadmin can restore it all together for 30 days.

0:47Deleted items wait in Administration, Trash, with who deleted them and when. Everything removed by one action shares a batch. Restore the subnet, and SpatiumDDI first tells you how many rows come back with it, here its reverse zone and gateway. After the retention window, thirty days by default, a nightly sweep removes them for good.

1:09Back in IPAM, refresh the tree, and Scratch is where it was, with its addresses intact and their DNS records published again. A deletion that used to mean a restore from backup is now a two-click undo.

1:22Every change lands in the audit log: who did what, to which object, from which address, and whether it worked. Filter by resource type, and the top of the list tells our scratch subnet's story: created, moved to Trash, and restored.

1:38Refusals are recorded too: here's Jordan's denied attempt from module 2.1. Each entry is chained to the one before it by a hash, so any tampering breaks the chain, and this badge confirms it's intact. Export PDF gives auditors a report, and you can forward the log to your SIEM over syslog or a webhook.

1:59You've undone a deletion from Trash, and traced every step, including a refusal, in a log that proves it hasn't been altered. Next: keeping watch with dashboards, logs and alerts, and then the last safety net, backups.

Step 1 of 22: IPAM

Nice work — walkthrough complete.
Now do it for real in the lab below.

Deleting a subnet is deliberately slow. It lives on the Danger zone tab of the subnet’s Edit dialog, behind two confirmations:

  1. Delete this subnet… opens Delete Subnet, which explains the impact: addresses leased through DHCP are revoked along with their DDNS records, while manually allocated addresses go to Trash with the subnet, and their DNS records stop resolving until a superadmin restores it. Continue moves on.
  2. Delete subnet spells out what moves to Trash: the subnet, its DHCP scopes and any reverse zone created for it that no other subnet still uses. The DNS records published for its addresses stop resolving while it’s there, and a superadmin can restore everything together within 30 days, which publishes those records again. You tick “I understand … will be moved to Trash.” before Move to Trash is enabled.

IP spaces, blocks, DNS zones and records, and DHCP scopes (with their pools and static reservations) also go to Trash when you delete them, and so do customers, overlays and services when their Network modules are on. Individual IP addresses are the exception: they never go to Trash on their own. Deleting one from the UI can instead leave it in the subnet as an orphan, which you can restore later, or remove it for good. Choose Mark as Orphan if you might want it back, rather than Delete Permanently.

Administration → Trash lists soft-deleted objects, newest first, and only superadmins can open it: an IPAM Editor can move a subnet to Trash but can’t bring it back. Filter by Type, by Since (a date and time), or by name or CIDR, and set Order to Oldest first (purged first) to see what the purge removes next. Each row shows Type, Name / CIDR, Deleted at, Deleted by and Batch size, with two actions:

  • Restore brings the object back, together with everything deleted with it: one delete stamps the parent and all its children with a single batch. Restoring a subnet brings back its addresses, its DHCP scopes and its reverse zone, and publishes its DNS records again; restoring a zone brings back its records. The confirmation says how big the batch is: for an empty Scratch subnet, “Restore 10.20.99.0/24 Scratch (Subnet) and the 2 other rows deleted with it?” (its reverse zone and its gateway’s PTR record).
  • Delete removes the row permanently. After that, only a backup brings it back.

A row whose parent is still in Trash, such as a subnet whose block was deleted too, can’t come back on its own: the restore dialog offers to restore the parent first. If a live object now clashes with the one you’re restoring (say someone has already recreated the same CIDR), the dialog shows the conflict instead of overwriting anything. Resolve the clash and restore again: a subnet, zone or scope comes back whole or not at all. The one exception is a batch of DNS records deleted together in a bulk delete, where Restore the others brings back the records that don’t clash and then lists what stayed in Trash.

A nightly purge permanently removes whatever has been in Trash longer than the retention window, set under Settings → Data Retention → Trash: 30 days by default, up to 365, and 0 turns the purge off.

Scripts get the same safety net. The default DELETE on a subnet is a soft delete; only ?permanent=true, which needs a superadmin, takes the hard path, and that refuses a subnet that still holds addresses or scopes unless you add ?force=true.

What happens to DNS while a subnet is in Trash

Section titled “What happens to DNS while a subnet is in Trash”

Moving a subnet to Trash withdraws the A, AAAA and PTR records SpatiumDDI published for its addresses, the gateway’s PTR included, and puts them in Trash in the same batch. In the Academy lab, the names stopped resolving within a couple of seconds, and Restore brought them back as quickly.

Records you created by hand are left alone, so to take a hand-made name out of service, delete or change the record itself. If someone recreates one of the withdrawn records by hand while the subnet sits in Trash, the restore refuses and names the record. On 2026.09.04-1 a trashed subnet’s names kept resolving until the purge, so update any runbook that relied on that.

Every change writes an audit row in the same database transaction as the change itself, before the API answers. A change that isn’t audited doesn’t happen: an audit gap and a rolled-back write are the same event.

Administration → Audit Log shows Timestamp, User, Action, Resource, Summary, Result and IP, with a filter under every column except Timestamp. Each row also keeps the old and new values and the list of changed fields. Actions you’ll meet in this course:

Action Recorded when
create, update, delete An object is created, changed or permanently deleted
soft_delete, restore An object moves to Trash, or comes back (trashing a subnet also writes one for each DNS record it withdrew)
login Anyone signs in, successfully or not, including unknown usernames
bulk_allocate, dns-sync A bulk allocation, or an applied Sync DNS
backup_created, backup_target_run_success, backup_restore_drill Backup work (module 2.6)
write, access and others, with result denied The server refused a request for lack of permission; access on superadmin is a superadmin-only page (module 2.1)

The Result column tells success from denied, and sign-ins record failure for a wrong password. A superadmin passes every permission check, so a superadmin’s requests never appear as permission denied rows; a refused password confirmation, or an attempt to remove the last superadmin, still writes one. Export PDF produces an auditor-facing report of the last 30 days of changes, grouped by user, resource and action.

A log that the database administrator could quietly edit wouldn’t convince an auditor. SpatiumDDI’s audit log is append-only: database triggers block updates and deletes, and every row is hash-chained to the one before it.

The Chain verified badge at the top of the page re-checks the newest 1,000 rows each time you open the page; hover over it to see the range it covered. A break shows Tampering detected (N) instead. Scripts and monitoring can check the whole chain:

Terminal window
curl -s -H "Authorization: Bearer $TOKEN" "$SPATIUM/api/v1/audit/integrity"

A healthy chain answers {"ok": true, "rows_checked": N, "breaks": [], "partial": false}, with the first_seq and last_seq it walked; add ?max_rows=1000&newest=true to run the badge’s check. The call needs a session or token whose owner may read the audit log. A nightly job checks the rows added since its last run, re-walks the whole chain about once a week, and opens a critical audit-chain-broken alert if it finds a break.

An audit trail that lives only on the box it describes can be lost with the box. Settings → Audit Event Forwarding sends every audit row to targets you add:

Kind Options
Syslog UDP, TCP or TLS; RFC 5424 with JSON (the default), CEF or LEEF; RFC 3164; or bare JSON lines
HTTP webhook Generic JSON, or formatted for Slack, Microsoft Teams (a Workflows webhook URL) or Discord
Email (SMTP) STARTTLS, SSL or plain, to a list of recipients

Each target can filter by minimum severity and by resource type, and has a test action that sends a synthetic event; it proves the connection, not that alerts get through (module 2.5). The same targets deliver alerts, so one SIEM destination covers both. Credential-shaped fields in the forwarded old and new values arrive as [redacted].

Delivery is best-effort. Forwarding runs after the change commits, so a dead collector never blocks or rolls back a change, and one failing target doesn’t affect the others.

The flip side is that an event can be lost if a collector is down. If you need at-least-once delivery, point a webhook at a durable queue and let that be the store. Some rows written by scheduled background tasks may not forward in this release. The audit log itself stays in PostgreSQL and is never pruned.

The tools only help if you use them. Habits that keep Ridgeline’s changes safe:

  • Know which install you’re on. The environment banner from Lab 1 labels every page, the sign-in page included.
  • Back up before anything risky. A manual backup takes seconds (module 2.6), and Trash doesn’t cover everything.
  • Preview, then commit. Sync DNS shows exactly what it will change before Apply. Splitting, merging and resizing a subnet preview the result first, then make you type the CIDR back before they commit.
  • Ask for a second pair of eyes. With the governance.approvals feature module on (it’s off by default) and a matching approval policy enabled, deleting a subnet, block, IP space, DNS zone, DHCP scope or DHCP server group queues a change request instead. Another operator who has the Change Approver role and the permission the change needs approves it, from the Change Requests page; the audit log records both people.
  • Freeze writes during a change window. Settings → Security → Maintenance Mode makes every write return 503 for everyone except superadmins. Reads keep working, and so do the agents, so DNS and DHCP keep serving.
  • Read the audit log afterwards. Filter on your own user and check that the rows match what you meant to do.
Hands-on lab 9 · about 20 min

Break it, restore it, prove it

You will:

  • Create a scratch subnet with one host, and resolve the host's name
  • Delete the subnet through the Danger zone, and see the name stop resolving
  • Restore it from Trash, and see the name come back
  • Trace the create, delete and restore in the audit log

Before you start: Finish Lab 3 first, so the campus block 10.20.0.0/16 exists. Sign in as admin: only a superadmin can restore from Trash. You need dig in a terminal, as in Lab 8.

  1. Open IPAM, select the block 10.20.0.0/16, and click New Subnet.

  2. Enter the network 10.20.99.0/24 and the name Scratch, and click Create. It inherits the block’s DNS settings, so SpatiumDDI also creates its reverse zone, 99.20.10.in-addr.arpa.

  3. Open 10.20.99.0/24, click Allocate IP, choose Specific IP, and allocate 10.20.99.10 with the hostname scratch-01.

  4. Resolve it. BIND9 answers 10.20.99.10:

    Terminal window
    dig @127.0.0.1 -p 1053 +short scratch-01.corp.example.edu
  5. With 10.20.99.0/24 open, click Edit, open the Danger zone tab, and click Delete this subnet….

  6. In Delete Subnet, read what happens to leased and manual addresses, and click Continue.

  7. In Delete subnet, read what moves to Trash, tick “I understand …” and click Move to Trash.

  8. Run the same dig again. Within a couple of seconds it prints nothing: moving the subnet to Trash withdrew the record. Without +short, the answer’s header shows status: NXDOMAIN.

  9. Open Administration → Trash. The subnet’s batch holds five rows: the subnet, its reverse zone and three DNS records (scratch-01’s A and PTR, and the gateway’s PTR). Click Restore on 10.20.99.0/24 Scratch; the dialog says how many other rows come back with it. Click Restore to confirm.

  10. Open IPAM and click Refresh IP spaces, the refresh icon above the tree. 10.20.99.0/24 is back in the campus block, with scratch-01.

  11. Run the dig once more. BIND9 answers 10.20.99.10 again.

  12. Open Administration → Audit Log and set the filter under Resource to subnet. The newest 10.20.99.0/24 rows show create, soft_delete and restore, and the header shows Chain verified.

✅ Check your work from the course folder:./lab/check.sh 9
Knowledge check · 6 questions

Audit log, Trash and change safety

1. Why can't a change in SpatiumDDI succeed without an audit record?

2. The Audit Log page shows Chain verified. What does that tell an auditor?

3. Twenty minutes ago someone deleted the "Scratch" subnet 10.20.99.0/24 together with its DHCP scope. How do you get it back?

4. Which of these can you not recover from Trash?

5. Why does Merge make you type the merged CIDR before Confirm merge turns on?

6. Ridgeline wants every DNS zone delete to need a second person's sign-off. What provides that?

Finished 2.4 Audit, Trash & safety?
Mark it complete to track your progress (stored only in this browser).