I am running kubernetes (k8s) on top of Google Cloud Patform's Container Engine (GKE) and Load Balancers (GLB). I'd like to limit the access at a k8s ingress to an IP whitelist.
Is this something I can do in k8s or GLB directly, or will I need to run things via a proxy which does it for me?
The way to whitelist source IP's in nginx-ingress is using below annotation.
ingress.kubernetes.io/whitelist-source-range
But unfortunately, Google Cloud Load Balancer does not have support for it, AFAIK.
If you're using nginx ingress controller you can use it.
The value of the annotation can be comma separated CIDR ranges.
More on whitelist annotation.
Issue tracker for progress on Google Cloud Load Balancer support for whitelisting source IP's.
Nowadays you can use nginx.ingress.kubernetes.io/whitelist-source-range
as specified here: https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#whitelist-source-range
You need to be sure that you are forwarding external IPs to your services - https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
And if you are using NGINX Ingress, make sure you set externalTrafficPolicy: Local
on your ingress controllers service.
GCP’s firewall rules cannot be applied on the Global Load Balancer it attaches with an Ingress that is created on GKE. If you want to restrict access to only specific IP addresses (for example : users connecting via VPN, in this case the VPN gateway’s IP address) then there is no out of the box solution on GCP, especially GKE.
Nginx and Http header “x-forwarded-for” to the rescue
If you are using GKE, chances are that you have a Microservices architecture and you are using an API Gateway, chances are that Nginx is the API Gateway. All that needs to be done is to configure nginx to only allow requests that have the following IPs
user.ext.static.ip → Public IP of the client
app.global.static.ip → Global static IP assigned to Ingress
nginx conf
location /my_service {
rewrite_by_lua_file validate_ip.lua;
proxy_pass http://my_service
}
validate_ip.lua
local cjson = require "cjson"
local status=""
local headers=ngx.req.get_headers()
local source_ips=headers["x-forwarded-for"]
if source_ips ~= "111.222.333.444, 555.666.777.888" then
status="NOT_ALLOWED"
end
if status ~= "" then
ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.header.content_type = "application/json; charset=utf-8"
ngx.say(cjson.encode({ status = "ERROR",message=status.."YOUR_MESSAGE" }))
return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end
For more details read here