Skip to content

Commit 7f1d77c

Browse files
himanshusainigFAREAST\hsainiCopilot
authored
Update Logic App templates, docs, and scripts (June 9th) (#136)
StandardLogicApp/ - Update SCIMTests, Orchestrator, Orchestrator_Parameters workflows - Update ValidateLogicAppRun-Standard.ps1 - Update scim-onboarding.agent.md, SetupLogicApp-Standard-Agent.md, SCIM-Validation-Test-Overview.md - Refresh 4 media images (image2, image3, image5, image6) - Bump VERSION 4.0 -> 5.0 (workflows changed) Microsoft.SCIM.LogicAppValidationTemplate/ - Update AssignRolesTOManagedIdentity-LogicApps.ps1 Co-authored-by: FAREAST\hsaini <hsaini@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7d1090f commit 7f1d77c

13 files changed

Lines changed: 553 additions & 109 deletions

Microsoft.SCIM.LogicAppValidationTemplate/AssignRolesTOManagedIdentity-LogicApps.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ $roleId = az ad sp show --id $graphSpId --query "appRoles[?value=='$roleValue'].
1212
$body = @{ principalId=$miObjId; resourceId=$graphSpId; appRoleId=$roleId } | ConvertTo-Json
1313
az rest --method POST --uri "https://graph.microsoft.com/v1.0/servicePrincipals/$miObjId/appRoleAssignments" --headers "Content-Type=application/json" --body "$body"
1414

15-
$roleValue="Synchronization.Read.All"
15+
$roleValue="Synchronization.ReadWrite.All"
1616
$roleId = az ad sp show --id $graphSpId --query "appRoles[?value=='$roleValue'].id" -o tsv
1717
$body = @{ principalId=$miObjId; resourceId=$graphSpId; appRoleId=$roleId } | ConvertTo-Json
1818
az rest --method POST --uri "https://graph.microsoft.com/v1.0/servicePrincipals/$miObjId/appRoleAssignments" --headers "Content-Type=application/json" --body "$body"

Microsoft.SCIM.LogicAppValidationTemplate/StandardLogicApp/Orchestrator_Parameters.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
"SCIM_Group_Update_Test",
2525
"SCIM_User_Delete_Test",
2626
"SCIM_Group_Delete_Test",
27-
"SCIM_Pagination_Test",
27+
"SCIM_User_Pagination_Test",
28+
"SCIM_Group_Pagination_Test",
2829
"POD_User_Test",
2930
"POD_Group_Test",
3031
"Restore_User_Test"
3132
],
3233
"type": "String",
33-
"value": "SCIMTests"
34+
"value": "All"
3435
},
3536
"IsSoftDeleted": {
3637
"metadata": {

Microsoft.SCIM.LogicAppValidationTemplate/StandardLogicApp/Orchestrator_Workflow.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@
460460
"scimUserUpdateTestEnabled": "@or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'SCIM_User_Update_Test'))",
461461
"scimGroupUpdateTestEnabled": "@and(coalesce(body('Call_Initialization_Workflow')?['isGroupSupported'], false), or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'SCIM_Group_Update_Test')))",
462462
"validateCredentialsTestEnabled": "@or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'Validate_Credentials_Test'))",
463-
"scimUserPaginationTestEnabled": "@or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'SCIM_User_Pagination_Test'))"
463+
"scimUserPaginationTestEnabled": "@or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'SCIM_User_Pagination_Test'))",
464+
"scimGroupPaginationTestEnabled": "@and(coalesce(body('Call_Initialization_Workflow')?['isGroupSupported'], false), or(equals(parameters('EnabledTests'), 'All'), equals(parameters('EnabledTests'), 'SCIMTests'), equals(parameters('EnabledTests'), 'SCIM_Group_Pagination_Test')))"
464465
},
465466
"testResults": {
466467
"createUserTestResult": "@coalesce(body('Get_UserTests_Output_Content')?['CreateUserTestOutputs']?['overallResult'], 'SKIPPED')",
@@ -663,6 +664,14 @@
663664
"runLink": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMUserPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'SKIPPED'), '', outputs('Compose_SCIMTests_RunLink'))",
664665
"message": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMUserPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'SKIPPED'), '', 'Click the runLink and search for the action Compose_Final_Results for more info.')"
665666
},
667+
{
668+
"testName": "SCIM_Group_Pagination_Test",
669+
"testResult": "@coalesce(body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['result'], if(not(coalesce(body('Call_Initialization_Workflow')?['isGroupSupported'], false)), 'SKIPPED - IsGroupSupported is false', 'SKIPPED'))",
670+
"provisioningErrorDetails": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'FAILED'), body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['errorDetails'], '')",
671+
"recommendationUrl": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'FAILED'), 'https://learn.microsoft.com/en-us/azure/active-directory/app-provisioning/known-issues', '')",
672+
"runLink": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'SKIPPED'), '', outputs('Compose_SCIMTests_RunLink'))",
673+
"message": "@if(equals(coalesce(body('Get_SCIMTests_Output_Content')?['SCIMGroupPaginationTestOutputs']?['overallResult'], 'SKIPPED'), 'SKIPPED'), '', 'Click the runLink and search for the action Compose_Final_Results for more info.')"
674+
},
666675
{
667676
"testName": "POD_User_Test",
668677
"testResult": "@coalesce(body('Get_UserTests_Output_Content')?['PODUserTestOutputs']?['result'], 'SKIPPED')",

Microsoft.SCIM.LogicAppValidationTemplate/StandardLogicApp/SCIM-Validation-Test-Overview.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Purpose
44

5-
The SCIM Validation Logic App runs **22 automated tests** against an ISV's SCIM 2.0 endpoint to verify it is ready for publication in the Microsoft Entra app gallery. Tests cover the full provisioning lifecycle — user and group CRUD, attribute mappings, soft delete, provision-on-demand, direct SCIM compliance, and credential validation.
5+
The SCIM Validation Logic App runs **23 automated tests** against an ISV's SCIM 2.0 endpoint to verify it is ready for publication in the Microsoft Entra app gallery. Tests cover the full provisioning lifecycle — user and group CRUD, attribute mappings, soft delete, provision-on-demand, direct SCIM compliance, and credential validation.
66

77
The Logic App is deployed as a Standard Azure Logic App with 5 workflows that execute in parallel, completing a full validation run in 30–60 minutes.
88

@@ -15,8 +15,8 @@ Orchestrator_Workflow (entry point)
1515
├── Initialization_Workflow — reads sync schema, builds dynamic test bodies
1616
├── UserTests_Workflow — 7 tests (parallel with Group/SCIM)
1717
├── GroupTests_Workflow — 7 tests (parallel with User/SCIM)
18-
└── SCIMTests_Workflow — 8 tests (parallel with User/Group)
19-
└── Final_TestResults — aggregates 22 results, determines pass/fail
18+
└── SCIMTests_Workflow — 9 tests (parallel with User/Group)
19+
└── Final_TestResults — aggregates 23 results, determines pass/fail
2020
```
2121

2222
**Dynamic capability detection:** The Initialization workflow reads the provisioning schema and automatically determines which tests apply based on the ISV's attribute mappings:
@@ -59,7 +59,7 @@ Tests that don't apply are reported as **SKIPPED** (not failures).
5959

6060
> **Note:** All 7 group tests are **skipped** if the ISV's schema does not have an enabled Group object mapping.
6161
62-
### SCIM Compliance Tests (SCIMTests_Workflow) — 8 tests
62+
### SCIM Compliance Tests (SCIMTests_Workflow) — 9 tests
6363

6464
| # | Test Name | What It Validates |
6565
|---|-----------|-------------------|
@@ -70,7 +70,8 @@ Tests that don't apply are reported as **SKIPPED** (not failures).
7070
| 19 | **SCIM_Group_Create_Test** | Directly calls `POST /Groups` with a SCIM group body. **Skipped** if groups are not supported. |
7171
| 20 | **SCIM_Group_Update_Test** | Directly calls `PATCH /Groups/{id}` with attribute updates. **Skipped** if groups are not supported. |
7272
| 21 | **SCIM_User_Pagination_Test** | Ensures ≥11 users exist on the endpoint (creates throwaway users from `initializationData.scimUserBody` if needed), then paginates `/Users?startIndex=N&count=5` across multiple pages. Verifies `startIndex`, `totalResults`, and page traversal. Cleans up created users afterward. |
73-
| 22 | **Validate_Credentials_Test** | Tests the OAuth 2.0 Client Credentials flow — acquires a token from the ISV's token endpoint using client ID/secret, then validates the SCIM connection. **Skipped** when `scimTokenEndpoint` is empty (static bearer token setup). |
73+
| 22 | **SCIM_Group_Pagination_Test** | Ensures ≥11 groups exist on the endpoint (creates throwaway groups from `initializationData.scimGroupBody` if needed), then paginates `/Groups?startIndex=N&count=5` across multiple pages. Verifies `startIndex`, `totalResults`, and page traversal. Cleans up created groups afterward. **Skipped** if groups are not supported. |
74+
| 23 | **Validate_Credentials_Test** | Tests the OAuth 2.0 Client Credentials flow — acquires a token from the ISV's token endpoint using client ID/secret, then validates the SCIM connection. **Skipped** when `scimTokenEndpoint` is empty (static bearer token setup). |
7475

7576
---
7677

@@ -80,17 +81,17 @@ Tests that don't apply are reported as **SKIPPED** (not failures).
8081
|----------|-------|-----------|
8182
| **User Lifecycle** | 7 | Full CRUD + Manager + Restore + POD via Entra provisioning engine |
8283
| **Group Lifecycle** | 7 | Full CRUD + Membership + POD + Restore via Entra provisioning engine |
83-
| **SCIM Direct Compliance** | 7 | Direct HTTP calls to SCIM endpoint — schema, CRUD, null update, pagination |
84+
| **SCIM Direct Compliance** | 8 | Direct HTTP calls to SCIM endpoint — schema, CRUD, null update, user & group pagination |
8485
| **Credential Validation** | 1 | OAuth client credentials flow |
85-
| **Total Scored** | **22** |
86+
| **Total Scored** | **23** |
8687

8788
---
8889

8990
## What "Passing" Means
9091

9192
| Scenario | Acceptable? |
9293
|----------|-------------|
93-
| All 22 tests: `success` | **Ready for gallery submission** |
94+
| All 23 tests: `success` | **Ready for gallery submission** |
9495
| Group tests: `SKIPPED` (no group mapping) | Acceptable if ISV only supports /Users |
9596
| Disable_User_Test: `SKIPPED` (no `active` mapping) | Acceptable — ISV should document |
9697
| Manager test: `SKIPPED` (no `manager` mapping) | Acceptable — ISV should document |
@@ -124,4 +125,4 @@ Both methods produce the same output: a `validation-result-<RunId>.json` file to
124125

125126
---
126127

127-
*Document version: June 2026 — Covers Logic App validation template v4 with 22 tests across 5 workflows. Includes User Pagination, Restore tests, Schema_Discoverability_Test v2 with flatten loops, scimTargetUserValues, and Provision on Demand.*
128+
*Document version: June 2026 — Covers Logic App validation template v4 with 23 tests across 5 workflows. Includes User & Group Pagination, Restore tests, Schema_Discoverability_Test v2 with flatten loops, scimTargetUserValues, and Provision on Demand.*

0 commit comments

Comments
 (0)