Skip to content

Commit 0560c4e

Browse files
commit suggestions
1 parent 5815a63 commit 0560c4e

4 files changed

Lines changed: 514 additions & 20 deletions

File tree

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,6 @@ Follow the quick deploy steps on the deployment guide to deploy this solution to
276276
277277
[Click here to launch the deployment guide](./docs/DeploymentGuide.md)
278278

279-
> ⚠️ **Post-Deployment Setup Required**
280-
> `azd up` provisions infrastructure only. After it completes, run the post-deployment scripts to register schemas, upload sample data, and configure authentication. See [Step 5 of the Deployment Guide](./docs/DeploymentGuide.md#step-5-post-deployment-configuration) for commands and required permissions.
281-
282279
| [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/microsoft/content-processing-solution-accelerator) | [![Open in Dev Containers](https://img.shields.io/static/v1?style=for-the-badge&label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/content-processing-solution-accelerator) | [![Open in Visual Studio Code Web](https://img.shields.io/static/v1?style=for-the-badge&label=Visual%20Studio%20Code%20(Web)&message=Open&color=blue&logo=visualstudiocode&logoColor=white)](https://vscode.dev/azure/?vscode-azure-exp=foundry&agentPayload=eyJiYXNlVXJsIjogImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9taWNyb3NvZnQvY29udGVudC1wcm9jZXNzaW5nLXNvbHV0aW9uLWFjY2VsZXJhdG9yL3JlZnMvaGVhZHMvbWFpbi9pbmZyYS92c2NvZGVfd2ViIiwgImluZGV4VXJsIjogIi9pbmRleC5qc29uIiwgInZhcmlhYmxlcyI6IHsiYWdlbnRJZCI6ICIiLCAiY29ubmVjdGlvblN0cmluZyI6ICIiLCAidGhyZWFkSWQiOiAiIiwgInVzZXJNZXNzYWdlIjogIiIsICJwbGF5Z3JvdW5kTmFtZSI6ICIiLCAibG9jYXRpb24iOiAiIiwgInN1YnNjcmlwdGlvbklkIjogIiIsICJyZXNvdXJjZUlkIjogIiIsICJwcm9qZWN0UmVzb3VyY2VJZCI6ICIiLCAiZW5kcG9pbnQiOiAiIn0sICJjb2RlUm91dGUiOiBbImFpLXByb2plY3RzLXNkayIsICJweXRob24iLCAiZGVmYXVsdC1henVyZS1hdXRoIiwgImVuZHBvaW50Il19) |
283280
|---|---|---|
284281

docs/DeploymentGuide.md

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ azd up
305305

306306
> Want to customize the schemas for your own documents? [Learn more about adding your own schemas here.](./CustomizeSchemaData.md)
307307

308-
`azd up` now provisions infrastructure and application containers only. Post-provision data setup is split into **separate manual steps** so you can run, retry, or skip them independently.
308+
Schema registration is **not** run automatically by `azd up`. The `azd up` command provisions infrastructure and application containers only, and post-provision data setup is split into **separate manual steps** so you can run, retry, or skip them independently.
309309

310310
Run schema registration first to:
311311

@@ -367,16 +367,6 @@ bash ./infra/scripts/setup_auth.sh
367367

368368
The auth script is idempotent and performs preflight validation before making changes.
369369

370-
#### Skipping auth setup
371-
372-
If your tenant blocks programmatic app registration, or you need to defer authentication setup, you can skip this step:
373-
374-
```powershell
375-
azd env set AZURE_SKIP_AUTH_SETUP true
376-
```
377-
378-
Then follow the manual instructions in [App Authentication Configuration](./ConfigureAppAuthentication.md). To re-enable later, set the value to `false` and re-run `setup_auth.ps1`.
379-
380370
#### Required Permissions for auth setup
381371

382372
- Create/update app registrations: **Application Administrator**, **Cloud Application Administrator**, or **Global Administrator**
@@ -387,12 +377,6 @@ If permissions are insufficient, the script exits early (or warns before consent
387377

388378
> **Note:** EasyAuth can take up to 10 minutes to fully propagate. If the Web app returns 500/401 immediately after setup, wait a few minutes and retry.
389379

390-
#### WAF (Well-Architected Framework) deployments
391-
392-
Authentication script execution is fully compatible with the WAF / production profile (`main.waf.parameters.json`, which enables `enablePrivateNetworking`, `enableRedundancy`, and `enableScalability`). The Web and API container apps keep external ingress in the default WAF profile, so registered redirect URIs (`https://<fqdn>/.auth/login/aad/callback`) remain valid public entry points.
393-
394-
> If you customize WAF to make Web or API ingress internal-only, run the auth script from an environment that can reach those private endpoints (for example, the deployed jumpbox or a VPN-connected host).
395-
396380
### 5.4 Verify Deployment
397381

398382
1. Access your application using the **Web App Endpoint** from the deployment output.
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
#Requires -Version 7.0
2+
<#
3+
.SYNOPSIS
4+
Validates configure_auth.ps1 --preflight-only behavior under each
5+
insufficient-permission scenario. No real Azure credentials are required.
6+
7+
.DESCRIPTION
8+
Creates temporary mock az.cmd / azd.cmd executables (backed by PowerShell
9+
helper scripts) in a temp folder, prepends that folder to PATH, then calls
10+
configure_auth.ps1 --preflight-only for each scenario and asserts the
11+
expected exit code and output text.
12+
13+
Scenarios tested (10 total):
14+
T01 Happy path — all checks pass
15+
T02 Check 1: Azure CLI not authenticated
16+
T03 Check 2: required azd env values missing
17+
T04 Check 3: Container Apps CLI extension absent
18+
T05 Check 4: no Contributor/Owner RBAC on resource group
19+
T06 Check 5: cannot read Entra app registrations
20+
T07 Check 6: target Container App is inaccessible
21+
T08 Check 7: Entra role below Application Administrator (FAIL)
22+
T09 Check 7: consent-only WARN — non-fatal (exit 0)
23+
T10 Check 7: service-principal login — dir check skipped (exit 0)
24+
25+
.EXAMPLE
26+
.\tests\infra-scripts\test_configure_auth_preflight.ps1
27+
#>
28+
29+
$ErrorActionPreference = "Stop"
30+
$ScriptDir = $PSScriptRoot
31+
$RepoRoot = Resolve-Path (Join-Path $ScriptDir "../..")
32+
$Subject = Join-Path $RepoRoot "infra/scripts/configure_auth.ps1"
33+
34+
if (-not (Test-Path $Subject)) {
35+
Write-Error "configure_auth.ps1 not found at $Subject"
36+
exit 1
37+
}
38+
39+
$PassCount = 0
40+
$FailCount = 0
41+
$TempDir = Join-Path ([System.IO.Path]::GetTempPath()) "auth_pfl_test_$([guid]::NewGuid().ToString('N'))"
42+
New-Item -ItemType Directory -Path $TempDir | Out-Null
43+
44+
# Clean up temp dir on script exit
45+
try {
46+
47+
# =============================================================================
48+
# Mock PowerShell helper for az.cmd
49+
# Behaviour controlled by AZ_MOCK_SCENARIO environment variable.
50+
# =============================================================================
51+
$MockAzPs1Content = @'
52+
$allArgs = $args
53+
$SCENARIO = if ($env:AZ_MOCK_SCENARIO) { $env:AZ_MOCK_SCENARIO } else { "happy" }
54+
$S = ($allArgs -join " ")
55+
function has($t) { $S -like "*$t*" }
56+
57+
if ((has "account show") -and -not (has "role assignment")) {
58+
if ($SCENARIO -eq "no_auth") { exit 1 }
59+
if (has "tenantId") { Write-Output "mock-tenant-id"; exit 0 }
60+
if (has "user.name") { Write-Output "sp-mock@service.principal"; exit 0 }
61+
Write-Output "mock-sub-id-12345"; exit 0
62+
}
63+
if (has "signed-in-user") {
64+
if ($SCENARIO -eq "sp_login") { exit 1 }
65+
Write-Output "mock-user-object-id-abc123"; exit 0
66+
}
67+
if (has "role assignment list") {
68+
if ($SCENARIO -eq "no_rbac") { Write-Output ""; exit 0 }
69+
Write-Output "Contributor"; exit 0
70+
}
71+
if ((has "ad app list") -and -not (has "ad app show")) {
72+
if ($SCENARIO -eq "no_entra_read") { exit 1 }
73+
Write-Output "mock-app-id-00001"; exit 0
74+
}
75+
if ((has "containerapp") -and (has " --help")) {
76+
if ($SCENARIO -eq "no_extension") { exit 1 }
77+
exit 0
78+
}
79+
if (has "containerapp show") {
80+
if ($SCENARIO -eq "no_container_app") { exit 1 }
81+
Write-Output "ca-testenv-web"; exit 0
82+
}
83+
if (has "rest") {
84+
switch ($SCENARIO) {
85+
"insufficient_dir_role" { Write-Output "Directory Readers"; exit 0 }
86+
"consent_warn_only" { Write-Output "Application Administrator"; exit 0 }
87+
default { Write-Output "Global Administrator"; exit 0 }
88+
}
89+
}
90+
if (has "ad app show") { exit 1 }
91+
exit 0
92+
'@
93+
94+
# =============================================================================
95+
# Mock PowerShell helper for azd.cmd
96+
# Behaviour controlled by AZD_MOCK_SCENARIO environment variable.
97+
# =============================================================================
98+
$MockAzdPs1Content = @'
99+
$allArgs = $args
100+
$SCENARIO = if ($env:AZD_MOCK_SCENARIO) { $env:AZD_MOCK_SCENARIO } else { "happy" }
101+
$S = ($allArgs -join " ")
102+
103+
if ($S -like "*env get-value*") {
104+
$KEY = $allArgs[-1]
105+
if ($SCENARIO -eq "no_env") {
106+
if ($KEY -eq "AZURE_ENV_NAME") { Write-Output "testenv" } else { Write-Output "" }
107+
exit 0
108+
}
109+
switch ($KEY) {
110+
"AZURE_ENV_NAME" { Write-Output "testenv" }
111+
"AZURE_RESOURCE_GROUP" { Write-Output "mock-rg" }
112+
"AZURE_SUBSCRIPTION_ID" { Write-Output "mock-sub-id" }
113+
"AZURE_TENANT_ID" { Write-Output "mock-tenant-id" }
114+
"CONTAINER_WEB_APP_NAME" { Write-Output "ca-testenv-web" }
115+
"CONTAINER_WEB_APP_FQDN" { Write-Output "ca-testenv-web.azurecontainerapps.io" }
116+
"CONTAINER_API_APP_NAME" { Write-Output "ca-testenv-api" }
117+
"CONTAINER_API_APP_FQDN" { Write-Output "ca-testenv-api.azurecontainerapps.io" }
118+
default { Write-Output "" }
119+
}
120+
exit 0
121+
}
122+
exit 0
123+
'@
124+
125+
# Write helper scripts
126+
$MockAzPs1Content | Out-File -FilePath (Join-Path $TempDir "mock_az.ps1") -Encoding UTF8
127+
$MockAzdPs1Content | Out-File -FilePath (Join-Path $TempDir "mock_azd.ps1") -Encoding UTF8
128+
129+
# Write .cmd wrappers — %~dp0 resolves to the directory containing the .cmd file
130+
@"
131+
@echo off
132+
pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%~dp0mock_az.ps1" %*
133+
"@ | Out-File -FilePath (Join-Path $TempDir "az.cmd") -Encoding ASCII
134+
135+
@"
136+
@echo off
137+
pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%~dp0mock_azd.ps1" %*
138+
"@ | Out-File -FilePath (Join-Path $TempDir "azd.cmd") -Encoding ASCII
139+
140+
# =============================================================================
141+
# Test runner
142+
# =============================================================================
143+
function Run-Test {
144+
param(
145+
[string]$Name,
146+
[int] $ExpectedExit,
147+
[string]$ExpectedText = "",
148+
[string]$AzScenario = "happy",
149+
[string]$AzdScenario = "happy"
150+
)
151+
152+
$origPath = $env:PATH
153+
$env:PATH = "$TempDir;$env:PATH"
154+
$env:AZ_MOCK_SCENARIO = $AzScenario
155+
$env:AZD_MOCK_SCENARIO = $AzdScenario
156+
$env:AZURE_SKIP_AUTH_SETUP = ""
157+
158+
$rawOutput = pwsh -NoProfile -NonInteractive -ExecutionPolicy Bypass `
159+
-File $Subject "--preflight-only" 2>&1
160+
$exitCode = $LASTEXITCODE
161+
$outputStr = ($rawOutput | Out-String)
162+
163+
$env:PATH = $origPath
164+
$env:AZ_MOCK_SCENARIO = $null
165+
$env:AZD_MOCK_SCENARIO = $null
166+
167+
$ok = $true; $reason = ""
168+
if ($exitCode -ne $ExpectedExit) {
169+
$ok = $false; $reason = "exit $exitCode (expected $ExpectedExit)"
170+
} elseif ($ExpectedText -and ($outputStr -notlike "*$ExpectedText*")) {
171+
$ok = $false; $reason = "expected text '$ExpectedText' not in output"
172+
}
173+
174+
if ($ok) {
175+
Write-Host (" `u{2705} {0,-62}" -f $Name)
176+
$script:PassCount++
177+
} else {
178+
Write-Host (" `u{274C} {0,-62} [{1}]" -f $Name, $reason)
179+
($outputStr -split "`n" | Select-Object -Last 4) | ForEach-Object {
180+
Write-Host " $_"
181+
}
182+
$script:FailCount++
183+
}
184+
}
185+
186+
# =============================================================================
187+
# Test scenarios
188+
# =============================================================================
189+
Write-Host ""
190+
Write-Host "============================================================"
191+
Write-Host " configure_auth.ps1 — preflight permission scenario tests"
192+
Write-Host "============================================================"
193+
194+
# T01 — Happy path: every check should pass
195+
Run-Test "T01 Happy path: all checks pass" `
196+
-ExpectedExit 0 -ExpectedText "Preflight-only mode" `
197+
-AzScenario "happy" -AzdScenario "happy"
198+
199+
# T02 — Check 1: Azure CLI not authenticated
200+
Run-Test "T02 Check 1: not authenticated" `
201+
-ExpectedExit 1 -ExpectedText "Azure CLI authenticated" `
202+
-AzScenario "no_auth" -AzdScenario "happy"
203+
204+
# T03 — Check 2: required azd env values missing
205+
Run-Test "T03 Check 2: missing required azd env values" `
206+
-ExpectedExit 1 -ExpectedText "Required azd env values" `
207+
-AzScenario "happy" -AzdScenario "no_env"
208+
209+
# T04 — Check 3: Azure Container Apps CLI extension absent
210+
Run-Test "T04 Check 3: containerapp CLI extension missing" `
211+
-ExpectedExit 1 -ExpectedText "Container Apps CLI" `
212+
-AzScenario "no_extension" -AzdScenario "happy"
213+
214+
# T05 — Check 4: no Contributor or Owner role on resource group
215+
Run-Test "T05 Check 4: no RBAC Contributor/Owner on resource group" `
216+
-ExpectedExit 1 -ExpectedText "Contributor/Owner" `
217+
-AzScenario "no_rbac" -AzdScenario "happy"
218+
219+
# T06 — Check 5: cannot read Entra app registrations
220+
Run-Test "T06 Check 5: cannot read Entra app registrations" `
221+
-ExpectedExit 1 -ExpectedText "Entra app registrations" `
222+
-AzScenario "no_entra_read" -AzdScenario "happy"
223+
224+
# T07 — Check 6: target Container App is inaccessible
225+
Run-Test "T07 Check 6: Container App is inaccessible" `
226+
-ExpectedExit 1 -ExpectedText "Container App" `
227+
-AzScenario "no_container_app" -AzdScenario "happy"
228+
229+
# T08 — Check 7: Entra role present but below Application Administrator (FAIL)
230+
Run-Test "T08 Check 7: insufficient Entra directory role (FAIL)" `
231+
-ExpectedExit 1 -ExpectedText "App-registration permission" `
232+
-AzScenario "insufficient_dir_role" -AzdScenario "happy"
233+
234+
# T09 — Check 7: Application Administrator present, consent role absent (WARN, non-fatal)
235+
Run-Test "T09 Check 7: consent-only WARN is non-fatal (exit 0)" `
236+
-ExpectedExit 0 -ExpectedText "Admin-consent permission" `
237+
-AzScenario "consent_warn_only" -AzdScenario "happy"
238+
239+
# T10 — Check 7: service principal login — directory-role check skipped (WARN, non-fatal)
240+
Run-Test "T10 Check 7: SP login — directory-role check skipped (exit 0)" `
241+
-ExpectedExit 0 -ExpectedText "directory-role check" `
242+
-AzScenario "sp_login" -AzdScenario "happy"
243+
244+
# =============================================================================
245+
# Summary
246+
# =============================================================================
247+
Write-Host ""
248+
Write-Host "============================================================"
249+
Write-Host " Results: $PassCount passed, $FailCount failed"
250+
Write-Host "============================================================"
251+
Write-Host ""
252+
253+
} finally {
254+
Remove-Item -Path $TempDir -Recurse -Force -ErrorAction SilentlyContinue
255+
}
256+
257+
if ($FailCount -gt 0) { exit 1 }

0 commit comments

Comments
 (0)