Skip to content

Defect/#7 systemuser testing support #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The Access Control Validator provides an easy to use tool for testers and develo
Features:
* Easy-to-read Yaml configuration file format
* Page and user management tests
* Testing of systemusers (since v1.0.2)
* Run mode support
* Health checks
* Service API
Expand All @@ -29,6 +30,8 @@ Therefore the tool temporarily creates a testuser, makes it member of the group

This not only makes testing more thorough but also allows to define additional parameters in the respective test definition like e.g. a template when testing if a page can be creates under a certain path of a property name which will be used when testing if modification of a page is possible.

Also systemuser permission can be tested using the Tool. In that case a testuser creation is not needed. Instead the tool uses an administrative session impersonating the systemuser of interest. In order for this to work, the accescontrolvalidator bundle is whitelisted via OSGi configuration.

The tool does not leave any test content in the repository such as the testuser, or modified properties, by either not persisting any changes or if this can not be avoided, deletes them when the test is done.

## Run Mode Support
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
import java.util.List;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.AuthorizableExistsException;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
Expand All @@ -34,7 +37,7 @@
*
*/
public class AcTestSet {

private final Logger LOG = LoggerFactory.getLogger(AcTestSet.class);


Expand All @@ -57,7 +60,7 @@ public AcTestSet(String authorizableID, String pathToTestfile) {
public void addAcTestCase(Testable testable){
this.acTestCase.add(testable);
}

public String getAuthorizableID(){
return this.authorizableID;
}
Expand All @@ -72,41 +75,45 @@ public String getAuthorizableID(){
public List<TestResult> isOk(ServiceResourceResolverService serviceResourceResolverService) throws RepositoryException, LoginException {
List<TestResult> resultList = new ArrayList<>();
User testuser = null;
Group testGroup = null;
Authorizable authorizableToTest = null;
ResourceResolver serviceResourcerResolver = null;
ResourceResolver testUserResolver = null;
try {
// create authorizables
serviceResourcerResolver = serviceResourceResolverService.getServiceResourceResolver();

UserManager userManager = getUserManager(serviceResourcerResolver);

testuser = userManager.createUser(ACVALIDATOR_TESTUSER_ID, ACVALIDATOR_TESTUSER_PASSWORD);
testGroup = getTestGroup(getUserManager(serviceResourcerResolver), authorizableID, testuser);

// we need to persist the created testuser in order to be able to get a resolver for him
serviceResourcerResolver.commit();
LOG.debug("comitting serviceResourcerResolver to persist testuser");
// create ResourceResolver for the testuser based on his permissions
testUserResolver = serviceResourceResolverService.getTestUserResourceResolver(ACVALIDATOR_TESTUSER_ID, ACVALIDATOR_TESTUSER_PASSWORD);

boolean isSystemUser = !userManager.getAuthorizable(authorizableID).isGroup();
if (isSystemUser) {
testUserResolver = serviceResourceResolverService.getSystemUserResourceResolver(authorizableID);
authorizableToTest = userManager.getAuthorizable(authorizableID);
} else {
testuser = userManager.createUser(ACVALIDATOR_TESTUSER_ID, ACVALIDATOR_TESTUSER_PASSWORD);
authorizableToTest = getTestGroup(getUserManager(serviceResourcerResolver), authorizableID, testuser);

// we need to persist the created testuser in order to be able to get a resolver for him
serviceResourcerResolver.commit();
LOG.debug("comitting serviceResourcerResolver to persist testuser");
// create ResourceResolver for the testuser based on his permissions
testUserResolver = serviceResourceResolverService.getTestUserResourceResolver(ACVALIDATOR_TESTUSER_ID, ACVALIDATOR_TESTUSER_PASSWORD);
}
// execute all testcases for the testuser
for(Testable testable: acTestCase){
resultList.add(testable.isOk(serviceResourcerResolver, testUserResolver, testGroup));
resultList.add(testable.isOk(serviceResourcerResolver, testUserResolver, authorizableToTest));
}
} catch (PersistenceException e) {
throw new RepositoryException(e);
}finally{
// clean up temporary testuser
if(testGroup != null && testuser != null){
testGroup.removeMember(testuser);
if(authorizableToTest != null && authorizableToTest instanceof Group && testuser != null){
((Group)authorizableToTest).removeMember(testuser);
}
if(testuser != null){
testuser.remove();
}

// close resolvers

if(testUserResolver != null){
testUserResolver.revert();
testUserResolver.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,7 @@ public interface ServiceResourceResolverService {

ResourceResolver getTestUserResourceResolver(String username, String password) throws LoginException;


ResourceResolver getSystemUserResourceResolver(String authorizableID);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/
package biz.netcentric.aem.tools.acvalidator.serviceuser;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -35,9 +36,9 @@ public class ServiceResourceResolverServiceImpl implements ServiceResourceResolv

@Reference
ResourceResolverFactory resourceResolverFactory;

@Reference
SlingRepository repository;
SlingRepository repository;

@Override
public ResourceResolver getServiceResourceResolver() throws LoginException {
Expand All @@ -51,13 +52,37 @@ public Session getUserSession(SimpleCredentials credentials) throws javax.jcr.Lo
javax.jcr.Session session = repository.login(credentials);
return session;
}

@Override
public ResourceResolver getTestUserResourceResolver(String username, String password) throws LoginException {
final Map<String, Object> authenticationInfo = new HashMap<>();
authenticationInfo.put(ResourceResolverFactory.USER, username);
authenticationInfo.put(ResourceResolverFactory.PASSWORD, password.toCharArray());
authenticationInfo.put(ResourceResolverFactory.PASSWORD, password.toCharArray());
return resourceResolverFactory.getResourceResolver(authenticationInfo);
}

@Override
public ResourceResolver getSystemUserResourceResolver(String authorizableID) {
ResourceResolver adminResolver = null;
Session systemUserSession = null;
try {
try {
adminResolver = resourceResolverFactory.getAdministrativeResourceResolver(null);
Session adminSession = adminResolver.adaptTo(Session.class);
if(adminSession == null) {
throw new IllegalStateException("Could not adapt ResourceResolver to Session!");
}
systemUserSession = adminSession.impersonate(new SimpleCredentials(authorizableID, new char[0]));
return resourceResolverFactory.getResourceResolver(Collections.singletonMap("user.jcr.session", (Object) systemUserSession));
} catch (RepositoryException | LoginException e) {
throw new IllegalStateException(e);
}
} finally {
if(adminResolver != null) {
adminResolver.close();
}
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
whitelist.name="accesscontrolvalidator"
whitelist.bundles=[ "biz.netcentric.aem.tools.accesscontrolvalidator.bundle" ]
6 changes: 3 additions & 3 deletions docs/testfiles.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Overall structure a of an AC test definition file

Every testfile comprises one or more variables section(s) (optional) and a „tests“ section. Inside, there can be testcases for one or more groups. Inside a group block a group for wich tescases should be executed gets defined by the respective groupID. Inside each group block, there can be page related testcases inside a „pages“ block and user/group related testcases inside a „useradmin“ block.
Every testfile comprises one or more variables section(s) (optional) and a „tests“ section. Inside, there can be testcases for one or more groups/systemuser. A group/systemuser for wich testcases should be executed gets defined by the respective ID. Inside each block, there can be page related testcases inside a „pages“ block and user/group related testcases inside a „useradmin“ block.

So here’s the overall structure:
```
Expand All @@ -12,13 +12,13 @@ So here’s the overall structure:

- tests:

- group1:
- group/systemuser 1:
- pages:
(testcases)
- useradmin:
(testcases)

- group n:
- group/systemuser n:
...
```

Expand Down