Following recipe provides a walk-through for setting up secure GKE Ingress with Identity-Aware Proxy based authentication.
IAP enforces access control policies for backend services associated with an Ingress, so they can be accessed only by authenticated users or applications with correct Identity and Access Management (IAM) role.
- Protect backend services with central, managed authorization layer that leverages IAM roles
- Take advantages of application-level access control model for backend services instead of relying on network-level solutions like firewalls or VPNs
- GKE version 1.10.5+ for BackendConfig support
- Tested and validated with GKE version 1.19.10 on Jun 16th 2021
IAP is integrated through ingress for GKE by leveraging BackendConfig CRD.
This object is associated with a given service and allows to specify configuration for HTTPs Load Balancer
that handles incoming traffic. IAP can be enabled for a service by specifying iap
block with required
configuration parameters in a related BackendConfig
.
Requests that are routed by Load Balancer to IAP protected service will be redirected to IAP authentication server. IAP will perform identity check, redirecting to Google Account sign-in flow if necessary. Once identity is validated, authentication server will check user's IAM roles and validate if the user is authorized to access the resource.
Prerequisites:
gcloud
setup (check Prerequisite: gcloud setup below)- GKE cluster up and running (check Prerequisite: GKE setup below)
- IAP configured (check Prerequisite: IAP setup below)
Steps:
-
Reserve global static IP address for an ingress
gcloud compute addresses create iap-test --global
-
Configure DNS
A
record for your domain with IP address reserved aboveYou can use
gcloud
command to get information about reserved address.$ gcloud compute addresses describe iap-test --global address: 123.213.53.69 addressType: EXTERNAL ...(output omitted)... $
Once configured, verify that your domain name resolves to the reserved IP address.
$ nslookup -query=a iap-test.mydomain.com ...(output omitted).. Non-authoritative answer: Name: iap-test.mydomain.comm Address: 123.213.53.69
-
Create kubernetes secret with oAuth client credentials from IAP setup prerequisite
kubectl create secret generic iap-test \ --from-literal=client_id=ATA4NDY1Mzc3NTEyMS1taMWNp1yW50LmNvbQ== \ --from-literal=client_secret=MjgySf4zSXF1Yk5uTlAwandOc0xrRjFY
-
Replace
$DOMAIN
variable iniap-ingress.yaml
file with your domain namesed -i '.bak' 's/$DOMAIN/iap-test.mydomain.com/g' iap-ingress.yaml
-
Apply
iap-ingress.yaml
file$ kubectl apply -f iap-ingress.yaml ingress.networking.k8s.io/iap-test created managedcertificate.networking.gke.io/iap-test created backendconfig.cloud.google.com/iap-test created service/whereami created deployment.apps/whereami created $
-
Wait until all created objects reach desired state
-
Enable IAP on your backend service
Once backend service is created, enable IAP protection on it and update IAM policies. This can be done from Google Cloud Console.
- Browse to Identity-Aware Proxy page
- Locate your backend service on a resources list under HTTPS Resources tab
- Toggle IAP protection for your backend service
- Select checkbox next to your service so that info panel appears on the right
- Click Add Member button on the right panel to add members
- Add Google Account or Service Account with IAP-secured Web App User role
-
Verify and enjoy
Verification steps depends on Member type that was configured for a backend service in IAP configuration.
- For Google account, simply browse to your domain i.e.
https://iap-test.mydomain.com
and authenticate with your user credentials (you might need to switch your browser to incognito mode) - For service accounts, follow IAP Programmatic authentication guide
Once authenticated, whereami service used is this recipe will return JSON data, including client authentication request headers. Check below response example for reference:
{ "cluster_name": "cluster-test", "headers": { "X-Goog-Authenticated-User-Email": "accounts.google.com:[email protected]", "X-Goog-Authenticated-User-Id": "accounts.google.com:413563208703235040404", "X-Goog-Iap-Jwt-Assertion": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjBvZUxjUSJ9...", ...(output omitted)... }, ...(output omitted)... }
- For Google account, simply browse to your domain i.e.
-
Authorize gcloud to access GCP
gcloud auth login
-
Configure your project
gcloud config set project my-project
-
Enable GKE API
gcloud services enable container.googleapis.com
-
Create simple zonal GKE cluster for tests
gcloud container clusters create cluster-test \ --zone europe-central2-a \ --release-channel regular \ --enable-ip-alias
-
Configure client credentials for a new cluster
gcloud container clusters get-credentials cluster-test \ --zone europe-central2-a
IAP setup can be done from Google Cloud Console.
-
Configure oAuth consent screen
- Browse to OAuth consent screen
- Select desired usage type: Internal or External and click Create button
- As a minimum, fill all required fields: app name, user support email, developer contact email
- Click Save and Continue button
-
Configure oAuth credentials
- Browse to API & Services Credentials screen
- Click Create Credentials from bottom menu and select OAuth Client ID from drop-down list
- Select Web application as application type
- Fill name of your oAuth client
- Click Create button
- Once client is created, select it from the list to open details page
- Notice Client ID and Client Secret - you will use them in later configurations. They can be also downladed in JSON format.
- Add Authorized redirect URI in a format
https://iap.googleapis.com/v1/oauth/clientIds/CLIENT_ID:handleRedirect
(replace CLIENT_ID with your valid one)
The test for this recipe will be skipped if the required environment variables are not set.
To run the test, you need to have a project($DNS_PROJECT) that has Cloud DNS enabled. In this project, set up a public DNS zone with a DNS domain you control. See Create a managed public zone in Cloud DNS
in setup guide.
Then export the zone name and DNS name as environment variables. Make sure the current service account has role/dns_admin access to the DNS project.
export DNS_PROJECT=dns-project \
export DNS_ZONE=example-zone-name
export DNS_NAME=myzone.example.com
You also need to have a support email that follows the requirement described in Programmatic OAuth clients.
export SUPPORT_EMAIL=support-email