Skip to content

Commit daedf26

Browse files
authored
Backport guided EPP setup improvements to standalone script (#51)
1 parent b44acdf commit daedf26

15 files changed

Lines changed: 2477 additions & 451 deletions

‎.github/workflows/ci.yml‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,27 @@ jobs:
1414
os: [ubuntu-latest, windows-latest]
1515
steps:
1616
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17+
- name: Test script launcher without network access
18+
shell: pwsh
19+
run: ./setup/tests/Launcher.Tests.ps1
20+
- name: Test Azure account selection without Azure access
21+
shell: pwsh
22+
run: ./setup/tests/Accounts.Tests.ps1
1723
- name: Test certificate setup without Azure access
1824
shell: pwsh
1925
run: ./setup/tests/Certificates.Tests.ps1
26+
- name: Test CLI-backed Graph operations without Azure access
27+
shell: pwsh
28+
run: ./setup/tests/Graph.Tests.ps1
29+
- name: Test application provider configuration without Azure access
30+
shell: pwsh
31+
run: ./setup/tests/ProviderConfiguration.Tests.ps1
2032
- name: Test provider setup without Azure access
2133
shell: pwsh
2234
run: ./setup/tests/Providers.Tests.ps1
35+
- name: Test application and region selection without Azure access
36+
shell: pwsh
37+
run: ./setup/tests/Selections.Tests.ps1
2338
- name: Compile Bicep without deploying
2439
shell: pwsh
2540
run: |

‎README.md‎

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@ Have these ready:
3636

3737
- **Provider account:** complete the provider's account and sender registration for your chosen
3838
SMS or voice service. Check [guided provider support](docs/ONBOARDING.md#provider-credential-names).
39-
- **Workstation:** Windows, PowerShell 7+, and Azure CLI 2.60.0+ for Flex Consumption (FC1),
40-
or 2.48.1+ for Premium (EP1). Allow access to GitHub, Azure, Microsoft Graph, Key Vault, and
41-
the deployment endpoints. C# also needs the .NET 8 SDK and NuGet access.
39+
- **Shell:** Azure Cloud Shell in PowerShell mode, or PowerShell 7+ with an Azure CLI user login.
40+
Azure CLI 2.60.0+ is required for Flex Consumption (FC1), or 2.48.1+ for Premium (EP1).
41+
Allow access to GitHub, Azure, Microsoft Graph, Key Vault, and the deployment endpoints.
42+
C# also needs the .NET 8 SDK and NuGet access.
4243
- **Administrators:** an Azure operator with subscription deployment, resource-provider registration,
4344
and role-assignment permissions; an Entra Privileged Role Administrator for setup; and an
4445
Authentication Policy Administrator for later activation. These are separate permissions.
4546
- **Azure region and budget:** check availability and subscription quota for your chosen Linux
4647
plan. Azure resources and provider services can incur charges.
4748

4849
Review the [full prerequisites](setup/docs/README.md#prerequisites-for-step-2), including the
49-
required Entra allowed-tenants preview, before running setup. The script can install missing
50-
Graph modules and Bicep after confirmation; Azure CLI must already be installed.
50+
required Entra allowed-tenants preview, before running setup. Microsoft Graph operations reuse
51+
the Azure CLI login; no Graph PowerShell SDK or separate Graph sign-in is required. The script
52+
can install Bicep after confirmation; Azure CLI must already be installed.
5153

5254
Choose an **onboarding owner** in your organization to coordinate the administrators, provider,
5355
and Microsoft support. This is a sample, not production certification: it does not provide
@@ -103,19 +105,25 @@ Review the downloaded script, then run it:
103105
```
104106

105107
On a shared or multi-account workstation, use `.\Setup-Epp.ps1 -ForceAuthentication` to request
106-
explicit Azure and Microsoft Graph sign-in.
108+
an explicit Azure CLI device-code sign-in. Microsoft Graph reuses that CLI session.
109+
110+
Setup first lists cached Azure CLI user subscriptions. Select the customer tenant and subscription,
111+
then select or enter the dedicated application client ID and choose an Azure region. Refresh or
112+
sign in when the expected account is missing.
107113

108-
Follow the prompts for your tenant, subscription, application client ID, and Azure region.
109114
Choose the provider route and provider, then **one** platform: Node.js (JavaScript), .NET (C#), or Python.
115+
When `-Provider` is omitted, setup reads the application's allowed-tenant configuration: no
116+
supported provider means enter a provider name, one means confirm it, and several means choose
117+
one by name. Provider choices are never numbered, and existing allowed provider tenants are preserved.
110118
Setup configures both SMS and voice provider URLs without asking you to select a channel.
111119
It downloads and verifies the package, builds it if needed, and deploys it for you.
112120
You do not need a separate ZIP upload or local settings file.
113121

114122
![Earlier PowerShell setup prompts for tenant, subscription, application, region, and SMS or voice, with identifiers hidden](docs/images/onboarding/setup-identifiers.png)
115123

116-
*Use the IDs collected in Step 2, then enter your chosen Azure region. This screenshot is from
117-
an earlier script version; current setup no longer has the channel prompt. It is an input screen,
118-
not a deployment result.*
124+
*Use the dedicated application created in Step 2 and your intended Azure region. This screenshot
125+
is from an earlier script version; current setup uses selection lists for the tenant, subscription,
126+
application, and region, and no longer has the channel prompt. It is an input screen, not a deployment result.*
119127

120128
Choose **FC1** for on-demand hosting that can scale to zero, or **EP1** for paid warm capacity.
121129
FC1 can cold-start, and its free usage grant does not make the whole deployment free.
@@ -130,9 +138,9 @@ For the resource prefix, use 2-8 lowercase letters or digits, starting with a le
130138
The Global/EU choice is not the Azure region. The hosting-plan warning applies even when a
131139
plan has a free usage grant.*
132140

133-
Next, setup checks prerequisites, signs in to Azure and Microsoft Graph when needed, verifies
141+
Next, setup checks prerequisites, revalidates the Azure CLI and Microsoft Graph context, verifies
134142
the selected package, and prepares the deployment plan. For C#, this includes an automatic local build.
135-
Complete sign-in and MFA yourself. If a permission or prerequisite check fails, resolve it
143+
Complete any required CLI sign-in, MFA, or administrator consent yourself. If a permission or prerequisite check fails, resolve it
136144
before continuing.
137145

138146
Setup also checks the application's existing **encryption certificates** before deployment.
@@ -159,6 +167,10 @@ After you approve, leave the script running while it configures the application,
159167
Azure resources, and publishes the code. Wait for **Deployment completed** and the saved summary
160168
before moving to Step 4. The input screenshots do not show a completed deployment.
161169

170+
Normal console output ends with **Next steps** after resource generation. Use
171+
`.\Setup-Epp.ps1 -PassThru` when you also need the structured deployment result in a variable
172+
or pipeline; the summary JSON is always saved.
173+
162174
Setup creates the Function App, storage, Key Vault, identities, and monitoring resources.
163175
**Do not create these resources manually first.**
164176
Keep the public certificate and timestamped summary in `epp-output` beside the script.

‎setup/Setup-Epp.ps1‎

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
.DESCRIPTION
66
Download only this file. Supporting PowerShell, Bicep, and provider JSON files come from
77
the selected public GitHub repository (Azure-Samples by default).
8+
Microsoft Graph operations reuse the Azure CLI user session through az ad and az rest.
9+
Interactive setup can select cached tenants, subscriptions, applications, and Azure regions.
810
The endpoint supports SMS and voice, selected by each request.
911
Application registration and policy activation are manual steps.
1012
No Azure resources are changed until you approve the complete plan.
@@ -17,9 +19,12 @@
1719
Premium with cache settings set to true. Prompts when omitted; required for unattended setup.
1820
Cache control requires a Function package that reads these settings.
1921
.PARAMETER InstallPrerequisites
20-
Install missing Microsoft Graph modules and the Azure CLI Bicep component after explicit opt-in.
22+
Install the Azure CLI Bicep component after explicit opt-in. The Graph SDK is not required.
2123
.PARAMETER ForceAuthentication
22-
Require fresh tenant-specific device-code sign-in for Azure CLI and Microsoft Graph.
24+
Require fresh tenant-specific Azure CLI device-code sign-in. Graph reuses that CLI session.
25+
.PARAMETER PassThru
26+
Return the structured deployment result in addition to console output. The summary JSON is
27+
saved whether or not this switch is supplied.
2328
.PARAMETER CertificateAction
2429
Create when no encryption certificate is registered, Reuse a selected certificate, or Replace
2530
all registered encryption certificates. Existing certificates require an explicit choice.
@@ -58,7 +63,8 @@ param(
5863
[switch] $NonInteractive,
5964
[switch] $InstallPrerequisites,
6065
[switch] $ForceAuthentication,
61-
[switch] $ApproveDeployment
66+
[switch] $ApproveDeployment,
67+
[switch] $PassThru
6268
)
6369

6470
$ErrorActionPreference = 'Stop'
@@ -83,13 +89,30 @@ try {
8389
$sourceBaseUri = "https://raw.githubusercontent.com/$repository/$revision/setup"
8490
Write-Host "Downloading deployment tools from $repository at $revision"
8591

86-
foreach ($file in @('support/Epp.Setup.psm1', 'support/Epp.Packages.ps1', 'providers/catalog.json', 'packages/catalog.json', 'infra/main.bicep', 'infra/resources.bicep')) {
92+
foreach ($file in @('support/Epp.Setup.psm1', 'support/Epp.Packages.ps1', 'support/Epp.Graph.ps1', 'providers/catalog.json', 'packages/catalog.json', 'infra/main.bicep', 'infra/resources.bicep')) {
8793
$destination = Join-Path $downloadDirectory $file
8894
New-Item -ItemType Directory -Path (Split-Path -Parent $destination) -Force | Out-Null
8995
Invoke-WebRequest -Uri "$sourceBaseUri/$file" -OutFile $destination -TimeoutSec 60 -MaximumRedirection 0
9096
if ((Get-Item -LiteralPath $destination).Length -eq 0) { throw "GitHub returned an empty file: $file" }
9197
}
9298

99+
$providerCatalog = Get-Content -LiteralPath (Join-Path $downloadDirectory 'providers/catalog.json') -Raw |
100+
ConvertFrom-Json -ErrorAction Stop
101+
if ($providerCatalog.schemaVersion -ne 1 -or -not @($providerCatalog.providers).Count) {
102+
throw 'The downloaded provider catalog is unsupported or empty.'
103+
}
104+
$providerFiles = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal)
105+
foreach ($providerEntry in @($providerCatalog.providers)) {
106+
$file = [string]$providerEntry.file
107+
if ($file -cnotmatch '^[a-z][a-z0-9-]{1,31}\.json$' -or -not $providerFiles.Add($file)) {
108+
throw 'The downloaded provider catalog contains an invalid or duplicate file.'
109+
}
110+
$relativePath = "providers/$file"
111+
$destination = Join-Path $downloadDirectory $relativePath
112+
Invoke-WebRequest -Uri "$sourceBaseUri/$relativePath" -OutFile $destination -TimeoutSec 60 -MaximumRedirection 0
113+
if ((Get-Item -LiteralPath $destination).Length -eq 0) { throw "GitHub returned an empty file: $relativePath" }
114+
}
115+
93116
$module = Import-Module (Join-Path $downloadDirectory 'support/Epp.Setup.psm1') -PassThru -Force
94117
Invoke-EppSetup @arguments -AssetDirectory $downloadDirectory -SourceBaseUri $sourceBaseUri
95118
}

0 commit comments

Comments
 (0)