Announcing the Saviynt Knowledge Exchange unifying the Saviynt forums, documentation, training,
and more in a single search tool across platforms. Read the announcement here.

GitHub Repository Admin mapping as Entitlement(Repo) owners not happening

AS5278
Regular Contributor II
Regular Contributor II

Hi,

We are importing the repositories from GitHub Cloud as below and then the requirement is to map the Repo admins as entitlement owners in Saviynt(Here entitlement is the Repository).

We tried like below in 'acctEntParams':

 

"Repository": {
"call": {
 
// call1 here...
 
"call2": {
"callOrder": 1,
"stageNumber": 14,
"inputParams": {
"entitlementname": "Organization",
"statusFilter": "(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization": "${access_token}"
},
"url": "${id}/collaborators?permission=admin&per_page=100&page=1",
"httpContentType": "application/x-www-form-urlencoded",
"httpMethod": "GET"
},
"listField": "",
"acctKeyField": "accountID",
"entKeyField": "customproperty1",
"acctIdPath": "id",
 
"ownerIdPath": "id",
"ownerKeyField": "accountID",

"pagination": {
"nextUrl": {
"nextUrlPath": "${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
}
 
We have used the 'ownerIdPath' and 'ownerKeyField' as the owner info is coming as a part of the acctEntParams API.(As per approach suggested in Saviynt docs). However, the owner mapping is not happening for some reason. I tried running the Access Import job multiple times but to no luck.
 

Also tried below approach as suggested in Saviynt GitHub Connector documentation:

"entitlementParams": {
"connection""acctAuth",
"processingType""SequentialAndIterative",
"supportedEntitlementTypes": [
"Repository"
],
 
"entTypes": {
"Repository": {
"entTypeOrder"2,
"entitlementOwnerConfig": {
"maxNumberOfOwner": 4,
"typeOfImportOwner": [
"admin"
]
},
"call": {
"call1": {
"callOrder"0,
"stageNumber"7,
"inputParams": {
"entitlementname""Organization",
"statusFilter""(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization""${access_token}"
},
"httpContentType""application/x-www-form-urlencoded",
"httpMethod""GET"
},
"pagination": {
"nextUrl": {
"nextUrlPath""${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
},
"listField""",
"keyField""entitlementID",
"colsToPropsMap": {
"entitlementID""id~#~char",
"entitlement_value""name~#~char",
"customproperty1""url~#~char",
"customproperty6""private~#~char",
"customproperty7""size~#~char",
"customproperty8""permissions.admin~#~char",
"customproperty9""permissions.push~#~char",
"customproperty10""permissions.pull~#~char",
"customproperty11""owner.login~#~char",
"customproperty20""STORE#ENT#MAPPINGINFO#PARENTID#TYPE##ENTMAP~#~char",
"entitlementMappingJson""STORE#ENT#MAPPINGINFO#PARENTID~#~char"
}
}
}
}
}
}
 
"acctEntParams": {
"processingType""httpEntToAcct",
"connection""acctAuth",
"initPrivigesMap": [
{
"privName""Permission",
"attrType"3,
"entType""Repository",
"cfgType"1,
"attributeValues""",
"defaultValue"""
}
"entTypes": {

 

"Repository": {
"call": {
"call1": {
"callOrder"0,
"stageNumber"13,
"inputParams": {
"entitlementname""Organization",
"statusFilter""(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization""${access_token}"
},
"url""${id}/collaborators?permission=admin&per_page=100&page=1",
"httpContentType""application/x-www-form-urlencoded",
"httpMethod""GET"
},
"listField""",
"acctKeyField""accountID",
"entKeyField""customproperty1",
"acctIdPath""id",
"privilegeParams": {
"attrName": "Permission",
"attrValue": "admin"
},
"pagination": {
"nextUrl": {
"nextUrlPath""${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
}
}
}
}
}
}
 
This is not working as well.

Is Importing Repository Admins as Owners supported in Saviynt?

Please guide.
 
Thanks,
Atul Singh
xurde
8 REPLIES 8

SB
Saviynt Employee
Saviynt Employee

Let me check this.


Regards,
Sahil

AS5278
Regular Contributor II
Regular Contributor II

@SB Any updates on this?. I even tried importing  a single repository and importing admins of that repo as owners. But this also didn't work.

xurde

SB
Saviynt Employee
Saviynt Employee

You can refer to the attached template in order to config the JSON. Please make sure the below requirements are met before access import.
- User must be in active status.
- The ownerKeyField field defined in the JSON is a user attribute value and not of the account. 

As an example, if we are taking email as the key field, then email value has to be present at the user level and the value of email should come as a response in the access import url.


Regards,
Sahil

AS5278
Regular Contributor II
Regular Contributor II

@SB In our case, the owner details are not coming in the access(Repo) import API. It is coming in the accntEntParams API. So, I think this approach won't work:

"entOwnerMappings": { "listField": "", "idPath": "owner", "keyField": "email" }

 How do we import the entitlement owners when the owner details are coming the accntEntParams API?.

We are using the below call in accntEntParams API to get the repo admin details and these repo admins need to be assigned as the owners for that particular repo entitlement type.

 
"Repository": {
"call": {
"call1": {
"callOrder": 0,
"stageNumber": 13,
"inputParams": {
"entitlementname": "Organization",
"statusFilter": "(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization": "${access_token}"
},
"url": "${id}/collaborators?permission=admin&per_page=100&page=1",
"httpContentType": "application/x-www-form-urlencoded",
"httpMethod": "GET"
},
"listField": "",
"acctIdPath": "id",
"entKeyField": "customproperty1",
"acctKeyField": "accountID",
 
"privilegeParams": {
"attrName": "Permission",
"attrValue": "admin"
},
"pagination": {
"nextUrl": {
"nextUrlPath": "${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
}
}
}
 
This is what I am referring to:
Developer's Handbook > Importing Entitlement Owners > Point (c)
AS5278_0-1693559067769.png

 

Thanks.

xurde

AS5278
Regular Contributor II
Regular Contributor II

@SB 

I have tried all the options suggested in Saviynt docs. The owners are not getting assigned for Repositories.

It is important for us to assign the Repository admins as owners because only then we can proceed with User Access Reviews.

Should I proceed with raising a Freshdesk Support Ticket?. Please advice.

Thanks,

Atul Singh

xurde

SB
Saviynt Employee
Saviynt Employee

You need to use the format as below to define the path where the owner information is coming as part of the api call. Please not the keyField is not an account's value but will be a user's filed value. That means this value has to be present at the User's profile level in Saviynt and not the one assigned to its account.

"entOwnerMappings": { "listField": "", "idPath": "owner", "keyField": "email" }

If it is still not working for you, can you share the postman response of the call where we get the owner's information. Also mention the field in the response that tells us about the owner info.


Regards,
Sahil

AS5278
Regular Contributor II
Regular Contributor II

@SB 

Below are the calls for 'Repository' entitlement type inside 'accntEntParams'.

"Repository": {
"call": {
"call1": {
"callOrder": 0,
"stageNumber": 13,
"inputParams": {
"entitlementname": "Organization",
"statusFilter": "(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization": "${access_token}"
},
"url": "${id}/collaborators?per_page=100&page=1",
"httpContentType": "application/x-www-form-urlencoded",
"httpMethod": "GET"
},
"listField": "",
"acctKeyField": "accountID",
"entKeyField": "customproperty1",
"acctIdPath": "id",
"privilegeParams": {
"attrName": "Permission",
"attrValue": "member"
},
"pagination": {
"nextUrl": {
"nextUrlPath": "${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
},
"call2": {
"callOrder": 1,
"stageNumber": 14,
"inputParams": {
"entitlementname": "Organization",
"statusFilter": "(ev.status = 6 or ev.status = 1)"
},
"http": {
"httpHeaders": {
"Authorization": "${access_token}"
},
"url": "${id}/collaborators?permission=admin&per_page=100&page=1",
"httpContentType": "application/x-www-form-urlencoded",
"httpMethod": "GET"
},
"listField": "",
"acctKeyField": "accountID",
"acctIdPath": "id",
"entKeyField": "customproperty1",
"ownerIdPath": "login",
"ownerKeyField": "username",
"pagination": {
"nextUrl": {
"nextUrlPath": "${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
},
 
"call3": {
"callOrder": 2,
"stageNumber": 15,
"inputParams": {
"entitlementname": "Organization",
"statusFilter": "(ev.status = 6 or ev.status = 1)"
},
"acctEntMappingTypeParam": {
"mappingType": "ENT2PRIVREVERSE",
"entitlementName": "Team"
},
"http": {
"httpHeaders": {
"Authorization": "${access_token}"
},
"url": "${id}/teams?per_page=100&page=1",
"httpContentType": "application/x-www-form-urlencoded",
"httpMethod": "GET"
},
"listField": "",
"entKeyField": "customproperty1",
"entIdPath": "url",
"privilegeParams": {
"attrName": "Permission",
"attrValuePath": "permission"
},
"pagination": {
"nextUrl": {
"nextUrlPath": "${headers?.Link==null?'':headers?.Link?.contains('next')?headers?.Link?.split(',')?.size()==2?headers?.Link?.split(',')[0]?.replace('<', '')?.replace('>; rel=\"next\"','')?.trim():headers?.Link?.split(',')[1].replace('<', '').replace('>; rel=\"next\"','').trim():''}"
}
}
}
}
}
 
As you can see we have 3 calls inside accntEntParams > Repository. So, if we include:
"entOwnerMappings": { "listField": "", "idPath": "owner", "keyField": "email" }, in accntEntParams, which call will it consider. In our case repo admins info is coming in call2 only and not call1 and call3.
 
We are getting the Repository admins in the 'call2' and these admins need to be assigned as owners for Repository entitlement type in Saviynt.
 
Below is the response of 'call2'  API from Postman:
API: https://api.github.com/repos/z<org name>/<repo name>/collaborators?permission=admin
 
[
{
"login": "benhgonon",
"id": 306112,
"node_id": "MDQ6VXNlcjMwNzghMg==",
"gravatar_id": "",
"type": "User",
"site_admin": false,
"permissions": {
"admin": true,
"maintain": true,
"push": true,
"triage": true,
"pull": true
},
"role_name": "admin"
},
.
.
.
. and so on...for remaining repo admins.....
]
 
The field 'login' in call2 tells about the owner. The corresponding key field in users table is 'username'.
 
As far as I understand from the Saviynt documentation: "entOwnerMappings": { "listField": "", "idPath": "owner", "keyField": "email" }, is to be used only inside 'entitlementParams' when the owner info is coming as part of the entitlement API in entitlementParams. 
 
But, in our case the owner info is coming in the 'accntEntParams' API and not 'entitlementParams' API.
I am attaching the JSON we are using currently.
Thanks.
xurde

SB
Saviynt Employee
Saviynt Employee

In that case, you can add entOwnerParams section after acctEntParams. This example is also available in the REST documentation in case you want to see the full JSON.

https://docs.saviyntcloud.com/bundle/REST-v2022x/page/Content/Developers-Handbook.htm

{
"accountParams": {},
"entitlementParams": {},
"acctEntParams": {},
"entOwnerParams": {
"connection": "acctAuth",
"successResponses": {
"statusCode": [
200,
201,
202,
203,
204,
205
]
},
"unsuccessResponses": null,
"doNotChangeIfFailed": true,
"entTypes": {
"Safes": {
"call": {
"call1": {
"processingType": "httpOwner",
"connection": "acctAuth",
"showJobHistory": true,
"callOrder": 0,
"stageNumber": 0,
"http": {
"url": "URL",
"httpContentType": "application/json",
"httpMethod": "GET",
"httpHeaders": {
"Accept": "application/json"
}
},
"listField": "records",
"entIdPath": "Id",
"ownerIdPath": "Owner",
"ownerKeyField": "email",
"entKeyField": "entitlementID",
"pagination": {
"offset": {
"offsetParam": "startIndex",
"batchParam": "limit",
"batchSize": 1000,
"totalCountPath": "completeResponseMap.totalResults"
}
}
}
}
}
}
}
}

 


Regards,
Sahil