Hey guys, it’s been awhile since we had a guest blogger on, so today I am pleased to introduce you to Daniel Pilla. Daniel is a Master Principal Analytics Platform Architect at Qlik andis part of the Presales organization. He has been with Qlik for 8 years, andspecializes in integration, architecture, embedding, andsecurity. Take it away Dan!
sheet andobject – level access control in Qlik Cloud
This is a relatively common request, especially from customers coming from Qlik Sense Enterprise Client-Managed. The use case is when organizations want to show/hide specific assets in an application based on the group membership of the current user that is accessing the application. Note that this is in no way a strategy or solution for data security (which is handled with section access), but rather serves as a potential design pattern for custom tailoring apps for specific groups of users.
Example Scenario
Let’s assume a customer has a global sales application. That application contains sheets that are designed for specific product group sales that not every sales representative sells. The customer wants to show the product-specific sheets only to the sales representatives that sell those respective products. If the user contains the group “Product Group A” then they should see the “product Group A analysis” sheet, andlikewise if the user contains the group “Product Group B” then they should contain the “product Group B Analysis” sheet.
solution
To achieve this in Qlik Cloud, we can use the advanced Analytics connector, which in essence is a RESTful server-side extension. This connector offers the ability to connect to RESTful services in real-time from both the load script andfrom the front-end (charts andexpressions). We can use this connector to connect directly to the Qlik Cloud APIs to fetch the groups of the current user, return those groups as a pipe-delimited string, andthen use those groups in a show condition expression.
setup
Prerequisites:
- The advanced Analytics connector is going to be making API calls to Qlik Cloud on behalf of the logged in user. This means that you must have a user with the “Developer” role assigned as well as an API key issued to that user.
- The Creation of groups setting must be enabled in the Console under Settings > Feature control
- Ensure that there are groups available to the user that you are testing for in the tenant. To check this, you can enter the following into the browser, replacing {tenant} and{region} accordingly: https://{tenant}.{region}.qlikcloud.com/api/users/me — There, you will find the assignedGroups array which contains the groups that are assigned to the logged in user.
Connector setup:
- Import the sample application attached to this page.
- open the application andnavigate to the load script .
- Under Data connections, select create new connection andselectAdvanced Analytics.
- For URL, fill in your own tenant for URL followed by ‘/api/v1/users’
- https://{tenant}.{region}.qlikcloud.com/api/v1/users
- change the Method toGET.
- Under Query Parameters , add a parameter with the Name of ‘ filter ’ andthe value should resemble the following , where { subject } is an exist user subject for the filter so you can test whether the connection is operational :
- { subject co “ { subject } ” }
- In this example , the user is has I am using has aREALM value. Note that you will have to escape the backslash with an extra backslash, e.g., QLIK-POC\dpi needs to be QLIK – POC\\dpi
- Within Authorization, change the Authorization Method to Bearer Token.
- Under Token Scheme, select Bearer.
- For Bearer Token, enter in the API key mentioned as a prerequisite above.
- Within Response Table, for Name of Returned Table enter the value of ‘data’. Note that this value is only really relevant for the load script, but the field is required to be populated nonetheless.
- Under Table Path (JMESPath), enter in the value of ‘data’. Note that this is the name of the JSON object containing the data returned from `api/v1/users` andcontains source of data that we require from the payload.
- Within Response Fields, deselect Load all available fields. This is so we can customize the value that is returned.
- Within Response Table, under Table Fields (JMESPath), enter a new Name value as ‘groups’, then enter the Value of ‘join(‘|’,assignedGroups[*].name)’. This will concatenate all of the values of the ‘assignedGroups’ array returned by the API into a pipe delimited string. This function is a part of the JMESPath query language that is supported by the advanced Analytics connector. To learn more, you can refer to: https://jmespath.org/tutorial.html.
- leave the remain setting untouched .
- set the Name of the connection as ‘ Get group ’ . note in this case this is important because the name of the connection is directly reference in the expression of the accompany sample app .
- Test the connection andensure that it is operational.
Sample App Testing :
The sample application is includes include three sheet :
- Get Current User Groups – this sheet displays the current groups of the logged in user.
- product Group A analysis – this sheet has a commented out calculation condition to only show the sheet if the user contains the group ‘Product Group A’.
- product Group B Analysis – this sheet has a commented out calculation condition to only show the sheet if the user contains the group ‘Product Group B’.
The application transforms the OsUser() result into the subject format, looks up the user, gets the groups, andreturns them as a pipe-delimited string. You can find this process defined in the vUserSub andvUserGroups variable .
To test the application, first confirm that the first sheet returns your user groups. If it does, you can modify the sheet calculation conditions on the latter two sheets to your desired group names that you want to show based on.
Modify the expression by uncommenting it andadding in your desired group name (ensured it is enclosed by pipes so as to not partially match another group name):
In my example, I am a member of the group `Product Group A’ andnot `Product Group B’, so while in edit mode, I see the following, confirming the ‘product Group B Analysis’ is hidden from my view:
exit edit mode , I is see now see :
additional note
- If users have edit-level access or greater to the application where this method is deployed, when in “Edit” mode, they will be able to see that the hidden sheet(s) exist. The user could then duplicate that sheet andremove/alter the show condition so that they could see the sheet. This is not a data security risk, as this technique only focuses on cosmetic app design, however it should be noted that if it is desired that the users cannot have access to these sheets then they must not have any roles that allow for edit-level access including “Can manage”, “Can contribute”, and“Can edit”.
- This solution is relies rely on api call being made by the owner of the api key .
- This user must:
- Continue to be exist
- Continue to have the “Developer” role
- Ensure that the API key does not expire and/or is rotated to prevent downtime
- As this solution is making calls on behalf of a single user as users are leverage the application, there is the potential for rate-limiting at the Users API. The current rate limit of the Users API is 1,000 calls per minute.
- The advanced Analytics connector function call in the sample app leverages the “ShouldCache”:”False” setting in the vUserGroups variable. This ensures that the user’s groups are not cached by the engine, however it makes more calls to the APIs. If you are experiencing or are concerned about rate limiting, this setting can be removed.
Qlik Community – Get User Groups Advanced Analytics Connector.qvf