Skip to content

Commit 2a82cb8

Browse files
committed
Merge branch 'release/1.7.0'
2 parents 03e8ee1 + d9a902c commit 2a82cb8

File tree

18 files changed

+480
-128
lines changed

18 files changed

+480
-128
lines changed

README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ Overall format
5454
- isMemberOf: comma separated list of other groups
5555
- members: comma separated list of groups that are member of this group
5656
- description: (optional, description)
57-
- path: ?
57+
- path: (optional, path of the group in JCR)
58+
- migrateFrom: (optional, a group name assigned member users are taken over from, available from v1.7)
5859
```
5960

6061
Example
@@ -69,6 +70,8 @@ If the isMemberOf property of a group contains a group which is not yet installe
6970

7071
The members property contains a list of groups where this group is added as isMemberOf.
7172

73+
The property 'migrateFrom' allows to migrate a group name without loosing their members (members of the group given in migrateFrom are taken over and the source=old group deleted afterwards). This property is only to be used temporarily (usually only included in one released version that travels all environments, once all groups are migrated the config should be removed). If not set (the default) nothing happens. If the property points to a group that does not exist (anymore), the property is ignored.
74+
7275
## Configuration of users
7376

7477
In general it is best practice to not generate regular users by the AC Tool but use other mechanism (e.g. LDAP) to create users. However, it can be useful to create system users (e.g. for replication agents or OSGi service authentiation) or test users on staging environments.
@@ -84,13 +87,14 @@ Users can be configured in the same way as groups in the **user_config** section
8487

8588
The configurations are done per principal followed by indented informations which comprise of config data which represents the settings per ACE. This data includes
8689

87-
property | comment | optional
90+
property | comment | required
8891
--- | --- | ---
89-
path | a node path. Wildcards `*` are possible. e.g. assuming we have the language trees de and en then `/content/*./test` would match: `/content/de/test` and `/content/en/test` (mandatory). If an asterisk is contained then the path has to be written inside single quotes (`'...'`) since this symbol is a functional character in YAML. | no
90-
permission | the permission (either `allow` or `deny`) | no
91-
actions | the actions (`read,modify,create,delete,acl_read,acl_edit,replicate`). Reference: <http://docs.adobe.com/docs/en/cq/current/administering/security.html#Actions> | no, either actions or privileges; also a mix of both is possible
92-
privileges | the privileges (`jcr:read, rep:write, jcr:all, crx:replicate, jcr:addChildNodes, jcr:lifecycleManagement, jcr:lockManagement, jcr:modifyAccessControl, jcr:modifyProperties, jcr:namespaceManagement, jcr:nodeTypeDefinitionManagement, jcr:nodeTypeManagement, jcr:readAccessControl, jcr:removeChildNodes, jcr:removeNode, jcr:retentionManagement, jcr:versionManagement, jcr:workspaceManagement, jcr:write, rep:privilegeManagement`). References: <http://jackrabbit.apache.org/oak/docs/security/privilege.html> <http://www.day.com/specs/jcr/2.0/16_Access_Control_Management.html#16.2.3%20Standard%20Privileges> | no
93-
repGlob |a repGlob expression | yes
92+
path | a node path. Wildcards `*` are possible. e.g. assuming we have the language trees de and en then `/content/*./test` would match: `/content/de/test` and `/content/en/test` (mandatory). If an asterisk is contained then the path has to be written inside single quotes (`'...'`) since this symbol is a functional character in YAML. | yes
93+
permission | the permission (either `allow` or `deny`) | yes
94+
actions | the actions (`read,modify,create,delete,acl_read,acl_edit,replicate`). Reference: <http://docs.adobe.com/docs/en/cq/current/administering/security.html#Actions> | either actions or privileges need to be present; also a mix of both is possible
95+
privileges | the privileges (`jcr:read, rep:write, jcr:all, crx:replicate, jcr:addChildNodes, jcr:lifecycleManagement, jcr:lockManagement, jcr:modifyAccessControl, jcr:modifyProperties, jcr:namespaceManagement, jcr:nodeTypeDefinitionManagement, jcr:nodeTypeManagement, jcr:readAccessControl, jcr:removeChildNodes, jcr:removeNode, jcr:retentionManagement, jcr:versionManagement, jcr:workspaceManagement, jcr:write, rep:privilegeManagement`). References: <http://jackrabbit.apache.org/oak/docs/security/privilege.html> <http://www.day.com/specs/jcr/2.0/16_Access_Control_Management.html#16.2.3%20Standard%20Privileges> | either actions or privileges need to be present; also a mix of both is possible
96+
repGlob |a repGlob expression | no
97+
initialContent | Allows to specify docview xml to create the path if it does not exist. The namespaces for jcr, sling and cq are added automatically if not provided to keep xml short. Initial content must only be specified exactly once per path (this is validated). If paths without permissions should be created, it is possible to provide only a path/initialContent tuple. Available form version 1.7.0. | no
9498

9599
Every new data entry starts with a "-".
96100

@@ -102,8 +106,9 @@ Overall format
102106
- path: a valid node path in CRX
103107
permission: [allow/deny]
104108
actions: actions string
105-
privileges: privileges string (optional)
106-
repGlob: regex (optional, path restriction as regular expression)
109+
privileges: privileges string
110+
repGlob: regex (optional, path restriction as regular expression)
111+
initialContent: <jcr:root jcr:primaryType="sling:Folder"> (optional)
107112
```
108113

109114
Only ACEs for groups which are defined in the same configuration file can be installed! This ensures a consistency between the groups and their ACE definitions per configuration file.

accesscontroltool-bundle/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<parent>
1212
<groupId>biz.netcentric.cq.tools.accesscontroltool</groupId>
1313
<artifactId>accesscontroltool</artifactId>
14-
<version>1.6.2</version>
14+
<version>1.7.0</version>
1515
</parent>
1616

1717
<!-- ====================================================================== -->

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceservice/impl/AceServiceImpl.java

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import java.util.ArrayList;
1212
import java.util.Arrays;
13+
import java.util.Collection;
1314
import java.util.HashSet;
1415
import java.util.LinkedHashSet;
1516
import java.util.List;
@@ -22,6 +23,8 @@
2223
import javax.jcr.UnsupportedRepositoryOperationException;
2324
import javax.jcr.ValueFormatException;
2425

26+
import org.apache.commons.collections.CollectionUtils;
27+
import org.apache.commons.lang.StringUtils;
2528
import org.apache.commons.lang.time.StopWatch;
2629
import org.apache.felix.scr.annotations.Activate;
2730
import org.apache.felix.scr.annotations.Component;
@@ -120,17 +123,49 @@ private void installConfigurationFromYamlList(
120123
LOG.error(message);
121124
throw new IllegalArgumentException(message);
122125
}
123-
removeAcesForAuthorizable(history, session, authorizablesMapfromConfig.keySet(), repositoryDumpAceMap);
126+
127+
Set<String> authorizablesToRemoveAcesFor = getAuthorizablesToRemoveAcesFor(authorizablesMapfromConfig);
128+
129+
removeAcesForAuthorizables(history, session, authorizablesToRemoveAcesFor, repositoryDumpAceMap);
124130
installAuthorizables(history, authorizableHistorySet, authorizablesMapfromConfig);
125131
installAces(history, session, aceMapFromConfig);
126132
}
127-
128-
private void removeAcesForAuthorizable(AcInstallationHistoryPojo history, Session session, Set<String> authorizablesSet, Map<String, Set<AceBean>> repositoryDumpAceMap) throws UnsupportedRepositoryOperationException, RepositoryException {
129-
// loop through all ACLs found in the repository
133+
134+
private Set<String> getAuthorizablesToRemoveAcesFor(Map<String, LinkedHashSet<AuthorizableConfigBean>> authorizablesMapfromConfig) {
135+
Set<String> authorizablesToRemoveAcesFor = new HashSet<String>(authorizablesMapfromConfig.keySet());
136+
Set<String> authorizablesToBeMigrated = collectAuthorizablesToBeMigrated(authorizablesMapfromConfig);
137+
Collection<?> invalidAuthorizablesInConfig = CollectionUtils.intersection(authorizablesToRemoveAcesFor, authorizablesToBeMigrated);
138+
if (!invalidAuthorizablesInConfig.isEmpty()) {
139+
String message = "If migrateFrom feature is used, groups that shall be migrated from must not be present in regular configuration (offending groups: "
140+
+ invalidAuthorizablesInConfig + ")";
141+
LOG.error(message);
142+
throw new IllegalArgumentException(message);
143+
}
144+
authorizablesToRemoveAcesFor.addAll(authorizablesToBeMigrated);
145+
return authorizablesToRemoveAcesFor;
146+
}
147+
148+
private Set<String> collectAuthorizablesToBeMigrated(Map<String, LinkedHashSet<AuthorizableConfigBean>> authorizablesMapfromConfig) {
149+
Set<String> authorizablesToBeMigrated = new HashSet<String>();
150+
for (String principalStr : authorizablesMapfromConfig.keySet()) {
151+
LinkedHashSet<AuthorizableConfigBean> authorizableConfigBeans = authorizablesMapfromConfig.get(principalStr);
152+
for (AuthorizableConfigBean authorizableConfigBean : authorizableConfigBeans) {
153+
String migrateFrom = authorizableConfigBean.getMigrateFrom();
154+
if (StringUtils.isNotBlank(migrateFrom)) {
155+
authorizablesToBeMigrated.add(migrateFrom);
156+
}
157+
}
158+
}
159+
return authorizablesToBeMigrated;
160+
}
161+
162+
private void removeAcesForAuthorizables(AcInstallationHistoryPojo history, Session session, Set<String> authorizablesSet,
163+
Map<String, Set<AceBean>> repositoryDumpAceMap) throws UnsupportedRepositoryOperationException, RepositoryException {
164+
// loop through all ACLs found in the repository
130165
for (Map.Entry<String, Set<AceBean>> entry : repositoryDumpAceMap.entrySet()) {
131166
Set<AceBean> acl = entry.getValue();
132167
for (AceBean aceBean : acl) {
133-
// if the ACL form repo contains an ACE regarding an
168+
// if the ACL from repo contains an ACE regarding an
134169
// authorizable from the groups config then delete all ACEs from
135170
// this authorizable from current ACL
136171
if (authorizablesSet.contains(aceBean.getPrincipalName())) {
@@ -163,7 +198,7 @@ private void installAuthorizables(
163198
AcInstallationHistoryPojo history,
164199
Set<AuthorizableInstallationHistory> authorizableHistorySet,
165200
Map<String, LinkedHashSet<AuthorizableConfigBean>> authorizablesMapfromConfig)
166-
throws RepositoryException, Exception {
201+
throws RepositoryException, Exception {
167202
// --- installation of Authorizables from configuration ---
168203

169204
LOG.info("--- start installation of Authorizable Configuration ---");
@@ -198,7 +233,7 @@ private void installAuthorizables(
198233
}
199234
}
200235

201-
String message = "finished installation of groups configuration without errors!";
236+
String message = "Finished installation of groups configuration without errors";
202237
history.addMessage(message);
203238
LOG.info(message);
204239
}
@@ -256,7 +291,7 @@ public AcInstallationHistoryPojo execute() {
256291
public void installNewConfigurations(Session session,
257292
AcInstallationHistoryPojo history,
258293
Map<String, String> newestConfigurations, Set<AuthorizableInstallationHistory> authorizableInstallationHistorySet)
259-
throws Exception {
294+
throws Exception {
260295

261296
StopWatch sw = new StopWatch();
262297
sw.start();

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceservicejmx/impl/AceServiceMBeanImpl.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,23 @@
1515
import org.apache.commons.lang.time.StopWatch;
1616
import org.apache.felix.scr.annotations.Component;
1717
import org.apache.felix.scr.annotations.Properties;
18+
import org.apache.felix.scr.annotations.Property;
1819
import org.apache.felix.scr.annotations.Reference;
1920
import org.apache.felix.scr.annotations.Service;
20-
import org.apache.felix.scr.annotations.Property;
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
2323

24-
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
25-
2624
import biz.netcentric.cq.tools.actool.aceservice.AceService;
2725
import biz.netcentric.cq.tools.actool.aceservicejmx.AceServiceMBean;
2826
import biz.netcentric.cq.tools.actool.dumpservice.Dumpservice;
2927
import biz.netcentric.cq.tools.actool.installationhistory.AcHistoryService;
3028

29+
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
30+
3131
@Service
3232
@Component(immediate = true)
3333
@Properties({
34-
@Property(name = "jmx.objectname", value = "biz.netcentric.cq.tools.actool:id='ac installation'"),
34+
@Property(name = "jmx.objectname", value = "biz.netcentric.cq.tools:type=ACTool"),
3535
@Property(name = "pattern", value = "/.*") })
3636
public class AceServiceMBeanImpl extends AnnotatedStandardMBean implements
3737
AceServiceMBean {

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableutils/AuthorizableConfigBean.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public class AuthorizableConfigBean implements AcDumpElement {
3232
private String path;
3333
private String password;
3434

35+
private String migrateFrom;
36+
3537
private boolean isGroup = true;
3638
private boolean isSystemUser = false;
3739

@@ -186,6 +188,20 @@ public void setPath(final String path) {
186188
this.path = path;
187189
}
188190

191+
public String getMigrateFrom() {
192+
return migrateFrom;
193+
}
194+
195+
/** Set a group name, from which the users are taken over to this group. The group given is deleted after the run. This property is only
196+
* to be used temporarily (usually only included in one released version that travels all environments, once all groups are migrated the
197+
* config should be removed). If not set (the default) nothing happens. If the property points to a group that does not exist (anymore),
198+
* the property is ignored.
199+
*
200+
* @param migrateFrom */
201+
public void setMigrateFrom(String migrateFrom) {
202+
this.migrateFrom = migrateFrom;
203+
}
204+
189205
@Override
190206
public String toString() {
191207
final StringBuilder sb = new StringBuilder();

0 commit comments

Comments
 (0)