Remove identity from role by ID via beta Patch Role API endpoint

Hello,

I am trying to remove an identity from a role using a PATCH call to the /v3/roles/<role_id> Beta API endpoint with the identity ID, and I am having issues. I have tried multiple request bodies unsuccessfully. For example, if I pass the following body:

[
  {
    "op": "remove",
    "path": "/membership/identities",
    "value": {
        "id": "<identity id>"
    }
  }
]

It removes the entire list of identities from the role. No matter what I’ve tried putting in the “value” field in the body, it removes the entire identity list with that path. However, if I use the following body:

[
  {
    "op": "remove",
    "path": "/membership/identities/0"
  }
]

with /membership/identities/<index> as the path, it will remove the identity at that index in the list.

Based on this, it seems that the only way to remove an identity from a role would be to first make a GET call to get the list of identities in the role, then find the identity in the list, then remove that identity based on the index. That method seems fairly arduous and would be even more difficult if not impossible to do within a Sailpoint workflow (which is what I am trying to do) given the limitations that exist around loops.

This is a similar problem that apparently hasn’t been solved yet: Add/Remove operations on Beta Patch Roles/Access Profiles endpoints - #5 by Prooxie

Thank you

Instead of using the PATCH call to the [/v3/roles/<role_id> Beta API], you can try using the POST call [/v3/access-requests]. Body looks like below, you will need the requestor ID and the role ID that needs to be revoked.

{
“requestType”: “REVOKE_ACCESS”,
“requestedFor”: [
“5001f784e715xxxxxx0”
],
“requestedItems”: [
{
“comment”: “Please remove”,
“id”: “2c9180897xxxxx0a”,
“type”: “ROLE”
}
]
}

Be aware @bp77577 (Ben Pardon) that Anu’s solution will submit a request for removal, which takes you down the path of what a request will look like (who would own the request, approvals, etc.)

When I tested this, I just did a JSON PATCH call to /v3/roles with the payload being everyone in the list MINUS the identity intended for removal. Here’s a sample payload where I wanted “Adam.Kennedy” OUT of the IDENTITY_LIST, so I set the IDENTITY_LIST to every identity except his. (This also has the… advantage (do we want to say that?) of not having to go through a request and possible approval as well as waiting on approval process):

[
  {
    "op": "replace",
    "path": "/membership",
    "value": {
      "identities": [
        {
          "aliasName": null,
          "id": "5fa34928d04e47b6ae901417a36e8b76",
          "name": "Aaron.Nichols",
          "type": "IDENTITY"
        },
        {
          "aliasName": null,
          "id": "e1573f9d97074c0e9cf9bd60f61a04a3",
          "name": "Alan.Duffy",
          "type": "IDENTITY"
        },
        {
          "aliasName": null,
          "id": "d34ccf9c429c434c8bc3220be4296af0",
          "name": "Alisa.Sweeney",
          "type": "IDENTITY"
        }
      ],
      "type": "IDENTITY_LIST"
    }
  }
]

So now… the question is, how to get the “negative list”?

Triggering the workflow on an Identity Attribute Change (“inactive” or a custom value from a custom lifecycle state in the Identity Profile for this identity), we can gather just that identities roles and focus on IDENTITY_LIST roles, discarding the rest. Then assign the JSON PATCH call for /v3/roles the identities in the list, minus that identity.

I got a “negative list” with the following JSONPATH. All that would be left on what I’ve tested is to put all of this together in the proper loops:

  1. Trigger on Identity Attribute Change
  2. Gather that identities roles only
  3. Iterate the roles, focusing only on roles of IDENTITY_LIST type
  4. For each role, patch that IDENTITY_LIST role type with the “negative list”

See the JSONPATH example for building that list. I created the JSONPATH using a static value, so the value (probably the identity ID would be a better choice) needs to be used in the path – I’m unsure if that’s possible in the JSON flow. But someone else may know. If that works, the the JSON PATCH call “should” work?!

HTH and someone seeing this can help put this all together for the win.

The /v3/access-requests endpoint can be used for role revocation only in case where there is no approval required for revocation. If approval is required for the revocation of the role, this will only submit the request and will have to wait till its approved.

Thanks @chris_olive for providing detailed info on this.

Thanks, yes. And then the context (identity) of the workflow comes into play on the request as well. Just to add to the above.

Thanks for the information @chris_olive. I did some testing and was able to get the JSON path search that you described working to get the “negative list” (list of all identities except the one we want to remove) in a workflow. What I am running into now however, is that I can’t seem to find a way to construct the request body necessary to make the PATCH call for the removal. I have tried many different things but I believe the closest I got is this:

[{
    "op": "replace",
    "path": "/membership",
    "value": {
        "identities": "{{$.hTTPRequest.body.membership.identities[?(@.id != $.trigger.identity.id)]}}",
        "type":"IDENTITY_LIST"
    }
}]

This successfully takes the identity list returned from the HTTP request and gets the list of identities minus the one we are trying to remove, but it returns the list in a different format that is not proper JSON so the request fails. I did some research and found this topic about a similar issue and a response there that objects and arrays cannot be references with inline variables. Given that, do you have any suggestions for how I could put the pieces together to construct the body in a valid JSON format?

Thank you

What are you getting back from this? Can you share an example?

I have the same question. +1

Sure @iamnithesh @chris_olive,

Here you go:

\"[map[\"aliasName\":\"<alias_name>\" \"id\":\"<identity_id>\" \"name\":\"<identity_name>\" \"type\":\"IDENTITY\"] 
map[\"aliasName\":\"<alias_name>\" \"id\":\"<identity_id>\" \"name\":\"<identity_name>\" \"type\":\"IDENTITY\"] 
map[\"aliasName\":\"<alias_name>\" \"id\":\"<identity_id>\" \"name\":\"<identity_name>\" \"type\":\"IDENTITY\"] 
map[\"aliasName\":\"<alias_name>\" \"id\":\"<identity_id>\" \"name\":\"<identity_name>\" \"type\":\"IDENTITY\"]]\"

I replaced the actual values with <identity_name>, <identity_id>, and <alias_name> since they are actual users in my organization. Otherwise, I copied this directly from the results of the HTTP action to make the remove PATCH call (that failed). As you can see it is returning the values with the keyword map[]. I found this post about this as I shared above which says that arrays and objects are not supported as they “are serialized as Goland maps/arrays”.

On the bright side this is the correct list of identities which does not include the one I want to remove, so it just comes down to this formatting issue before it is working.

Thanks for the assistance!

1 Like

I’d have to build this up. I don’t know that I would select from the request object. Maybe there’s no way around this however per the other post you linked to.

There is a known issue in workflows where you cannot reference objects or arrays using inline variables. You can only reference single values in inline variables. Object and array inline variables evaluate to Golang maps and lists, which isn’t compatible with JSON. The engineering ticket linked to this issue is PLTWRKFLW-1352.

This means that your approach of using the PATCH endpoint to provide a list of identities to keep in the role will not work until the above ticket is completed.

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.