Sunday, December 29, 2019

CryptoSupport in AEM 6.5

Hello Everyone,

While working with AEM, The information related to an API like endpoint,username and
password  used to be maintained in OSGi Configurations.

Sometimes these API’s are really secure and the client don’t want the password to be seen
by anyone. OSGi Configurations are always part of the code.Even in some cases, clients
don’t want to share the password even with developer, they want to use an encryption methodology so that they can share the encrypted code with the developer and the code can be decrypted only at run time and nobody can not know about it.

AEM provides us that kind of cryptosupport which can really make things really confidential
and secure.
  • There is Crypto console in AEM, through which clients can generate the encryption code without even sharing the plain text with the developer.
  • They can just share the encryption key and developer can put it in codebase as OSGi Configuration. There is no console in AEM, from where the encrypted code can be decrypted into plain text.
  • Every instance hmac/master key is different and if the developer knows the encrypted key they can’t get to know the plain text by any way.In other words, the encrypted key will be unique for each and every servers.

So how to use CryptoSupport in AEM?
1.Go to Crypto Support using felix console in AEM and type your password/any sensitive information in plain text field and click on Protect to encrypt this.
2.The code to decrypt the key is below:

CryptoSupport cryptosupport;

Public getDecryptedKey(int encryptedKey)
Now the major concern of using this encryption method come up with production servers. As i mentioned previously that every instance is unique and generate a different encrypted key. But ideally the production server might have two publishers and we can't create configuration based on individual publisher. So the ideal scenario is, we want to use the same key for all authors and publishers belong to one environment.

So ideally all the servers related to one environment irrespective of author/publishers must be sharing the same key.

How to do that?
Before AEM 6.2, you can see the “hmac” and master files directly in AEM CRX, but due to security concerns, these keys have been removed from crx and moved inside the bundle.
1. Go to the author instance and see the bundle id of “Adobe Granite Crypto Bundle Key Provider (com.adobe.granite.crypto.file)”, usually it is bundle No 25 , then go to crx-quickstart/launchpad/felix/bundle25/data. There are two files sitting in data which are hmac and master. Copy the files and replace them with the files sitting in publishing servers under the same path.
2. Restart the AEM server or you can restart the bundle Adobe Granite Crypto Support (com.adobe.granite.crypto). I always prefer restarting the server because it takes lesser time than restarting the Crypto Support Bundle ( this also do a kind of restart for all bundles and takes time).

How to validate the keys:
You can run a command in terminal “md5sum hmac” under the data folder and can help to match the key with all the servers to validate if the same key exists for all the servers.
Note: Initially to validate the keys, I was trying to generate the encrypted code from author and publisher and trying to match them, to validate if they are sharing the same hmac and master files But when you enter the same text on an AEM server and try to generate the encrypted code again and again, the server generates the different encryption code in every attempt. So you need not worry about it, encrypt the plain text once and put in the configurations. AEM will take care of decryption part.

When you put the encrypted key in the OSGI configuration, the encrypted key is always having curly brackets in start and end.
So if you put a config like :

You won’t be able to deploy configuration because curly brackets are always used to mention data type in OSGI Config like {boolean} true,so always mention the data type of config for encrypted keys.

Hope it will help you guys !!
Thanks and Happy Learning.

Thursday, December 12, 2019

AEM Logs in Detail Part-2

Hi everyone,

It’s been quite a long time since I published Part-1 for AEM Logs in Detail.
In the previous blog,I have already discussed all the logs provided by AEM.

But AEM provided logs are not sufficient for us sometimes. We want separate
logs for our application, so that it will be easy to debug our code.So In the blog we will discuss how to create custom loggers in AEM.

2. Go to Apache Sling Logging Logger Configuration.
3. Click on + to Add a new configuration.logging logger.PNG
  • Log level: The log level defines which type of logs you want to have in your custom log file for ex: trace,debug,info,warn,error.
  • Log File:Here you can identify the name of the log file,which needs to be created under the logs folder.
  • Message Pattern:The java.util.MessageFormat pattern to use for formatting log messages with the root logger. This is a java.util.MessageFormat pattern supporting up to six arguments:
    • {0} The timestamp of type java.util.Date,
    • {1} the log marker,
    • {2} the name of the current thread,
    • {3} the name of the logger,
    • {4} the log level and
    • {5} the actual log message.

    If the log call includes a Throwable, the stacktrace is just appended to the message regardless of the pattern.
    The Pattern can be like this: {0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* {2} {3} {5}
  • Logger: Here we define the package name of the application,for which we want to print the logs.You can add multiple packages also.
  • Additivity: If set to false then logs from these loggers would not be sent to any appender attached higher in the hierarchy.
Let's suppose we have one logging configuration for package “com.sgaem.* “and we have created one more logger for “com.sgaem.servlet.TestServlet”, so by default the TestServlet loggers will not get printed in com.sgaem.* logger file but if you enable the additivity then the loggers will go in both log files
4.Go to Apache Sling Logging Writer Configuration.
5.Click on + to Add a new configuration.
  • Log File: Here you define the log file Name for which you want to write a logging writer.
  • Number of Log Files:Here you can define how many logs file you want to maintain for the specific Log File defined above.
  • Log File Threshold: Defines how the log file is rotated (by schedule or by size) and when to rotate.Meaning you can define if you want to rotate the log file on daily,weekly or monthly basis or on the basis of size.

Log File Rotation

Log files can grow rather quickly and fill up available disk space. To cope with this growth log files may be rotated in two ways: At specific times or when the log file reaches a configurable size. The first method is called Scheduled Rotation and is used by specifying a SimpleDateFormat pattern as the log file "size". The second method is called Size Rotation and is used by setting a maximum file size as the log file size.

Scheduled Rotation:The rolling schedule is specified by setting the property to a java.text.SimpleDateFormat pattern. It is possible to specify monthly, weekly, half-daily, daily, hourly, or minutely rollover schedules.Check this section to see available Scheduled Rotation. Do not use the colon ":" character anywhere in the pattern option. The text before the colon is interpreted as the protocol specification of a URL which is probably not what you want.

Size Rotation:Log file rotation by size is specified by setting the property to a plain number or a number plus a size multiplier. The size multiplier may be any of K, KB, M, MB, G, or GB where the case is ignored and the meaning is probably obvious.

Important to Know:

Apache Sling Logging logger Configuration is self sufficient to print the log then the question can come in your mind, what is the need of Apache Sling Logging Writer Configuration.

There is one more configuration in AEM, which is Apache Sling Logging Configuration which can be considered a global configuration for all log files.Here you define a few things like Number of Log Files,Log File Threshold,Message Pattern etc.
If you don’t override your values in your application related Logging Logger and Writer Configuration, it will take the value from Global.So if you don't define writer configuration it will take Number of Log Files and Threshold Message from global configuration.

Conclusion: if you really need any change in the two properties(Number of log files and Threshold Message) defined in the logging Writer then only create a writer configuration else no need.

There are two ways to see the log files in AEM.

1.Go to the felix console ->Sling->Log Support, and search for your log file. You can directly open the log file from here.

2. The logs files also gets created under crx-quickstart/logs. You can open your log files and see the logs.

Demonstration Video of Custom Logger in AEM:
Hope it will help you guys !!
Thanks and Happy Learning.

Sunday, December 8, 2019

href=tel issue for international numbers in AEM RTE

Hello Everyone,

RTE is the most used component in AEM. There are always high expectations from this component, but the RTE component has some issues, which are actually not issues,but those features doesn't come with RTE basic behavior and we need to do something to make it work.

1. Handing Custom Protocols (tel:,callto:,emailto:) in Link Href in Rich Text Editor:

Problem Statement: When you want to use a telephone number as a hyperlink and want to call
on the number by clicking on it, you need to use HTML like <a href="tel:1-847-555-5555">
1-847-555-5555</a>RTE is not able to render the same HTML as added in RTE.

Reason:Adding protocols like tel: (or any custom) in anchor tag href attribute, may not be printed as entered in RTE as link checker and XSS protection com.adobe.granite.xss.impl.HtmlToHtmlContentContext AntiSamy removes unrecognized protocols during component rendering. 

Solution: To resolve this issue:
  1. Overlay /libs/cq/xssprotection/config.xml in /apps/cq/xssprotection/config.xml
  2. Add the protocol say : <regexp name="telURL" value="tel:[0-9]+"/>
  3. Add telURL configuration to the accepted list of anchor href.
  4. <attribute name="href">
      <regexp name="onsiteURL"/>
      <regexp name="offsiteURL"/>
      <regexp name="telURL"/>
  5. Go to “Day CQ Link Checker Service” and add “tel:” in special Link Prefixes”option.
  6. Fig1: Day CQ Link Checker Service
2. Handing International Numbers Link Href in Rich Text Editor :

After doing the above mentioned steps,if I configure tel:12345 in rte it works fine, but when using
href=tel for international numbers  i.e., href=tel:+61.... AEM removes the link and it start stripping
the code.
So need to follow the below step to make it work.
By default, the RTE supports these protocols in href:http://,https://,ftp://,mailto:
To configure an additional protocol, you will have to add the following structure in the RTE at
the same level of the rtePlugins node, 
The definition of this node will be:
<htmlRules jcr:primaryType="nt:unstructured">
protocols="[http://,https://,ftp://,mailto:,tel:]" />
And that's how the issue can be resolved.

Hope it will help you guys !!
Thanks and Happy Learning.

Wednesday, October 23, 2019

Component and Template level design dialogs in Template Editors in AEM

Hello Everyone,

Template Editors is a feature in AEM, which everybody is using right now.
Clients also find it quite exciting, when creation of templates are in their hands.
But Template Editors create few myths in developers minds and I have seen people to
write code based on the basis of myths so I thought of clearing the doubts and wrote about it.

Design Dialog is one of the features which we are using since long and to fetch the value
of design dialog, we always use ${currentStyle.propertyName}.

The concept of design dialog is if you want to share the values of a component across
all the pages created from a single template, we create design dialogs.

I have seen people saying that currentStyle doesn't work with dynamic templates so they
always use the PolicyManager whether they really need it or not.Their idea is because previously design_dialog values gets stored in /etc/design/default.. ,currentStyle is only meant for that but because the design dialog value is now inside” /conf/projectName/policies/…” so to fetch the value from policies we need to use PolicyManager API like shown below.
ContentPolicyManager policyManager = resourceResolver.adaptTo(ContentPolicyManager.class);
        if (policyManager != null) {
            ContentPolicy contentPolicy = policyManager.getPolicy(resource);
            if (contentPolicy != null) {
                title= (String) contentPolicy.getProperties().get("title");

But this is not correct. currentStyle can also handle design_dialog values stored inside the
But i just kept on thinking if ${currentstyle.propertyName} works fine for design dialogs then why so much big logic to do the same thing.

So the answer is in template editors, we have two kinds of design dialogs. 
Component Level: Like any older version of AEM, we can create design dialogs in the components and fetch the value using currentStyle.I already talk about it here.
Template Level: Now you can manage the page level design dialog value also and to fetch that value you need to use the PolicyManager API. You just need to pass “currentPage.getContentResource” as resource and you are able to fetch the value.

You can see the template level design values(Page Policy) from here:
Fig 1: Page Policy in a Template

Fig 2: Design Dialog for a Template
If you want to add a template policy then you add fields in design_dialog of page component and you will able to see the options here.
Because the above logic works well for both "Component and Template Level design dialog", that's why developers like to create utility and use it for both.

Demo Video to understand the concept better:

Hope it will help you guys !!
Thanks and Happy Learning.

Sunday, October 20, 2019

Implementing Header and Footer with Editable Templates

Hello Everyone,

I have already wrote a lot about editable templates, but a lot of people ask me about
what is the best way to manage header and footer in AEM with editable Templates.
We-Retail project really mislead us about this concept as in that project, when we drag and
drop header/footer, no need to configure anything. The header and footers itself got populated.
But we never have that ideal use case in real life when we don't need to configure anything
in header and footer.
As there is no inheritance between two templates so what can be best suited
implementation for header and footer.

Solution 1:
Experience fragment is one of the ways to solve this issue as you can create an XF, one
for header and one for the footer and reference those using XF Component in the template
level then all the pages will automatically get the value of header and footer created from that template.

Pros and Cons of Using this approach:

  1. In this approach, you need to drag and drop XF component in place of header and footer on each template and link it to corresponding XF.
  2. If you are using the same content for header and footer,you can put it in the structure of the initial template, then you don't need to drag and drop it  in each template, but if you have multiple sites using same initial template,I won't recommend it as different sites may have different header and footer XF.
  3. If you are using XF, it is best to drag and drop and configure on each template individually.
Demonstration Video of Implementing Header and Footer using XF in editable Templates:

Solution 2: There is one more solution which I prefer the most and used in my two recent projects, It goes well in both cases static/dynamic templates.

  1. Create a template (may be home-page template) for the root-page to configure header and footer of the site under which all the pages exist.and provide a configuration to configure rootPath in the page properties of the home-page template.
  2. Make the change in body.html and add the "pageheader.html" in body.html and include the below code in pageheader.html.
    <sly data-sly-test.resourceType="${}"/>
    <sly data-sly-test.mode="${resourceType == 'aem-project/components/structure/homepage' ? 'edit' : 'disabled'}"/>
    <sly data-sly-test.rootPath="${inheritedPageProperties.rootPath}"/>
    <sly data-sly-test.header="${rootPath}/jcr:content/header"/>
       <sly data-sly-resource="${ @path= header, resourceType='/apps/aem-project/components/content/languagenavigation', wcmmode=mode}"></sly>

  3. By this approach all the templates and pages will share the same header and footer and author can only change the header and footer at the root Page level.
  4. All the pages inside the rootPage must inherit the home-page component.Then only the logic of header footer will work fine.

Pros and Cons of this solution: 

  • You don’t need to drag and drop the component on each template.On the root Page itself you can change the content.
  • Any author can change the header and footer at the root page.
  • The header/footer should work with MSM based live/language copies. You can change the value of the rootpath by rollout configuration for each live/language copy.
Demonstration Video of Implementing Header and Footer using the above approach:

Solution 3: You can create a template for the root level and provide configurations for all the header and  footer in the page properties and fetch the value by calling inherited Page properties and all the pages will share the same header and footer.

Pros and Cons of this solution: 

  1. No Need to put any additional logic to render header and footer and the configuration of header and footer is free from template.
  2. If header and footer has so many configurations, your page properties may look messy.

Hope it will help you guys !!
Thanks and Happy Learning.