CR: Prod SSRS VNet Integration
Jira: TBD Status: Scheduled Scheduled: 2026-03-31, after 17:00 CDT (after school hours) Owner: Leon Geldenhuys Risk: LOW | Duration: ~30m | Rollback: ~5m
Summary
Enable VNet integration on wa-eshars-prod so the web app can reach vm-ssrs16-prod (SSRS)
via its private IP (10.0.0.5) instead of the public IP (23.99.180.223). This removes the
dependency on a public IP and is the prod equivalent of the nonprod change validated on
2026-03-25 across all wa-eshars-nonprod slots. Risk is low because the public IP remains
in place as a fallback throughout execution — reports continue working at every point.
Background
The wa-eshars-nonprod App Service was previously reaching vm-sql16-np (SSRS, 10.1.0.4)
via its public IP. When that public IP was removed on 2026-03-25, all report viewing broke.
The fix was to:
- Create a dedicated subnet for App Service VNet integration
- Add VNet integration to each slot so traffic routes privately
- Update the two required app settings (dot-notation + camelCase — both must be set)
That fix was validated across all nonprod slots (dev, qa, regression, uat, trn). This change replicates the exact same pattern in prod.
Scope
| Resource | Change | Environment |
|---|---|---|
VNet rg-eshars-prod | Create subnet sn-webapp-eshars-prod (10.0.3.0/24) delegated to Microsoft.Web/serverFarms | prod |
wa-eshars-prod | Add VNet integration → sn-webapp-eshars-prod | prod |
wa-eshars-prod app settings | MvcReportViewer.ReportServerUrl → http://10.0.0.5/ReportServer | prod |
wa-eshars-prod app settings | MvcReportViewerReportServerUrl → http://10.0.0.5/ReportServer | prod |
vm-ssrs16-prod | (Optional, post-soak) Remove public IP 23.99.180.223 | prod |
Prerequisites
- Nonprod validated — all 5 slots working since 2026-03-25
- Current app setting values documented (see Pre-checks)
- After-hours window confirmed (after 5 PM CDT, avoid month-end billing window)
- Azure portal access verified
Procedure
Pre-checks
- Note current values of both app settings on
wa-eshars-prod:MvcReportViewer.ReportServerUrl— current value:http://23.99.180.223/ReportServerMvcReportViewerReportServerUrl— current value: (verify in portal before execution)
- Confirm
vm-ssrs16-prodprivate IP is10.0.0.5(Azure Portal →vm-ssrs16-prod→ Networking) - Confirm VNet
rg-eshars-prod/defaulthas no existing subnet using10.0.3.0/24
Execution Steps
-
Create subnet in Azure Portal or CLI:
- VNet:
rg-eshars-prod→ Subnets → Add - Name:
sn-webapp-eshars-prod - CIDR:
10.0.3.0/24 - Delegation:
Microsoft.Web/serverFarms
- VNet:
-
Add VNet integration to
wa-eshars-prod:- App Service → Networking → VNet Integration → Add
- Select VNet
rg-eshars-prod, subnetsn-webapp-eshars-prod
-
Update app settings on
wa-eshars-prod(App Service → Configuration → Application settings):- Set
MvcReportViewer.ReportServerUrl→http://10.0.0.5/ReportServer - Set
MvcReportViewerReportServerUrl→http://10.0.0.5/ReportServer - Click Save
- Set
-
App Service restarts automatically after saving settings.
Verification
- Wait ~60 seconds for restart to complete
- Log in to eSHARS prod and navigate to Historical Data → run any report
- Verify report renders correctly (no “Service unavailable” or “Unable to connect to remote server” error)
- Confirm VNet integration shows Connected in Azure Portal →
wa-eshars-prod→ Networking - Check Application Insights (
ai-eshars-prod) for any spike in errors on report endpoints
Optional: Remove Public IP (post-soak)
Only after 24-48 hours of confirmed stable operation:
- In Azure Portal, navigate to
vm-ssrs16-prod→ Networking → NIC → IP Configurations - Disassociate the public IP
23.99.180.223 - Re-test reports end-to-end (should still work via private routing)
- Update VM SSRS16 (Production) to reflect removal
Rollback
Trigger: Any report fails to render after step 4 (restart), OR VNet integration status is not “Connected”.
- Revert
MvcReportViewer.ReportServerUrl→http://23.99.180.223/ReportServer - Revert
MvcReportViewerReportServerUrl→http://23.99.180.223/ReportServer - Click Save — app restarts automatically
- Verify reports work again via public IP
The subnet and VNet integration can remain in place — they cause no harm and save time on a retry.
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Reports fail via private IP | Low | Medium | Public IP still active — rollback is instant app setting revert (~5 min) |
| Subnet CIDR conflict | Very Low | Low | 10.0.3.0/24 mirrors nonprod pattern; prod VNet has only default (10.0.0.0/24) and AzureBastionSubnet (10.0.1.0/26) confirmed |
| App restart disruption | Low | Low | After-hours; minimal concurrent users |
| VNet integration takes effect slowly | Low | Low | Standard Azure propagation ~60s; extend soak before declaring success |
Outcome
Executed: — Result: — Notes: —