Skip to content

Read keystore configuration from the toml file #105

Merged
KalinduGandara merged 1 commit into
wso2:masterfrom
KalinduGandara:fix_4942
Jun 23, 2026
Merged

Read keystore configuration from the toml file #105
KalinduGandara merged 1 commit into
wso2:masterfrom
KalinduGandara:fix_4942

Conversation

@KalinduGandara

Copy link
Copy Markdown
Contributor

Purpose

Change the priority order of reading keystore configs 1.[keystore.intrnal] in deployment.toml
2.[kesytore.primary] in deployment.toml
3.default.json
4.carbon.xml

Port of #75
Fixes wso2/product-integrator-mi/issues/4942

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Overview

This PR modifies the keystore configuration resolution order in the Cipher Tool to prioritize deployment.toml over carbon.xml. The new priority order is: [keystore.internal] in deployment.toml → [keystore.primary] in deployment.toml → default.json → carbon.xml. This ensures that user-configured keystore settings in deployment.toml are respected from the first server startup.

Changes

Constants.java

Added new constants to support keystore configuration resolution:

  • Default JSON file location constants: DEFAULT_JSON_FILE, DEFAULT_JSON_DIR_PATH
  • Keystore property map names: PRIMARY_KEYSTORE_PROPERTY_MAP_NAME, INTERNAL_KEYSTORE_PROPERTY_MAP_NAME
  • Keystore attribute constants for primary/internal keystores: file name, type, and alias properties
  • Generic key attribute constants: KEY_FILE_NAME, KEY_TYPE, KEY_ALIAS

Utils.java

Enhanced configuration resolution logic with the following changes:

Modified methods:

  • Updated resolveKeyStorePath method signature to accept a defaultMap parameter for resolving $ref indirection in configuration values

New helper methods:

  • getValueFromConfigs() - Resolves configuration values from deployment.toml or default.json with fallback to carbon.xml XPath lookups; supports $ref{...} references
  • getKeystoreFromConfiguration() - Parses TOML configuration file to extract keystore properties by section name
  • getJSONConfiguration() - Reads and parses default.json file using Gson

Updated setSystemProperties() logic:

  • Loads keystore configurations from deployment.toml for both internal and primary keystores
  • Loads default.json into a configuration map
  • Implements keystore selection: prioritizes internal keystore if configured, falls back to primary keystore
  • Uses the new getValueFromConfigs() method to resolve keystore attributes with support for $ref indirection and XPath fallback to carbon.xml

Impact

This change enables the Cipher Tool to read keystore configurations from deployment.toml before startup, resolving the issue where the tool would ignore deployment.toml updates on first startup and default to carbon.xml settings instead.

Walkthrough

The PR modifies Constants.java and Utils.java in the ciphertool module. Constants.java adds twelve new string constants covering a default JSON file name, its directory path system property key, primary and internal keystore property map names, and individual key attribute names (file_name, type, alias).

Utils.java adds Gson and path-related imports, introduces getKeystoreFromConfiguration to read a named TOML table, getJSONConfiguration to load default.json via Gson, and getDefaultJSONFilePath to locate default.json from a system property or CARBON_HOME-relative paths. A new getValueFromConfigs method resolves configuration values using a chain: explicit config value → defaultMap lookup → $ref{...} indirection → XPath fallback against carbon.xml. setSystemProperties is updated to use these new helpers for keystore selection instead of reading directly from carbon.xml. resolveKeyStorePath gains a defaultMap parameter to support $ref path resolution and now throws CipherToolException on InvalidPathException.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly describes the main change—reading keystore configuration from the TOML file instead of carbon.xml—which aligns with the primary objective of the PR.
Description check ✅ Passed The description identifies the purpose, references related issues, and explains the priority order for reading keystore configs. However, it lacks details on Goals, Approach, test coverage, security checks, and other template sections.
Linked Issues check ✅ Passed The changes implement the required priority order for reading keystore configuration (deployment.toml sections before carbon.xml) and add support for default.json, directly addressing issue #4942.
Out of Scope Changes check ✅ Passed All changes are scoped to keystore configuration reading and resolution, adding constants, helper methods, and updating configuration retrieval logic as required by the linked issue.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java (2)

454-460: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

$ref parsing duplicated and unguarded.

The same $ref{...} extraction logic is repeated here and in getValueFromConfigs (Lines 205-209). Consider extracting a shared helper that validates the braces are present before calling substring, both to avoid duplication and to prevent an uncaught StringIndexOutOfBoundsException on malformed references.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java`
around lines 454 - 460, The $ref{...} parsing logic is duplicated in the current
method and in the getValueFromConfigs method and lacks validation, risking a
StringIndexOutOfBoundsException on malformed references. Create a shared helper
method that takes a path string as input and extracts the reference value
between the curly braces while validating that both opening and closing braces
are present before attempting substring operations. Then replace the inline
substring extraction at lines 454-460 (where path.substring is called) and the
equivalent code in getValueFromConfigs with calls to this new helper method to
ensure consistent and safe reference parsing across both locations.

195-218: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Avoid relying on NullPointerException for control flow, and guard $ref parsing.

Two concerns in getValueFromConfigs:

  • The carbon.xml fallback is triggered by catching NullPointerException from defaultMap.get(key).toString(). This is fragile and can mask unrelated NPEs originating elsewhere in the try block. Prefer an explicit null check on the map lookup.
  • value.substring(value.indexOf('{') + 1, value.indexOf('}')) will throw StringIndexOutOfBoundsException (not caught here) if a value begins with $ref but is missing a {/}, leaving malformed input unhandled.
♻️ Suggested approach
-        String value = config;
-        try {
-            // If the value is empty in deployment.toml, read from default.json.
-            if (StringUtils.isBlank(value)) {
-                value = defaultMap.get(key).toString();
-            }
-            // If the value is given as a reference, read from default.json.
-            if (value.startsWith("$ref")) {
-                // Read the value between the curly braces as the reference.
-                // e.g. $ref{<reference>} -> <reference>
-                String reference = value.substring(value.indexOf('{') + 1, value.indexOf('}'));
-                return defaultMap.get(reference).toString();
-            }
-            return value;
-            // Throw NullPointerException if the value is not available in default.json.
-        } catch (NullPointerException e) {
-            // Read from carbon.xml if default.json is not available.
-            System.err.println("Invalid value " + key + " " + e);
-            return Utils.getValueFromXPath(element, xPath);
-        }
+        String value = config;
+        // If the value is empty in deployment.toml, read from default.json.
+        if (StringUtils.isBlank(value)) {
+            Object mapped = defaultMap.get(key);
+            if (mapped == null) {
+                // Read from carbon.xml if not available in default.json.
+                return Utils.getValueFromXPath(element, xPath);
+            }
+            value = mapped.toString();
+        }
+        // If the value is given as a reference, resolve it from default.json.
+        String resolved = resolveReference(value, defaultMap);
+        return resolved != null ? resolved : value;

Where resolveReference validates the presence of {/} before substring extraction and returns null for non-reference values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java`
around lines 195 - 218, In the getValueFromConfigs method, replace the try-catch
block that relies on catching NullPointerException with explicit null checks
after defaultMap.get(key) and defaultMap.get(reference) calls to properly handle
missing values. Additionally, before parsing the reference in the $ref block
using substring with indexOf('{') and indexOf('}'), add validation to ensure
both curly braces are present in the value string; if they are missing, throw a
descriptive exception rather than allowing StringIndexOutOfBoundsException to
occur. Consider extracting the $ref reference parsing logic into a separate
helper method to improve code clarity and maintainability.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java`:
- Around line 595-609: The getJSONConfiguration method currently only catches
IOException in its try-catch block, but Gson's fromJson method can also throw
JsonSyntaxException when encountering malformed JSON. To fix this, add a catch
clause for JsonSyntaxException alongside the existing IOException catch block so
that both exceptions are handled gracefully, allowing the method to return the
empty map fallback as documented in the comment instead of aborting on invalid
JSON syntax.

---

Nitpick comments:
In `@components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java`:
- Around line 454-460: The $ref{...} parsing logic is duplicated in the current
method and in the getValueFromConfigs method and lacks validation, risking a
StringIndexOutOfBoundsException on malformed references. Create a shared helper
method that takes a path string as input and extracts the reference value
between the curly braces while validating that both opening and closing braces
are present before attempting substring operations. Then replace the inline
substring extraction at lines 454-460 (where path.substring is called) and the
equivalent code in getValueFromConfigs with calls to this new helper method to
ensure consistent and safe reference parsing across both locations.
- Around line 195-218: In the getValueFromConfigs method, replace the try-catch
block that relies on catching NullPointerException with explicit null checks
after defaultMap.get(key) and defaultMap.get(reference) calls to properly handle
missing values. Additionally, before parsing the reference in the $ref block
using substring with indexOf('{') and indexOf('}'), add validation to ensure
both curly braces are present in the value string; if they are missing, throw a
descriptive exception rather than allowing StringIndexOutOfBoundsException to
occur. Consider extracting the $ref reference parsing logic into a separate
helper method to improve code clarity and maintainability.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c146bdd2-b780-43db-b817-1ab232ed981d

📥 Commits

Reviewing files that changed from the base of the PR and between 32741fd and 8872a3c.

📒 Files selected for processing (2)
  • components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Constants.java
  • components/ciphertool/src/main/java/org/wso2/ciphertool/utils/Utils.java

@KalinduGandara KalinduGandara merged commit 7483c2e into wso2:master Jun 23, 2026
2 checks passed
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.

Cipher Tool Fails to Retrieve values from deployment.toml on First Startup

2 participants