Reputation: 9669
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?
Upvotes: 8
Views: 10504
Reputation: 1032
To add to @rahul-sharma 's answer:
You can use BackendConfig
CRD from GKE to bind the CloudArmour rules to the ingress service.
This was a pain to handle with terraform which I was trying for quite some time. With CRD, it is very easy.
# my-backendconfig.yaml
apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
name: my-backendconfig
spec:
securityPolicy:
name: "deny-access-policy" #cloud-armour policy name
and add these annotations to the service behind the Ingress
apiVersion: v1
kind: Service
metadata:
name: my-api
labels:
app: my-app
annotations:
cloud.google.com/backend-config: '{"ports": {"80":"my-backendconfig"}}'
cloud.google.com/neg: '{"ingress": true}'
spec:
type: ClusterIP
ports:
- port: 80
targetPort: api-http
protocol: TCP
name: api-http
selector:
app: my-app
Upvotes: 0
Reputation: 2117
I was looking into doing this and I found a fairly easy way to do it, assuming your service is of type: LoadBalancer
, all you need to do nowadays is to add the following field to the spec
definition.
loadBalancerSourceRanges:
- x.x.x.x/32
You can add as many sources cidr's as needed, in case you are curious this is translated to a firewall rule that allows traffic from those sources, you can find the rule in the network that your service is using.
Upvotes: 1
Reputation: 5058
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 annotations.
Issue tracker for progress on Google Cloud Load Balancer support for whitelisting source IP's.
Upvotes: 6
Reputation: 857
You can use Cloud Armor, Add a Policy, create your Allow/Deny Rules, then simply attach k8s LB in the target.
Upvotes: 4
Reputation: 39
You could use CORS and only allow the IP from the frontend to hit your microservices.
Upvotes: 0
Reputation: 73
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.
Upvotes: 2
Reputation: 11
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
Upvotes: 0