How an AI agent extended our on-premises Active Directory into the cloud — provisioning, networking, and validating a new domain controller with a human approving every credentialed step.
As a sysadmin managing on-prem Active Directory (two Windows Server domain controllers, already hybrid-synced to Microsoft Entra ID), we set out to test a practical question: could an AI agent handle real, end-to-end infrastructure deployment — not a scripted demo, but actual cloud provisioning, networking, and Active Directory work — while a human stayed in control of every sensitive step?
The project: deploy a new, additional domain controller in Azure that joins and replicates with our existing on-prem domain. Nothing on-prem was removed or replaced — this was extending our AD environment into the cloud, coordinated through an AI agent with terminal, SSH, and browser-automation access.
An isolated, no-uplink clone of one domain controller was created early on as an additional safety measure. In practice, most of the networking and troubleshooting work took place directly against the production environment — a real, live infrastructure test, with every privileged or potentially destructive action requiring explicit human execution rather than agent autonomy.
Result: a fully functioning, replicating domain controller running in Azure, verified with zero replication errors across all three domain controllers, in both directions.
| Component | Details |
|---|---|
| Azure | Resource group with a VNet, network security groups locked to a single trusted IP, a VPN Gateway supporting both site-to-site and point-to-site connectivity, and a Windows Server 2022 VM |
| On-prem | Existing KVM host running the two production domain controllers, an isolated test network used for early validation, and strongSwan providing the IPsec tunnel |
| Connectivity | A site-to-site VPN tunnel carrying only traffic between the on-prem subnet and the Azure VNet, with every AD-relevant port (Kerberos, LDAP, DNS, RPC, SMB) explicitly allowed and everything else denied |
Provisioning went the way automation should: the AI agent handled Azure CLI work directly, built the VNet, subnets, NSGs, VPN Gateway, and VM, and caught several of its own mistakes along the way — an invalid package name, a misconfigured firewall rule, an Azure capacity wall on the first VM size requested. In each case it diagnosed the actual error text and adjusted rather than guessing blindly.
The real test, though, was what happened once the infrastructure existed but the new domain controller still couldn't properly talk to the rest of the domain. Getting from "VM exists" to "VM is a healthy, replicating domain controller" required finding and fixing three genuinely subtle network faults — the kind that don't show up in a checklist and don't have a single obvious cause.
The VPN tunnel reported a healthy, connected state on both ends. But pings and connection tests across it failed 100% of the time. Rather than assume the tunnel itself was broken, the agent checked its actual encryption counters directly and found them frozen at zero — meaning no real traffic had ever crossed it, despite the healthy status.
Tracing further, it found the on-prem host's own firewall was silently rewriting the source address of outbound traffic before the tunnel's encryption policy could ever match it — so packets bound for Azure were losing the very identity the tunnel needed to recognize and encrypt them. The fix was a single, precisely ordered firewall exception. Verification wasn't just "no more errors" — the agent re-checked the same encryption counters and watched them move from zero to real traffic before calling it fixed.
With the tunnel actually carrying data, on-prem-to-Azure connections worked — but Azure-to-on-prem connections were explicitly rejected, not merely timing out. That distinction mattered: a timeout would suggest a routing gap, but an explicit rejection meant something was actively firing.
The agent traced the exact firewall rule evaluation order and found the inbound rule required a connection to already be "established" — a condition no brand-new connection can ever satisfy. The outbound-direction rule had no such restriction, which explained the asymmetry perfectly. This same bug reappeared once, after a routine reboot regenerated the firewall configuration with the broken rule instead of the fix — so the agent didn't just patch it again, it rewrote its own recovery script to verify the rule's position and correctness, not merely its presence, closing the gap for good.
This was the hardest problem of the project. Small operations across the tunnel — DNS lookups, short authentication exchanges — worked perfectly. But the domain controller promotion process itself, which requires larger network exchanges, would hang for ten-plus minutes and fail with an unhelpful, generic Windows error.
The agent worked through this methodically: ruling out clock synchronization (a real but insufficient earlier fix), confirming the tunnel's actual usable packet size was smaller than either side assumed, and finally identifying that Windows was sending packets larger than the tunnel could carry — with the network's standard "please shrink your packets" signal being silently dropped rather than delivered. This is a notoriously difficult class of network fault precisely because it produces no useful error message at all.
The fix required a kernel-level rule rewriting oversized packets down to a safe size at the tunnel boundary. What stands out here is the verification discipline: the agent's first attempt to confirm the fix used an indirect signal, and it explicitly declined to accept that as proof. It then built a direct, unambiguous test — and in doing so caught a second, more subtle bug: the fix's own matching rule excluded exactly the packets that needed rewriting. It corrected that too, and only declared the issue closed after a counter-based test showed 41 out of 41 relevant packets crossing at the corrected size, with zero at the old, broken size.
Once all three faults were fixed, the agent noted — unprompted — that none of the fixes would survive a reboot, since they existed only in the running system's memory. It built a dedicated boot-time service to reapply them automatically, carefully avoiding a trap it identified in advance: naively enabling the system's default firewall service would have wiped out unrelated rules for other services running on the same host.
This wasn't just claimed to work — a real, full reboot was performed, and every fix was confirmed present and correctly ordered afterward, with the tunnel automatically reconnecting and full connectivity restored without any manual intervention.
Three categories of action never left human hands, for the entire project:
repadmin /replsummary Source DSA largest delta fails/total %% error CONTO-DC 28m:30s 0 / 10 0 CONTO-DC2 32m:59s 0 / 10 0 vm-w2022-poc 23m:12s 0 / 10 0 Destination DSA largest delta fails/total %% error CONTO-DC 23m:12s 0 / 10 0 CONTO-DC2 21m:24s 0 / 10 0 vm-w2022-poc 33m:00s 0 / 10 0
Zero replication failures, in both directions, across all three domain controllers — confirmed live, in an active session on the newly deployed Azure domain controller.
The interesting result isn't that an AI agent can run a single well-documented promotion command — it's that, given real infrastructure access and a disciplined human-in-the-loop model, it performed genuinely hard systems debugging: correlating symptoms across firewall rule order, packet captures, and kernel networking behavior; distinguishing a real fix from one that only looked correct; and knowing when to stop and hand a step back to a human rather than push through.
Equally important is what it never did. Across dozens of privileged operations, the agent never held a production credential, never executed an irreversible domain change unsupervised, and — when a password was accidentally exposed mid-project — flagged it for rotation immediately rather than proceeding as if nothing had happened. That boundary wasn't added afterward. It was the operating model from the first message, and it held for the entire project without exception.