Skip to content

Fix false "Private Access is not enabled" error when tenant has multiple forwarding profiles - #82

Merged
Thomas Detzner (tdetzner) merged 2 commits into
mainfrom
fix/multiple-pa-forwarding-profiles-validation
Aug 13, 2026
Merged

Fix false "Private Access is not enabled" error when tenant has multiple forwarding profiles#82
Thomas Detzner (tdetzner) merged 2 commits into
mainfrom
fix/multiple-pa-forwarding-profiles-validation

Conversation

@tdetzner

@tdetzner Thomas Detzner (tdetzner) commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Problem

On tenants enrolled in the multiple traffic forwarding profiles private preview, Export-EntraPrivateAccessConfig fails during validation with:

[ERROR] [Validation] Private Access is not enabled on this tenant. Current state: enabled disabled disabled disabled
Exception: Private Access feature validation failed. Please enable Private Access before exporting.

Private Access is enabled on the tenant — the validation is wrong.

Root cause

GET /beta/networkAccess/forwardingProfiles historically returned exactly one profile per trafficForwardingType. With the preview it returns a default profile plus up to 10 custom profiles per type.

The enablement guards assumed a single profile:

$paProfile = Get-IntNetworkAccessForwardingProfile -ProfileType 'private'
if (-not $paProfile -or $paProfile.state -ne 'enabled') { throw }

With four private profiles, $paProfile is an array. PowerShell then:

  1. member-enumerates $paProfile.state into @('enabled','disabled','disabled','disabled') — this is the space-mashed string visible in the error message,
  2. applies the filtering form of -ne to that array, returning the 3 non-matching elements,
  3. treats the resulting non-empty array as truthy, so the guard fires and throws.

Note this would throw even if all profiles were enabled, since a non-empty array is truthy either way.

Fix

Treat the result as a collection and pass when at least one profile of that traffic type is enabled:

$paProfiles = @(Get-IntNetworkAccessForwardingProfile -ProfileType 'private')
$enabledPaProfiles = @($paProfiles | Where-Object { $_.state -eq 'enabled' })
if ($enabledPaProfiles.Count -eq 0) { ... }

Applied to all three call sites. The other two had the same latent bug and would have failed identically — Internet Access also gets multiple profiles in the preview, via the Fail-Close preview:

  • Export-EntraPrivateAccessConfig
  • Export-EntraPrivateAccessAppDiscovery
  • Export-EntraInternetAccessConfig

Diagnostics improved alongside: the failure message now lists each profile as name: state instead of a space-mashed string, and the success line reports N of M forwarding profile(s) enabled. The multi-profile return contract is now documented on Get-IntNetworkAccessForwardingProfile.

Scope

This restores the on/off gate only. The exports still have no notion of which forwarding profile exposes which apps, so a preview tenant's profile topology is not captured and a restore would silently collapse every app into the default profile. That larger gap is tracked separately — see the companion docs PR and tracking issue.

Verification

pwsh scripts/verify.ps1 passes: manifest valid, module imports cleanly, no Pester tests present.

assistance: agentic-ide
type: bug
agent-tool: copilot-chat
agent-model: claude-opus-5
work-item: n/a

GET /beta/networkAccess/forwardingProfiles returns more than one profile per trafficForwardingType for tenants in the multiple-forwarding-profiles private preview. The feature-enablement checks assumed a single profile, so $paProfile.state enumerated to an array and the -ne 'enabled' array filter made the guard truthy, throwing even when the feature was enabled.

Treat the result as a collection and pass when at least one profile of that traffic type is enabled. Applied to the Private Access config export, the Private Access app discovery export, and the Internet Access config export (all three had the same latent bug).
@tdetzner Thomas Detzner (tdetzner) changed the title Fix false 'not enabled' error when multiple forwarding profiles exist Fix false "Private Access is not enabled" error when tenant has multiple forwarding profiles Aug 13, 2026
@tdetzner Thomas Detzner (tdetzner) added the bug Something isn't working label Aug 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes false “feature not enabled” validation failures in the export cmdlets for tenants that return multiple forwarding profiles per trafficForwardingType. The previous guards assumed a single profile object; when multiple profiles existed, $profile.state enumerated and the -ne 'enabled' comparison produced a truthy array result, incorrectly throwing even when the feature was enabled.

Changes:

  • Update Private Access config export to treat forwarding profiles as a collection and pass when at least one matching profile is enabled.
  • Apply the same collection-based enablement check to Private Access app discovery export.
  • Apply the same collection-based enablement check to Internet Access config export, and clarify the internal helper’s help text accordingly.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
Migrate2GSA/internal/functions/Get-IntNetworkAccessForwardingProfile.ps1 Updates comment-based help to clarify that callers may receive multiple profiles per traffic type and should evaluate as a collection.
Migrate2GSA/functions/GSA/Export-EntraPrivateAccessConfig.ps1 Fixes the Private Access enablement guard by checking for at least one enabled forwarding profile and improves diagnostic logging.
Migrate2GSA/functions/GSA/Export-EntraPrivateAccessAppDiscovery.ps1 Fixes the Private Access enablement guard using the same “any enabled profile” logic.
Migrate2GSA/functions/GSA/Export-EntraInternetAccessConfig.ps1 Fixes the Internet Access enablement guard using the same “any enabled profile” logic and improves diagnostic logging.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@tdetzner
Thomas Detzner (tdetzner) merged commit 8650dc1 into main Aug 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants