How to use Environment Variables in Adobe Experience Manager (AEM) as Cloud Service.

Lokesh Kashaboina
Slalom Technology
Published in
6 min readAug 3, 2021

Introduction:

The problem we were trying to solve was the most secure way to store API keys used to make REST calls in the AEM as Cloud Service. We explored number of options and found that through the Cloud Manager Application Programming Interface (API) plugin Adobe I/O Command Line Interface (CLI) this would be possible as it gives us capabilities to set up environment variables, pipeline variables, cancel pipelines, etc. In this post, I am going to explain when & how you can set up environment variables and access them in your code through Open Service Gateway Initiative (OSGI) Configuration.

Inline Variables vs Environment Non-Secret Variables vs Environment Secret Variables

Setting and Accessing Environment Variables:

Below we are going to learn about

1. Creating the Adobe I/O API Integration.

2. Setting Environment Variables.

3. OSGI Configuration File.

4. Service with OSGI Configuration.

Creating the Adobe I/O Console integration:

This is the first and the most important step in this process. To interact with Cloud Manager API you need to set up Adobe I/O Console Integration. For creating this integration, please follow this well-articulated article.

Setting Environment Variables:

Once the integration is done, you can start using the aio-cli-plugin.

  • First, you need to set the default program ID which you want to access. Set the program ID with the below command. Program ID can be found going to your cloud manager.

Example: https://experience.adobe.com/#/@randomcompany /cloud-manager/home.html/program/12345

aio config:set cloudmanager_programid PROGRAM_ID

  • Once the program ID is set you can list all the environments along with their environment IDs inside that program with the below command.

aio cloudmanager:list-environments

  • There are two ways you can set environment variables. These are runtime variables available to components running inside the runtime environment.

1. Setting each variable individually: Use below command to set multiple variables individually.

aio cloudmanager:set-environment-variables ENVIRONMENT_ID –variable MY_VAR1 “plaintext value” –secret MY_VAR2 “some secret value”

Flag –secret is to indicate that MY_VAR2 is a secret variable.

2. Setting variables from a JSON file: This is the method I have used in my demo since I had to set multiple variables and this approach makes it easy.

Create a JSON file with all the variables, below is my config named keys.json.

[
{
"name":"MY_TEST_TITLE",
"value":"I am config title",
"type":"secretString"
},
{
"name":"MY_TEST_DESC",
"value":"I am config description and I am only placeholder text",
"type":"string"}
]

Run the below command to use this file and set the variables for a particular environment.

aio cloudmanager:environment:set-variables ENVIRONMENT_ID — jsonFile=keys.json

Note: I created keys.json inside aio-cli project folder itself hence directly referencing it in the above command. If your JSON file is elsewhere on your system, please give that path.

Once I run the above command, API deploys the new variables and values to Cloud environments, like a typical customer code deployment pipeline. The author and publish services will be restarted and reference the new values, typically taking a few minutes. Note that the quality gates and tests that Cloud Manager executes during a regular code deployment are not performed during this process.

Using the below command you can see all the environment variables you have set for an environment.

aio cloudmanager:environment:list-variables ENVIRONMENT_ID

I ran the above command with our environment ID, and I see the below result. You can see that both my variables are set and are ready to be used in my OSGI Configuration.

Config output in console

OSGI Configuration File:

OSGI configurations target OSGI components via their Persistent Identity (PID), which defaults to the OSGI component’s Java class name.

For example, to provide OSGI configuration for an OSGi service implemented by:

com.example.core.services.impl.MyTestEnvVarsImpl.java

an OSGi configuration file is defined at:

/apps/example/config/com.example.core.services.impl.MyTestEnvVarsImpl.cfg.json

Below is the OSGI config file that I have for the demo

{
“myTestTitle” : “$[secret:MY_TEST_TITLE]”,
“myTestDesc”: “$[env:MY_TEST_DESC]”
}

myTestTitle and myTestDesc are the names of the variables to be used in OSGI Configuration Service and its values are $[secret:MY_TEST_TITLE] and $[env:MY_TEST_DESC]. These are the same variable names from keys.json, which we have previously set in the environment. In this case, MY_TEST_TITLE is as defined as a secret value and MY_TEST_DESC is just a regular value just like in keys.json.

Note: Prior versions of AEM supported OSGi configuration files using different file formats such as .cfg., .config and as XML sling:OsgiConfig resource definitions. These formats are superseded by the cfg.json OSGI configuration format.

Service with OSGI Configuration:

I have created 3 Java classes to implement this OSGI Configuration Service. I have provided exact code snippets below.

OSGI Configuration Interface Class:

This OSGI Configuration can be referred in any backend component, I am referring to this in MyTestEnvVarsService. @ObjectClassDefinition specifies that the interface contains the OSGI property definition.

@ObjectClassDefinition(name=”Testing Env Vars Cfg”)public @interface EnvVarsTestOsgiConfig {
@AttributeDefinition(
name=”My Title”,
description = “My Title”,
type = AttributeType.STRING
)
String myTestTitle();
@AttributeDefinition(
name=”My Desc”,
description = “My Desc”,
type = AttributeType.STRING
)
String myTestDesc();
}

Implementation Class for this Service:

To use the OSGI Configuration in this service you should use @Designate annotation along with ocd (object class definition) property and its value should be the class name of your OSGI Configuration. This is used to generate OSGI Configuration for this class.

@Component(immediate = true,service = MyTestEnvVarsService.class)
@Designate(ocd = EnvVarsTestOsgiConfig.class)
public class MyTestEnvVarsImpl implements MyTestEnvVarsService {
private String myTitle;private String myDesc;@Activate@Modifiedprotected void activate(EnvVarsTestOsgiConfig cfg) {
myTitle = cfg.myTestTitle();
myDesc = cfg.myTestDesc();
}
@Overridepublic String getMyTitle() {
return myTitle;
}
@Overridepublic String getMyDesc() {
return myDesc;
}
}

Interface Class for this Service:

public interface MyTestEnvVarsService {
String getMyTitle();
String getMyDesc();
}

This OSGI service will fetch us the configurations that were set in the config file. This service can be later called inside another Service, Sling Model, Scheduler, Event Handler, Servlet, Workflow Process etc

Advantages of using Environment Variables over traditional OSGI configurations:

1. Environment Variables allows you to vary the behavior of your code based on context and environment.

2. You only must configure and setup these variables once and only update/delete them when necessary.

3. Since these configurations live outside your code, it boosts the security of your application.

4. You can change the values of these variables at any point of time and no code changes or deployments would be required to take effect.

Key Considerations:

1. To create and use Adobe I/O Console Integration, you need to be either a System Administrator in your IMS organization or need to have a Developer role inside it.

2. Since the environment variables live outside of Git and are not part of the standard deployment process, the administrator needs to manage, govern and integrate deploy environment variables into their deployment process.

3. The administrator needs to set these variables first before deploying the code that relies on them.

4. When changing the values of existing variables, create new variable names instead of just changing the value of old variables so the old code never references the new value. Then when the new code release looks stable, one can choose to remove the older values.

Now you’re ready to use environment variables:

I have put together this article because I have seen how powerful Adobe I/O CLI is and how we can make the best use of it. Although my use case was only to set and use environment variables in my application, in the process of doing research on this CLI I got to know about many more features it offers. Hopefully, this has given you enough information on how to use Adobe I/O CLI and how to set and fetch environment variables in your application.

--

--