Advanced APISIX Routing: A Guide to Create Exception Routes via Helm
This guide will equip users with the understanding and practical steps to define "exception routes" in APISIX using Helm values.yaml
. This allows specific sub-paths of a service to have different routing behaviors (e.g., bypassing authentication) than the main service route.
Introduction to Exception Routes
A. What is an Exception Route?
An exception route is a specialized APISIX route configuration that overrides the default or general routing behavior for a very specific subset of traffic targeting a service. Think of it like a special access lane on a highway that has different rules than the main lanes, but only for specific vehicles or destinations. For our services managed by APISIX, this means a particular URL path might bypass standard authentication, have unique rewrite rules, or different security policies.
B. Why Use Exception Routes? (Purpose & Use Cases)
Exception routes provide granular control and are typically used for:
Public Endpoints: Exposing specific API paths (e.g.,
/service/api/v1/public/status
,/service/webhooks/external-system
) that should not require user authentication, while the rest of the service remains secured.Specific Authentication Schemes: Applying a different authentication method (e.g., API key) to one endpoint while others use OIDC.
Custom URL Rewriting: Supporting legacy URL paths by rewriting them to new backend structures, or creating user-friendly vanity URLs for specific functionalities.
Targeted Security Policies: Applying stricter rate-limiting or IP whitelisting to sensitive administrative sub-paths.
Unique CORS Policies: Allowing cross-origin requests from specific domains for certain API endpoints but not others.
A/B Testing or Canary Releases: Directing a small fraction of traffic for a particular path to a new version of a service.
C. How it Works with APISIX & Helm
In your environment, APISIX routes are defined within the apisixRoutes
list in the relevant component's section of your Helm values.yaml
file. When a request arrives:
APISIX evaluates potential matching routes based on criteria like path, method, headers, etc.
If multiple routes match, the route with the highest
priority
value is chosen (higher number means higher precedence).The plugins configured for that chosen route are then executed.
To create an exception, you define a new route for the specific path with a higher priority than the general route for that service, and then customize its plugins
block.
Before Creating an Exception Route: Key Considerations
Thoughtful planning before adding an exception route can prevent headaches and security issues down the line.
A. Is an Exception Truly Necessary?
Alternatives: Could the desired behavior be implemented within the application logic itself? Can existing plugins be configured more flexibly?
Simplicity: Strive to keep the gateway configuration as simple as possible. Each exception adds a layer of complexity.
B. Security Implications (⚠️ CRITICAL)
Bypassing Authentication: This is the most common use case for exceptions but also the riskiest.
Thoroughly vet the endpoint: Ensure it reveals no sensitive data and does not allow any state-changing operations that could be exploited.
Principle of Least Privilege: The exception should grant the absolute minimum necessary access.
Modifying Other Security Plugins: If you're also disabling or altering rate limiting, IP restrictions, or other security plugins for the exception path, understand the cumulative risk.
C. Scope Definition
Path Specificity: Be as precise as possible with your
paths
. An overly broad path (e.g.,/service/public/*
) could unintentionally expose more than intended if new sub-paths are added later. Prefer specific paths like/service/public/resource-info
.HTTP Methods: Does the exception need to apply to all methods (
GET
,POST
,PUT
,DELETE
, etc.), or only one or two (e.g.,GET
for public data,POST
for an unauthenticated webhook)? Specify this in themethods
array of the route if necessary.Other Conditions: While your current Helm structure primarily focuses on paths and methods for matching, APISIX itself can match on headers, query parameters, and more. If an exception needs to be highly conditional, direct APISIX CRD modification might be needed if not expressible via current Helm templates.
D. Impact on Existing Routes & Services
Priority Conflicts: Map out the priorities of existing routes for the component. Ensure your new exception route has a distinctly higher priority to be evaluated first but doesn't clash with other high-priority routes in an unexpected way.
Unintended Overrides: A poorly defined exception (e.g., a too-generic path with high priority) could "steal" traffic intended for other routes or even other services if paths are not carefully namespaced.
E. Maintainability & Documentation
Clarity: Use a very descriptive
nameSuffix
for the route so its purpose is immediately obvious (e.g.,login-unsecured
,webhook-external-system-noauth
).Internal Documentation: Crucially, maintain a log or dedicated documentation page (e.g., in Confluence) detailing each exception:
What service it's for.
The specific path(s).
The reason for the exception and its intended behavior.
Who requested/approved it and when.
Any associated risks and mitigations.
Lifecycle Management: Is the exception permanent or temporary? If temporary, set a review date or a plan for its removal to prevent obsolete exceptions from accumulating.
Pros and Cons of Using Exception Routes
Pros | Cons |
---|---|
✅ Flexibility: Fine-grained control over specific API paths without altering application code. | ❌ Increased Complexity: More routes can make the gateway configuration harder to manage and reason about. |
✅ Targeted Policies: Apply different security, rewrite, or CORS rules precisely where needed. | ❌ Potential Security Holes: Incorrectly configured exceptions (especially those bypassing auth) can inadvertently create vulnerabilities. |
✅ Decoupling: Handles some cross-cutting concerns (like public access) at the gateway layer. | ❌ Debugging Challenges: Tracing requests through multiple route possibilities can be more complex. |
✅ Rapid Adjustments: Quickly enable/disable access or change behavior for sub-paths via Helm value changes. | ❌ Configuration Obscurity: Overuse can make the overall system's behavior less obvious from application code alone. The gateway's role becomes critical. |
✅ Simplified App Logic: Applications might not need to handle every edge case for exposure if the gateway manages it. | ❌ Maintenance Overhead: Requires careful documentation, review, and cleanup of obsolete exceptions. |
How to Add an Exception Route (Practical Steps & Example)
Let's walk through adding an exception to the agent-manager
service. Assume the main /agent-manager/*
path requires authentication (as per global.apisix.keycloak
defaults when enableAuth: true
), but we want to expose /agent-manager/public-status
without authentication.
A. Locate Component & apisixRoutes
in values.yaml
Find the agent-manager
section in your Helm values.yaml
file.
B. Define the New Exception Route
You will add a new YAML dictionary (an item starting with -
) to the apisixRoutes
list for agent-manager
. For readability, it's good practice to place higher priority (exception) routes before lower priority (general) routes within the list for that component.
Example values.yaml
modification for agent-manager
:
agent-manager:
# ... other agent-manager settings ...
apisixRoutes:
# --- START: New Exception Route for Public Status ---
- nameSuffix: "public-status-noauth" # 1. Clearly identifies the exception's purpose
enabled: true # 2. Route is active
priority: 10 # 3. HIGHER priority than the main route below
paths: ["/agent-manager/public-status"] # 4. The specific path for this exception
# methods: ["GET"] # 5. Optional: Restrict to GET if only status retrieval
backendServicePort: 3000 # 6. Usually targets the same backend service
plugins: # 7. Define the exceptional behavior
enableAuth: false # << CRITICAL: Authentication is DISABLED for this path
enableRewrite: true # Example: still strip /agent-manager prefix
# so backend receives /public-status.
# If the backend expects the full path, or a different
# rewrite, adjust 'rewriteStripPrefix',
# 'rewriteRegexUriFrom'/'To' as needed.
# enableCors: true # Optionally, define specific CORS if this public path
# corsAllowOrigins: "*" # needs broader access than other agent-manager paths.
# customPlugins: [] # Any other plugins specific to this exception
# --- END: New Exception Route ---
# Existing main "secured" route for agent-manager (conceptual example)
- nameSuffix: "secured-main"
enabled: true
priority: 0 # Lower priority, acts as a general rule for /agent-manager/*
paths: ["/agent-manager/*"] # Matches requests not caught by higher priority routes
backendServicePort: 3000
plugins:
enableAuth: true # Main access to agent-manager requires authentication
enableRewrite: true # Standard prefix stripping (backend sees /*)
enableCors: true # Default CORS behavior for this service
# ... other standard plugins for agent-manager ...
Explanation of Key Fields for the Exception Route:
nameSuffix: "public-status-noauth"
: Helps create a unique and understandable APISIX route name (e.g.,ef-cx-agent-manager-public-status-noauth
).priority: 10
: This ensures APISIX evaluates this route before thesecured-main
route (which haspriority: 0
). If a request comes for/agent-manager/public-status
, this route will match first.paths: ["/agent-manager/public-status"]
: This route only applies to requests for this exact path.plugins.enableAuth: false
: This is the core of the exception for this example – it tells APISIX not to enforce the default authentication (e.g., Keycloak OIDC defined inglobal.apisix.keycloak
) for this specific path.
After the Modification: What to Expect & Verify
Once you've added the exception route definition to your values.yaml
and deployed the changes (e.g., via helm upgrade
):
A. Expected Behavior
Requests to the exception path (e.g.,
https://<your-fqdn>/agent-manager/public-status
) should now operate under the new plugin rules (e.g., accessible without an authentication token).Requests to all other paths under
/agent-manager/*
(e.g.,https://<your-fqdn>/agent-manager/some-other-api
) should still be governed by the original, lower-priority "secured-main" route and its plugins (e.g., still require authentication).Traffic to entirely different services/components should be completely unaffected.
B. Verification Steps (🧪 CRITICAL)
Always test thoroughly after deploying changes!
Test the Exception Path:
Use a tool like
curl
, Postman, or your browser.Access the exception URL (e.g.,
https://<your-fqdn>/agent-manager/public-status
).Verify that it behaves as expected (e.g., you get a successful response without providing an auth token if
enableAuth: false
).If you configured specific rewrites or custom plugin behaviors, verify those too.
Test Non-Exception Paths (for the same component):
Access other URLs for the same component (e.g.,
https://<your-fqdn>/agent-manager/some-secured-data
).Verify they still adhere to the original rules (e.g., prompt for authentication or return a 401/403 if no token is provided).
Test Other Services:
Make a few sample requests to unrelated services to ensure they haven't been inadvertently affected.
Check Logs (If Accessible):
APISIX Logs: If you have access, APISIX logs can show which route was matched for a given request and which plugins were applied. This is very useful for debugging.
Application Logs: Check the logs of the backend service (
agent-manager
in our example) to see if requests are arriving as expected (e.g., with the correct rewritten path, and without user identity information if authentication was bypassed at the gateway).
C. Troubleshooting Common Issues
Exception Not Working (Old behavior persists):
Priority: Double-check the
priority
value. Is it numerically higher than the general route?Path Matching: Is the path in your test request exactly matching one defined in the
paths
array of your exception route? Check for trailing slashes, case sensitivity (paths are usually case-sensitive), or typos.enabled: true
: Confirm the exception route is enabled in the YAML.Helm Deployment: Ensure your
helm upgrade
command was successful and the Kubernetes resources reflecting your changes (especially APISIX CRDs likeApisixRoute
) were updated in the cluster. There can sometimes be a short delay for APISIX to pick up changes.
Exception Too Broad (Affecting other paths):
Your exception route's
paths
might be too generic. Make them more specific.Re-evaluate
priority
if multiple custom routes could potentially overlap.
Security Vulnerability Introduced:
If an endpoint is exposed that shouldn't be, immediately disable the problematic exception route (
enabled: false
and redeploy) or fix its path/plugin configuration.
Best Practices & Maintaining Sanity
🧘 Minimize Exceptions: Use them only when genuinely necessary. The more exceptions, the harder the system is to understand and maintain.
🏷️ Clear Naming: Use descriptive
nameSuffix
values (e.g.,login-unsecured
,metrics-prometheus-only
,webhook-systemX-noauth
).🎯 Specificity is Key: Define
paths
(andmethods
if applicable) as narrowly and precisely as possible for your exceptions.✍️ Document Everything: For each exception route, maintain clear documentation (e.g., in Confluence, or as extensive comments in your
values.yaml
):Its purpose and justification.
The component and specific path(s) it affects.
The exact plugin changes and why they are needed.
Any associated security considerations or approvals.
🧐 Regular Audits: Periodically review all defined exception routes. Are they still necessary? Are they configured correctly according to current security best practices? Remove obsolete exceptions promptly.
💾 Version Control: All
values.yaml
changes should be committed to Git (or your version control system), with clear commit messages explaining the addition, modification, or removal of exception routes.