Spring Cloud Gateway route to itself for rate limiting - spring-cloud

Is it possible to route the request to itself? The idea is to apply only the rate-limiting feature of Spring Cloud Gateway for the app. It seems like the routing is not working at all.
I have the below configuration, here application is running on port 8443 and the request should route to the same app and apply rate-limiting. Did not apply rate limit on the incoming requests.
spring:
cloud:
gateway:
routes:
- id: default_route
uri:
localhost:8443
predicates:
- Path=/app/{resource}
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 1
redis-rate-limiter.burstCapacity: 1
redis-rate-limiter.requestedTokens: 1
Also tried below to test whether only rate limiting is not working or routing itself is not working, here I'm trying to route the request to the same app and attach an extra header in response for all the POST requests. And it didn't attach the extra header, so looks like routing itself is not working.
spring:
cloud:
gateway:
routes:
- id: default_route
uri:
localhost:8443
predicates:
- Method=GET
filters:
- AddResponseHeader=X-Response-Red, Blue
Can someone please advise?

Related

How to pass extra http headers to Okteto pod?

I've deployed the Duende IdentityServer to Okteto Cloud: https://id6-jeff-tian.cloud.okteto.net/.
Although the endpoint is https from the outside, the inside pods still think they are behind HTTP protocol. You can check the discovery endpoint to find out: https://id6-jeff-tian.cloud.okteto.net/.well-known/openid-configuration
That causes issues during some redirecting. So how to let the inner pods know that they are hosted in https scheme?
Can we pass some headers to the IdP to tell it the original https schema?
These headers should be forwarded to the inner pods:
X-Forwarded-For: Holds information about the client that initiated the request and subsequent proxies in a chain of proxies. This parameter may contain IP addresses and, optionally, port numbers.
X-Forwarded-Proto: The value of the original scheme, should be https in this case.
X-Forwarded-Host: The original value of the Host header field.
I searched from some aspnet documentations and found this: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?source=recommendations&view=aspnetcore-6.0, however, I don't know how to configure the headers in Okteto, or in any k8s cluster.
Is there anyone who can shed some light here?
My ingress configurations is as follows (https://github.com/Jeff-Tian/IdentityServer/blob/main/k8s/app/ingress.yaml):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: id6
annotations:
dev.okteto.com/generate-host: id6
spec:
rules:
- http:
paths:
- backend:
service:
name: id6
port:
number: 80
path: /
pathType: ImplementationSpecific
The headers that you mention are being added to the request when it’s forwarded to your pods.
Could you dump the headers on the receiving end?
Not familiar with Duende, but does it have a setting to specify the “public URL”? That’s typically what I’ve done in the past for similar setups.

Explain CORS in Kubernetes context

The following configuration has been taken out from here:
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: cors-example
spec:
virtualhost:
fqdn: www.example.com
corsPolicy:
allowCredentials: true
allowOrigin:
- "*" # allows any origin
allowMethods:
- GET
- POST
- OPTIONS
allowHeaders:
- authorization
- cache-control
exposeHeaders:
- Content-Length
- Content-Range
maxAge: "10m" # preflight requests can be cached for 10 minutes.
routes:
- conditions:
- prefix: /
services:
- name: cors-example
port: 80
My understanding is that entrance to the cluster is allowed only through www.example.com. Any other external url won't even hit the HTTPProxy.
Hence, I really do not get the role of corsPolicy. What exactly does? What does allows any origin mean? The only origin HTTPProxy allows, is www.example.com. Correct?
In general, are there any CORS restrictions inside K8s cluster (pod to pod)? My understanding again is no.
P.S. Please do not explain what CORS is. I know very well.This is not my question
I guess your overconfidence in knowing what CORS means is clouding your reasoning. Lets imagine the following scenario:
You are hosting a REST API at www.example.com
I am a developer of www.somewebsite.com and I want to use your API.
My website tries to fetch data from www.example.com.
The above policy will tell the browser to allow me to fetch your data since I will get a response from your server with a header that allowed origins are *.
If you don't include this configuration, the browser will not let me consume your API since the domain of my website [www.somewebsite.com] is not allowed to call this API and is not the same with the one where you host the API.
You see I am still trying to fetch data from your domain, www.example.com, and the HTTP Proxy will hit your pods, but the browser is the one that will prevent me from getting the data, unless you have the above configuration.

Client Pod identity in http request header while internal service call

I have deployed an application on Kubernetes and exposed with Istio service mesh. There is 2 components in the application, UI and API. I am trying to setup canary based setup to enable AB testing. So, for these 2 components, there is 2 versions (v1 and v2) has deployed, so (min) 4 pods are running.
Assume, v1 is stable and v2 is release version. Version v1 will serve real internet traffic and version v2 will serve the request from specific ip address to make sure promotion of version v2 will not impact real production environment. Refer the attached image for clarity of traffic flow within application.
Testing of UI V2 (release version) is quite easy by filter real client ip address of user using virtualService-
- headers:
x-forwarded-for:
regex: .*1.2.3.4.*
Testing of API v2 (release version) is complex, because it is not exposed to internet and must serve traffic only from UI v2 (release version) internally but I am unable to do.
url = "http://service-api"
hdr = { 'CALLER_POD' : 'ui_v2_pod_hostname_with_release' }
req = urllib.request.Request(url, headers=hdr)
response = urllib.request.urlopen(req)
One hacky trick I have applied in application, added custom http request headers "CALLER_POD" while calling API from UI v2 pod, so that API virtualService can filter out request based on "CALLER_POD". But it looks more complex because it need code refactoring on a broader level and more human manageable in future if any changes come.
Is there any way to add UI v2 pod identity (preferable hostname) in http request header while calling API service internally on Kubernetes or Istio level.
Have you tried using sourceLabels based routing? For example:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: socks-com
spec:
hosts:
- sock.com
http:
- match:
- sourceLabels:
UI: v2
- route:
- destination:
host: API
label: v2
- route:
- destination:
host: API
subset: v1
It would also require DestinationRule update with two subsets.

Service Mesh: Using Istio to route TCP traffic based on Client IP in Virtual Service

Ingress gateway is located behind AWS ELB(classic) using nodeport and I want to route TCP traffic in Virtual Service based on client ip.
Of course Proxy Protocol of ELB is enabled.
When I use HTTP, it works. The configuration is below.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: app-vservice
namespace: test
spec:
hosts:
- "app-service"
http:
- match:
- headers:
x-forwarded-for:
exact: 123.123.123.123
route:
- destination:
host: app-service
subset: v2
- route:
- destination:
host: app-service
subset: v1
But I can't find headers field of TCP route in official documents.
Is it impossible?
Thank you.
According to docs yes there is no field to pass headers in TCPRoute in Istio. Also to answer your question every header manipulation should be done using envoy filters because Istio, built on envoy supports that and also decreases the complexity.
Using envoy and lua filters as stated in Istio docs. It can be achieved. Please follow envoy docs.
Checkout the Istio Discussion for headers in Virtual Service.
For implementation of the same using Lua. And a blog showing an example how to implement filters on envoy.

Spring Cloud Consul's gateway server returns Unable to find instance for mall-service-test

Please help.
I am using spring cloud consul 1.5.3 and spring boot 2.1.6. The default host and port that spring cloud consul uses to connect to the consul agent is localhost:8500. It works so far.
However when I change the consul host from 'localhost' to remote ip '192.168.1.89' and restart the gateway service, remote consul shows that Service Check is failed.
The output description is here:
Get http://PCOS-2019NFFBBI:8503/actuator/health:
dial tcp: lookup PCOS-2019NFFBBI on 192.168.1.1:53: no such host
And when I visited URL http://localhost:8010/mall-service-test/ to redirect to my service mall-service-test, shows the error:
org.springframework.cloud.gateway.support.NotFoundException:
Unable to find instance for mall-service-test
I use zuul gateway instead of Spring Cloud Gateway, it returns the same error.
Here is the spring cloud gateway application.yml:
server:
port: 8010
spring:
application:
name: angelcloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: mall-service-test
uri: lb://mall-service-test
predicates:
- Path= /mall-service-test/**
filters:
- StripPrefix= 1
consul:
host: http://192.168.1.89
port: 8500
healthCheckInterval: 15s
The Consul connection values need to go in bootstrap.yml.