Skip to content

Conversation

@msm1992
Copy link
Contributor

@msm1992 msm1992 commented Nov 12, 2025

Purpose

$subject
Fixes wso2/api-manager#4395

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

  • Since java ssl does not have in built support to pick a certificate from the keystore by an alias, introduced a wrapper class AliasBasedKeyManager .
  • In case the keystore alias value is configured, kms will be initalized by using the new AliasBasedKeyManager.
  • To avoid, behaviour changes for existing users who already had the alias value(although not used) configured in deployment.toml, we have introduced below new config.
[keystore.tls]
serverCertificateAlias =  "mycert"

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to [email protected] and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

  • New Features
    • Added support for server certificate alias selection for TLS connections. Users can now specify which certificate from the keystore to use via the new ServerCertificateAlias configuration element. This enables enhanced control and flexibility over certificate selection in multi-certificate deployments, ensuring the appropriate certificate is selected for each connection.

@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Walkthrough

Introduces certificate alias selection for TLS/SSL server communications. Adds AliasBasedKeyManager to wrap existing key managers and prefer a configured certificate alias. ServerConnFactoryBuilder integrates this wrapper when a ServerCertificateAlias is specified, enabling passthrough listeners to use a selected certificate instead of defaulting to the first alphabetical keystore entry.

Changes

Cohort / File(s) Summary
New Alias-based Key Manager
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/AliasBasedKeyManager.java
New public class extending X509ExtendedKeyManager that wraps an X509KeyManager and preferentially returns a configured alias from chooseServerAlias() and chooseEngineServerAlias() methods while delegating all other operations to the underlying manager.
Server Connection Factory Configuration
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java
Modified to read optional ServerCertificateAlias configuration element and conditionally wrap X509KeyManager instances with AliasBasedKeyManager when an alias is specified; otherwise maintains existing default behavior.

Sequence Diagram

sequenceDiagram
    participant Client
    participant SSLEngine
    participant AliasBasedKeyManager
    participant WrappedKeyManager
    
    Client->>SSLEngine: initiate TLS connection
    SSLEngine->>AliasBasedKeyManager: chooseServerAlias(keyType, issuers, engine)
    alt preferredKeyAlias configured and available
        AliasBasedKeyManager->>AliasBasedKeyManager: verify alias in server aliases
        AliasBasedKeyManager-->>SSLEngine: return preferredKeyAlias
    else alias not configured or unavailable
        AliasBasedKeyManager->>WrappedKeyManager: chooseServerAlias(keyType, issuers, socket)
        WrappedKeyManager-->>AliasBasedKeyManager: return default alias
        AliasBasedKeyManager-->>SSLEngine: return default alias
    end
    SSLEngine->>AliasBasedKeyManager: getCertificateChain(alias)
    AliasBasedKeyManager->>WrappedKeyManager: getCertificateChain(alias)
    WrappedKeyManager-->>AliasBasedKeyManager: X509Certificate[]
    AliasBasedKeyManager-->>SSLEngine: X509Certificate[]
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • AliasBasedKeyManager.java: Straightforward delegation pattern with conditional logic in chooseServerAlias(). The implementation is direct and follows standard X509ExtendedKeyManager practices.
  • ServerConnFactoryBuilder.java: Minimal invasiveness; the change is a conditional wrapper application based on configuration presence, preserving all existing paths when no alias is specified.
  • Focus areas: Verify that the alias validation logic in chooseServerAlias() correctly checks if the preferred alias exists within the returned server aliases array; confirm the chooseEngineServerAlias() delegation correctly handles the SSLEngine-to-Socket adaptation.

Poem

🐰 A keystore full of secrets, alphabetically lined,
But now we choose the cert by alias, perfectly designed!
No more first-in-order picks, the preference is clear,
The right certificate hops forward without any fear! 🔐

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is largely incomplete, missing concrete details in most required sections like Goals, User stories, Release note, Documentation, Training, Certification, Marketing, Automation tests, Security checks, Samples, Related PRs, Migrations, Test environment, and Learning. Complete all required template sections with specific information: Goals (explicit benefits), User stories (formatted summary), Release note (customer-facing description), Documentation links, test coverage details, security verification (yes/no answers), and test environment specifications.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title accurately summarizes the main change: adding support to select a server certificate by a specified alias.
Linked Issues check ✅ Passed The code changes successfully address the linked issue #4395 by implementing alias-based certificate selection through the new AliasBasedKeyManager wrapper class and ServerCertificateAlias configuration.
Out of Scope Changes check ✅ Passed All changes are directly scoped to resolving issue #4395: introducing AliasBasedKeyManager for alias-based certificate selection and modifying ServerConnFactoryBuilder to use it when configured.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

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)
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java (1)

129-130: Consider validating the configured alias exists in the keystore.

While the alias extraction logic is correct, there's no validation that the configured ServerCertificateAlias actually exists in the keystore. If users misconfigure the alias, the system will silently fall back to default behavior without any warning, making troubleshooting difficult.

Consider adding validation after line 152 (after keyStore is loaded):

                kmfactory.init(keyStore, keyPassword.toCharArray());
+               if (requiredAlias != null && !keyStore.containsAlias(requiredAlias)) {
+                   log.warn(name + " Configured ServerCertificateAlias '" + requiredAlias + 
+                           "' not found in keystore. Available aliases: " + 
+                           java.util.Collections.list(keyStore.aliases()));
+               }
                if (requiredAlias != null) {
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/AliasBasedKeyManager.java (1)

57-64: Consider adding debug logging when preferred alias is unavailable.

The logic correctly validates that the preferred alias is compatible with the requested key type and issuers before returning it. However, when the preferred alias is not in the available aliases list, the method silently falls back to the default selection without logging. This could make it difficult to diagnose configuration issues.

Consider adding debug logging:

     public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
         String[] aliases = keyManager.getServerAliases(keyType, issuers);
         if (aliases != null && Arrays.asList(aliases).contains(preferredKeyAlias)) {
             return preferredKeyAlias;
         }
+        // Log at debug level to help diagnose why preferred alias wasn't used
+        if (log.isDebugEnabled()) {
+            log.debug("Preferred alias '" + preferredKeyAlias + "' not available for keyType=" + keyType + 
+                     ", falling back to default selection");
+        }
         return keyManager.chooseServerAlias(keyType, issuers, socket);
     }

Note: You'll need to add a logger field:

private static final Log log = LogFactory.getLog(AliasBasedKeyManager.class);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89a471d and 2d37395.

📒 Files selected for processing (2)
  • modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/AliasBasedKeyManager.java (1 hunks)
  • modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java (2 hunks)
🔇 Additional comments (5)
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/ServerConnFactoryBuilder.java (1)

153-163: LGTM! Clean conditional wrapping logic.

The implementation correctly wraps X509KeyManager instances with AliasBasedKeyManager when an alias is configured, while maintaining backward compatibility by falling back to the default behavior when no alias is specified. The instanceof check ensures type safety.

modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/AliasBasedKeyManager.java (4)

37-40: LGTM! Constructor is clean and thread-safe.

The constructor properly initializes final fields, ensuring thread safety for concurrent SSL handshakes.


42-55: LGTM! Proper delegation pattern.

These methods correctly delegate to the wrapped key manager without modification, which is appropriate since alias preference only needs to affect server alias selection.


66-69: LGTM! Correct reuse of server alias selection logic.

Delegating to chooseServerAlias with a null socket is appropriate and safe. The preferred alias is selected before the socket parameter would be used, and null is a valid socket value in the X509KeyManager API for the fallback delegation.


71-79: LGTM! Proper delegation for certificate and key access.

These methods correctly delegate certificate chain and private key retrieval to the wrapped manager, which is appropriate since alias selection is handled separately.

Comment on lines +30 to +33
/**
* Custom X509KeyManager that selects a specific alias for client and server certificates
*/
public class AliasBasedKeyManager extends X509ExtendedKeyManager {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix misleading class documentation.

The comment states this class "selects a specific alias for client and server certificates," but the implementation only customizes server alias selection. Client alias methods (chooseClientAlias at line 48) delegate directly to the wrapped key manager without applying the preferred alias logic.

Apply this diff:

 /**
- * Custom X509KeyManager that selects a specific alias for client and server certificates
+ * Custom X509KeyManager that selects a specific server certificate alias
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Custom X509KeyManager that selects a specific alias for client and server certificates
*/
public class AliasBasedKeyManager extends X509ExtendedKeyManager {
/**
* Custom X509KeyManager that selects a specific server certificate alias
*/
public class AliasBasedKeyManager extends X509ExtendedKeyManager {
🤖 Prompt for AI Agents
In
modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/config/AliasBasedKeyManager.java
around lines 30 to 33, the class Javadoc incorrectly claims it "selects a
specific alias for client and server certificates" while the implementation only
applies the preferred-alias logic to server-side selection. Update the
class-level comment to accurately state that this KeyManager customizes server
(SSLServer) alias selection only and that client alias methods delegate to the
wrapped KeyManager (or alternatively implement symmetric client-alias behavior
if you prefer that change), ensuring the Javadoc matches the actual behavior.

@msm1992 msm1992 merged commit 2b10bd4 into wso2:master Dec 2, 2025
2 of 3 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.

Using the configured certificate(via alias) for the passthrough communication in APIM

2 participants