Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions setup/Setup-Epp.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
Public GitHub owner/repository containing the setup files. Use with SourceRef to test a fork.
.PARAMETER InstallPrerequisites
Install missing Microsoft Graph modules and the Azure CLI Bicep component after explicit opt-in.
.PARAMETER ForceAuthentication
Require fresh tenant-specific device-code sign-in for Azure CLI and Microsoft Graph.
.EXAMPLE
.\Setup-Epp.ps1
.EXAMPLE
Expand All @@ -34,6 +36,7 @@ param(
[string] $SourceRef = 'main',
[switch] $NonInteractive,
[switch] $InstallPrerequisites,
[switch] $ForceAuthentication,
[switch] $ApproveDeployment
)

Expand Down
20 changes: 17 additions & 3 deletions setup/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ disclosed outbound managed-identity federated credential.
- An Azure **user** account permitted to deploy at subscription scope, create the listed resources,
and create the scoped Azure role assignments.
- A Microsoft Entra **Privileged Role Administrator** for granting the Microsoft first-party service
principal Graph `Application.Read.All`, plus delegated Graph scopes `Application.ReadWrite.All`,
`Application.Read.All`, and `AppRoleAssignment.ReadWrite.All`.
principal Graph `Application.Read.All`, plus delegated Graph scopes `User.Read`,
`Application.ReadWrite.All`, `Application.Read.All`, and `AppRoleAssignment.ReadWrite.All`.
`User.Read` is for the setup operator's `/me` lookup; it is not granted to the first-party service
principal or the endpoint app.
- Microsoft Graph **beta** access for the Entra `signInAudienceRestrictions` allowed-tenants preview.
The selected provider tenant is allowed in addition to the app's home tenant, which Entra always allows.
- **Linux Premium EP1** available in the chosen region. Setup registers missing required Azure
Expand Down Expand Up @@ -96,11 +98,17 @@ Setup normally detects these automatically. For unattended execution, allow inst
Install Azure CLI through its official installation instructions if necessary. Setup checks the
explicitly supplied subscription and tenant without changing the CLI's selected subscription. If no
matching Azure user session exists, it runs `az login --tenant <tenant-id>`. It separately requests
Graph sign-in before displaying the plan if the delegated session is missing required scopes. The
Graph sign-in before displaying the plan if the delegated session is missing required scopes,
including `User.Read` for operator identity readback. The
consent includes broad app-role-management scopes because the approved deployment grants
`Application.Read.All` to the Microsoft phone-provider service principal. Authentication, module
installation, Bicep installation, MFA, and consent prompts are not resource-creation approvals.

Use `-ForceAuthentication` when the machine has ambiguous cached identities. It requires interactive
device-code authentication for Azure CLI and Microsoft Graph, does not clear shared token caches,
and cannot be combined with `-NonInteractive`. Azure RBAC always uses the selected ARM token's
validated `oid`; Graph `/me` is tracked separately for application-management operations.

## Step 2 - download and run one script

Download and inspect [Setup-Epp.ps1](../Setup-Epp.ps1), or save it from the upstream raw URL:
Expand All @@ -112,6 +120,12 @@ Invoke-WebRequest `
.\Setup-Epp.ps1
```

Force explicit account selection when testing on a shared or multi-account computer:

```powershell
.\Setup-Epp.ps1 -ForceAuthentication
```

The flow is:

1. **Collect missing customer inputs:** tenant, subscription, existing application client ID, Azure
Expand Down
36 changes: 35 additions & 1 deletion setup/docs/Troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,48 @@ setup makes it multi-tenant, restricts it to its home tenant plus the provider J
through the Entra allowed-tenants preview, creates both required service principals, adds and assigns
`Epp.Invoke`, and grants the Microsoft phone-provider service principal Graph `Application.Read.All`.

Graph needs delegated `Application.ReadWrite.All`, `Application.Read.All`, and
Graph needs delegated `User.Read`, `Application.ReadWrite.All`, `Application.Read.All`, and
`AppRoleAssignment.ReadWrite.All`. Granting a Microsoft Graph application permission normally
requires a Privileged Role Administrator. Noninteractive runs must authenticate both clients first
with these scopes and supply `-ApproveDeployment` separately.

The tenant restriction uses Microsoft Graph beta `signInAudienceRestrictions`. If that preview is
unavailable or the tenant policy blocks it, setup stops before mutation rather than silently allowing
all organizational tenants.

## Graph /me returns 403 Forbidden

`GET /me?$select=id,userPrincipalName` requires delegated
[`User.Read`](https://learn.microsoft.com/en-us/graph/api/user-get?view=graph-rest-1.0#permissions).
The application-management scopes do not authorize this profile lookup. Versions that added the
Graph operator readback without requesting `User.Read` could therefore fail during preflight.
This is a setup sign-in scope issue, not a request for another Azure or Entra administrator role.

Use the updated script and source revision. It requests `User.Read` for the operator's Graph
PowerShell session and reconnects interactively when a cached session lacks it, before calling
`/me`. `-ForceAuthentication` also requests the complete scope set. Noninteractive runs must
authenticate first:

```powershell
Connect-MgGraph -TenantId '<customer-tenant-id>' -ContextScope Process `
-Scopes 'User.Read', 'Application.ReadWrite.All', 'Application.Read.All', 'AppRoleAssignment.ReadWrite.All'
```

This does not grant `User.Read` to the Microsoft phone-provider service principal or endpoint app.
Azure role assignments continue to use the ARM token's `oid`, not Graph `/me`.

## PrincipalNotFound for the Azure operator

Azure RBAC and Microsoft Graph can expose different object IDs for the same interactive account,
especially with brokered, guest, or aliased identities. Setup must not use Graph `/me` as an Azure
role-assignment principal. The current script decodes the selected subscription's ARM access token
in memory, validates its tenant, and passes its `oid` to Bicep. The token is never printed or saved.

Use `-ForceAuthentication` to require fresh Azure CLI and Graph device-code sign-in when account
selection is ambiguous. This does not replace ARM-token identity selection and does not run
`az logout`, `az account clear`, or delete shared authentication caches. If a correct ARM `oid`
still receives `PrincipalNotFound`, wait for actual directory/RBAC replication and rerun with the
same prefix; retries must not substitute a Graph object ID.
Use a distinct resource prefix for each language; setup rejects changing a previously tagged
app to another runtime with the same prefix.

Expand Down
10 changes: 5 additions & 5 deletions setup/providers/telesign.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,33 @@
"routes": {
"sms": {
"global": {
"endpoint": "https://rest-ww.telesign.com/integration/microsoft-cyot/sms",
"endpoint": "https://verify.telesign.com/integration/msft/cyot",
"appId": "00000000-0000-0000-0000-000000000000",
"timeoutMilliseconds": 1500,
"retryIntervalSeconds": 30
},
"eu": {
"endpoint": "https://rest-ww.telesign.com/integration/microsoft-cyot/sms",
"endpoint": "https://verify.telesign.com/integration/msft/cyot",
"appId": "00000000-0000-0000-0000-000000000000",
"timeoutMilliseconds": 1500,
"retryIntervalSeconds": 30
}
},
"voice": {
"global": {
"endpoint": "https://rest-ww.telesign.com/integration/microsoft-cyot/voice",
"endpoint": "https://verify.telesign.com/integration/msft/cyot",
"appId": "00000000-0000-0000-0000-000000000000",
"timeoutMilliseconds": 1500,
"retryIntervalSeconds": 30
},
"eu": {
"endpoint": "https://rest-ww.telesign.com/integration/microsoft-cyot/voice",
"endpoint": "https://verify.telesign.com/integration/msft/cyot",
"appId": "00000000-0000-0000-0000-000000000000",
"timeoutMilliseconds": 1500,
"retryIntervalSeconds": 30
}
}
},
"note": "The supplied global SMS and voice URLs are preserved. EU URLs and application IDs are explicit test values until Telesign provides them."
"note": "All Telesign channel and region selections use the supplied Microsoft CYOT integration endpoint. Application IDs remain explicit test values until Telesign provides them."
}
}
Loading
Loading