Suppression de profils d'accès dans un role

j’ai fait ce script pour supprimer un accès sur plusieurs roles :

Entete spec pour envoi en PATCH

$headersmove = @{
Authorization = "Bearer $($token.access_token)"
Accept = "application/json"
"Content-Type" = "application/json-patch+json"
}
# On boucle sur les roles pour supprimer le profil d'accès sélectionné
foreach ($role in $rolesAvecProfil) {
    $lerole = Repair-ApiText $role.name
    Write-Host "Traitement du rôle : $lerole" -ForegroundColor Blue
    $roleId = $role.id
    ##recherche index du profil afin de le supprimer
    $index = -1
    $role.accessProfiles
    for ($i = 0; $i -lt $role.accessProfiles.Count; $i++) {
        if ($role.accessProfiles[$i].id -eq $profileId) {
            $index = $i
            break
        }
    }
    # Profil non retrouvé
    if ($index -lt 0) {
        Write-Verbose "Le profil $profileId n’est pas associé au rôle $lerole"
        continue
    }
    # Envoi du retrait 
    $patchBody = @(
        @{
            op   = "remove"
            path = "/accessProfiles/$index"
        }
    ) | ConvertTo-Json -Depth 6
    $patchBody = "[" + $patchBody + "]"
    # Envoi API 
    # Retrait du profil du role
    Write-Host "Envoi de retrait du profil d'accès  au rôle : $lerole" -ForegroundColor Blue
    $response = Invoke-RestMethod -Method PATCH -Uri "$tenantUrl/v3/roles/$roleId" -Headers $headersmove -Body $patchBody
    Write-Host "Traitement fini" -ForegroundColor Green

    Start-Sleep -Seconds 1

    $roleCheck = Invoke-RestMethod -Method GET -Uri "$tenantUrl/v3/roles/$roleId" -Headers $headersmove

    if ($roleCheck.accessProfiles.id -contains $profileId) {
        $roleCheck
        Write-Host "Profil TOUJOURS présent sur $lerole" -ForegroundColor Red
    } else {
        Write-Host "Profil supprimé de $lerole" -ForegroundColor Green
    }
        }
}

ça fonctionne bien sauf que sur certains roles rien ne se fait.
Est ce que c normal ? 
sinon il y a peut-être un moyen plus efficace ?

Merci.

J’ai fait quelques recherches là-dessus et je pense que le souci vient du remove par index.

/accessProfiles/{index} est fragile parce que GET /v3/roles/{id} ne retourne pas toujours accessProfiles dans le même ordre d’un appel à l’autre. Du coup l’index calculé sur une réponse peut pointer vers un AP différent au moment où le PATCH part. Ça expliquerait pourquoi certains roles passent et d’autres ne font rien en apparence, même si l’appel retourne 200.

J’ai trouvé un comportement similaire discuté ici : Weird behavior when patching access profile entitlements or role access profiles. Au lieu de supprimer par index, essaie de supprimer par valeur sur le path parent :

[
  {
    "op": "remove",
    "path": "/accessProfiles",
    "value": {
      "type": "ACCESS_PROFILE",
      "id": "<accessProfileId>"
    }
  }
]

Garde aussi :

Content-Type: application/json-patch+json

Autre point que j’ai remarqué dans ton script : le body du PATCH doit être un tableau JSON. Sur PowerShell 7+, c’est plus propre comme ça :

$patchOp = @{
  op    = "remove"
  path  = "/accessProfiles"
  value = @{
    type = "ACCESS_PROFILE"
    id   = $profileId
  }
}

$patchBody = ConvertTo-Json -InputObject $patchOp -Depth 6 -AsArray

Si tu es sur Windows PowerShell 5.1, ton wrapping manuel "[" + $patchBody + "]" reste valide vu que -AsArray n’existe pas dans cette version.

Petit sanity check avant d’envoyer la requête : $patchBody doit commencer par [ et finir par ].

Docs :

Désolé s’il y a quelques erreurs en français, j’ai utilisé un traducteur :slightly_smiling_face: