Proxy chaining is one of the most commonly used features in Apigee for sharing common / discreet API resources to achieve lightweight service orchestration without adding network hops. A chained proxy is an internal proxy that is called by one or more proxies. You can specify that one proxy is the target endpoint of another, effectively connecting the two proxies in a proxy chain. You can find more information in the official documentation.
Image source: Apigee documentation
Image source: Apigee documentation
In this article I will explain how you can set up governance controls to restrict access and recognize chained traffic in Apigee.
Securing access among chained proxies can be problematic. If both proxies are part of the same product bundle then they could easily share common security policies, but both will be available to clients. Customers usually prefer to have a separation between external APIs and internal / discreet APIs that should only be consumable by other APIs, and the usual workaround has been to include Access Control and Security policies to limit access to these kinds of APIs. This workaround introduces unnecessary complexity to the proxy configuration and (sometimes) latency.
So, how do we identify a proxy from an external user calling the API?
Starting with Apigee X, there is now a flow variable called `client.local` that will be set to ‘true’ when a proxy is being called from another proxy and this variable will be set to ‘null’ or ‘false’ when an end user is calling the proxy directly. Additionally, a dot (.) character followed by a random number will be appended to the `messageid` flow variable.
How to use the new variables to restrict access?
Very simple! Just configure a conditional flow that raises a fault for all transactions that do not have client.local as true. You can customize the error code returned to the consumer in the Raise Fault policy or in the Fault Rules section.
Here’s some sample code:
<RaiseFault name="RF-Unathorized-Proxy-chain">
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
<FaultResponse>
<Set>
<StatusCode>403</StatusCode>
<ReasonPhrase>You don’t have permission to access this resource</ReasonPhrase>
</Set>
</FaultResponse>
</RaiseFault>
2. We can then create the conditional flow in our proxy configuration:
<ProxyEndpoint name="default">
<PreFlow>
<Request/>
<Response/>
</PreFlow>
<Flows>
<Flow name="Flow-1">
<Request>
<Step>
<Name>RF-Unathorized-Proxy-chain</Name>
<Condition>client.local != “true”</Condition>
</Step>
</Request>
<Response/>
</Flow>
</Flows>
<PostFlow>
<Request/>
<Response/>
</PostFlow>
...
</ProxyEndpoint>
Thanks to @gonzalezruben for his help brainstorming and reviewing this article.
Hi! Very nice, thank you! But can't find any references in documentation to `client.local`. @epbgonzalez I'm wondering if it's really reliable to use it. Will this variable `client.local` be supported in future same as dot (.) character in x-request-header-id?
As icherk points out, this is a completely undocumented field in the link provided. Is it safe to refer to this value? Similarly https://cloud.google.com/apigee/docs/api-platform/fundamentals/connecting-proxies-other-proxies#chai...suggests that i should be able to use `AccessControl` with localhost, however no matter what I do, I get external IP addresses reported in my denial messages when hitting the chained proxy. It is _really_ hard to know what is an actually supported approach for using these techniques...
Hi @emarcotte @icherk Apologies for the delayed response. We are in between releases and that's why that flow variable still hasn't made it to the official documentation but it is safe to use. Hope this helps.
Hi @epbgonzalez
We have been testing in our ApigeeX instance but we cant seem to get`client.local`variable in our chained proxy implementation. Is this feature live yet?
Yes, @apigee_achu this feature is live. Do you mind sharing the debug session? Thanks!