Introduction
During my current SEAL engagement, my customer has a large number of team members who help maintain a large and complex Portal site. Each of the team members manages a subset of the larger site.
A reoccurring problem with this arrangement is making sure that each team member has the correct role to adequately manage their "sub-site". I've had to take a "Portal Access Control" (PAC) trace each time and figure out what role that person in question was missing that kept them from the task at hand.
The problem was happened enough now that I have automated the process and want to pass it along here.
Initial Problem
You know that you have a problem because on the browser window and likely in the SystemOut.log there is a message about not being able to complete an action due to a missing permission. The exact format of the message may vary from screen to screen, but generally the message only provides the name of the resource but not the actual role that was missing.
The goal is to find the role that user was missing for the action the user was attempting.
For example, to change the page layout on a particular page, a user needs both roles of "Editor" as well as "Markup_Editor" on that page. If the user has the role of "Editor" but not "Markup_Editor" and if this user tries to change the layout of the page, they are presented with an error dialog with the page ID and a cryptic message regarding the lack of permissions. The trick now is to figure out which role that user is missing.
Note also, that for Portal 8.5, this Portal InfoCenter page has all the required roles for various operations. In "Table 3" it shows that to change a page layout you need both Editor and Markup_Editor. However, this table is complex and hard to consume. This situation leads to a missing role that needs to be determined.
Process to Find Missing Role
We start by enabling the correct PAC trace. This trace shows all requests into PAC to find roles for a resource and whether or not a user or the groups that user is a member of have the required role for the intended operation. If PAC finds a match, it returns "true". Otherwise, it returns false.
Here is the trace that you need to set:
com.ibm.wps.ac.impl.ChildEntitlementsEngine=all: com.ibm.wps.ac.impl.FullEntitlementsEngine=all
These 2 traces record all requests to PAC for Portal and WCM articifacts to see if an appropriate role exists for the operation requested.
Here is a sample line we are interested in:
[5/16/16 13:22:36:948 MST] 00000116 FullEntitleme > com.ibm.wps.ac.impl.FullEntitlementsEngine checkExplicitPermission ENTRY ACPrincipalPumaImpl: Name: CN=1062775,OU=PEOPLE,O=aCompany,C=US, OID:[ExtIDImpl 'Z9eAe3IJQJO06MHCEJRK6CPJALU0A5QJ056L8CPJQ31T95AISK3H53AFAL91', USER, CN=1062775,OU=PEOPLE,O=aCompany,C=US, [Domain: rel]] [ObjectIDImpl 'Z6_CGAH47L00GOIB0A5TIKBAN00I6', CONTENT_NODE, VP: 0, [Domain: rel], DB: 0000-0CAA484E050062B9802A5DD2A52E00D2] 8 (ActionSet)Edit, (-1) (/ActionSet)
This line is complex, but there a couple of things that interest us. The first is the resource. In this case it's a "Page" which Portal calls a "Content_Node". It's name is "Z6_CGAH47L00GOIB0A5TIKBAN00I6". The second thing of interest is the actual user for which a role is examined. In this case it is a user whose CN is "1062775". In this particular example, PAC is looking to see if the user in question has an explicit role assignment on the resource. PAC might also check the groups of which this user is a member.
Finally, the actual roles are found between the "(ActionSet)" and "(/ActionSet)" characters. In this case, we were checking to see if the "Edit" role was present.
Notice this line has the word "ENTRY". For each "ENTRY", there will be a "RETURN" with either "true" or "false" depending on whether or not the principle (user) in question has the required role. Unfortunately, they are not on the same line. Therefore we have to use some complex Unix scripting to get what we need.
Removing Requests For Roles That Exist
Let's start by removing all the requests that resulted in a "RETURN true" which means that the user had the required role.
grep checkExplicitPermission trace.log | grep -A1 Z6_CGAH47L00GOIB0A5TIKBAN00I6 | grep -B1 "RETURN true" | grep "(ActionSet)" | cut -d ' ' -f29-31 | uniq
Let's examine this command in detail. Note that we are assuming only one active thread is doing work in this Portal. Otherwise, we also need an additional "grep" to isolate the correct thread.
1) grep checkExplicitPermission trace.log: Find all lines in the current trace that have the class "checkExplicitPermission" as noted in the line above.
2) grep -A1 Z6_CGAH47L00GOIB0A5TIKBAN00I6: Find all lines and the next line afterwards that contain the resource in question. In this case it's the page called "Z6_CGAH47L00GOIB0A5TIKBAN00I6". By getting the next line, we get the "RETURN" that includes whether the role was present or not.
3) grep -B1 "RETURN true": Only get the line and the one immediately above it where the required role was found.
4) grep "(ActionSet)": Get rid of the "RETURN" statements since we now only have "RETURN true" instances.
5) cut -d ' ' -f29-31: Only return the portion of the line with the ActionSet.
6) uniq: Only show unique role requests.
At this point we know for a particular resource what roles the interesting user had. Now we find the roles they need but don't have!
Finding the Missing Roles
Now we do a similar exercise as before but we remove all the roles that were found to exist. Here is the general command we use:
grep checkExplicitPermission trace.log | grep -A1 Z6_CGAH47L00GOIB0A5TIKBAN00I6 | sed '/(ActionSet)Edit, (-1) (\/ActionSet)/,+1 d'
1) grep checkExplicitPermission trace.log: Find all lines in the current trace that have the class "checkExplicitPermission".
2) grep -A1 Z6_CGAH47L00GOIB0A5TIKBAN00I6: Find all lines and the next line afterwards that contain the resource in question. In this case it's the page called "Z6_CGAH47L00GOIB0A5TIKBAN00I6". By getting the next line, we get the "RETURN" that includes whether the role was present or not.
3) sed '/(ActionSet)Edit, (-1) (\/ActionSet)/,+1 d': For each line that contains a role that the user already has, delete that line and the next one (which is the "RETURN" line). Not the escape of the "/" character.
4) If multiple roles already exist, pipe into a new "sed" stanza that looks like "3". So you might have a command that looks like this:
grep checkExplicitPermission trace.log | grep -A1 Z6_CGAH47L00GOIB0A5TIKBAN00I6 | sed '/(ActionSet)Edit, (-1) (\/ActionSet)/,+1 d' | sed '/(ActionSet)View, (-1) (\/ActionSet)/,+1 d'
At this point you be left with the exact statement(s) in the trace that show the ActionSet of the missing roles.