Dear Dev Community,

Over the past few days, I've been working on adding optional Secret
Manager/Vault integration to Apache OFBiz, and I'd like to share it with
the Dev list for feedback before taking it further.

The goal is simple: today, DB passwords, JWT/login keys, and various
gateway credentials mostly live as plain text in .properties files or in
the SystemProperty entity, which is a real concern for production and
compliance-sensitive deployments (PCI-DSS, SOC2, etc.). This work gives
adopters a way to back those values with an external secret manager of
their choice, while leaving everything else untouched.

To make this happen, I've added six provider plugins, each implementing a
small SecretProvider SPI: AWS Secrets Manager, GCP(Google Cloud Platform)
Secret Manager, Azure Key Vault, HashiCorp Vault by IBM, 1Password, and
Bitwarden Secrets Manager.

On the framework side, the key additions are a
SecretProvider/SecretProviderFactory/FallbackSecretProvider setup in
framework/base, a ConfigCryptoUtil class for local AES-256-GCM encryption
of values as ENC(...) keyed by OFBIZ_MASTER_KEY, and a SecretValueResolver
that resolves any SECRET(key) reference in a property file or
SystemProperty row through the configured provider, with a configurable
cache TTL.

entityengine.xml now supports jdbc-password-lookup on inline-jdbc elements,
which is resolved via SecretProviderFactory at startup, so the DB password
never needs to appear in entityengine.xml at all. Previously,
passwords.properties only supported plain-text values; now those same
entries can be encrypted at rest using a new generateDBPassword gradle
task, which prompts for the value via masked stdin and writes out the
ENC(...) form, so no secret ever needs to be typed on the command line or
land in shell history.

SystemProperty also has a new systemPropertyLookup field so individual
properties can opt into secret-manager resolution.

I've also added unit tests (e.g. SecretValueResolverTest) covering plain
values, ENC(...) values, cached lookups, and provider failure/fallback
behavior, plus a generateDBPassword gradle task with the same masked-prompt
approach for setting up the local DB password.

On the impact to existing implementations/configurations, this is fully
backward-compatible and opt-in only:

1) passwords.properties / entityengine.xml – Existing plain-text
jdbc-password values continue to work exactly as before. Sites can
optionally migrate to ENC(...) (AES-256-GCM, keyed by OFBIZ_MASTER_KEY,
generated via generateEncryptedSecret) or to a jdbc-password-lookup key
resolved via a secret manager, but if they do nothing, behavior is
unchanged.

2) SystemProperty – The new systemPropertyLookup field is additive.
Existing rows with only systemPropertyValue (plain or ENC(...)) behave as
they do today. A site only sees secret-manager resolution if it explicitly
sets systemPropertyLookup on a row.

3) Secret managers – All six provider plugins (AWS, Azure, HashiCorp, GCP,
1Password, Bitwarden) are optional. None are enabled by default, with no
new mandatory dependencies in core. You can enable one plugin/provider at a
time by changing values in the respective plugin's ofbiz-component.xml
file.

4) Fallback chain – Lookup → remote secret manager (if configured) → local
ENC(...)/plain value. If the remote provider is unreachable or
unconfigured, OFBiz falls back to the existing file/entity-based value,
resulting in no new failure mode for sites that do not adopt this
functionality.

5) Testing – The new resolver, crypto utility, and provider fallback logic
are all covered by unit tests, so existing config-loading paths remain
verified alongside the new optional ones.

Here is the source code for your kind review:

Framework related changes:
https://github.com/ashishvijaywargiya/ofbiz-framework/tree/various-secret-manager

Plugins related changes:
https://github.com/ashishvijaywargiya/ofbiz-plugins/tree/plugins-various-secret-manager

Further work:

1) I am working on adding an Admin Screen in webtools where a user can
create secrets either in the SystemProperty entity or the password.properties
file. I will provide an option where a user can create multiple secrets in
a CSV file and upload them in bulk. The AES algorithm will encrypt the
password and put it either in SystemProperty or password.properties file.

2) Another item on the roadmap is secret key/password rotation handling
from the remote service, with the corresponding values updated in
passwords.properties or the relevant SystemProperty records. Many
third-party services expect support for secret key rotation at regular
intervals for security reasons. For now, we won't provide support for
database password rotation in the Secret Manager, since that would also
require handling of the user password rotation on the database side itself
(MySQL, PostgreSQL, etc.).

3) Merge the generateDBPassword and generateEncryptedSecret Gradle tasks
and make them one, i.e generateEncryptedSecret.

Please let me know your thoughts/feedback on this work. I will quickly
accommodate
your thoughts/ideas in the current implementation.

I'm planning to commit the current work to the Apache OFBiz project(trunk)
in the next few days.

Thank you.

--
Kind Regards,
Ashish Vijaywargiya
Vice President of Operations
*HotWax Systems*
*Enterprise open source experts*
http://www.hotwaxsystems.com

Reply via email to