How to add Custom-Headers and send it to Backend Service based-on a Client IP condition?

Hi All,

I'm new to Apigee and trying  to achieve the following use-case:

When the request comes to Apigee, if the request from the client belongs to a particular CIRD-Block / IP, then I need to add a Custom-Header and send it to the back-end server. If the condition is not met, then I just need to pass it to the back-end server without any change in the Header.

Is there any option to achieve the following use-case?  Thanks in Advance!!

0 4 6,714
4 REPLIES 4

You can extract the xff header from the payload, and check it with regex as a condition to assign a message that adds the header, not sure if you can use this kind of regex for the condition, if not, you can always take the header to JS script and calculate regex there, and if regex true, add your header as needed. 

Yes, thanks Denis. 

And.... one good way to inject a header, in case you're new to Apigee, is via AssignMessage.  Like this: 

<AssignMessage name='AM-InjectHeader'>
  <Set>
    <Headers>
      <Header name='Custom-Header'>{variable-containing-client-ip-address-here}</Header>
    </Headers>
  </Set>
</AssignMessage>

 You would need to attach this to the request flow in Apigee, to get that header to be sent to the request that goes to the upstream system.

You can also do something similar in JavaScript like this: 

var value = context.getVariable('variable-containing-client-ip');
context.setVariable('request.header.Custom-Header', value);

 

Akshay,

Welcome to Apigee. Some very good suggestions here, I would like to add just a bit of context on how conditions work in a flow. First, you likely want to ensure you are executing the policy that will inject the Custom-Header in the right spot. Apigee uses the concept of flows which you can read about in detail here. Typically injecting a header required for a specific resource server would go in the conditional flows section of the TargetEndpoint. Second, you have several options for identifying if the client address is in a range that requires a modification of the custom header.

Before going into that though it is probably worth a quick discussion on how configurable you want this solution to be. The easiest approach might be to hard code the logic into a condition statement. This works fine if the CIDR range isn't anticipated to change, or new ranges won't be introduced. If for instance you are making the decision based on a Class A block the likelihood of change is likely quite low and the solution can be "hard coded" into a conditional block in your proxy. But if you are trying to differentiate address blocks on a fine grained basis and anticipate  changes or new ranges being added it is worth considering an approach that uses configuration data stored in a back end system or in a Key Value Map. 

To flag a request from a client in the AT&T Class A space (12.0.0.0/8) you could wrap an AssignMessage policy as such:

 

<Flow name="Insert Custom Header">
    <Description>Insert customer header for requests originating from AT&T Class A addresses or that was forwarded through an AT&T class A address proxy</Description>
    <Request>
        <Step>
            <Name>AssignMessage-ATT-Header</Name>
        </Step>
    </Request>
    <Condition>(proxy.header.X-Forwarded-For JavaRegEx "(^12.*)|(, 12.)")</Condition>
</Flow>

 

The disadvantage of this approach is that if you need to add a new range, or modify the range you will be making a change to the proxy itself requiring a new deployment. While this is handled quite adeptly without interrupting traffic flow, it may require extra diligence if you have tight controls on production.

If you wanted to avoid changing the proxy itself you could instead pull a list of ranges from KVM. My preference is to create a JSON object that holds the configuration. With this approach you can modify the KVM entry on the fly any time a new range is added or an existing range needs to be modified. In that instance you would do something like:

  1. Read KVM entry that contains the addresses that should be handled in a special way into flow variable "foo". You can rely on Apigee runtime to efficiently cache the entry.
  2. Call a JavaScript policy that parses "foo" and examines the request to determine matches - if one is found then set flow variable "bar" to true.
  3. Call your AssignMessage policy to change the custom header if bar==true.

Obviously this approach requires more testing and requires some smart coding in the JavaScript to be efficient but can be advantageous in many scenarios.

Best of luck!

David Allen, joining the party on the new Community!  Welcome and thank you for the informative and helpful contribution, sir!