Skip to content

Instantly share code, notes, and snippets.

@salrashid123
Last active March 8, 2025 13:34
Show Gist options
  • Save salrashid123/6b7e65ae927edde93312e25157a5c51e to your computer and use it in GitHub Desktop.
Save salrashid123/6b7e65ae927edde93312e25157a5c51e to your computer and use it in GitHub Desktop.
Istio with GCP OIDC Authorization

Simple demo of istio authorization rules using GCP OIDC tokens

Basically, this will allow inbound OIDC authentication and authorization for a service using a google issued id_token

Setup

First install minikube (i'm using kvm2 but you can use anything)

minikube start --driver=kvm2  --cpus=4 --kubernetes-version=v1.28 --host-only-cidr 192.168.39.1/24

## enable an external LB
minikube addons enable metallb

### get its ip
$ minikube ip
192.168.39.59

### configure the LB, when prompted, pick a range cidr, i entered in the following
minikube addons configure metallb
# -- Enter Load Balancer Start IP: 192.168.39.104
# -- Enter Load Balancer End IP: 192.168.39.110

## optionally start the dashboard
# minikube dashboard


### download and install istio
kubectl create ns istio-system
export ISTIO_VERSION=1.24.0
export ISTIO_VERSION_MINOR=1.24
wget -P /tmp/ https://github.com/istio/istio/releases/download/$ISTIO_VERSION/istio-$ISTIO_VERSION-linux-amd64.tar.gz
tar xvf /tmp/istio-$ISTIO_VERSION-linux-amd64.tar.gz -C /tmp/
rm /tmp/istio-$ISTIO_VERSION-linux-amd64.tar.gz

export PATH=/tmp/istio-$ISTIO_VERSION/bin:$PATH
istioctl install --set profile=demo \
 --set meshConfig.enableAutoMtls=true  \
 --set values.gateways.istio-ingressgateway.runAsRoot=true \
 --set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY \
 --set meshConfig.defaultConfig.gatewayTopology.forwardClientCertDetails=SANITIZE_SET

kubectl label namespace default istio-injection=enabled
kubectl get svc istio-ingressgateway -n istio-system

export GATEWAY_IP=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $GATEWAY_IP

GCP Authentication

In this demo, i used a GCP service account json file for the oidc token

gcloud auth activate-service-account --key-file=/path/to/svc_account.json
TOKEN=`gcloud auth print-identity-token --audiences=https://svc1.example.com`

if you decoded the token i got, the claims showed:

{
  "aud": "https://svc1.example.com",
  "azp": "[email protected]",
  "email": "[email protected]",
  "email_verified": true,
  "exp": 1741234050,
  "iat": 1741230450,
  "iss": "https://accounts.google.com",
  "sub": "100890260483227123173"
}

Which means we need to authoize the iss, aud and sub (preferably) or email fields

In my case, see the values in the auth-policy.yaml file below.

For your svc account, edit it appropriately and then apply:

kubectl apply  -f istio-ingress-gateway.yaml 
kubectl apply  -f istio-fe-svc1.yaml -f auth-policy.yaml -f auth-deployment.yaml

Specifically note auth-policy.yaml. What that enforces is any google issued id_token through the gateway but the backend service will only accept a single source serve.

The source service enforcement can be done either by inspecting to or from rules:

 rules:
 - to:
   - operation:
       methods: ["GET"]
   when:
   - key: request.auth.claims[iss]
     values: ["https://accounts.google.com"]
   - key: request.auth.claims[aud]
     values: ["https://svc1.example.com"]
   - key: request.auth.claims[email]
     values: ["[email protected]"]

or

 rules:
 - from:
   - source:
      requestPrincipals: ["https://accounts.google.com/100890260483227123173"]

Once the services are running, call:

curl -s  --resolve istio.domain.com:80:$GATEWAY_IP  \
    -H "Host: svc1.example.com" -H "Authorization: Bearer $TOKEN"  -w "%{http_code}\n" http://istio.domain.com/get


### you should see a 200 ok response back
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "svc1.example.com", 
    "User-Agent": "curl/8.12.1-DEV", 
    "X-Envoy-Attempt-Count": "1", 
    "X-Envoy-Internal": "true", 
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/svc1-sa;Hash=f2998dfeeb4690a95ae10fd1145848f26fec61b8fc531d0a49b89f2bd6f4a107;Subject=\"\";URI=spiffe://cluster.local/ns/istio-system/sa/istio-ingressgateway-service-account"
  }, 
  "origin": "10.244.0.1", 
  "url": "http://svc1.example.com/get"
}
200

To verify the authorization steps, change the value of request.auth.claims[email] or the value of requestPrincipals and reapply the config


  • `istio-ingress-gateway.yaml
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: my-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*" 
  • istio-fe-svc1.yaml
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
  name: svc1-virtualservice
spec:
  hosts:
  - "svc1.example.com"
  gateways:
  - my-gateway
  http:
  - route:
    - destination:
        host: svc1
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
  name: svc1-destination
spec:
  host: svc1
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
    loadBalancer:
      simple: ROUND_ROBIN
  • auth-deployment.yaml
apiVersion: v1
kind: Service
metadata:
  name: svc1
  labels:
    app: svc1
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: svc1
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: svc1-sa
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: svc1
spec:
  selector:
    matchLabels:
      app: svc1
  replicas: 1
  template:
    metadata:
      labels:
        app: svc1
    spec:
      serviceAccountName: svc1-sa
      containers:
      - name: myapp-container
        image: kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
  • auth-policy.yaml
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: deny-all-authz-ns
spec:
  {}
---
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
 name: igaupolicy
 namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  jwtRules:
  - issuer: "https://accounts.google.com"
    audiences:
    - "https://svc1.example.com"
    jwksUri: "https://www.googleapis.com/oauth2/v3/certs"
    forwardOriginalToken: true
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: igazpolicy
 namespace: istio-system
spec:
 selector:
   matchLabels:
     app: istio-ingressgateway
 rules:
 - to:
   - operation:
       methods: ["GET"]
   when:
   - key: request.auth.claims[iss]
     values: ["https://accounts.google.com"]
---
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
 name: svc1-au
spec:
  selector:
    matchLabels:
      app: svc1
  jwtRules:
  - issuer: "https://accounts.google.com"
    audiences:
    - "https://svc1.example.com"
    jwksUri: "https://www.googleapis.com/oauth2/v3/certs"
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
 name: svc1-az
spec:
 action: ALLOW
 selector:
   matchLabels:
     app: svc1
 rules:
#  - to:
#    - operation:
#        methods: ["GET"]
#    when:
#    - key: request.auth.claims[iss]
#      values: ["https://accounts.google.com"]
#    - key: request.auth.claims[aud]
#      values: ["https://svc1.example.com"]
#    - key: request.auth.claims[email]
#      values: ["[email protected]"]
 - from:
   - source:
      requestPrincipals: ["https://accounts.google.com/100890260483227123173"]
---
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment