How to chain proxies securely in Apigee

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.

 

epbgonzalez_0-1672420094139.png

                                  Image source: Apigee documentation

 

epbgonzalez_1-1672420094155.png

                                      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.

 

The problem

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.

 

epbgonzalez_0-1672420667287.png

 

Here’s some sample code:

  1. First we need to create the RaiseFault definition:
<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.

Contributors
Comments
icherk
Bronze 1
Bronze 1

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?

emarcotte
Bronze 5
Bronze 5

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

epbgonzalez
Staff

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.

apigee_achu
Bronze 1
Bronze 1

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?

epbgonzalez
Staff

Yes, @apigee_achu  this feature is live. Do you mind sharing the debug session? Thanks!

Version history
Last update:
‎12-30-2022 09:21 AM
Updated by: