Skip to content

Fix #8054: decrypt trustStorePassword in REST transform init - #8061

Open
kotwal-itpro wants to merge 1 commit into
apache:mainfrom
kotwal-itpro:fix/rest-truststore-password-decryption-8054
Open

Fix #8054: decrypt trustStorePassword in REST transform init#8061
kotwal-itpro wants to merge 1 commit into
apache:mainfrom
kotwal-itpro:fix/rest-truststore-password-decryption-8054

Conversation

@kotwal-itpro

Copy link
Copy Markdown
Contributor

Fixes #8054.

Problem

The REST transform's init() reads the trust store password with resolve() only, missing the Encr.decryptPasswordOptionallyEncrypted(...) call that every other password field in Hop wraps around resolve(). This includes the httpPassword branch a dozen lines above it in the very same method:

data.realHttpPassword =
    Encr.decryptPasswordOptionallyEncrypted(resolve(meta.getHttpPassword()));  // decrypted
...
data.trustStorePassword = resolve(meta.getTrustStorePassword());               // NOT decrypted

Both fields are declared identically in RestMeta:

@HopMetadataProperty(key = "httpPassword", injectionKey = "HTTP_PASSWORD", password = true)
@HopMetadataProperty(key = "trustStorePassword", injectionKey = "TRUSTSTORE_PASSWORD", password = true)

Every peer usage decrypts:

Location Handling
plugins/misc/rest/.../RestConnection.java:566 (same field name) Encr.decryptPasswordOptionallyEncrypted(resolve(trustStorePassword))
plugins/databases/oracle/.../OracleDatabaseMeta.java:561 decrypt(variables, trustStorePassword)
plugins/transforms/ldap/.../LdapSslProtocol.java:41 Utils.resolvePassword(variables, ...) (resolve + decrypt)
plugins/transforms/rest/.../Rest.java:2258 (before this PR) resolve(...) only

As a result, an encrypted value that reaches the field through a variable is passed to the trust store loader verbatim and the SSL context cannot be built.

Why it's not visible in the simple case

A password typed straight into the dialog works, because XmlMetadataUtil already decrypts password = true properties on deserialization (core/src/main/java/org/apache/hop/metadata/serializer/xml/XmlMetadataUtil.java:1211). The bug only surfaces on the variable path — which is the whole point of password = true fields being encryptable in the first place.

Fix

One-line change to Rest.java: wrap resolve(meta.getTrustStorePassword()) in Encr.decryptPasswordOptionallyEncrypted(...), matching the peer pattern. The Encr import is already present in the file. Added a short comment tying the pattern to the peer locations and to this issue.

Test

New testInitDecryptsTrustStorePasswordFromVariable in RestInitAndProcessTest:

  • Encrypts a known plaintext with Encr.encryptPasswordIfNotUsingVariables
  • Puts the encrypted value behind a ${TRUST_PWD} variable
  • Runs init() and asserts data.trustStorePassword equals the original plaintext
  • Also asserts data.realHttpPassword on the same run for parity with the pre-existing httpPassword handling — makes the equivalence explicit for future readers

Verified locally

  • ./mvnw test on plugins/transforms/rest168 tests, 0 failures, 0 errors
  • ./mvnw spotless:apply — no formatting changes
  • Java 21 build

The REST transform's init() reads the trust store password with resolve()
only, missing the Encr.decryptPasswordOptionallyEncrypted(...) call every
other password field in Hop wraps around resolve(). This includes the
httpPassword branch a dozen lines above it in the very same method:

  data.realHttpPassword =
      Encr.decryptPasswordOptionallyEncrypted(resolve(meta.getHttpPassword()));
  ...
  data.trustStorePassword = resolve(meta.getTrustStorePassword());  // not decrypted

As a result, an encrypted value that reaches the field through a variable
is passed to the trust store loader verbatim and the SSL context cannot
be built. A password typed straight into the dialog works, because
XmlMetadataUtil already decrypts password=true properties on
deserialization -- the bug only surfaces on the variable path.

Both fields are declared identically in RestMeta (password = true) and
every peer usage decrypts:

  - plugins/misc/rest/.../RestConnection.java:566 (same field name)
  - plugins/databases/oracle/.../OracleDatabaseMeta.java:561
  - plugins/transforms/ldap/.../LdapSslProtocol.java:41

Fix: wrap resolve() in Encr.decryptPasswordOptionallyEncrypted() to
match the peer pattern. One-line production change plus a regression
test that runs init() with an encrypted trust store password behind a
variable, asserting the plaintext lands on RestData (parity with the
pre-existing httpPassword assertion in the same test).

Verified: full plugins/transforms/rest test suite passes (168 tests, 0
failures, 0 errors). ./mvnw spotless:apply clean. Java 21 build.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: REST transform does not decrypt trustStorePassword, unlike every other password field

1 participant