Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.slf4j.LoggerFactory;

import biz.netcentric.cq.tools.actool.aem.AcToolCqActions;
import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration;
import biz.netcentric.cq.tools.actool.configmodel.AceBean;
import biz.netcentric.cq.tools.actool.helper.AccessControlUtils;
import biz.netcentric.cq.tools.actool.helper.RestrictionsHolder;
Expand All @@ -58,7 +59,7 @@ public class AceBeanInstallerClassic extends BaseAceBeanInstaller implements Ace
*
* @throws RepositoryException */
protected void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<String> principalsToRemoveAcesFor, Session session,
InstallationLogger installLog) throws RepositoryException {
InstallationLogger installLog, AcConfiguration acConfiguration) throws RepositoryException {

// Remove all config contained authorizables from ACL of this path
int countRemoved = AccessControlUtils.deleteAllEntriesForPrincipalsFromACL(session,
Expand All @@ -72,7 +73,7 @@ protected void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<St
LOG.debug("Writing bean to repository {}", bean);

Principal currentPrincipal = new SimpleNamePrincipal(bean.getPrincipalName());
installAce(bean, session, currentPrincipal, installLog);
installAce(bean, session, currentPrincipal, installLog, acConfiguration);

}

Expand All @@ -84,7 +85,7 @@ protected void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<St
*
* @throws NoSuchMethodException */
private void installAce(AceBean aceBean, final Session session, Principal principal,
InstallationLogger installLog) throws RepositoryException {
InstallationLogger installLog, AcConfiguration acConfiguration) throws RepositoryException {

if (aceBean.isInitialContentOnlyConfig()) {
return;
Expand All @@ -99,7 +100,7 @@ private void installAce(AceBean aceBean, final Session session, Principal princi
}

// first install actions
final JackrabbitAccessControlList newAcl = installActions(aceBean, principal, acl, session, acMgr, installLog);
final JackrabbitAccessControlList newAcl = installActions(aceBean, principal, acl, session, acMgr, installLog, acConfiguration);
if (acl != newAcl) {
installLog.addVerboseMessage(LOG, "Added action(s) for path: " + aceBean.getJcrPath()
+ ", principal: " + principal.getName() + ", actions: "
Expand All @@ -109,7 +110,7 @@ private void installAce(AceBean aceBean, final Session session, Principal princi
}

// then install (remaining) privileges
if (installPrivileges(aceBean, principal, acl, session, acMgr)) {
if (installPrivileges(aceBean, principal, acl, session, acMgr, acConfiguration)) {
installLog.addVerboseMessage(LOG, "Added privilege(s) for path: " + aceBean.getJcrPath()
+ ", principal: " + principal.getName() + ", privileges: "
+ aceBean.getPrivilegesString() + ", allow: " + aceBean.isAllow());
Expand All @@ -130,7 +131,7 @@ private void installAce(AceBean aceBean, final Session session, Principal princi
* AccessControlList (comprising the entres being installed for the actions).
* @throws RepositoryException */
private JackrabbitAccessControlList installActions(AceBean aceBean, Principal principal, JackrabbitAccessControlList acl,
Session session, AccessControlManager acMgr, InstallationLogger installLog) throws RepositoryException {
Session session, AccessControlManager acMgr, InstallationLogger installLog, AcConfiguration acConfiguration) throws RepositoryException {
final Map<String, Boolean> actionMap = aceBean.getActionMap();
if (actionMap.isEmpty()) {
return acl;
Expand All @@ -139,8 +140,22 @@ private JackrabbitAccessControlList installActions(AceBean aceBean, Principal pr
AcToolCqActions cqActions = new AcToolCqActions(session);
Collection<String> inheritedAllows = cqActions.getAllowedActions(
aceBean.getJcrPathForPolicyApi(), Collections.singleton(principal));
// this does always install new entries
cqActions.installActions(aceBean.getJcrPathForPolicyApi(), principal, actionMap, inheritedAllows);

boolean ignoreMissingPrincipals = acConfiguration.getGlobalConfiguration().getIgnoreMissingPrincipals() != null
&& acConfiguration.getGlobalConfiguration().getIgnoreMissingPrincipals().booleanValue();

try {
// this does always install new entries
cqActions.installActions(aceBean.getJcrPathForPolicyApi(), principal, actionMap, inheritedAllows);
} catch (Exception e) {
if (ignoreMissingPrincipals && isPrincipalNotFoundException(e)) {
LOG.warn("Ignoring missing principal '{}' for actions on path '{}' due to ignoreMissingPrincipals=true",
principal.getName(), aceBean.getJcrPath());
return acl; // return original ACL unchanged
} else {
throw e;
}
}

// since the aclist has been modified, retrieve it again
final JackrabbitAccessControlList newAcl = AccessControlUtils.getAccessControlList(session, aceBean.getJcrPath());
Expand Down Expand Up @@ -250,5 +265,16 @@ private void extendExistingAceWithRestrictions(JackrabbitAccessControlList acces
// 3. remove old entry
accessControlList.removeAccessControlEntry(accessControlEntry);
}

private boolean isPrincipalNotFoundException(Exception e) {
// Check for various forms of principal not found exceptions
String message = e.getMessage();
return message != null && (
message.toLowerCase().contains("principal") &&
(message.toLowerCase().contains("not found") ||
message.toLowerCase().contains("does not exist") ||
message.toLowerCase().contains("unknown"))
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.slf4j.LoggerFactory;

import biz.netcentric.cq.tools.actool.aem.AcToolCqActions;
import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration;
import biz.netcentric.cq.tools.actool.configmodel.AceBean;
import biz.netcentric.cq.tools.actool.configmodel.Restriction;
import biz.netcentric.cq.tools.actool.helper.AcHelper;
Expand All @@ -69,7 +70,7 @@ public class AceBeanInstallerIncremental extends BaseAceBeanInstaller implements
*
* @throws RepositoryException */
protected void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<String> principalsInConfiguration, Session session,
InstallationLogger installLog) throws RepositoryException {
InstallationLogger installLog, AcConfiguration acConfiguration) throws RepositoryException {

boolean hadPendingChanges = session.hasPendingChanges();

Expand Down Expand Up @@ -146,7 +147,7 @@ protected void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<St
for (int i = currentPositionConfig; i < configuredAceEntries.size(); i++) {
AceBean aceBeanToAppend = configuredAceEntries.get(i);

installPrivileges(aceBeanToAppend, new SimpleNamePrincipal(aceBeanToAppend.getPrincipalName()), acl, session, acMgr);
installPrivileges(aceBeanToAppend, new SimpleNamePrincipal(aceBeanToAppend.getPrincipalName()), acl, session, acMgr, acConfiguration);
diffLog.append(" APPENDED (from Config) " + toAceCompareString(aceBeanToAppend, acMgr) + "\n");

countAdded++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void installPathBasedACEs(
Set<String> principalsToRemoveAcesForAtThisPath = acConfiguration.getAuthorizablesConfig()
.removeUnmanagedPrincipalNamesAtPath(path, principalsToRemoveAcesFor,
acConfiguration.getGlobalConfiguration().getDefaultUnmanagedAcePathsRegex());
installAcl(orderedAceBeanSetFromConfig, path, principalsToRemoveAcesForAtThisPath, session, history);
installAcl(orderedAceBeanSetFromConfig, path, principalsToRemoveAcesForAtThisPath, session, history, acConfiguration);

}

Expand Down Expand Up @@ -134,28 +134,53 @@ private Set<String> filterReadOnlyPaths(Set<String> paths, InstallationLogger hi
*
* @throws RepositoryException */
protected abstract void installAcl(Set<AceBean> aceBeanSetFromConfig, String path, Set<String> authorizablesToRemoveAcesFor,
Session session, InstallationLogger history) throws RepositoryException;
Session session, InstallationLogger history, AcConfiguration acConfiguration) throws RepositoryException;


protected boolean installPrivileges(AceBean aceBean, Principal principal, JackrabbitAccessControlList acl, Session session,
AccessControlManager acMgr)
AccessControlManager acMgr, AcConfiguration acConfiguration)
throws RepositoryException {

final Set<Privilege> privileges = getPrivilegeSet(aceBean.getPrivileges(), acMgr);
if (!privileges.isEmpty()) {
final RestrictionsHolder restrictions = getRestrictions(aceBean, session, acl);
if (!restrictions.isEmpty()) {
acl.addEntry(principal, privileges
.toArray(new Privilege[privileges.size()]), aceBean.isAllow(),
restrictions.getSingleValuedRestrictionsMap(), restrictions.getMultiValuedRestrictionsMap());
} else {
acl.addEntry(principal, privileges
.toArray(new Privilege[privileges.size()]), aceBean.isAllow());

boolean ignoreMissingPrincipals = acConfiguration.getGlobalConfiguration().getIgnoreMissingPrincipals() != null
&& acConfiguration.getGlobalConfiguration().getIgnoreMissingPrincipals().booleanValue();

try {
if (!restrictions.isEmpty()) {
acl.addEntry(principal, privileges
.toArray(new Privilege[privileges.size()]), aceBean.isAllow(),
restrictions.getSingleValuedRestrictionsMap(), restrictions.getMultiValuedRestrictionsMap());
} else {
acl.addEntry(principal, privileges
.toArray(new Privilege[privileges.size()]), aceBean.isAllow());
}
return true;
} catch (Exception e) {
if (ignoreMissingPrincipals && isPrincipalNotFoundException(e)) {
LOG.warn("Ignoring missing principal '{}' for path '{}' due to ignoreMissingPrincipals=true",
principal.getName(), aceBean.getJcrPath());
return false;
} else {
throw e;
}
}
return true;
}
return false;
}

private boolean isPrincipalNotFoundException(Exception e) {
// Check for various forms of principal not found exceptions
String message = e.getMessage();
return message != null && (
message.toLowerCase().contains("principal") &&
(message.toLowerCase().contains("not found") ||
message.toLowerCase().contains("does not exist") ||
message.toLowerCase().contains("unknown"))
);
}

/** Creates a RestrictionHolder object containing 2 restriction maps being used in
* {@link JackrabbitAccessControlList#addEntry(Principal, Privilege[], boolean, Map, Map)} out of the set actions on this bean.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class GlobalConfiguration {
public static final String KEY_ALLOW_EXTERNAL_GROUPS_IN_IS_MEMBER_OF = "allowExternalGroupsInIsMemberOf";

public static final String KEY_AUTOCREATE_TEST_USERS = "autoCreateTestUsers";

public static final String KEY_IGNORE_MISSING_PRINCIPALS = "ignoreMissingPrincipals";

@Deprecated
public static final String KEY_KEEP_EXISTING_MEMBERSHIPS_FOR_GROUP_NAMES_REGEX = "keepExistingMembershipsForGroupNamesRegEx";
Expand All @@ -51,6 +53,8 @@ public class GlobalConfiguration {
private Boolean allowCreateOfUnmanagedRelationships = null;

private Boolean allowExternalGroupsInIsMemberOf = null;

private Boolean ignoreMissingPrincipals = null;

private AutoCreateTestUsersConfig autoCreateTestUsersConfig;

Expand Down Expand Up @@ -102,6 +106,10 @@ public GlobalConfiguration(Map<String, ?> globalConfigMap) {
setAllowExternalGroupsInIsMemberOf(Boolean.valueOf(globalConfigMap.get(KEY_ALLOW_EXTERNAL_GROUPS_IN_IS_MEMBER_OF).toString()));
}

if (globalConfigMap.containsKey(KEY_IGNORE_MISSING_PRINCIPALS)) {
setIgnoreMissingPrincipals(Boolean.valueOf(globalConfigMap.get(KEY_IGNORE_MISSING_PRINCIPALS).toString()));
}

}

}
Expand Down Expand Up @@ -169,6 +177,14 @@ public void merge(GlobalConfiguration otherGlobalConfig) {
}
}

if (otherGlobalConfig.getIgnoreMissingPrincipals() != null) {
if (ignoreMissingPrincipals == null) {
ignoreMissingPrincipals = otherGlobalConfig.getIgnoreMissingPrincipals();
} else {
throw new IllegalArgumentException("Duplicate config for " + KEY_IGNORE_MISSING_PRINCIPALS);
}
}

}

public String getMinRequiredVersion() {
Expand Down Expand Up @@ -235,5 +251,13 @@ public Boolean getAllowExternalGroupsInIsMemberOf() {
public void setAllowExternalGroupsInIsMemberOf(Boolean allowExternalGroupsInIsMemberOf) {
this.allowExternalGroupsInIsMemberOf = allowExternalGroupsInIsMemberOf;
}

public Boolean getIgnoreMissingPrincipals() {
return ignoreMissingPrincipals;
}

public void setIgnoreMissingPrincipals(Boolean ignoreMissingPrincipals) {
this.ignoreMissingPrincipals = ignoreMissingPrincipals;
}

}
Loading