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
8 changes: 4 additions & 4 deletions .github/workflows/ci-c-e2e-mqttv5-adr-namespace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
# E2E_MQTTV5_SHARED_HUB_NAME, E2E_MQTTV5_SHARED_DPS_NAME,
# E2E_MQTTV5_SHARED_ADR_NAMESPACE,
# E2E_MQTTV5_SHARED_ADR_API_VERSION (optional; default 2026-11-02-preview)
# secrets: AZURE_CLIENT_ID, AZURE_TENANT_ID (OIDC). On the resource group the
# identity needs Contributor, and role assignment write for
# Contributor, IoT Hub Data Contributor and Azure Device Registry
# Contributor.
# secrets: AZURE_CLIENT_ID, AZURE_TENANT_ID (OIDC). The identity needs
# Contributor on the resource group. Grant the link's role
# assignments on the resource group once; otherwise it also needs
# role assignment write.

name: ci-c-e2e-mqttv5-adr-namespace

Expand Down
6 changes: 4 additions & 2 deletions c/docs/eng/end-to-end-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,14 @@ The shared mqttv5 environment (ADR-linked mqttv5 hub and DPS) is kept usable by
(hourly, manual, or `workflow_call` as the first job of a mqttv5 e2e workflow). The ADR namespace
can disappear from ARM, removing its role assignments; DPS registrations then fail.
[`c/eng/e2e-mqttv5-adr-namespace.ps1`](../../eng/e2e-mqttv5-adr-namespace.ps1) re-creates it
(same name, hub region), re-grants the 8 role assignments, re-links hub and DPS, and pushes the
(same name, hub region), ensures the 8 role assignments, re-links hub and DPS, and pushes the
namespace to DPS; when the namespace is healthy it makes one ARM read. Inputs are repository
variables `E2E_MQTTV5_SHARED_SUBSCRIPTION_ID`, `_RESOURCE_GROUP`, `_HUB_NAME`, `_DPS_NAME`
and `_ADR_NAMESPACE` (unset `_ADR_NAMESPACE` skips the job); optional `_ADR_API_VERSION`
(default `2026-11-02-preview`) must match the version the namespace was linked with. The OIDC identity needs Contributor
and role assignment write on the resource group.
on the resource group. Grant the link's role assignments (hub, DPS and namespace identities) on the
resource group once: those survive the namespace, so the job creates none and needs no role
assignment write unless the namespace identity changes.

> **Software updates e2e** runs in its own workflow
> ([`ci-c-e2e-adu.yml`](../../../.github/workflows/ci-c-e2e-adu.yml), Linux, manual dispatch). See [Software updates e2e](#software-updates-e2e).
Expand Down
26 changes: 20 additions & 6 deletions c/eng/e2e-mqttv5-adr-namespace.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ Workaround: in some regions the ADR namespace can disappear from ARM while the A
holds it; its role assignments go with it, and DPS registrations then fail. When the namespace
is missing, or an endpoint is not linked, this script:
1. re-creates it (same name/region; if ADR still holds it, re-asserts its endpoints),
2. re-grants the 8 role assignments the link needs (idempotent),
2. ensures the 8 role assignments the link needs; one already present at the target scope or above
(e.g. on the resource group, which survives the namespace) is not re-created,
3. links the hub (messaging/hub-1) and DPS (provisioning/dps-1) and waits for Succeeded,
4. pushes the namespace to the DPS data plane (tags-only DPS update).
If the namespace is present with both endpoints Succeeded it makes one ARM read and exits.

Requires `az` logged in with, on the resource group: Contributor, and
Microsoft.Authorization/roleAssignments/write (e.g. Role Based Access Control Administrator)
for Contributor (b24988ac-...), IoT Hub Data Contributor (4fc6c259-...) and
Azure Device Registry Contributor (a5c3590a-...).
Requires `az` logged in with Contributor on the resource group. Role assignment write (for
Contributor b24988ac-..., IoT Hub Data Contributor 4fc6c259-..., Azure Device Registry Contributor
a5c3590a-...) is needed only for grants not already present at the resource group or above.
Hub and DPS must have system-assigned identities.
#>
[CmdletBinding(PositionalBinding = $false)]
Expand Down Expand Up @@ -119,10 +119,24 @@ function Wait-For([string]$What, [int]$Minutes, [scriptblock]$Probe) {
}
}

# Scope of an existing assignment of RoleId to PrincipalId at Scope or any parent, else $null.
function Get-CoveringScope([string]$Scope, [string]$PrincipalId, [string]$RoleId) {
$ras = Invoke-Arm get "$Arm$Scope/providers/Microsoft.Authorization/roleAssignments?api-version=2022-04-01&`$filter=principalId%20eq%20'$PrincipalId'"
foreach ($ra in @($ras.value)) {
$s = ([string]$ra.properties.scope).TrimEnd('/')
$parent = $s -eq '' -or $Scope -ieq $s -or $Scope.StartsWith("$s/", [StringComparison]::OrdinalIgnoreCase)
if ($ra.properties.roleDefinitionId -match "/$RoleId$" -and $parent) { return $ra.properties.scope }
}
}

function Grant-Role([string]$Scope, [string]$PrincipalId, [string]$RoleId, [string]$What) {
if ($covering = Get-CoveringScope $Scope $PrincipalId $RoleId) { Write-Host " role: $What (present at $covering)"; return }
for ($i = 1; $i -le 8; $i++) {
$out = ((& az role assignment create --assignee-object-id $PrincipalId --assignee-principal-type ServicePrincipal --role $RoleId --scope $Scope -o none 2>&1) | Out-String).Trim()
if ($LASTEXITCODE -eq 0 -or $out -match 'RoleAssignmentExists|already exists') { Write-Host " role: $What"; return }
if ($out -match 'AuthorizationFailed') {
throw "Role assignment '$What' is missing and this identity cannot create it. Grant it once on the resource group (it survives the namespace): $out"
}
if ($i -eq 8) { throw "Role assignment '$What' failed: $out" }
Start-Sleep -Seconds 15
}
Expand Down Expand Up @@ -189,7 +203,7 @@ $ns = (Wait-For 'namespace' 10 {
@{ Done = ($terminal -and $n.identity.principalId); Failed = ($terminal -and -not $n.identity.principalId); Detail = $ps; Ns = $n } }).Ns
$nsPid = $ns.identity.principalId

# 2. Role assignments (removed with the namespace; the namespace identity may be new).
# 2. Role assignments. Those scoped to the namespace go with it; the namespace identity may be new.
Grant-Role $HubId $nsPid $RoleContributor 'namespace -> hub (Contributor)'
Grant-Role $NsId $hubPid $RoleContributor 'hub -> namespace (Contributor)'
Grant-Role $DpsId $nsPid $RoleContributor 'namespace -> DPS (Contributor)'
Expand Down
Loading