-
Type:
Bug
-
Status: Resolved
-
Priority:
Major
-
Resolution: Fixed
-
Affects Version/s: 13.5.0, 14.0.0, 14.5.0, 6.0.0
-
Component/s: entitlements
-
Labels:
-
Sprint:AM Sustaining Sprint 53, AM Sustaining Sprint 54
-
Story Points:3
-
Needs backport:No
-
Support Ticket IDs:
-
Needs QA verification:Yes
-
Functional tests:No
-
Are the reproduction steps defined?:Yes and I used the same an in the description
Bug description
AMIdentitySubject.isMember should not check privilege for group in different realm
User found policy evaluation performance issue when they were load testing using the following command against subrealm :
curl --request POST \ --header "Content-Type: application/json" \ --header "Accept-API-Version:resource=2.0" \ --header "iPlanetDirectoryPro: <admin user>" \ --data '{ "resources": [ "http://openam.example.com:38080/helloworld/index.html" ], "application": "iPlanetAMWebAgentService", "subject": { "ssoToken": "<end user>"} }' \ "http://openam.example.com:18080/openam/json/realms/root/realms/testrealm01/realms/testrealm02/policies?_action=evaluate"
They noticed that the slowness is coming from the membership check against Active Directory which is configured as user datastore under top realm. Note that user belongs to /testrealm01 subrealm and admin group is under top realm in the below sample log entry
amPolicy:07/27/2018 04:29:33:575 AM GMT: Thread[tomcat-http--1247,5,main]: TransactionId[...-1264]
AMIndentitySubject.isMember(): checking membership with
userDN = uid=testuser01,ou=testrealm01,ou=US,dc=openam,dc=forgerock,dc=org, subjectValue =
id=TopRealmAdminGroup1,ou=group,dc=openam,dc=forgerock,dc=org
AMIndentitySubject.isMember() eventually calls DJLDAPv3Repo.getMemberships() .
Daemon Thread [http-bio-18080-exec-2] (Suspended (breakpoint at line 1475 in DJLDAPv3Repo)) owns: SocketWrapper<E> (id=13301) DJLDAPv3Repo.getMemberships(SSOToken, IdType, String, IdType) line: 1475 IdCachedServicesImpl(IdServicesImpl).getMemberships(SSOToken, IdType, String, IdType, String, String) line: 998 AMIdentity.isMember(AMIdentity) line: 1013 AMIdentitySubject.isMember(SSOToken) line: 382 PolicySubject.evaluate(String, SubjectAttributesManager, Subject, String, Map<String,Set<String>>) line: 219 OpenSSOPrivilege(Privilege).doesSubjectMatch(Subject, String, Subject, String, Map<String,Set<String>>) line: 669 OpenSSOPrivilege.internalEvaluate(Subject, String, Subject, String, String, Set<String>, Map<String,Set<String>>, boolean) line: 140 :
Audit/debug logs from performance test show slowness is caused by calls to lists of AMIdentitySubject.isMember to AD groups.
Delegation permission is checked from top to bottom realm and this is because "Realm Admin" can create sub-realms, modify configurations for the realm's services and create, modify and delete Users, Groups, and Agents. However, user could be logged into /sub/sub realm. Therefore, delegation checks for admin groups under top realm for /sub/sub realm admin user should be skipped.
https://docs.oracle.com/cd/E19316-01/820-3885/gilyb/index.html
How to reproduce the issue
- login to admin console and create /testrealm01 (NOTE: Configure Top Level Realm with slow external user datastore to see the issue)
click [+New Realm] -> "Name: testrealm01" -> [Create] button - under root realm, create a group "TestGroup01"
click [Top Level Realm] -> [Identities] -> [Groups] -> [+Add Group]
type "Group ID: TestGroup01" -> [Create] button - under "/testrealm01", create another group "TestGroup02"
click [testrealm01] -> [Identities] -> [Groups] -> [+Add Group]
type "Group ID: TestGroup02" -> [Create] button - under "/testrealm01", create user "testuser01"
click [testrealm01] -> [Identities] -> [Groups] -> [+Add Identity]
type "Id: testuser01" etc -> [Create] button - assign all privileges to "TestGroup01"
click [Top Level Realm] -> [Identities] -> [Groups] -> select "TestGroup01"
click [Privileges] -> enable all privileges -> [Save Changes] - assign all privileges to "TestGroup02"
click [testrealm01] -> [Identities] -> [Groups] -> select "TestGroup02"
click [Members] -> add "testuser01" -> [Save Changes]
click [Privileges] -> enable all privileges -> [Save Changes] - under "/testrealm01", create policy
click [testrealm01] -> [PolicySets] -> [New Policy Set] -> [+New Policy Set]
"Id: iPlanetAMWebAgentService", "Resource Types: URL" -> [Create]
[+Add a Policy] -> "Name:TestPolicy01", "Resource Type: URL" - login as "testuser01"
curl --request POST --header "X-OpenAM-Username: testuser01" --header "X-OpenAM-Password: cangetin" --header "Content-Type: application/json" --header "Accept-API-Version:protocol=1.0,resource=2.1" --data "{}" "http://openam.example.com:18080/openam/json/realms/root/realms/testrealm01/authenticate"
- request policy evaluation as testuser01
curl --request POST \ --header "Accept-API-Version: resource=2.0" \ --header "Content-Type: application/json" \ --header "iPlanetDirectoryPro: <testuser01 token>" \ --data '{ "resources": [ "http://openam.example.com:38080/helloworld/index.html" ], "application": "iPlanetAMWebAgentService", "subject": { "ssoToken": "<testuser01 token>"}. <---- better to use different token than admin user's token, but not absolutely necessary to recreate issue }' \ "http://openam.example.com:18080/openam/json/realms/root/realms/testrealm01/policies?_action=evaluate"
You can see OpenAM will check if subject user has privilege against TestGroup01 under root realm.
amPolicy:08/03/2018 06:12:43:584 AM NZST: Thread[entitlementThreadPool0,5,main]: TransactionId[edf6ca7c-c678-4de7-bb16-abe8a4f5d830-81] AMIdentitySubject.isMember: adding entry in SubjectEvaluationCache for , for userDN = id=testuser01,ou=user,o=testrealm01,ou=services,dc=openam,dc=forgerock,dc=org, subjectValue = id=TestGroup01,ou=group,dc=openam,dc=forgerock,dc=org, subjectMatch = false
Expected behaviour
AMIdentitySubject should not check if user belongs to a group under different realm than the user belongs to.
Current behaviour
AMIdentitySubject checks if user belongs to a group from top realm to subrealm.
Work around
Use amadmin token or Policy Agent token as AMIdentitySubject doesn't check membership if IdType is AGENT or if token belongs to super user
Code analysis
DataStore.searchPrivileges() will search all privileges from top realm. I think this could be because policies which should be applied to subrealm can now defined on the top realm? In any case, it may not be possible to change the filter and base DN of privilege search as it might affect normal policy evaluation.
filter = (&(|(sunxmlKeyValue=hostindex=:\2f\2fdc=openam,dc=forgerock,dc=org)(sunxmlKeyValue=hostindex=:\2f\2fou=services,dc=openam,dc=forgerock,dc=org)(sunxmlKeyValue=hostindex=:\2f\2fo=testrealm01,ou=services,dc=openam,dc=forgerock,dc=org)(sunxmlKeyValue=hostindex=:\2f\2f))(|(sunxmlKeyValue=pathindex=\2frest\2f1.0)(sunxmlKeyValue=pathindex=\2frest\2f1.0\2fpolicies\2fevaluate)(sunxmlKeyValue=pathindex=\2frest\2f1.0\2fpolicies)(sunxmlKeyValue=pathindex=\2frest)(sunxmlKeyValue=pathindex=\2f))) baseDN = ou=default,ou=default,ou=OrganizationConfig,ou=1.0,ou=sunEntitlementIndexes,ou=services,o=sunamhiddenrealmdelegationservicepermissions,ou=services,dc=openam,dc=forgerock,dc=org
AMIdentitySubject.isMember doesn't check if userIdentity (policy evaluation subject) and subjectIdentity (privilege) belongs to the same orgName. The check can be added around line 384.
} else if ( ((allowedMemberTypes = subjectIdType.canHaveMembers()) != null) && allowedMemberTypes.contains(userIdType)) { <<< --- orgDN check should be added --->> subjectMatch = userIdentity.isMember(subjectIdentity); if (debug.messageEnabled()) { debug.message("AMIdentitySubject.isMember():" + "userIdentity type " + userIdType + " can be a member of " + "subjectIdentityType " + subjectIdType + ":membership=" + subjectMatch); } }
- duplicates
-
OPENAM-13406 High Response Times being introduced during policies?_action=evaluate calls (AMIdentitySubject) if a group with Delegated Admin privileges exists.
-
- Closed
-
- is related to
-
OPENAM-12202 When authenticating, deprecated AMIdentitySubject class is called if there exist a group with agent privileges
-
- Closed
-