Streams, specific app access, single users & AD groups
I know there are lots of posts on this sort of topic already, but rather than try and stitch together separate bits of of advice, I'm hoping someone can just steer me right, so I can ensure the correct Streams and Apps are visible to the relevant users, with the correct access level.
My current situation is as follows:
- About 30 data extract apps and 30 front end apps.
- The apps have been published to Streams based on department. I currently have 14 streams (7 for data extracts and 7 for front ends).
- 2 types of user initially:
* Developers - to be given access to specific Streams only (extract and front end) and every app within those streams. Create, Read, Update, Export Data, Duplicate rights.
* Testers - a handful of general users, to be given access to specific Streams (front end only) and only specific apps within those streams. Read and Export Data rights only.
- No users will have access to every app in a stream, even after testing is complete, so it is essential to handle user access at App level.
- Initially, I want to grant Developer and Tester access specifically by username. I have an AD group set up for each front end app, so once the testing is complete, the specified Testers will be replaced by the relevant AD groups. The Developers can continue to be specified by username.
I began trying to configure this in Qlik Sense, but ran into difficulty with the Testers access. Here's what I did:
1. Security Rules: Created a new rule for certain Developers to access 1 stream. Resource Filter = Stream_<streamID>, Actions as noted above, users specified by name. Works fine, developers can see all apps in stream.
2. Security Rules: Created a new rule for certain Testers to access the same stream, but with fewer permissions (Actions).
3. Need to limit the particular apps the Testers can see, so went to Custom Properties: Created AppLevelMgmt Set Resource Types = Apps and Users.
4. In the AppLevelMgmt custom property, set Values for several (front end) Apps.
5. Security Rules: Disabled the default Stream rule.
6. Security Rules: Duplicated the default Stream rule, renamed it to App Access. Added a Condition: @AppLevelMgmt .empty()). Ensured it was enabled. As I understand it, this means the user can now see the Stream, but no apps within it at this stage.
7. Apps: Edited each App. Under Custom Properties > AppLevelMgmt, applied the relevant Value created in step 4.
8. Users: Edited each Tester. Under Custom Properties > AppLevelMgmt, applied the relevant Values created in step 4.
The stream is visible (to a sample user) and he can see thumbnails for every app in the stream (not just those I created custom properties for). When he tries to open any app, it appears to be blank (no sheets). When he right-clicks a thumbnail, it does nothing, so can't Duplicate.
I also tried some additional steps:
9. Custom Properties: Created new property called StreamLevelMgmt, Resource Types set to Streams and Users.
10. Applied a value for the front end Stream.
11. Streams: Applied this Value to the Stream.
12. Users: Applied this Value to the User.
However, this made no difference, the user can still see all thumbnails, but can't open any.
So... can you tell me where I've gone wrong, and how to fix?
In a nutshell, my requirements were to configure user access for 3 sets of users: Testers, Developers and AD Groups for general users.
Testers - Read access to specific Apps in specific Streams. Solely used during the user testing phase, prior to Qlik Sense going live.
Developers - Create, Read, Update, Delete and Duplicate access to Apps within specific Streams. My Developers will support specific business areas, so will not be given global access. I may also need to restrict which Apps they can access in a Stream.
AD groups - Read access to specific apps in specific streams. We have an AD group in place already for every individual (Front End) App, as we used these for Qlikview.
To get the above working in Qlik Sense took a fair bit of research, advice, testing and tweaking. There are numerous threads and guides on how to configure Qlik Sense access, but none quite fit my scenario. So now that I have everything working, I thought I'd post my full config as a reply and accept it as the solution, as it may potentially help others in a similar position.
New Rule: AppAccess. Copy the existing default rule called Stream (I tend to use Snipping Tool to screenshot). This will be the new rule for Streams without App level management. In the Conditions, before the "or", add the following: and resource.@AppLevelMgmt.empty() and resource.@ADGroupRead.empty())
Amend Rule: Stream. Set Disabled to Yes. We no longer need the default rule, as we now have AppAccess.
New Rule: AppAccessSpec. This rule enables App-level access to users and AD groups.
Resource filter = App*
Actions = Read
Conditions = (resource.stream.HasPrivilege("read") and ((user.@AppLevelMgmt=resource.@AppLevelMgmt) or (user.roles!="Developer" and user.group = resource.@ADGroupRead)))
New Rule: AccessDev. This is to apply advanced access for Developers, in particular, allowing them to duplicate and work on apps.
Conditions = (user.roles="Developer") and ((user.@AppLevelMgmt=resource.@AppLevelMgmt) or (user.group = resource.@ADGroupRead))
New Rule: AccessDevDLE. This rule is necessary to allow the Developers to view and edit scripts, as this is not enabled by default for security purposes.
Resource filter = App Object_*
Actions = Read, Update
Conditions = ((resource.objectType="loadmodel" or resource.objectType="app_appscript")) and resource.app.HasPrivilege("read")
New Rule: AdminPublish. Copy the existing default rule OwnerPublishDuplicate. I only want to allow the Root Admin to Publish apps to live streams at present. Set the Conditions to ((user.roles="RootAdmin")).
Amend Rule: OwnerPublishDuplicate. Set Disabled to Yes. We no longer need the default rule as we now have AdminPublish. Developers are already granted Duplicate access by the AccessDev rule.
New Rules: One for every stream. In my environment, I have two Streams for every department, one for Extracts and one for Front Ends. For example: Access HR EXT and Access HR FE.
Resource filter = Stream_<Stream ID>
Actions = Read
Users = Here I am specifying the Developers by user.name in both the EXT and FE rules, and the Testers by user.name to the FE rule only (they don't need to see Extract Apps).
Once user testing is complete, I will remove the Testers from these rules, and replace with the relevant AD groups.
The Stream ID can be found by opening the Stream in the QS Hub and taking the last part of the URL, e.g. https://<your server>/hub/stream/1a23456-b789-1a23-4567-c891d23e4f56
New CP: AppLevelMgmt.
Resource Types = Apps, Users
Values = Currently, I have one CP Value for every Front End App, and one CP Value covering all Apps in each Extract Stream. I’ve just used recognisable names for these values, e.g. HR Holidays, HR Personnel, and HR EXT.
Should I need to, I could replace the Stream-wide CP Value HR EXT with CP Values for each individual Extract App (HR Holidays EXT, HR Personnel EXT). This would allow me to specify exactly which Extract Apps Developers can see. However, this isn’t necessary for me at the moment.
New CP: ADGroupRead.
Resource Types = Apps
Values = One for every AD group that will be used to grant App access to regular users. I’ve named these Values exactly the same as the AD groups themselves, as the Group needs to match the CP value to allow the User access. E.g., say we have an AD group called ABC_HR_Holidays, then I’ll have a Value under the ADGroupRead property called ABC_HR_Holidays.
Amend Front End Apps. Under each App > Custom Properties > AppLevelMgmt, set it to the relevant CP Value added in the AppLevelMgmt Custom Property. E.g., in my Front End App called Human Resources Holidays, the AppLevelMgmt Custom Property Value = HR Holidays.
Amend Extract Apps. Under each App > Custom Properties > AppLevelMgmt, set it to the relevant “EXT” value above, so for my two Extract Apps called Human Resources Holidays Extract and Human Resources Personnel Extract, I'm using the same AppLevelMgmt property = HR EXT.
Amend Front End Apps. Under each App > Custom Properties > ADGroupRead, set it to the AD group name, e.g. ABC_HR_Holidays.
We only grant access to Extract Apps to specific Developers, not to general users and not by AD group. So, we don’t need to update the ADGroupRead Custom Property on any Extract Apps.
Amend all Users who are specified by name. I'm granting permission by name to Developers (permanently) and Testers (temporarily). For each of these users, under Custom Properties > AppLevelMgmt, I enter all relevant values. So, I may have a Tester with HR Holidays and HR Personnel, and I may have a Developer with those two plus the Extract property HR EXT.
Amend Developers only. Add the Role = Developer. This was specified within the Security Rule AccessDev, granting these users CRUD access.
USER DIRECTORY CONNECTORS
We have an AD group for each Qlikview Front End App, and will be re-using these in Qlik Sense.
Our AD groups initially included our Developers. I could grant the Developers CRUD access by including the relevant Custom Property on the User along with the Developer role. However, when I excluded the CP, it would still grant them Read access to all Apps in any Stream they had access to, due to the other Security Rules in place.
To circumvent this unwanted Read access, I removed the Developers from the AD groups. QS access will be granted to Developers by specifying their user.name, and to general users by their AD group membership.
After updating the AD Groups, I went to User Directory Connectors, selected my LDAP connector and clicked Sync.
License Management > Professional / Analyser access allocations. Here I granted a license to each of my Developers and Testers, so they can do their jobs before Qlik Sense goes live.
If you change a Custom Property (e.g. renaming it), it will disappear from the App and any specified Users, so be sure to reapply them. I don’t think the same thing happens when renaming Security Rules, but it’s always worth checking!
Audit is your friend. It helped me many times during this, to confirm AppLevelMgmt properties had been applied to users, to compare permission levels for Developers and Testers, to ensure the Developer Role had been correctly applied, to check that the correct Associated Rules were triggered by particular users and AD groups, etc. Audit made me aware that the OwnerPublishDuplicate rule existed and was granting Developers Publish rights, which I needed to disable.
Ok, so I've been tweaking this further to try and get it working. I'm a lot closer, but have a couple of small outstanding issues.
To try and keep it simple, I've listed the current config below.
Security Rule: Stream. Disabled this default rule, as it would give access to all apps in a stream.
Security Rule: AppAccess - replacement for the default Stream rule. Resource filter = App*. Actions = Read. Includes the Condition = and resource.@AppLevelMgmt.empty(), allowing us to give access to a stream with unspecified apps not visible.
Security Rule: AppAccessSpec - rule to allow us to set the apps the user can see. Resource filter = App*. Condition = resource.stream.HasPrivilege("read") and ((resource.stream.HasPrivilege("read") and (user.@AppLevelMgmt=resource.@AppLevelMgmt or user.group=resource.@Group))).
Security Rule: StreamAccessSpec - rule to allow us to set the streams the user can see. Resource filter = App*. Condition = resource.stream.HasPrivilege("read") and ((user.@StreamLevelMgmt = resource.@StreamLevelMgmt)).
Security Rules: A rule for each stream and access level. e.g. Access Dept1 FE User - gives access to the Dept1 Front End Stream. Resource filter = Stream_<streamID>, Actions = Read (for general users). Access Dept1 FE Dev would have Actions = CRUD (for developers).
Custom Property: AppLevelMgmt. Resoruce Types = Apps & Users. Values = one for each individual Front End app (for users), plus one for all Front End apps per department and one for all Extract apps per department (for developers).
Custom Property: StreamLevelMgmt. Resoruce Types = Streams & Users. Values = one for each stream.
Apps: For each App, under Custom Properties > AppLevelMgmt, the relevant AppLevelMgmt Custom Property value is present.
Users: Under each User, under Custom Properties > AppLevelMgmt, the relevant AppLevelMgmt Custom Property value is present. Under Custom Properties > StreamLevelMgmt, the relevant StreamLevelMgmt Custom Property value is present.
* Test user can see only specified Streams.
* Test user can see only specified Apps within those Streams.
* Test user can open (view) the Apps, and they are not longer appearing blank.
* Test user can not duplicate apps.
* I have a feeling that I might be overcomplicating things...
OUTSTANDING ISSUES =
* The above is now operating correctly for our Testers. However, Developers need additional permissions - e.g. to be able to duplicate existing apps to their Work area. I can modify the AppAccessSpec rule (no. 3 above) to include Duplicate, which works, but this would also allow the Testers to duplicate apps, which we don't want at the moment.
One solution here would be to create a separate Security Rule like AppAccessSpec, but with Duplicate (etc) applied, then create a new Custom Property for it like AppLevelMgmt, add values for each app, and apply the values to Apps and Dev Users. However, this seems a long-winded way to go about allowing one Action for some users but not others, so I'm hoping there's a simpler solution.
* When it comes to granting access to AD groups, I know I can edit the Security Rules for each stream (in step 5 above) and add groups. I've also included the condition user.group=resource.@Group to the AppAccessSpec rule (step 3).
However, Is there a way to apply the AppLevelMgmt Custom Property Values to AD groups?
It looks like I could go to Users, search for an AD group, select all, Edit and add the values that way. However, this is just mass updating a list of users, and is not dynamic, so if the AD group changed (people joining or leaving the group), their access wouldn't be automatically applied or removed.
The default stream rule has two parts that grant access to app_objects. You likely have applied your custom property empty test to just one part. The other part is allowing them to see the thumbnails, but they are cut out of every other object. You can test this theory by going into your audit in the QMC, selecting the user who *can* see it but shouldn't, select app_objects and then double-clicking on the "R" to see which rule is granting rights. If they don't show up in the audit for app_objects, then the issue may go deeper. I'd recommend combing through your newly copied stream rule and pulling it out into notepad++ (or your fav tool) to format the parenthesis with nesting so you can see exactly what your new condition is applying to.
Thanks Andoryuu. I think your response was just to my initial post. I only had the AppAccess rule at that point, and was missing the AppAccessSpec and StreamAccessSpec rules.
I did have and resource.@AppLevelMgmt.empty() outside the first set of brackets, rather than inside, so I've corrected that (though I don't think it will have affected anything.
As you can see from my last reply, I've got most things working now, I'm just trying to iron out a couple of final issues. First is how to ensure the correct Actions are applied when different users access the apps.
The Actions I have applied to Security Rules at the moment, are as follows:
* AppAccess rule = CRUD, Export Data & Duplicate
* AppAccessSpec rule = CRUD, Export Data & Duplicate
* StreamAccessSpec rule = Read
plus specific Stream rules, e.g.:
* Access Dept1 EXT (Extract app stream for Department 1, only accessible to developers) = CRUD
* Access Dept1 FE Dev (Front End app stream for Dept 1, only accessible to developers) = CRUD
* Access Dept1 FE User (same Front End app stream, restricted for users) = Read only
If I change the selected Actions in the AppAccessSpec, it works, but it affects all users, regardless of whether they're included in Access Dept1 FE Dev or Access Dept1 FE User rules. So how do I get the Actions on these rules to take precedent, rather than the global Actions on the AppAccessSpec rule?
There isn't precedence in Qlik Sense. Everything is additive and grant model only. You have a complex set of issues here and without seeing either screenshots of every rule or the exact text of the conditions/filters it's hard to troubleshoot. Without having access to your system to run audits and see which rules are granting what, it becomes that much harder. If you want to attach screenshots of all of your rules and conditions I can try to take a look, but honestly, auditing to see exactly which rule is doing what is your best bet here. We have a very similar setup to you with many, many departments and streams. However, we have about 30 production streams and 90 apps. We DO NOT grant individual access - only by Group to keep it dynamic like you are trying to do. We likewise have turned off the default stream rule and have configured sheet level access so that some users can see some sheets in some apps and others not. So we have a very dynamic setup. However, to help you get from a to b to c there needs to be more detail. On the surface it sounds like you want to have AppAccessSpec only apply to your department security rules. You can't do that. You're likely going to have to create AppAccessSpec type rules for your different groups, but honestly, until I see your filters and set up it's hard to say.
Ok, from what you said, I think I've figured out the problem - I wasn't thinking of it in additive terms. I also realised I was mixing up App actions and Stream actions.
So, instead of setting the Stream-specific rules to CRUD, they should all be set to Read only, as we don't want anyone creating, updating or deleting Streams.
I've also set the Actions on the AppAccess and AppAccessSpec rules to Read only - as you imply, adding any further access to these rules would grant it to all users.
In order to grant Create, Update & Delete access to developers only, I created a new Security Rule called Access Dev, applied the requried Actions and Conditions = ((user.roles="Developer")). I then added this role to the user.
Without the role, the sample user can read only (as per standard user). With the role, he can right-click Duplicate (as per Developer), so it looks like it is working.
The only issue I noted was on removing one of the apps under User > Custom Properties > AppLevelMgmt, the user could still see it. I'll investigate that further tomorrow, but following what you said, perhaps I can get round this by just adding the Condition (user.@AppLevelMgmt=resource.@AppLevelMgmt or user.group=resource.@Group))) from the AppAccessSpec rule to the Stream-specific rules.
A quick look at Audit for the sample user, with the above noted amendments applied:
STREAMS: User has access to 4 streams. All 4 are set to Read. Each has1 associated rule, which is the Stream-specific one I created, e.g. Access Dept1 FE Dev.
APPS: User has access to 39 Apps. All 39 set to Read. All have the same 5 Associated Rules: AppAccessSpec = Read. CreateApp = Create. ExportAppData = Export data. Offline Access = Access offline. Stream = Read (disabled).
APP OBJECTS: User has access to... lots. Most are set to Create & Read, except a bunch called "My new sheet" with either just Create, or CRUD access, probably depending on when during our testing they were generated. For the majority, the Associated Rules are: Stream = Read (disabled). CreateAppObjectsPublishedApp = Create. AppAccess = Read.
On further investigation, I find I don't need the Security Rule StreamAccessSpec or the Custom Property StreamLevelMgmt. The user is already specified within the stream-specific rules. Obviously this also means Streams and Users no longer need the StreamLevelMgmt custom property values assigning either.
With regard to the issue I hit yesterday, where the user could still see an app after the AppLevelMgmt Custom Property value was removed under User > Custom Properties > AppLevelMgmt. It looks like this only affects users with the Developer role, and this is confirmed under Audit > Apps for the user. The Associated Rule granting CRUD is, indeed, the Access Dev rule, i.e. the one defining the role Developer. For general users, the app does disappear when the custom property is removed.
So, I modified the Condition on the Access Dev rule to ((user.@AppLevelMgmt=resource.@AppLevelMgmt or user.group=resource.@Group) and (user.roles="Developer")) and the developer can no longer see the app I'd removed from his custom properties.
I also tested removing the user from the stream-specific Security Rule and adding an AD group he is in instead. This also works fine.
Great, so this means I can now:
- Specify which streams any user can see.
- Specify the apps general users see in those streams.
- Specify the apps users with roles can see in those streams.
- Specify the apps AD groups can see, including those AD group members with roles like Developer, as long as the Users have the relevant AppLevelMgmt custom properties set.
So, onto the final issue, then: How can I restrict which apps an AD group can see, without having to apply AppLevelMgmt Custom Properties for every single user within the group (and maintaining for new starters and leavers)? Is there any way to assign Custom Properties to an AD group? Or do I have to create a Security Rule for every app?
So if you want users to still have access to a stream but only see select apps what we've done is to turn off default security to see all apps in a stream, add a custom property called "ADGroupReadRights" at the app level, and grant app read rights where user.group = app.@ADGroupReadRights. This allows you to add an AD group to an app on the custom property on the app instead of thinking about it from the AD side of things. You aren't able to control the data brought in from AD - that's simply stored in the Postgresql db as is. Everything has to be done from the Qlik Sense object side of things. The worst is when the requirement here came down for SHEET level security.