Created
February 24, 2024 17:56
-
-
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Identity Aware Proxy (IAP) on GKE using Gateway API
This example illustrates how you can configure an application running on GKE to be secured using Google's Identity Aware Proxy (IAP) via Oauth consent flow, leveraging the latest "Ingress" best practice
Gateway API
andHTTPRoute
.Results
After authentication, the demo app (thanks to Digital Ocean for cute

podinfo
demo app) should look like thisPrior to authorization, however, the app access will be restricted like this:

Auth flow example
When first visiting the site, it may prompt you to log in with Google's OAuth flow

And if you are wise, you will likely have a 2-factor authentication step

After you authenticated, and your user is added in the IAP admin "Add Principals" (see below), you should be granted access to the site.
Authenticating additional users