From 7b97a69ad0909d99aabbb0630737b8873f0fb705 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Thu, 31 Jul 2014 17:53:47 +0200 Subject: [PATCH] Fixing user login with conditional roles (+test) --- .../ModelExpressionThreadLocalHolder.java | 1 + .../midpoint/model/impl/lens/LensContext.java | 4 + .../impl/lens/LensContextPlaceholder.java | 54 +++++++++++++ .../impl/security/UserProfileServiceImpl.java | 18 ++++- ...bstractConfiguredModelIntegrationTest.java | 2 + .../midpoint/model/intest/TestSecurity.java | 79 +++++++++++++++++++ .../resources/security/role-conditional.xml | 35 ++++++++ 7 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContextPlaceholder.java create mode 100644 model/model-intest/src/test/resources/security/role-conditional.xml diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/ModelExpressionThreadLocalHolder.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/ModelExpressionThreadLocalHolder.java index f1592437cc3..dcbd7aa2cb5 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/ModelExpressionThreadLocalHolder.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/expr/ModelExpressionThreadLocalHolder.java @@ -19,6 +19,7 @@ import java.util.Deque; import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.model.impl.lens.LensContextPlaceholder; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java index 0e770fcc9ea..56fb19727d8 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContext.java @@ -125,6 +125,10 @@ public LensContext(Class focusClass, PrismContext prismContext, ProvisioningS this.focusClass = focusClass; } + protected LensContext(PrismContext prismContext) { + this.prismContext = prismContext; + } + public PrismContext getPrismContext() { return prismContext; } diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContextPlaceholder.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContextPlaceholder.java new file mode 100644 index 00000000000..69ab206bc9f --- /dev/null +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/lens/LensContextPlaceholder.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2014 Evolveum + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.evolveum.midpoint.model.impl.lens; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; + +/** + * This class does nothing. It just takes place when no real Lens Context is available. + * @see ModelExpressionThreadLocalHolder + * + * @author semancik + * + */ +public class LensContextPlaceholder extends LensContext { + + public LensContextPlaceholder(PrismContext prismContext) { + super(prismContext); + } + + @Override + public String toString() { + return "LensContextPlaceholder()"; + } + + @Override + public String dump(boolean showTriples) { + return "LensContextPlaceholder()"; + } + + @Override + public String debugDump(int indent, boolean showTriples) { + StringBuilder sb = new StringBuilder(); + DebugUtil.indentDebugDump(sb, indent); + sb.append("LensContextPlaceholder"); + return sb.toString(); + } + + +} diff --git a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java index 0f740b36458..26d96377457 100644 --- a/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java +++ b/model/model-impl/src/main/java/com/evolveum/midpoint/model/impl/security/UserProfileServiceImpl.java @@ -25,6 +25,8 @@ import com.evolveum.midpoint.model.impl.UserComputer; import com.evolveum.midpoint.model.impl.lens.AssignmentEvaluator; import com.evolveum.midpoint.model.impl.lens.EvaluatedAssignment; +import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.model.impl.lens.LensContextPlaceholder; import com.evolveum.midpoint.model.impl.lens.LensUtil; import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; @@ -41,6 +43,8 @@ import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.security.api.UserProfileService; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.exception.ExpressionEvaluationException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; @@ -84,6 +88,9 @@ public class UserProfileServiceImpl implements UserProfileService { @Autowired(required = true) private PrismContext prismContext; + + @Autowired(required = true) + private TaskManager taskManager; @Override public MidPointPrincipal getPrincipal(String username) throws ObjectNotFoundException { @@ -169,18 +176,25 @@ private void addAuthorizations(MidPointPrincipal principal) { assignmentEvaluator.setMappingFactory(valueConstructionFactory); assignmentEvaluator.setActivationComputer(activationComputer); assignmentEvaluator.setNow(clock.currentTimeXMLGregorianCalendar()); + // We do need only authorizations. Therefore we not need to evaluate constructions, // so switching it off is faster. It also avoids nasty problems with resources being down, // resource schema not available, etc. assignmentEvaluator.setEvaluateConstructions(false); + + // We do not have real lens context here. But the push methods in ModelExpressionThreadLocalHolder + // will need something to push on the stack. So give them context placeholder. + LensContext lensContext = new LensContextPlaceholder<>(prismContext); + assignmentEvaluator.setLensContext(lensContext); - OperationResult result = new OperationResult(UserProfileServiceImpl.class.getName() + ".addAuthorizations"); + Task task = taskManager.createTaskInstance(UserProfileServiceImpl.class.getName() + ".addAuthorizations"); + OperationResult result = task.getResult(); for(AssignmentType assignmentType: userType.getAssignment()) { try { ItemDeltaItem> assignmentIdi = new ItemDeltaItem<>(); assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType)); assignmentIdi.recompute(); - EvaluatedAssignment assignment = assignmentEvaluator.evaluate(assignmentIdi, false, userType, userType.toString(), null, result); + EvaluatedAssignment assignment = assignmentEvaluator.evaluate(assignmentIdi, false, userType, userType.toString(), task, result); if (assignment.isValid()) { authorizations.addAll(assignment.getAuthorizations()); } diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java index b0bd267cfff..cc914bb7e34 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/AbstractConfiguredModelIntegrationTest.java @@ -327,6 +327,8 @@ public class AbstractConfiguredModelIntegrationTest extends AbstractModelIntegra protected static final String AUTZ_COMMAND_URL = QNameUtil.qNameToUri(AUTZ_COMMAND_QNAME); protected static final QName AUTZ_PUNISH_QNAME = new QName(NS_TEST_AUTZ, "punish"); protected static final String AUTZ_PUNISH_URL = QNameUtil.qNameToUri(AUTZ_PUNISH_QNAME); + protected static final QName AUTZ_CAPSIZE_QNAME = new QName(NS_TEST_AUTZ, "capsize"); + protected static final String AUTZ_CAPSIZE_URL = QNameUtil.qNameToUri(AUTZ_CAPSIZE_QNAME); private static final Trace LOGGER = TraceManager.getTrace(AbstractConfiguredModelIntegrationTest.class); diff --git a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java index 32a9d0554b0..0c4c524bdea 100644 --- a/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java +++ b/model/model-intest/src/test/java/com/evolveum/midpoint/model/intest/TestSecurity.java @@ -184,6 +184,9 @@ public class TestSecurity extends AbstractInitializedModelIntegrationTest { protected static final File ROLE_BUSINESS_1_FILE = new File(TEST_DIR, "role-business-1.xml"); protected static final String ROLE_BUSINESS_1_OID = "00000000-0000-0000-0000-00000000aab1"; + + protected static final File ROLE_CONDITIONAL_FILE = new File(TEST_DIR, "role-conditional.xml"); + protected static final String ROLE_CONDITIONAL_OID = "00000000-0000-0000-0000-00000000aac1"; private static final String LOG_PREFIX_FAIL = "SSSSS=X "; private static final String LOG_PREFIX_ATTEMPT = "SSSSS=> "; @@ -220,6 +223,8 @@ public void initSystem(Task initTask, OperationResult initResult) throws Excepti repoAddObjectFromFile(ROLE_APPLICATION_2_FILE, RoleType.class, initResult); repoAddObjectFromFile(ROLE_BUSINESS_1_FILE, RoleType.class, initResult); + repoAddObjectFromFile(ROLE_CONDITIONAL_FILE, RoleType.class, initResult); + assignOrg(USER_GUYBRUSH_OID, ORG_SWASHBUCKLER_SECTION_OID, initTask, initResult); PrismObject userRum = createUser(USER_RUM_ROGERS_NAME, "Rum Rogers"); @@ -344,6 +349,80 @@ public void test052GetUserGuybrush() throws Exception { assertNotAuthorized(principal, AUTZ_COMMAND_URL); } + @Test + public void test060GuybrushConditionalRoleFalse() throws Exception { + final String TEST_NAME = "test060GuybrushConditionalRoleFalse"; + TestUtil.displayTestTile(this, TEST_NAME); + assertLoggedInUser(USER_ADMINISTRATOR_USERNAME); + + assignRole(USER_GUYBRUSH_OID, ROLE_CONDITIONAL_OID); + + // WHEN + MidPointPrincipal principal = userProfileService.getPrincipal(USER_GUYBRUSH_USERNAME); + + // THEN + display("Principal guybrush", principal); + assertEquals("wrong username", USER_GUYBRUSH_USERNAME, principal.getUsername()); + assertEquals("wrong oid", USER_GUYBRUSH_OID, principal.getOid()); + assertTrue("Unexpected authorizations", principal.getAuthorities().isEmpty()); + display("User in principal guybrush", principal.getUser().asPrismObject()); + + principal.getUser().asPrismObject().checkConsistence(true, true); + + assertNotAuthorized(principal, AUTZ_LOOT_URL); + assertNotAuthorized(principal, AUTZ_COMMAND_URL); + } + + @Test + public void test061GuybrushConditionalRoleTrue() throws Exception { + final String TEST_NAME = "test061GuybrushConditionalRoleTrue"; + TestUtil.displayTestTile(this, TEST_NAME); + assertLoggedInUser(USER_ADMINISTRATOR_USERNAME); + + Task task = taskManager.createTaskInstance(TestRbac.class.getName() + "." + TEST_NAME); + OperationResult result = task.getResult(); + modifyUserReplace(USER_GUYBRUSH_OID, UserType.F_EMPLOYEE_TYPE, task, result, "looser"); + + // WHEN + MidPointPrincipal principal = userProfileService.getPrincipal(USER_GUYBRUSH_USERNAME); + + // THEN + display("Principal guybrush", principal); + assertEquals("wrong username", USER_GUYBRUSH_USERNAME, principal.getUsername()); + assertEquals("wrong oid", USER_GUYBRUSH_OID, principal.getOid()); + assertTrue("Unexpected authorizations", principal.getAuthorities().isEmpty()); + display("User in principal guybrush", principal.getUser().asPrismObject()); + + principal.getUser().asPrismObject().checkConsistence(true, true); + + assertNotAuthorized(principal, AUTZ_LOOT_URL); + assertNotAuthorized(principal, AUTZ_COMMAND_URL); + assertNotAuthorized(principal, AUTZ_CAPSIZE_URL); + } + + @Test + public void test062GuybrushConditionalRoleUnassign() throws Exception { + final String TEST_NAME = "test062GuybrushConditionalRoleUnassign"; + TestUtil.displayTestTile(this, TEST_NAME); + assertLoggedInUser(USER_ADMINISTRATOR_USERNAME); + + unassignRole(USER_GUYBRUSH_OID, ROLE_CONDITIONAL_OID); + + // WHEN + MidPointPrincipal principal = userProfileService.getPrincipal(USER_GUYBRUSH_USERNAME); + + // THEN + display("Principal guybrush", principal); + assertEquals("wrong username", USER_GUYBRUSH_USERNAME, principal.getUsername()); + assertEquals("wrong oid", USER_GUYBRUSH_OID, principal.getOid()); + assertTrue("Unexpected authorizations", principal.getAuthorities().isEmpty()); + display("User in principal guybrush", principal.getUser().asPrismObject()); + + principal.getUser().asPrismObject().checkConsistence(true, true); + + assertNotAuthorized(principal, AUTZ_LOOT_URL); + assertNotAuthorized(principal, AUTZ_COMMAND_URL); + } @Test public void test100JackRolePirate() throws Exception { diff --git a/model/model-intest/src/test/resources/security/role-conditional.xml b/model/model-intest/src/test/resources/security/role-conditional.xml new file mode 100644 index 00000000000..8325a652a56 --- /dev/null +++ b/model/model-intest/src/test/resources/security/role-conditional.xml @@ -0,0 +1,35 @@ + + + Conditional + + http://midpoint.evolveum.com/xml/ns/test/authorization#superspecial + + + + $user/employeeType + + + + + +