Application Development, Product to Market
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use
  • Home
  • Notes
  • Projects
  • Resources
    • Discovery Log
    • Books I Read
    • Blogs I Visit
    • Tools I Use

Copy Users, Groups, Permissions (ACLs) between Adobe CQ Instances

8/15/2013

11 Comments

 
It is common to have multiple CQ Publisher instances in different environments (DEV, QA, PROD, etc.). When you make user administration and security changes toward users and groups on the production server, you may want to bring them down to the lower DEV and QA environments so they don't go out of sync. In such scenario, you have to copy over both user/group definition and the permission definition. This post shows you how to copy users and groups you set up on one CQ instance (source CQ) to another instance (destination CQ), and how to bring over the permissions (resource-based ACLs) from the source CQ to the destination CQ.

copy users and groups definition

To copy over users and groups definition from one CQ to another,  we'd take the approach of packaging users/groups definition up into a package, then install the package to the destination CQ. We simply use CQ's package capability to package up everything under /home which hold users/groups definition into a package with AC Handling set to 'overwrite.' The 'overwrite' access control tells JcrPackageDefinition to overwrite the ACLs in the destination CQ upon installing a package. When copy over users/groups definition via package installation, we wan the underlying ACLs also be copied over (overwritten).

To create such package, go on to the source CQ to create a package with the following package named UsersGroups.zip with filter and AC Handling: 
Picture
Picture
Then, move on to the destination CQ side, install the above created UsersGroups.zip package. The 'overwrite' AC Handling will tell the package importer to overwrite ACL's upon installation. The installation process of the package will complete in a minute but the front-end javascript will hang for unknown reason (may be related to the ACLs?) until you use another window to log yourself (admin user) back in. When you're back in, check out User Admin console on the destination CQ instance (e.g., at http://<host>:4502/useradmin) to make sure now the console reflects what's there on the source CQ.

copy permissions (ACLs) pertaining to all nodes

Policies that control how users and groups can access resources are saved in ACL nodes:
Resource-based ACLs are stored per resource/node in a special child rep:policy node. This one will have a list of rep:GrantACE child nodes (usually named allow, allow0,...) for grant access control entries and rep:DenyACE child nodes (usually named deny, deny0,...) for deny access control entries.

Each ACE node has a rep:principalName STRING property pointing to the user or group this ACE belongs to, and a rep:privileges NAME multi-value property, containing all the privileges of this ACE.

- How Resource-based ACLs are stored, Jackrabbit Wiki - Access Control/Authorization
Picture
Picture
These ACLs that contains ACEs are all over the places under content nodes. Unfortunately, the out-of-the-box package builder does not support to extract these nodes out, we can use a 'create-package' tool developed by Yogesh Upadhyay to create a package based on XPath to extract ACL nodes :
  1. Download create_package-4.zip package written by Yogesh Upadhyay.
  2. Manually install create_package-4.zip package to your source CQ.
  3. Go on access the source CQ: <host>:<port>/apps/tools/components/createPackage/run.html
  4. Create a package named ACLDump with all nodes of rep:ACL type, select AC handling behavior of 'overwrite' to assure the ACLs are overwritten upon installing the package.
Picture
Picture
Lastly, on the destination CQ instance, install ACLDump.zip package to overwrite all ACL permissions on the destination CQ. Installation should complete in a minute or two but the front-end javascript will hang until you use another window to log back in.
Picture
Congratulations, you've just completed copying over users, groups, and security policies from one CQ to another.

code walkthrough

The following code snippets are extracted from the POST.jsp file of createPackage by yogi1306 on sourceforge. In his code, he uses JcrPackageManager to create a package of matched resources for download.
<%@include file="/libs/foundation/global.jsp"%>       // 1

...

<%
Session sess = resourceResolver.adaptTo(Session.class);
BundleContext bundleContext = sling.getService(BundleContext.class);

...

Iterator<Resource> iter = resourceResolver.findResources(path+xpath,"xpath"); // 2
JcrPackageManager packMgr = PackagingService.getPackageManager(sess); // 3

// check if package already exists
String packPath = pkgGroupName + "/" + packageName + ".zip";
Node packages = packMgr.getPackageRoot();
if (packages.hasNode(packPath)) {
  packages.getNode(packPath).remove();
  packages.getSession().save();
}
JcrPackage pack = packMgr.create(pkgGroupName,packageName,null);
//packMgr.ensureVersion(pack);
DefaultWorkspaceFilter filters = new DefaultWorkspaceFilter();
out.println("<br> Adding following filter path <br> ");
while(iter.hasNext()){
   Resource curRes = iter.next();
  
   //Don't include exlude path in the filter.
   if(!isExclude(curRes.getPath(),excludePath)){
     out.println("<br><font color=red>"+curRes.getPath()+"</font>");
      filters.add(new PathFilterSet(curRes.getPath()));    // 4
     
   }
}
JcrPackageDefinition jcrPackageDefinition = pack.getDefinition();
jcrPackageDefinition.setFilter(filters, true);
jcrPackageDefinition.set("acHandling",acHandling,false);

packMgr.assemble(pack, null);                              // 5
String serverName = (request.getProtocol().split("/")[0]).toLowerCase()+"://"+request.getServerName();
if(!"".equals(request.getServerPort())){
  serverName+=":"+request.getServerPort();
}

String docroot = serverName +"/crx/packmgr/service.jsp";
out.println("<br><br><strong>Package Creation Done with name "+ packageName +"</strong>");
%>


<%!
boolean isExclude(String path,String exludePath){
  if("".equals(exludePath) || null==exludePath){
    return false;
  }else{
    String[] allExcludePath = exludePath.split(",");
    for(String eachPath:allExcludePath){
      if(path.startsWith(eachPath)){
        return true;
      }
    }
  }
  return false;  
}

%>
<form method="get" action="<%=docroot %>">                // 6
<input name="cmd" id="cmd" value="get"></input>
<input name="name" id="name" value="<%=Text.escape(packageName) %>"></input>
<input name="group" id="group" value="<%=Text.escape(pkgGroupName) %>"></input>
<input value="Download Package"></input>
</form>
</body>
</html>
[1] declares the sling, cq and jstl taglibs and exposes the regularly used scripting objects (e.g. resourceResolver) defined by the <cq:defineObjects /> tag.
[2] Searches for resources using the given query (e.g. /jcr:root//element(*,rep:ACL)) formulated in "jcr xpath" language.
[3] Returns a repository-based package manager.
[4] Add matched resources to be packaged up to the filter of the package definition.
[5] Assemble a package based on its definition. Generate the package under repository's default location (/etc/packages/<package-group>/), which is available for download through CQ Package Manager.
[6] A button to download the package available in the CQ Package Manager.


references

  • User Administration and Security
  • User, Group and Access Rights Administration
  • Jackrabbit Wiki - Access Control / Authorization
  • Creating packages based on query parameters
  • How to create package based on Xpath in CQ5 / WEM
  • Querying and Searching using JCR

11 Comments
Ravi KS
11/21/2013 01:43:19 pm

Excellent tools. It works fine without any errors :)

Reply
Chetan
7/13/2015 05:23:58 am

Hi,

I am getting below error when trying to run the tool in CQ 5.5 SP2; any inputs would be appreciated.

An exception occurred processing JSP page /apps/tools/components/createPackage/POST.jsp at line 96

Cannot serve request to /apps/tools/components/createPackage/run.html on this server

Reply
Sunil Kumar Singh
11/8/2015 11:23:32 pm

I was trying to migrate users and permission from AEM6.0 to AEM6.1. While running the package I am getting the blank screen. Does this package require some changes to perform the same in AEM 6.0.

Reply
Hsufeng
11/9/2015 01:48:43 am

This tool was never tested on the new AEM6. If you ever successfully make this work for AEM6.0 in the future, please share your experience. Thanks!

Reply
Kevin Bell
11/17/2015 01:44:28 pm

It worked great on 5.6.1 sp2 with one exception, it did not bring in the properties; First Name, Last Name and email address. Is there a way to capture those as well?

Reply
shekhar
3/8/2016 10:30:07 am

how do I add filters??? I just do not want to export all the users and permissions. I just want to export our own company users,permissions.. I have created 'abc' node of type authorizableFolder in groups and users, and I have included groups and users of mine. How do i extract only my users and permissions. Could you please

Reply
shekhar
3/8/2016 10:57:56 am

Component that threw Exception: /apps/tools/components/createPackage/POST.jsp

Exception:

org.apache.sling.scripting.jsp.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 51 in the generated java file
Only a type can be imported. com.day.cq.packaging.CQPackageManager resolves to a package

An error occurred at line: 78 in the jsp file: /apps/tools/components/createPackage/POST.jsp
CQPackageManager cannot be resolved to a type
75: packages.getNode(packPath).remove();
76: packages.getSession().save();
77: }
78: CQPackageManager pckgManager = sling.getService(CQPackageManager.class);
79: JcrPackage pack = pckgManager.createPackage(sess,pkgGroupName,packageName);
80: pckgManager.ensureVersion(pack);
81: DefaultWorkspaceFilter filters = new DefaultWorkspaceFilter();


An error occurred at line: 78 in the jsp file: /apps/tools/components/createPackage/POST.jsp
CQPackageManager cannot be resolved to a type
75: packages.getNode(packPath).remove();
76: packages.getSession().save();
77: }
78: CQPackageManager pckgManager = sling.getService(CQPackageManager.class);
79: JcrPackage pack = pckgManager.createPackage(sess,pkgGroupName,packageName);
80: pckgManager.ensureVersion(pack);
81: DefaultWorkspaceFilter filters = new DefaultWorkspaceFilter();

at org.apache.sling.scripting.jsp.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)
at org.apache.sling.scripting.jsp.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330)
at org.apache.sling.scripting.jsp.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:136)
at org.apache.sling.scripting.jsp.jasper.compiler.Compiler.compile(Compiler.java:312)
at org.apache.sling.scripting.jsp.jasper.compiler.Compiler.compile(Compiler.java:290)
at org.apache.sling.scripting.jsp.jasper.compiler.Compiler.compile(Compiler.java:277)

Reply
Samer link
3/10/2016 03:03:08 pm

I was using this tool in AEM 6.1 and it is not working throwing exception. If anyone used it in AEM 6.1 then please share the setting/configuration what is required

Thanks
Samer

Reply
Samer link
3/10/2016 03:08:25 pm

I disable the POST entry temporary and able to execute it. Now it is working perfectly. it is nice tool

Thank
Samer

Reply
Sunag
3/14/2016 03:38:50 am

Hi Samer,

How did you disable POST entry? . Even i am also facing same issue. Getting error when creating ACL.

Regards,
Sunag

Stacy Morley link
11/22/2020 06:10:28 pm

Great read

Reply



Leave a Reply.

    Categories

    All
    Algorithm
    Concurrency
    CQ
    Data Structure
    Design Pattern
    Developer Tool
    Dynamic Programming
    Entrepreneur
    Functional Programming
    IDE
    Java
    JMX
    Marketing
    Marklogic
    Memory
    OSGI
    Performance
    Product
    Product Management
    Security
    Services
    Sling
    Social Media Programming
    Software Development

    Feed Widget

    Archives

    May 2020
    March 2020
    April 2018
    March 2018
    February 2018
    December 2017
    March 2017
    November 2016
    June 2016
    May 2016
    April 2016
    October 2015
    September 2015
    August 2015
    September 2014
    July 2014
    June 2014
    May 2014
    March 2014
    January 2014
    December 2013
    November 2013
    October 2013
    September 2013
    August 2013
    July 2013
    June 2013

    RSS Feed

in loving memory of my mother  and my 4th aunt
Photos used under Creative Commons from net_efekt, schani, visnup, Dan Zen, gadl, bobbigmac, Susana López-Urrutia, jwalsh, Philippe Put, michael pollak, oskay, Creative Tools, Violentz, Kyknoord, mobilyazilar