Skip to content

Support multiple traffic forwarding profiles in EPA/EIA export and provisioning #83

Description

Summary

Global Secure Access is rolling out multiple traffic forwarding profiles per traffic type as a private preview (two previews exercise the same mechanism: Multiple Forwarding Profiles for Private Access on private, and Fail-Close on internet). Migrate2GSA's export and provisioning cmdlets were written against the old assumption of exactly one forwarding profile per traffic type.

PR #82 fixes the immediate breakage — a false Private Access is not enabled error on preview tenants — but that only restores the on/off gate. This issue tracks the remaining coverage gaps.

Full analysis, proposed CSV shape, sized work breakdown, and blockers: docs/featureImprovements/mtfp-coverage-fixideas.md (added in the companion docs PR).

Gaps

  1. Export loses profile topology. Export-EntraPrivateAccessConfig emits one CSV row per application segment with no representation of which forwarding profiles exist, their priority / state / clientFallbackAction, which apps belong to which profile, or per-profile user/group/device/platform assignment. An admin exporting a preview tenant gets a CSV that silently implies every app is reachable by every assigned user — exactly the assumption the preview breaks.

  2. Provisioning cannot reproduce a preview tenant. Start-EntraPrivateAccessProvisioning has no concept of a forwarding profile, so a restore into a preview tenant collapses everything into the default profile. This is security-relevant: apps intended for a narrow custom profile become broadly reachable.

  3. Internet Access export misses fail-close posture. Export-EntraInternetAccessConfig exports filtering policies and security profiles but no forwarding-profile data, so a clientFallbackAction: block profile is invisible in the export.

Proposed direction

Two artifacts, following the pattern Export-EntraInternetAccessConfig already uses for its separate Policies and SecurityProfiles CSVs:

  • {timestamp}_EPA_Config.csv — one new additive column, ForwardingProfiles (semicolon-separated profile names, same convention as EntraGroups). Existing CSVs keep importing unchanged.
  • {timestamp}_EPA_ForwardingProfiles.csv — new file carrying ProfileName, Priority, State, IsDefault, ClientFallbackAction, QuickAccessEnabled, AssignedGroups, AssignedUsers, DevicePlatforms, Provision.

Import side mirrors this with an optional -ForwardingProfileConfigPath parameter; absent means today's behaviour exactly.

Recommended split

  • A — unblocked. Export every PA and IA forwarding profile plus metadata into the new profiles CSV. Leave ForwardingProfiles blank on the app CSV and warn when more than one profile of a traffic type is detected. Makes the export honest without asserting membership the tool cannot determine. Small, low risk, no new Graph scopes.
  • B — blocked. Profile→app membership, provisioning writes, and assignment round-trip. Gated on the blockers below. A wrong guess about the join model means rewriting the CSV contract, which is a breaking change for anyone who has adopted it.

Blockers — need preview product team input

  1. Profile→app join has no confirmed public surface. forwardingRule carries no appId in the public schema, and private profiles may not expose policyRules at all. Without a confirmed Graph representation the membership column cannot be populated — and that is the most valuable part of the export.
  2. associations is opaque. No @odata.type values or field names published for user/group/device/platform assignment, so assignment provisioning is unimplementable and the export can only round-trip a blob that will not survive a CSV.
  3. Write API unverified. Nothing confirms POST/PATCH on /beta/networkAccess/forwardingProfiles is available in the preview, or whether profile creation is portal-only. If portal-only, the write slice collapses to "export only, document the manual step".
  4. Field details unconfirmed. Exact clientFallbackAction name and casing; the default profile's priority sentinel (100? absent? null?) — needed to reliably distinguish default from custom.
  5. Scope requirements unknown. Whether NetworkAccess.Read.All covers the expanded policies / associations reads, or whether the preview gates them behind an additional scope. Changes the consent story for the export.

Open questions

  1. Can a private custom profile also set clientFallbackAction: block, or is fail-close exclusively an Internet Access scenario in this preview?
  2. Does the preview API expose an explicit app reference on PA forwarding profiles? If not, is destination-matching against application segments acceptable, or is a separate Graph call required?
  3. Should Export-EntraPrivateAccessAppDiscovery become profile-aware, or is discovery inherently profile-agnostic?
  4. Does the default profile always contain every app, making it a reliable superset for validation during provisioning?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions