We're finally getting the green light to implement ZTNA here, but we have a hard requirement: the existing VPN (OpenVPN on-prem) must remain fully operational for at least six months during the transition. No breaking legacy access. I've been sketching out a phased approach and would love to compare notes.
My current plan leans on a parallel run strategy, using the ZTNA provider's identity integration as the control plane from day one.
**Phase 1: Identity Unification**
* Before touching any network rules, we're syncing all VPN user groups from our AD into Okta (our IdP).
* The ZTNA connector is deployed in a DMZ-like segment, with initial policies set to `DENY ALL`. It can see the legacy app servers, but nothing can reach it yet.
* This is mostly configuration work. The key here is that the VPN continues to work untouched.
**Phase 2: Pilot Application Migration**
* We pick one low-risk internal app (think an internal wiki) for the first cutover.
* In the ZTNA policy, we create a rule: `If user is in group "pilot-users" AND uses device with our agent, ALLOW access to wiki_IP:443`.
* Pilot users install the ZTNA agent. Their traffic to the wiki now goes via the ZTNA cloud, through the connector, to the app. All other traffic still goes through the VPN.
* We test coexistence thoroughly. A user with both VPN and ZTNA agent connected should have split tunneling work correctly.
**Phase 3: Phased App Migration & DNS Shift**
* This is the bulk of the work. We migrate application groups one by one, updating ZTNA policies and internal DNS.
* For example, once the `finance-app` cluster is migrated, we change the internal DNS record `finance-app.corp.local` to resolve to the ZTNA connector's private IP instead of the app's direct IP *for specific pilot users* (using DNS views or a similar mechanism). This is the trickiest part to do without breaking VPN users.
* We monitor VPN usage stats. As traffic for a migrated app drops to near-zero on the VPN, we formally decommission its VPN route.
**Phase 4: VPN Sunset**
* Once all apps are migrated and VPN traffic is minimal, we enforce agent requirements for all access and finally shut down the VPN gateway.
The big technical questions I'm wrestling with:
1. **DNS Management:** How are you handling the DNS cutover without causing issues for users still on the VPN? Are you using split-brain DNS or something more dynamic?
2. **Agent vs. Agentless for Legacy:** We're using an agent for managed devices. For unmanaged/contractor access, we'll use agentless ZTNA to a dedicated portal, but they'll remain on the VPN for now. Any pitfalls in running both models side-by-side?
3. **Session Persistence:** For stateful apps, ensuring a user session isn't broken when their traffic flips from VPN to ZTNA mid-day.
Here's a simplified snippet of the kind of policy-as-code we're defining for Phase 2, using a pseudo-config format our chosen vendor supports:
```yaml
access_policies:
- name: "pilot-wiki-access"
user_group: "okta:group:pilot-users"
device_trust: "agent-present"
action: "allow"
resources:
- "tcp:wiki.internal.corp:443"
```
Has anyone walked this path already? I'm particularly interested in how you handled the DNS transition and any gotchas with concurrent VPN/ZTNA sessions on the same machine.
--builder
Latency is the enemy, but consistency is the goal.
Your phase 1 is spot on. The "DENY ALL" start for the connector is crucial a lot of teams miss. I'd add one thing: instrument that connector from day one with metrics for connection attempts, even though they'll all be denies. It gives you a baseline and might catch misconfigured clients poking at it during the parallel run.
For Phase 2, picking the internal wiki is a classic. One caveat - make sure your pilot group's traffic *only* goes through ZTNA for that app. Sometimes you need a local PAC file or a slight nudge in DNS to prevent their devices from still trying to hit the wiki via the legacy VPN subnet.
Sleep is for the weak