IM's ENV Variables Handling
Request
We want to get rid of sensitive data (such as credentials) from application property files. It is a security risk because everything stored in a Git repository can be viewed by anybody in Pricefx company via gitgrep.
Solution
Store such data in secured environment (Hades) and pass them to IM as environment variables during the deploy time.
Implementation
On Hades server there is a binary application “imdeployer” and “database” (/root/bin/integration_managers.csv) of all IMs. It contains four columns.
ID | TARGET | DEPLOY_FUNCTION | ENV_VARS |
---|---|---|---|
arm_dev | node1.arm-qa.pricefx.net | deploy_im_standard_im_1_2_and_newer |
|
watsco_qa | node1.watsco-qa.pricefx.net | deploy_im_standard_openjdk11andnewer |
|
dn_dev | node1.dn-qa.pricefx.net | deploy_im_standard_im_1_2_and_newer | integration.pfx.url=https://dn-qa.pricefx.com/pricefx,integration.pfx.username=integration,integration.pfx.partition=dn-dev,integration.pfx.password=SecretPass |
tfg_prod | node1.tfg.pricefx.net | deploy_im_standard |
|
Notes:
ID – Has to be unique. In this case it is tfg_prod.
TARGET – It is Salt’s minion ID. Usually it is real server hostname.
DEPLOY_FUNCTION – Deploy function defines the .conf file on the server and its content.
For example,deploy_im_standard
function will create the following .conf file:salt $TARGET cmd.run "/bin/echo -e 'JAVA_OPTS=\"-Xmx${MAX_HEAP_SIZE} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/pricefx/runtime/${2} -Xloggc:gc.log -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=5M -Dfile.encoding=UTF-8 -Dspring.cloud.config.enabled=false -Dspring.profiles.active=${3}\"\nidentity=${2}\nLOG_FOLDER=/dev\nLOG_FILENAME=null' > /var/pricefx/runtime/${2}/${2}.conf"
deploy_im_standard_im_1_2_and_newer
creates a different .conf file:salt $TARGET cmd.run "/bin/echo -e 'JAVA_OPTS=\"-Xmx${MAX_HEAP_SIZE} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/pricefx/runtime/${2} -Xloggc:gc.log -XX:+PrintGCDetails -Dfile.encoding=UTF-8 -Dspring.cloud.config.enabled=true -Dlogging.file.name=main.log -Dspring.profiles.active=${3}\"\nidentity=${2}\nLOG_FOLDER=/dev\nLOG_FILENAME=null\nJAVA_HOME=/usr/lib/jvm/java-openjdk' > /var/pricefx/runtime/${2}/${2}.conf"
As you can see, both .conf file vary. We cannot use some Java properties in open-jdk11 as in oracle-java 7 etc.
ENV_VARS – Here is the place for your custom environment variables. It is just a string delimited by comma “,”.
Do not use delimiter [, or ; ] in the data.
Now, take a look at arm_dev and dn_dev. One has something in env_variables and the other does not.
Final .conf file for arm_dev:
root@node1.arm-qa.pricefx.net /var/pricefx/runtime/im-arm-dev # cat im-arm-dev.conf
JAVA_OPTS="-Xmx4G -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/pricefx/runtime/im-arm-dev -Xloggc:gc.log -XX:+PrintGCDetails -Dfile.encoding=UTF-8 -Dspring.cloud.config.enabled=true -Dlogging.file.name=main.log -Dspring.profiles.active=arm_dev"
identity=im-arm-dev
LOG_FOLDER=/dev
LOG_FILENAME=null
JAVA_HOME=/usr/lib/jvm/java-openjdk
root@node1.arm-qa.pricefx.net /var/pricefx/runtime/im-arm-dev #
Final .conf file for dn_dev:
Based on this you can see that we can now remove properties from the application property file and it will still work.
No more credentials in Git.
Benefits
All IM data in one secured place.
No more 1200 lines and more of IF statements in the deploy_jenkins_job script.
Possibility to define fine grained environment variables.
Possibility to mass edit IM properties (such as password change on Pricefx side – now you will change it in “database” and restart IM. Integration Engineers do not need to even know about it and there is no need to change it in the application properties and do the commit.)
Easier transfer to AWS (Kubernetes could take a look at that database as well and provide those ENV variables directly to the container in the same way as it salt does it now).
Integration Engineer Instructions
Data which you consider to be sensitive should be moved to ENV variables and removed from application properties.
Create a helpdesk ticket where you will define that you want, for example, to specify a new ENV variable for Salesforce password.
Then you can remove that line from your property file or remap it if needed:
Once Ops/Support add it to the database, you will end up with .conf file like this:
Ops/Support Instructions
Lets assume you have received the above request.
Open the “database” file on Hades (currently it is /root/bin/integration_managers.csv).
Navigate to the line which starts with “arm_dev”.
It will look like this (example):
There are no ENV variables yet.
Let’s add the requested one:
Save it and you’re done.
If you receive another request asking you to specify a new environment variable such as “test=test”, then you will do:
Just use “,” as the ENV variables delimiter.
Do not create new records for IMs in those IF conditions anymore. Add a line to the database file instead. You can use “imdeployer” CLI.
IM Deployer CLI
There is a binary application called “imdeployer” which is located next to the database file (/root/bin/imdeployer). It serves as a layer between deploy_jenkins_job and CSV DB file. Its purpose is to handle data validation, errors, commented (disabled) records and to resolve proper records. You can see examples in its Git repository (https://gitlab.pricefx.eu/integration/imdeployer).
Conclusion
This solution brings a lot of improvements in security and code organization as well as in design and future usage.
It is backward compatible and if it will not find anything in the DB file, it will continue to search for it in IF statements.
There is no need to change anything on IM side.
IntegrationManager version 5.8.0