Skip to content

Add Mediator Access Control#2535

Open
HeshanSudarshana wants to merge 1 commit intowso2:masterfrom
HeshanSudarshana:master-mediator-access-control
Open

Add Mediator Access Control#2535
HeshanSudarshana wants to merge 1 commit intowso2:masterfrom
HeshanSudarshana:master-mediator-access-control

Conversation

@HeshanSudarshana
Copy link
Copy Markdown
Contributor

@HeshanSudarshana HeshanSudarshana commented Apr 10, 2026

Purpose

This PR adds Mediator Access Control.

Summary by CodeRabbit

  • New Features
    • Added mediator access control with configurable allowlist and blocklist modes to restrict mediator usage during XML parsing.
    • Improved error reporting to consolidate and display all blocked mediators in a single message, rather than failing on the first violation.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 10, 2026

Walkthrough

This pull request introduces a mediator access control system for Apache Synapse that enforces configuration-driven allowlist/blocklist policies during XML-based mediator deployment. It adds infrastructure for policy enforcement, error handling, and integrates access checks into the mediator factory initialization and instantiation flows.

Changes

Cohort / File(s) Summary
Access Control Infrastructure
modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java, modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControlException.java
New utility class (MediatorAccessControl) loads allowlist/blocklist configuration from synapse.properties and validates mediator element names at deployment time. New exception type (MediatorAccessControlException) provides a dedicated signal for access control violations while extending SynapseException.
Factory Integration
modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java, modules/core/src/main/java/org/apache/synapse/config/xml/AbstractListMediatorFactory.java
MediatorFactoryFinder initializes access control during factory loading and enforces checks before mediator instantiation. AbstractListMediatorFactory wraps mediator creation in error handling that accumulates blocked mediators and logs a consolidated error message instead of failing on the first violation.

Sequence Diagram(s)

sequenceDiagram
    participant SynapseConfig as Synapse Config
    participant MFF as MediatorFactoryFinder
    participant MAC as MediatorAccessControl
    participant Factory as MediatorFactory
    participant ALM as AbstractListMediatorFactory
    
    SynapseConfig->>MFF: loadMediatorFactories()
    MFF->>MFF: Register built-in & pluggable factories
    MFF->>MAC: init()
    MAC->>MAC: Load config from synapse.properties
    MFF->>MFF: Set initialized = true
    
    SynapseConfig->>MFF: getMediator(OMElement, ...)
    MFF->>MAC: checkByElementName(localName)
    alt Blocked by Policy
        MAC-->>MFF: throw MediatorAccessControlException
    else Allowed
        MAC-->>MFF: OK
    end
    MFF->>Factory: Instantiate mediator
    
    SynapseConfig->>ALM: addChildren(parent, mediators)
    loop For each child
        ALM->>MFF: getMediator(childElement, ...)
        alt Access Denied
            MFF-->>ALM: MediatorAccessControlException
            ALM->>ALM: Accumulate blocked name
        else Success
            MFF-->>ALM: Mediator instance
            ALM->>ALM: Add to parent
        end
    end
    ALM->>ALM: If any blocked, log consolidated message
    alt Blocked mediators exist
        ALM-->>SynapseConfig: throw SynapseException
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A whisker-twitch of access control
Allowlists and blocklists take their toll,
Built in the factories where mediators dwell,
Now guarded gates with exceptions that tell,
Which rascals can't hop through the Synapse as well!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal and incomplete, containing only a single-line Purpose statement without addressing any of the required template sections. Complete the PR description by filling in critical sections: Goals (what the feature achieves), Approach (implementation details), Release notes, and other relevant template sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 45.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a mediator access control feature across multiple new and modified files.

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

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (3)
modules/core/src/main/java/org/apache/synapse/config/xml/AbstractListMediatorFactory.java (1)

50-57: Move configuration extraction outside the loop for efficiency.

The SynapseConfiguration extraction from properties (lines 50-55) is performed on every loop iteration, but the result is the same each time. This should be moved outside the while loop.

♻️ Proposed refactor
     protected static void addChildren(OMElement el, ListMediator m, Properties properties) {
         Iterator it = el.getChildren();
         StringBuilder blockedMediators = null;
+        SynapseConfiguration configuration = null;
+        if (properties != null) {
+            configuration = properties.get(SynapseConstants.SYNAPSE_CONFIGURATION) != null
+                    ? (SynapseConfiguration) properties.get(SynapseConstants.SYNAPSE_CONFIGURATION)
+                    : null;
+        }
 
         while (it.hasNext()) {
             OMNode child = (OMNode) it.next();
             if (child instanceof OMElement) {
                 if (!DESCRIPTION_Q.equals(((OMElement) child).getQName())) { // neglect the description tag
                     try {
-                        SynapseConfiguration configuration = null;
-                        if (properties != null) {
-                            configuration = properties.get(SynapseConstants.SYNAPSE_CONFIGURATION) != null
-                                    ? (SynapseConfiguration) properties.get(SynapseConstants.SYNAPSE_CONFIGURATION)
-                                    : null;
-                        }
                         Mediator med = MediatorFactoryFinder.getInstance().getMediator((OMElement) child, properties,
                                 configuration);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/core/src/main/java/org/apache/synapse/config/xml/AbstractListMediatorFactory.java`
around lines 50 - 57, The code repeatedly extracts SynapseConfiguration from the
properties map inside the loop; move the extraction of SynapseConfiguration
(using properties.get(SynapseConstants.SYNAPSE_CONFIGURATION) cast to
SynapseConfiguration) to before the loop in AbstractListMediatorFactory so the
same configuration variable is reused for each iteration, then call
MediatorFactoryFinder.getInstance().getMediator((OMElement) child, properties,
configuration) inside the loop without re-reading properties on every pass.
modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java (2)

147-159: Consider elevating log level for security audit events.

Blocked mediator attempts are security-relevant events that may warrant audit logging. The current DEBUG level (lines 150, 156) might not be enabled in production environments, potentially missing important security audit trails.

♻️ Proposed change to use INFO level for audit
         if (AccessControlListType.BLOCK_LIST == mediatorAccessControlConfig.listType) {
             if (mediatorAccessControlConfig.mediators.contains(normalizedName)) {
                 String msg = "Mediator '" + displayName + "' is blocked by mediator access control.";
-                log.debug(msg);
+                if (log.isInfoEnabled()) {
+                    log.info(msg);
+                }
                 throw new MediatorAccessControlException(msg, displayName);
             }
         } else if (AccessControlListType.ALLOW_LIST == mediatorAccessControlConfig.listType) {
             if (!mediatorAccessControlConfig.mediators.contains(normalizedName)) {
                 String msg = "Mediator '" + displayName + "' is not in the allowed mediators list.";
-                log.debug(msg);
+                if (log.isInfoEnabled()) {
+                    log.info(msg);
+                }
                 throw new MediatorAccessControlException(msg, displayName);
             }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java`
around lines 147 - 159, The security-relevant blocked/denied mediator events in
MediatorAccessControl (the checks using mediatorAccessControlConfig.listType and
the normalizedName/displayName variables) are currently logged with log.debug;
change these to a higher audit level (use log.info) for both the BLOCK_LIST and
ALLOW_LIST branches where you construct the msg and before throwing
MediatorAccessControlException so denied attempts are recorded in production
logs.

70-70: Consider marking config as volatile for defensive clarity.

While the current usage appears safe due to the synchronized initialization in MediatorFactoryFinder.getInstance() establishing a happens-before relationship, marking the field as volatile would make the thread-safety intent explicit and guard against future refactoring that might bypass the synchronized path.

♻️ Proposed change
-    private static MediatorAccessControlConfig config = MediatorAccessControlConfig.NONE;
+    private static volatile MediatorAccessControlConfig config = MediatorAccessControlConfig.NONE;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java`
at line 70, Mark the static field 'config' in MediatorAccessControl as volatile
to make the concurrency intent explicit: change the declaration of
MediatorAccessControl.config (type MediatorAccessControlConfig) to be volatile
so reads/writes have the proper memory visibility guarantees established by
MediatorFactoryFinder.getInstance(); this prevents future refactorings from
accidentally breaking the happens-before assumptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@modules/core/src/main/java/org/apache/synapse/config/xml/AbstractListMediatorFactory.java`:
- Around line 50-57: The code repeatedly extracts SynapseConfiguration from the
properties map inside the loop; move the extraction of SynapseConfiguration
(using properties.get(SynapseConstants.SYNAPSE_CONFIGURATION) cast to
SynapseConfiguration) to before the loop in AbstractListMediatorFactory so the
same configuration variable is reused for each iteration, then call
MediatorFactoryFinder.getInstance().getMediator((OMElement) child, properties,
configuration) inside the loop without re-reading properties on every pass.

In
`@modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java`:
- Around line 147-159: The security-relevant blocked/denied mediator events in
MediatorAccessControl (the checks using mediatorAccessControlConfig.listType and
the normalizedName/displayName variables) are currently logged with log.debug;
change these to a higher audit level (use log.info) for both the BLOCK_LIST and
ALLOW_LIST branches where you construct the msg and before throwing
MediatorAccessControlException so denied attempts are recorded in production
logs.
- Line 70: Mark the static field 'config' in MediatorAccessControl as volatile
to make the concurrency intent explicit: change the declaration of
MediatorAccessControl.config (type MediatorAccessControlConfig) to be volatile
so reads/writes have the proper memory visibility guarantees established by
MediatorFactoryFinder.getInstance(); this prevents future refactorings from
accidentally breaking the happens-before assumptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 122d86cb-0467-4708-8f1b-c719f3b64b5e

📥 Commits

Reviewing files that changed from the base of the PR and between d6c415e and 5a4c63f.

📒 Files selected for processing (4)
  • modules/core/src/main/java/org/apache/synapse/config/xml/AbstractListMediatorFactory.java
  • modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControl.java
  • modules/core/src/main/java/org/apache/synapse/config/xml/MediatorAccessControlException.java
  • modules/core/src/main/java/org/apache/synapse/config/xml/MediatorFactoryFinder.java

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.

2 participants