Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Created February 24, 2024 17:56
Show Gist options
  • Select an option

  • Save mikesparr/907e1dae7cfd2a2b57b1e4f4da4915c0 to your computer and use it in GitHub Desktop.

Select an option

Save mikesparr/907e1dae7cfd2a2b57b1e4f4da4915c0 to your computer and use it in GitHub Desktop.
Demo securing a Google Kubernetes Engine (GKE) hosted app using Gateway API, HTTPRoute, and Identity Aware Proxy (IAP)
#!/usr/bin/env bash
#####################################################################
# REFERENCES
# - https://cloud.google.com/iap/docs/concepts-overview
# - https://cloud.google.com/iap/docs/enabling-kubernetes-howto
# - https://cloud.google.com/kubernetes-engine/docs/how-to/configure-gateway-resources#configure_iap
# - https://cloud.google.com/sdk/gcloud/reference/container/clusters/create
# - https://github.com/digitalocean/kubernetes-sample-apps/tree/master/podinfo-example
# - https://cloud.google.com/kubernetes-engine/docs/how-to/container-native-load-balancing
# - https://cloud.google.com/kubernetes-engine/docs/how-to/deploying-gateways#gateway_ip_addressing
# - https://cloud.google.com/kubernetes-engine/docs/how-to/secure-gateway#secure-using-ssl-certificate
# - https://cloud.google.com/iap/docs/enabling-kubernetes-howto#enabling_iap
# - https://cloud.google.com/iap/docs/managing-access
#####################################################################
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_USER=$(gcloud config get-value core/account) # set current user
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
export IDNS=${PROJECT_ID}.svc.id.goog # workflow identity domain
export GCP_REGION="us-central1" # CHANGEME (OPT)
export GCP_ZONE="us-central1-a" # CHANGEME (OPT)
export NETWORK_NAME="default"
# enable apis
gcloud services enable compute.googleapis.com \
storage.googleapis.com \
container.googleapis.com \
iap.googleapis.com \
beyondcorp.googleapis.com \
certificatemanager.googleapis.com
# configure gcloud sdk
gcloud config set compute/region $GCP_REGION
gcloud config set compute/zone $GCP_ZONE
# define vars
export EXTERNAL_ADDRESS_NAME="public-ip"
export CLUSTER_NAME="central"
export APP_NAME="podinfo"
export APP_NS=$APP_NAME
export DOMAIN="iapdemo.msparr.com" # CHANGEME: YOUR DOMAIN
export CERT_NAME="iapdemo-msparr-com" # CHANGEME: YOUR DOMAIN
export GATEWAY_NS="gateway-infra"
export GATEWAY_FILE="$APP_NAME-gateway.yaml"
export CLIENT_ID="<YOUR-OAUTH-CLIENT-ID>"
export CLIENT_SECRET="<YOUR-OAUTH-CLIENT-SECRET>" # "<copy client secret from oauth credentials>"
export SECRET_FILE="iap-secret.txt"
export SECRET_NAME="iap-secret"
# create external IP
gcloud compute addresses create $EXTERNAL_ADDRESS_NAME \
--purpose=SHARED_LOADBALANCER_VIP \
--global
export EXTERNAL_IP=$(gcloud compute addresses describe $EXTERNAL_ADDRESS_NAME --global --format="value(address)")
# create cluster
gcloud container clusters create $CLUSTER_NAME \
--location $GCP_REGION \
--gateway-api=standard \
--num-nodes=1
# deploy demo app
git clone https://github.com/digitalocean/kubernetes-sample-apps.git
kubectl apply -k ./kubernetes-sample-apps/podinfo-example/kustomize
# verify
kubectl -n $APP_NS get pods
kubectl -n $APP_NS get svc/$APP_NAME
# create ssl cert
gcloud compute ssl-certificates create $CERT_NAME \
--domains=$DOMAIN \
--global
# create gateway namespace and update ns labels for cross-namespace container-native load balancing
kubectl create ns $GATEWAY_NS
kubectl label namespaces $GATEWAY_NS shared-gateway-access=true --overwrite=true
kubectl label namespaces $APP_NS shared-gateway-access=true --overwrite=true
kubectl annotate --overwrite svc/$APP_NAME -n $APP_NS cloud.google.com/neg='{"ingress": true}'
# create k8s secret for iap oauth credentials
echo -n $CLIENT_SECRET > $SECRET_FILE
kubectl create secret generic $SECRET_NAME --from-file=key=$SECRET_FILE
# create gateway (in infra namespace) and httproute (in app namespace)
cat > $GATEWAY_FILE << EOF | kubectl apply -f -
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: external-http
namespace: $GATEWAY_NS
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
options:
networking.gke.io/pre-shared-certs: $CERT_NAME
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"
addresses:
- type: NamedAddress
value: $EXTERNAL_ADDRESS_NAME
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: $APP_NAME-external
namespace: $APP_NS
labels:
gateway: external-http
spec:
parentRefs:
- name: external-http
namespace: $GATEWAY_NS
hostnames:
- "$DOMAIN"
rules:
- backendRefs:
- name: $APP_NAME
port: 9898
---
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
name: backend-policy
namespace: $APP_NS
spec:
default:
iap:
enabled: true
oauth2ClientSecret:
name: $SECRET_NAME
clientID: $CLIENT_ID
targetRef:
group: ""
kind: Service
name: $APP_NAME
EOF
@random-972784796738
Copy link

Have you a particular configuration for your ID clients OAuth 2.0 (redirect uri, js origin, ...) ?

I got an error Error 400: redirect_uri_mismatch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment