Spring-cloud-gateway: Configure RemoteAddr predicate to use X-Forwarded-For in configuration file only

Created on 16 Jan 2019  路  12Comments  路  Source: spring-cloud/spring-cloud-gateway

Concerning https://github.com/spring-cloud/spring-cloud-gateway/pull/156, every example I see needs some modification to the code. Is it possible to configure the RemoteAddr predicate to use the X-Forwarded-For header using ONLY the configuration file ?

Thanks!

enhancement help wanted

Most helpful comment

So, simplest way is to drop support for the shortcut form, which would produce this:

Using the default resolver:
````
predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    sources:

    • 192.168.11.1/24

      ````

Using a resolver defined as a bean:
````
predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    remoteAddressResolver: "#{@myReusableRemoteAddressResolver}"
    sources:

    • 192.168.11.1/24

      Using a dynamic resolver:

      predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    remoteAddressResolver: "#{T(org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver).maxTrustedIndex(2)}"
    sources:

    • 192.168.11.1/24

      ````

Let me know if this is acceptable and i will send a pull request (along with updated docs).

All 12 comments

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

Sorry for the delay.

You mean like this? http://cloud.spring.io/spring-cloud-static/Greenwich.RC2/single/spring-cloud.html#_remoteaddr_route_predicate_factory

Yes but to use the non-default resolver (x-forwarded-for w/cidr notation and trust index) we need to configure it through code, and provide our own configuration mecanism to handle different deployment scenarios.

Is it possible to configure the XForwardedRemoteAddressResolver through configuration only ? If not, wouldnt that be a nice addition, as having some kind of layers (proxy, LB) in front of gateway must be quite common ? Even different routes in the same gateway could have different rules for trust indexes of x-forwarded-for.

As a workaround we could use the Host header predicate, but we are limited to regular expressions instead of CIDR.

It is not currently. PRs welcome

Looking at this, and trying to fit the RemoteAddressResolver into an optional configuration parameter. There doesnt seem to be a way Im satisifed with, without changing the way the RemoteAddr predicate loads its config (GATHER_LIST, currently). I feel its either drop support for the shortcut form or add another type of shortcut form with optional object (much like GATHER_LIST_TAIL_FLAG), but this seems kinda odd.

Shouldnt this be in its own predicate (ie XForwardForRoutePredicateFactory) ? the configuration would be straightforward: maxTrustIndex, sources.

So, simplest way is to drop support for the shortcut form, which would produce this:

Using the default resolver:
````
predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    sources:

    • 192.168.11.1/24

      ````

Using a resolver defined as a bean:
````
predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    remoteAddressResolver: "#{@myReusableRemoteAddressResolver}"
    sources:

    • 192.168.11.1/24

      Using a dynamic resolver:

      predicates:

  • Path=/route_1
  • name: RemoteAddr
    args:
    remoteAddressResolver: "#{T(org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver).maxTrustedIndex(2)}"
    sources:

    • 192.168.11.1/24

      ````

Let me know if this is acceptable and i will send a pull request (along with updated docs).

I don't think we should drop support for the shortcut form. Just if you want to do this you can't use the shortcut.

Since we are dealing here with a list, and an optional resolver, as soon as the shortcut form is defined to be GATHER_LIST, the long form fails (the resolver is assumed to be included in the list). Shouldnt GATHER_LIST detects that a long form is used and fallback on the DEFAULT behaviour (with named keys)?

@mathieufortin01 I think your idea is very good. How did you solve this problem in the end? I feel XForwardForRoutePredicateFactory is a good idea.

I resolved in this way :

public class XForwardedAddrRoutePredicateFactory
        extends RemoteAddrRoutePredicateFactory {

    @Override
    public ShortcutType shortcutType() {
        return DEFAULT;
    }

}

then, in configuration (yaml) :

          predicates:
          - name: XForwardedAddr
            args:
              remoteAddressResolver: "#{@xForwardedRemoteAddressResolver}"
              sources:
                - 127.0.0.1

and in code :


    @Bean()
    public RemoteAddressResolver xForwardedRemoteAddressResolver() {
        return XForwardedRemoteAddressResolver.maxTrustedIndex(1);
    }

    @Bean()
    public XForwardedAddrRoutePredicateFactory xForwardedAddrRoutePredicateFactory() {
        return new XForwardedAddrRoutePredicateFactory();
    }

But probably there's a better way to do the same thing... (I mean... without the need to extend RemoteAddrRoutePredicateFactory)

because RemoteAddrRoutePredicateFactory have two methods:
`

   @Override
public ShortcutType shortcutType() {
    return GATHER_LIST;
}

@Override
public List<String> shortcutFieldOrder() {
    return Collections.singletonList("sources");
}

`

In org.springframework.cloud.gateway.support.ShortcutConfigurable, we will see the ShortcutType.GATHER_LIST process like this:

 GATHER_LIST {
            public Map<String, Object> normalize(Map<String, String> args, ShortcutConfigurable shortcutConf, SpelExpressionParser parser, BeanFactory beanFactory) {
                Map<String, Object> map = new HashMap();
                List<String> fieldOrder = shortcutConf.shortcutFieldOrder();
                Assert.isTrue(fieldOrder != null && fieldOrder.size() == 1, "Shortcut Configuration Type GATHER_LIST must have shortcutFieldOrder of size 1");
                String fieldName = (String)fieldOrder.get(0);
                map.put(fieldName, args.values().stream().map((value) -> {
                    return ShortcutConfigurable.getValue(parser, beanFactory, value);
                }).collect(Collectors.toList()));
                return map;
            }
        }

so, when I config the predicates in yml:

predicates:
  - Path=/route_1
  - name: RemoteAddr
    args:
       remoteAddressResolver: "#{T(org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver).maxTrustedIndex(2)}"
       sources: 
       - 192.168.11.1/24

When spring initialize the class RemoteAddrRoutePredicateFactory.Config as it's property "sources" as a list for two elements ,one is "192.168.11.1/24",another is a Object for XForwardedRemoteAddressResolver.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xfworld picture xfworld  路  3Comments

chsi13 picture chsi13  路  6Comments

vborcea picture vborcea  路  6Comments

esacaceres picture esacaceres  路  7Comments

aresa7796 picture aresa7796  路  6Comments