Professional Documents
Culture Documents
This article discusses two methods for debugging access control in WebSphere® Commerce:
trace searching and direct database querying.
Introduction
Exercising proper access control is critical for securing the WebSphere Commerce environment.
The complexity of the implemented access control grows as new commands and views are added
or removed. With each addition or removal, it is easy to break existing policies or see the newly
added policy behave differently from expected. This article discusses methods for debugging
access control.
Problem determination usually starts with an access control error in the storefront. To better
identify the problem, two methods are available: trace searching and direct database querying.
When the problem is identified, you can fix it by using two methods: using loading xml files or
direct SQL inserts to the database. Both of these methods are covered in this article.
Note: This article focuses on debugging access control. It assumes the reader has some
knowledge of access control in WebSphere Commerce.
You may also experience an access control failure directly from the store front with the following
error message: ERR_USER_AUTHORITY.
After confirming an access control problem, determine if the failure is a legitimate one or if you
need to fix it. A legitimate failure is access control doing what it was designed to do; for example,
preventing a specific registered user from accessing another registered user's order or account
information. An example of an access control issue is when a newly written command fails to
execute because of a user authority error, as seen in the previous log snippet.
Troubleshooting techniques
There are two ways to debug access control failures:
• Read through the trace, check policy-by-policy why they are not applying, and co-relate to the
XML loaded in.
• database directly to see what is missing, based on the criteria being checked.
For more information about turning on tracing, see Configuring logging in the WebSphere
Commerce Information Center. You can analyze it after the trace is enabled, after the scenario is
reproduced, and trace.log is gathered. Starting from the end of the file, perform a backward search
for "=false" to find the access control check that failed. For example:
[1/01/08 13:44:27:141 CDT] 6a36e74e WC_ACCESSCONT d
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed PASSED? =false
[1/01/08 13:44:27:141 CDT] 6a36e74e WC_ACCESSCONT <
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed Exit
[1/01/08 13:44:27:141 CDT] 6a36e74e CommerceSrvr E AccManager isAllowed CMN1501E:
User 40501 does not have the authority to perform action "MyNewView" on resource
"com.ibm.commerce.command.HttpForwardViewCommandlmpl"
To determine what action was being checked which led to this failure, perform another backward
search for the string "isAllowed?". Ensure that it is for the same thread ID:
WC_ACCESSCONT ... PolicyManagerImpl.isAllowed
isAllowed? User=40501; Action=MyNewView; Resource=
com.ibm.commerce.command.HttpForwardViewCommandlmpl; Owner=7000000020002000000;
Resource Ancestor Orgs=7000000020002000000,7000000020000000000,-2001;
Resource Applicable Orgs=7000000020002000000
In between the "isAllowed?" and "PASSED? =false" statements, the PolicyManager iterates
through the access control policies one by one to determine if any apply to the above criteria. For
WebSphere Commerce V6.0, any policy where the action is in the ActionGroup and the resource is
in the ResourceGroup will be identified and evaluated in the trace, similar to the following:
WC_ACCESSCONT d
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isAllowed Found
PolicyName: BecomeUserCustomerServiceGroupExecutesBecomeUserCmdsResourceGroup;
PolicyType: 2; PolicyOwner: -2001
WC_ACCESSCONT >
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl
getPolicyApplicableOrgs Entry
WC_ACCESSCONT d
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs
Policy Applicable Orgs=-2000
WC_ACCESSCONT <
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl getPolicyApplicableOrgs
Exit
WC_ACCESSCONT d
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy
Evaluating PolicyName: BecomeUserCustomerServiceGroupExecutesBecomeUserCmdsResourceGroup
When the "Evaluating PolicyName" statement is made, the PolicyManager checks for each of the
following criteria, based on the elements in the isAllowed statement:
Figure 1 describes how these four pieces fit together and shows a typical access control scenario.
We will take a deeper look at each of these criteria and what happens if they are not upheld.
Because the trace shows only SiteAdministratorsCanDoEverything and no other policies and you
made a new view, define it as an action and include it in an ActionGroup tied to a policy.
Here, the ActionGroup is AllSiteUsersViews. For a new view, define it to be a part of the
AllSiteUsersViews ActionGroup. Define the view as an action and then use ActionGroupAction to
tie into the ActionGroup:
<Action Name="MyNewView"
CommandName="MyNewView">
</Action>
Alternatively, you can also define a new ActionGroup and tie the new action into this one. If doing
this, ensure that you also define a policy to use this ActionGroup. Otherwise, it will have no effect
during runtime.
Note: In the above query and all subsequent ones in this article, you must update the action and
the resource to match those in your "isallowed?" statement. If the action is in place, make sure it is
tied into an ActionGroup:
select acactgrp_id from acactactgp where acaction_id in (select ACACTION_ID from ACACTION
where ACTION = 'MyNewView')
Figure 2 portrays how the entries are arranged in the database, from the ACPOLICY table all the
way down to the ACACTION table.
You can recognize a command-level failure when Execute is the action and the resource is the
command.
The trace shows only the SiteAdministratorsCanDoEverything policy. Since you made a new
command, you need to define it as a resource and include it in a ResourceGroup tied to a policy.
As a sample solution, you can make a new policy for all commands similar to the out-of-the-box
one, but with a different resource group:
<Policy Name="AllUsersExecuteCmdResourceGroup"
OwnerID="RootOrganization"
UserGroup="AllUsers"
ActionGroupName="ExecuteGroup"
ResourceGroupName="MyResourceGroup"
PolicyType="groupableStandard">
</Policy>
Here the ResourceGroup is MyResourceGroup. For a new command, define it to be a part of the
MyResourceGroup ResourceGroup. Define the command as a ResourceCategory, and then use
ResourceGroupResource to tie into the ResourceGroup:
<ResourceCategory Name="com.yourcompany.MyOrderItemAddCmdCategory"
ResourceBeanClass=" com.yourcompany.MyOrderItemAddCmd">
<ResourceAction Name="ExecuteCommand"/>
</ResourceCategory>
Note that you also want to allow the "Execute" action for the command, as denoted by the
ResourceAction above.
Figure 3 shows the new resource along with its connection to the ResourceGroup, all the way up
to the policy.
Again, the trace shows only the SiteAdministratorsCanDoEverything and no other policies. That is
because you have not defined a resource-level policy tying the command to this bean.
As a sample solution, add the bean as a resource in the resource group used for the command,
the policy attachments stay the same:
<ResourceCategory Name="com.ibm.commerce.user.objects.UserResourceCategory"
ResourceBeanClass="com.ibm.commerce.user.objects.User">
<ResourceAction Name="com.yourcompany.MyOrderItemAddCmd"/>
</ResourceCategory>
If the action and resource are both defined correctly based on the above, make sure that the single
access control policy is defined for both combinations. You can merge the two queries to check
this:
select distinct acpolicy_id from acpolicy where acactgrp_id in
(select acactgrp_id from acactactgp where acaction_id in
(select ACACTION_ID from ACACTION where ACTION = 'MyNewView')) and acresgrp_id in
(select acresgrp_id from acresgpres where acrescgry_id in
(select acrescgry_id from acrescgry
where resclassname = 'com.yourcompany.command.MyHttpForwardViewCommandlmpl'))
If this query does not return a result, then either the action or resource needs to be pulled into the
corresponding group accordingly.
Note that the message "Command Level UserGroup does not match" may be different, depending
on which UserGroup is failing and where it is failing (command level check or resource level
check). Similar messages you may see are:
Condition table using the user's role. The following code snippet shows how the out-of-the-box
"RegisteredCustomers" UserGroup is defined.
<UserGroup Name="RegisteredCustomers"
OwnerID="RootOrganization"
Description="Users with Registered Customer role"
MemberGroupID="-197">
<UserCondition> <!
[CDATA[
<profile>
<orListCondition>
<simpleCondition>
<variable name="role"/>
<operator name="="/>
<value data="Registered Customer"/>
</simpleCondition>
</orListCondition>
</profile>
]]>
</UserCondition></UserGroup>
The above will evaluate at runtime to check that the user invoking the action plays the role of
"Registered customer". Here, you are not checking which organization that the role is played in, it
just needs to be in any organization. This is referred to as a Normal UserGroup.
Alternatively, you can also define the UserGroup for the policy to require the role to be played in a
specific organization.
<profile>
<simpleCondition>
<variable name="role"/>
<operator name="="/>
<value data="Registered Customer"/>
<qualifier name="org" data="OrgAndAncestorOrgs"/>
</simpleCondition>
</profile>
The qualifier of OrgAndAncestorOrgs checks if the user has the specified role in the organization
that owns the resource or any of its ancestor organizations. This defines a Template UserGroup.
Whereas the Normal UserGroup was RegisteredCustomers, all Template UserGroups follow the
naming convention of appending "ForOrg" to the name, such as RegisteredCustomersForOrg.
Note that the Normal and Template UserGroups are what determine whether your
access control policy is a Standard (type 2) or Template Policy (type 3), as defined in the
ACPOLICY.POLICYTYPE field.
Figure 4 depicts a diagram with the UserGroup along with its condition in the MBRGRPCOND
table.
One special UserGroup is the AllUsers group, which uses <trueCondition>, meaning it always
evaluate to true implicitly, including any and all users.
Along with implicit MemberGroups, there are explicit ones as well. That means the affiliation to a
group is done explicitly by associating the MBRGRP_ID and MEMBER_ID of the user in question
in the MBRGRPMBR (Member Group Member) table. If a MemberGroup is used, Figure 5 shows
what the database content will look like.
The UserGroup allows the policy to scope which users have access to it. Let's look at a previously
discussed policy and see how you can adapt it to only pertain to registered customers:
<Policy Name="AllUsersExecuteCmdResourceGroup"
OwnerID="RootOrganization"
UserGroup="RegisteredCustomers"
ActionGroupName="ExecuteGroup"
ResourceGroupName="MyResourceGroup"
PolicyType="groupableStandard">
</Policy>
• ACPOLICY
• MBRGROUP
• MBRGRPCOND
• MBRROLE
• MGRGRPMBR (if using explicit MemberGroups)
The following queries illustrate which data to get from which table.
For implicit groups, you need two steps to validate that the user is in this group:
If this query shows a different role than "Registered Customer", then you can set this
customer up to have a registered customer role through the OrgAdminConsole (preferred
method), or make an SQL INSERT in the MBRROLE table to make this user play the
Registered Customer role in a needed organization (for example, the B2C organization).
For explicit UserGroups, run different queries. The initial step to get the MBRGRP_ID from the
ACPOLICY table is the same. Next, run a query to find out if the MEMBER_ID of this user is
associated with the MemberGroup you want to use in the Policy, for example, MyMbrGroup as
seen in Figure 5.
Select MBRGRP_ID,MEMBER_ID from MBRGRPMBR where MEMBER_ID=2002
AND MBRGRP_ID =(Select MBRGROUP_ID from ACPOLICY
where Policyname = 'AllUsersExecuteCmdResourceGroup'")
In the above query, you may replace the part that fetches MBRGRP_ID directly if you know
your MBRGRP_ID. If this query comes back empty, then the user is not in the MemberGroup.
Therefore, you must make an SQL insert in the MBRGRPMBR table to associate user 2002 with
the needed MemberGroup.
In addition to providing the usual checks for UserGroup, ActionGroup and ResourceGroup, this
policy adds an extra check for the Relation. Having the relation allows this policy to be validated
only if the user checked is the actual creator of the resource checked (for example, an Order
bean). This is validated at runtime. For example, a user currently shopping on the storefront is the
creator of the shopping cart containing his items. If other users try to do operations on the previous
user's cart, this policy stops them.
To troubleshoot this kind of policy, make sure all the three groups seen in the previous sections
of this article are valid. Next, you need to be familiar with the beans and database tables in
WebSphere Commerce. You must locate the table pertaining to the bean and check to see if the
user checked during access control is indeed the creator of the resource in question. You can
locate this type of resource level failure in the logs as shown in the snippet below:
WC_ACCESSCONT 3
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed
isAllowed? User=18135; Action=Display;
Resource=com.My.commerce.order.beans.OrderListDataBean; Owner=7000000000000000151;
Resource Ancestor
Orgs=7000000000000000151,7000000000000000004,7000000000000000003,
7000000000000000001,-2001; Resource Applicable Orgs=7000000000000000151
WC_ACCESSCONT 3
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl isExecutionAllowed
Found PolicyName: AllUsersDisplayOrderDatabeanResourceGroup;
PolicyType: 2; PolicyOwner: -2001
...
WC_ACCESSCONT 3
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl evaluatePolicy
Relationship check: creator -> false
WC_ACCESSCONT 3
com.ibm.commerce.accesscontrol.policymanager.PolicyManagerImpl
isExecutionAllowed PASSED? =false
As mentioned previously, identify the table mapping to the bean being checked. For example,
when dealing with Order beans, do the following:
1. Note the userID being checked in the policy, in this case, User 18135.
2. Search the trace to find out which orderId is currently being worked on. For that, you will most
likely need WC_ORDER tracing.
This step depends on the type of resource in use. You may or may not need to turn on
additional tracing. For instance, if the resource being retrieved is a user bean (data from the
USERS table), there is no need to turn on additional tracing as the userID is in the isallowed?
part of the trace.
3. Last, check the Orders table and look for the MEMBER_ID associated with the order (note
that we use the MEMBER_ID as in the USERS table and not ORGENTITY_ID, which is also
available in the Orders table).
When you have those two IDs, compare them to see if the MEMBER_ID in the isallowed?
portion of the trace is the same as the one in the ORDERS table. If not, then you have a valid
case of access control where another user tried to access someone else's shopping cart.
Query the database
The following query helps with the steps provided above:
Select * from ORDERS where ORDERS_ID=<identified OrderID> AND MEMBER_ID=18135
Here, the policy meets all other criteria, but no organization is subscribing to a policy group
containing this policy. If the only policy that is applicable in our policy manager evaluation is the
AllUsersExecuteResellerUserCmdResourceGroup, then there are two things you need to ensure
for this check to pass:
• This policy has to be in a policy group. A policy alone is of no use because all subscriptions
are to a policy group, not a single policy.
• The policy group is subscribed to by the correct organization.
Ensure that the resource owner is subscribing to the correct policy groups. For example:
<Policies>
<PolicyGroup Name="SomeKnownPolicyGroup" OwnerID="RootOrganization">
<PolicyGroupPolicy Name=
"AllUsersExecuteResellerUserCmdResourceGroup"
PolicyOwnerId="RootOrganization" />
<PolicyGroupSubscription OrganizationID="RootOrganization"/>
</PolicyGroup>
</Policies>
orgentity_id acpolgrp_id
2002 10001
2002 10003
Subscribe the organization to the policy group. In this example, the organization subscribes to
policy group 10001. You can do this through the OrgAdminConsole or a direct SQL INSERT in the
ACPLGPSUBS table.
If you have a policy subscription problem, look at the resource references from the trace, for
example:
Resource Ancestor Orgs=2002,-2001; Resource Applicable Orgs=2002
When checking policy group subscriptions, this checks for the subscriptions from the first
organization listed, such as 2002. If it subscribes to a group containing the relevant policy, this will
pass. If it does subscribe to policy groups, but none contain the relevant policy, access control will
fail. If it does not subscribe to any policies of its own, then only in this case it will check its closest
ancestor, such as -2001. The subscriptions of this organization are inherited and applicable for the
organization, only because you do not subscribe to any of the policy groups.
Conclusion
This article described how to troubleshoot and fix an access control policy failure from all angles
of a policy. Remember that access control enables security on your site and you do not have to
fix every access control "failure". Take the example where the failure reports that a user cannot
display the account information of another user. This clearly is access control reporting that has
worked. In cases where you need to fix access control failures, the "divide and conquer" attitude
works well for the access control policy. Locate all four components (MemberGroup, AccessGroup,
Relation, and ResourceGroup) and make sure each one is properly loaded in the database.
Acknowledgements
The authors would like to thank Ibrahim Boubacar Doumbia and Assa H. Cisse for their help in
preparing and reviewing the article.
Related topics
• Webcast replay: Access Control WebSphere Support Technical Exchange
• WebSphere Commerce Information Center: Troubleshooting access control problems
• WebSphere Commerce Information Center: Implementing access control
• WebSphere Commerce Infomation Center: Access control data model
• WebSphere Commerce Information Center: Member data model