Merge pull request #47 from kklaeger/TSK-65

TSK-65: Enable JAAS-Subjects in unit tests and REST Service
This commit is contained in:
BerndBreier 2017-12-08 11:09:48 +01:00 committed by GitHub
commit f399135a9d
7 changed files with 274 additions and 37 deletions

View File

@ -6,6 +6,8 @@ import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@ -88,31 +90,44 @@ public final class CurrentUserContext {
private static String getUseridFromJAASSubject() {
Subject subject = Subject.getSubject(AccessController.getContext());
LOGGER.debug("Subject of caller: {}", subject);
LOGGER.trace("Subject of caller: {}", subject);
if (subject != null) {
Set<Object> publicCredentials = subject.getPublicCredentials();
LOGGER.debug("Public credentials of caller: {}", publicCredentials);
for (Object pC : publicCredentials) {
LOGGER.debug("Returning the first public credential: {}", pC.toString());
return pC.toString();
Set<Principal> principals = subject.getPrincipals();
LOGGER.trace("Public principals of caller: {}", principals);
for (Principal pC : principals) {
if (!(pC instanceof Group)) {
LOGGER.trace("Returning the first principal that is no group: {}", pC.getName());
return pC.getName();
}
}
}
LOGGER.debug("No userid found in subject!");
LOGGER.trace("No userid found in subject!");
return null;
}
public static List<String> getGroupIds() {
return null;
Subject subject = Subject.getSubject(AccessController.getContext());
LOGGER.trace("Subject of caller: {}", subject);
List<String> groupIds = new ArrayList<>();
if (subject != null) {
Set<Group> groups = subject.getPrincipals(Group.class);
LOGGER.trace("Public groups of caller: {}", groups);
for (Principal group : groups) {
LOGGER.trace("Returning the groupId: {}", group.getName());
groupIds.add(group.getName());
}
return groupIds;
}
LOGGER.trace("No groupids found in subject!");
return groupIds;
}
public static List<String> getAccessIds() {
List<String> accessIds = new ArrayList<>();
List<String> groupIds = getGroupIds();
accessIds.add(getUserid());
if (getGroupIds() != null) {
accessIds.addAll(getGroupIds());
}
if (accessIds.isEmpty()) {
return null;
if (!groupIds.isEmpty()) {
accessIds.addAll(groupIds);
}
return accessIds;
}

View File

@ -0,0 +1,46 @@
package pro.taskana.security;
import java.security.Principal;
import java.security.acl.Group;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Set;
/**
* Represents a group with a name and a set of members.
*/
public class GroupPrincipal implements Group {
private String name;
private Set<Principal> members;
public GroupPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public boolean addMember(Principal user) {
return this.members.add(user);
}
@Override
public boolean removeMember(Principal user) {
return this.members.remove(user);
}
@Override
public boolean isMember(Principal member) {
return this.members.contains(member);
}
@Override
public Enumeration<? extends Principal> members() {
return Collections.enumeration(this.members);
}
}

View File

@ -0,0 +1,21 @@
package pro.taskana.security;
import java.security.Principal;
/**
* Represents a user principal with a name.
*/
public class UserPrincipal implements Principal {
private String name;
public UserPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
}

View File

@ -109,13 +109,14 @@ public class TaskServiceImplIntAutocommitTest {
throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
TaskanaEngineConfiguration taskanaEngineConfiguration = new TaskanaEngineConfiguration(null, false, false);
TaskanaEngine te = taskanaEngineConfiguration.buildTaskanaEngine();
((TaskanaEngineImpl) te).setConnectionManagementMode(ConnectionManagementMode.AUTOCOMMIT);
TaskServiceImpl taskServiceImpl = (TaskServiceImpl) te.getTaskService();
Workbasket wb = new Workbasket();
wb.setName("workbasket");
taskanaEngine.getWorkbasketService().createWorkbasket(wb);
te.getWorkbasketService().createWorkbasket(wb);
Classification classification = new Classification();
taskanaEngine.getClassificationService().addClassification(classification);
te.getClassificationService().addClassification(classification);
Task task = new Task();
task.setName("Unit Test Task");

View File

@ -1,7 +1,30 @@
package pro.taskana.impl.integration;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;
import javax.sql.DataSource;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.h2.store.fs.FileUtils;
import org.junit.*;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import pro.taskana.ClassificationQuery;
import pro.taskana.ObjectReferenceQuery;
import pro.taskana.TaskanaEngine;
@ -15,15 +38,8 @@ import pro.taskana.impl.*;
import pro.taskana.impl.configuration.DBCleaner;
import pro.taskana.impl.configuration.TaskanaEngineConfigurationTest;
import pro.taskana.model.*;
import javax.security.auth.login.LoginException;
import javax.sql.DataSource;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import pro.taskana.security.GroupPrincipal;
import pro.taskana.security.UserPrincipal;
/**
* Integration Test for TaskServiceImpl transactions with connection management mode EXPLICIT.
@ -36,6 +52,7 @@ public class TaskServiceImplIntExplicitTest {
private TaskanaEngineConfiguration taskanaEngineConfiguration;
private TaskanaEngine taskanaEngine;
private TaskanaEngineImpl taskanaEngineImpl;
private Subject subject;
@BeforeClass
public static void resetDb() throws SQLException {
@ -47,17 +64,49 @@ public class TaskServiceImplIntExplicitTest {
@Before
public void setup() throws FileNotFoundException, SQLException, LoginException {
dataSource = TaskanaEngineConfigurationTest.getDataSource();
taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false, false);
taskanaEngineConfiguration = new TaskanaEngineConfiguration(dataSource, false);
taskanaEngine = taskanaEngineConfiguration.buildTaskanaEngine();
taskServiceImpl = (TaskServiceImpl) taskanaEngine.getTaskService();
taskanaEngineImpl = (TaskanaEngineImpl) taskanaEngine;
taskanaEngineImpl.setConnectionManagementMode(ConnectionManagementMode.EXPLICIT);
DBCleaner cleaner = new DBCleaner();
cleaner.clearDb(dataSource, false);
subject = new Subject();
List<Principal> principalList = new ArrayList<>();
principalList.add(new UserPrincipal("Elena"));
principalList.add(new GroupPrincipal("group1"));
principalList.add(new GroupPrincipal("group2"));
principalList.add(new GroupPrincipal("group3"));
subject.getPrincipals().addAll(principalList);
try {
Connection connection = dataSource.getConnection();
ScriptRunner runner = new ScriptRunner(connection);
runner.runScript(
new InputStreamReader(this.getClass().getResourceAsStream("/sql/workbasket-access-list.sql")));
} catch (SQLException e1) {
e1.printStackTrace();
}
}
@Test
public void testStart() throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
public void testCreateTask() throws Throwable {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws TaskNotFoundException, WorkbasketNotFoundException, FileNotFoundException, NotAuthorizedException, SQLException, ClassificationNotFoundException {
do_testCreateTask();
return null;
}
});
} catch (PrivilegedActionException e) {
throw e.getCause();
}
}
public void do_testCreateTask() throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
@ -73,7 +122,24 @@ public class TaskServiceImplIntExplicitTest {
}
@Test(expected = TaskNotFoundException.class)
public void testStartTransactionFail()
public void testStartTransactionFail() throws TaskNotFoundException {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
public Object run() throws TaskNotFoundException, FileNotFoundException, NotAuthorizedException, SQLException, WorkbasketNotFoundException, ClassificationNotFoundException {
do_testStartTransactionFail();
return null;
}
});
} catch (PrivilegedActionException e) {
Throwable cause = e.getCause();
if (cause != null) {
Assert.assertTrue(cause instanceof TaskNotFoundException);
throw (TaskNotFoundException) cause;
}
}
}
public void do_testStartTransactionFail()
throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
@ -81,6 +147,7 @@ public class TaskServiceImplIntExplicitTest {
Workbasket workbasket = new Workbasket();
workbasket.setName("workbasket");
workbasket.setId("1"); // set id manually for authorization tests
Classification classification = new Classification();
taskanaEngine.getWorkbasketService().createWorkbasket(workbasket);
taskanaEngine.getClassificationService().addClassification(classification);
@ -100,7 +167,21 @@ public class TaskServiceImplIntExplicitTest {
}
@Test
public void testCreateTaskInTaskanaWithDefaultDb()
public void testCreateTaskInTaskanaWithDefaultDb() throws Throwable {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws TaskNotFoundException, WorkbasketNotFoundException, FileNotFoundException, NotAuthorizedException, SQLException, ClassificationNotFoundException {
do_testCreateTaskInTaskanaWithDefaultDb();
return null;
}
});
} catch (PrivilegedActionException e) {
throw e.getCause();
}
}
public void do_testCreateTaskInTaskanaWithDefaultDb()
throws FileNotFoundException, SQLException, TaskNotFoundException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
DataSource ds = TaskanaEngineConfiguration.createDefaultDataSource();
TaskanaEngineConfiguration taskanaEngineConfiguration = new TaskanaEngineConfiguration(ds, false, false);
@ -112,7 +193,7 @@ public class TaskServiceImplIntExplicitTest {
ClassificationServiceImpl classificationServiceImpl = (ClassificationServiceImpl) te.getClassificationService();
Workbasket workbasket = new Workbasket();
workbasket.setName("workbasket");
workbasket.setName("workbasket99");
Classification classification = new Classification();
workbasketServiceImpl.createWorkbasket(workbasket);
classificationServiceImpl.addClassification(classification);
@ -130,7 +211,21 @@ public class TaskServiceImplIntExplicitTest {
}
@Test
public void testCreateTaskWithPlannedAndName() throws SQLException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
public void testCreateTaskWithPlannedAndName() throws Throwable {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws WorkbasketNotFoundException, ClassificationNotFoundException, NotAuthorizedException, SQLException {
do_testCreateTaskWithPlannedAndName();
return null;
}
});
} catch (PrivilegedActionException e) {
throw e.getCause();
}
}
public void do_testCreateTaskWithPlannedAndName() throws SQLException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
@ -176,16 +271,50 @@ public class TaskServiceImplIntExplicitTest {
@Test(expected = WorkbasketNotFoundException.class)
public void createTaskShouldThrowWorkbasketNotFoundException() throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException, SQLException {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
public Object run() throws NotAuthorizedException, SQLException, WorkbasketNotFoundException, ClassificationNotFoundException {
do_createTaskShouldThrowWorkbasketNotFoundException();
return null;
}
});
} catch (PrivilegedActionException e) {
Throwable cause = e.getCause();
if (cause != null) {
Assert.assertTrue(cause instanceof WorkbasketNotFoundException);
throw (WorkbasketNotFoundException) cause;
}
}
}
public void do_createTaskShouldThrowWorkbasketNotFoundException() throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException, SQLException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
Task test = this.generateDummyTask();
test.setWorkbasketId("1");
test.setWorkbasketId("2");
taskServiceImpl.createTask(test);
}
@Test(expected = ClassificationNotFoundException.class)
public void createManualTaskShouldThrowClassificationNotFoundException() throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException, SQLException {
public void createManualTaskShouldThrowClassificationNotFoundException() throws ClassificationNotFoundException {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
public Object run() throws NotAuthorizedException, SQLException, WorkbasketNotFoundException, ClassificationNotFoundException {
do_createManualTaskShouldThrowClassificationNotFoundException();
return null;
}
});
} catch (PrivilegedActionException e) {
Throwable cause = e.getCause();
if (cause != null) {
Assert.assertTrue(cause instanceof ClassificationNotFoundException);
throw (ClassificationNotFoundException) cause;
}
}
}
public void do_createManualTaskShouldThrowClassificationNotFoundException() throws NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException, SQLException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
@ -195,13 +324,27 @@ public class TaskServiceImplIntExplicitTest {
}
@Test
public void should_ReturnList_when_BuilderIsUsed() throws SQLException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
public void should_ReturnList_when_BuilderIsUsed() throws Throwable {
try {
Subject.doAs(subject, new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws WorkbasketNotFoundException, NotAuthorizedException, SQLException, ClassificationNotFoundException {
do_should_ReturnList_when_BuilderIsUsed();
return null;
}
});
} catch (PrivilegedActionException e) {
throw e.getCause();
}
}
public void do_should_ReturnList_when_BuilderIsUsed() throws SQLException, NotAuthorizedException, WorkbasketNotFoundException, ClassificationNotFoundException {
Connection connection = dataSource.getConnection();
taskanaEngineImpl.setConnection(connection);
Workbasket workbasket = new Workbasket();
workbasket.setName("workbasket");
workbasket.setId("1"); // set id manually for authorization tests
Classification classification = new Classification();
taskanaEngine.getWorkbasketService().createWorkbasket(workbasket);
taskanaEngine.getClassificationService().addClassification(classification);
@ -222,7 +365,7 @@ public class TaskServiceImplIntExplicitTest {
.systemInstance("sysInst1", "sysInst2").value("val1", "val2", "val3");
List<Task> results = taskServiceImpl.createTaskQuery().name("bla", "test").descriptionLike("test")
.priority(1, 2, 2).state(TaskState.CLAIMED).workbasketId("asd", "asdasdasd")
.priority(1, 2, 2).state(TaskState.CLAIMED).workbasketId("1", "2")
.owner("test", "test2", "bla").customFields("test").classification(classificationQuery)
.objectReference(objectReferenceQuery).list();
@ -233,6 +376,7 @@ public class TaskServiceImplIntExplicitTest {
private Task generateDummyTask() {
Workbasket workbasket = new Workbasket();
workbasket.setName("wb");
workbasket.setId("1"); // set id manually for authorization tests
taskanaEngine.getWorkbasketService().createWorkbasket(workbasket);
Classification classification = new Classification();

View File

@ -0,0 +1,3 @@
INSERT INTO WORKBASKET_ACCESS_LIST VALUES ('1', '1', 'Elena', true, true, true, true, true, false, false, false, false, false, false, false, false);
INSERT INTO WORKBASKET_ACCESS_LIST VALUES ('2', '2', 'Elena', true, true, true, true, true, true, true, true, true, false, false, false, false);
INSERT INTO WORKBASKET_ACCESS_LIST VALUES ('3', '3', 'Simone', true, true, true, true, true, true, true, true, true, true, true, true, true);

View File

@ -4,6 +4,9 @@ import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.jaas.JaasAuthenticationToken;
import org.springframework.security.core.Authentication;
import pro.taskana.security.GroupPrincipal;
import pro.taskana.security.UserPrincipal;
public class CustomAutenticationProvider implements AuthenticationProvider {
private AuthenticationProvider delegate;
@ -17,14 +20,18 @@ public class CustomAutenticationProvider implements AuthenticationProvider {
.authenticate(authentication);
if (jaasAuthenticationToken.isAuthenticated()) {
jaasAuthenticationToken.getLoginContext().getSubject().getPublicCredentials().add(jaasAuthenticationToken.getPrincipal());
String userName = jaasAuthenticationToken.getPrincipal().toString();
jaasAuthenticationToken.getLoginContext().getSubject().getPrincipals().add(new UserPrincipal(userName));
jaasAuthenticationToken.getLoginContext().getSubject().getPrincipals().add(new GroupPrincipal("group1"));
jaasAuthenticationToken.getLoginContext().getSubject().getPrincipals().add(new GroupPrincipal("group2"));
jaasAuthenticationToken.getLoginContext().getSubject().getPrincipals().add(new GroupPrincipal("group3"));
return jaasAuthenticationToken;
} else {
return null;
}
}
@Override
@Override
public boolean supports(Class<?> authentication) {
return delegate.supports(authentication);
}