Google SAML
Set up SSO with SAML for KubeSense
This article describes how to set up SAML-based single sign-on (SSO) for the KubeSense observability platform using Google as the identity provider (IdP).
When you set up SSO for a SAML application, your users sign in to KubeSense using their managed Google Account credentials.
Before you begin
To configure SSO for the KubeSense SAML app, sign in to your Google Admin console using a super administrator account.
You'll also need:
- A KubeSense deployment reachable at a public HTTPS URL (e.g.
https://kubesense.example.com) - The ability to run
helm upgradeagainst the deployment
Step 1: Add the custom SAML app
- In the Admin console, go to Menu → Apps → Web and mobile apps
- Click Add app → Add custom SAML app
- On the App details page:
- Enter App name:
KubeSense - App icon (optional): download the official KubeSense logo and upload it
- Enter App name:
- Click Continue
Step 2: Download the IdP metadata
On the Google Identity Provider details page:
- Click Download metadata to save the IdP metadata XML file (e.g.
GoogleIDPMetadata.xml) - Click Continue
You'll paste the contents of this file into the KubeSense config in Step 5.
Step 3: Enter Service provider details
On the Service provider details page, enter the following values exactly:
| Field | Value |
|---|---|
| ACS URL | https://<KUBESENSE_DOMAIN>/api/saml/acs |
| Entity ID | https://<KUBESENSE_DOMAIN>/saml |
| Start URL (optional) | https://<KUBESENSE_DOMAIN>/login |
| Signed response | Leave unchecked |
| Name ID format | EMAIL |
| Name ID | Basic Information > Primary email |
Replace <KUBESENSE_DOMAIN> with your actual KubeSense domain (e.g. kubesense.example.com).
Click Continue.
Step 4: Add attribute mappings
On the Attribute mapping page, add the following mappings:
| Google directory attribute | App attribute |
|---|---|
| Primary email | email |
| First name | first_name |
| Last name | last_name |
Click Finish.
Step 5: Configure KubeSense via Helm values
SAML is fully driven by Helm values — you do not edit ConfigMaps, Secrets, or Deployment manifests directly. Add the following block to your values.yaml (or pass via --set-file):
api:
saml:
enabled: true
rootUrl: "https://<KUBESENSE_DOMAIN>"
entityId: "https://<KUBESENSE_DOMAIN>/saml"
# Paste the contents of GoogleIDPMetadata.xml from Step 2 here.
idpMetadataXml: |
<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://accounts.google.com/o/saml2?idpid=...">
...full XML body...
</md:EntityDescriptor>Replace <KUBESENSE_DOMAIN> with your actual domain (no trailing slash).
If you'd rather keep the metadata XML in a separate file, use --set-file:
helm upgrade kubesense ./charts/kubesense-server \
-f values.yaml \
--set api.saml.enabled=true \
--set api.saml.rootUrl=https://kubesense.example.com \
--set api.saml.entityId=https://kubesense.example.com/saml \
--set-file api.saml.idpMetadataXml=./GoogleIDPMetadata.xmlThat's it. The chart takes care of everything else:
kubesense-saml-secretSecret created on first install with a random 32-byte master key. Preserved acrosshelm upgradevialookup(no rotation, no churn).- API ConfigMap rendered with
SAML_ENABLED,SAML_ENTITY_ID,SAML_ROOT_URL,SAML_IDP_METADATA_XMLenv vars (Viper reads them at startup). - API Deployment envFrom-wired to
kubesense-saml-secretsoSAML_KEY_ENCRYPTION_KEYis injected. - Webapp ConfigMap sets
ENABLE_GOOGLE_SAML=trueso the "Sign in with Google SAML" button renders. - API binary auto-generates the SP signing key (self-signed cert + RSA-2048) on first SAML init, encrypts it with AES-256-GCM using the master key, and persists in the
saml_sp_keystable. Restarts reuse the same key.
Configuration reference
values.yaml → api.saml
| Field | Required | Description |
|---|---|---|
enabled | yes | Set to true to render SAML resources and register /api/saml/* routes |
rootUrl | yes | Public HTTPS URL of the KubeSense deployment, e.g. https://kubesense.example.com |
entityId | yes | SP Entity ID — must match the Entity ID in Google admin (typically <rootUrl>/saml) |
idpMetadataXml | one of two | Inline IdP metadata XML (recommended) |
idpMetadataUrl | one of two | URL fetched at startup (discouraged — adds startup network dep) |
Chart-managed Secrets
| Name | Purpose |
|---|---|
kubesense-saml-secret | Holds SAML_KEY_ENCRYPTION_KEY (32-byte AES-256 master key). Auto-generated on install, preserved on upgrade via lookup. Don't delete (see warning). |
The SAML SP signing key itself (a self-signed cert + RSA-2048 key pair) is auto-generated by the API on first SAML init and persisted in the saml_sp_keys table in the primary database. Restarts and rolling upgrades reuse the same key.
warning: Do not delete kubesense-saml-secret. If it is removed, the next reconcile generates a fresh master key and the API can no longer decrypt the existing saml_sp_keys row → SAML returns 503 until you DELETE FROM saml_sp_keys WHERE id = 1; and let the API regenerate the SP cert under the new master key. Other auth methods (password, OAuth) are unaffected.
Step 6: Turn on the app for users
By default, the new SAML app is off for everyone. Until you turn it on, users see app_not_enabled_for_user from Google.
- In the Admin console, go to Apps → Web and mobile apps → KubeSense
- Click User access
- Set Service status to ON for everyone (or for a specific OU)
- Click Save
Propagation can take up to a few minutes.
Step 7: Verify SSO
- Open
https://<KUBESENSE_DOMAIN>/loginin a private browser window - Click Sign in with Google SAML
- Authenticate with your Google Workspace account
- You should land on the KubeSense dashboard
Rotate the IdP metadata
Google rotates SAML signing certificates from time to time. When that happens:
- In the Admin console, open the KubeSense SAML app
- Click Download metadata to get the new XML
- Replace
api.saml.idpMetadataXmlin your Helm values (or re-run--set-file) helm upgrade ...— the chart re-renders the API ConfigMap and the Deployment automatically rolls.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Endpoint doesn't exists on /api/saml/login | SAML disabled or init failed | Confirm saml.enabled: true; check pod logs for SAML routes registered |
503 SAML is not available | Init failed at startup | Check API pod logs (kubectl logs deployment/kubesense-api) for the actual reason — typically a malformed idp_metadata_xml or a missing kubesense-saml-secret |
app_not_enabled_for_user from Google | App not granted to user | Re-do Step 6 |
SAML assertion validation failed | Generic message returned to clients on purpose; real reason in API logs | Check pod logs for SAML: failed to parse/validate assertion with private_detail field |
private_detail: "Destination does not match" (in logs) | ACS URL in Google admin ≠ <root_url>/api/saml/acs | Fix ACS URL in Google admin |
private_detail: "Audience does not match" (in logs) | Entity ID mismatch | Make Google admin Entity ID = config entity_id |
private_detail: "Signature could not be verified" (in logs) | IdP metadata stale (cert rotated) | Re-download metadata, update ConfigMap |
503 SAML is not available after deleting kubesense-saml-secret | New master key generated, can't decrypt old saml_sp_keys row | DELETE FROM saml_sp_keys WHERE id = 1;, then kubectl rollout restart deployment kubesense-api. The API regenerates a fresh SP cert under the new master key. Re-export SP metadata to Google admin only if your IdP enforces SP signature validation (Google by default does not). |
Login completes but bounces to /login | webapp cannot read auth cookies | Confirm KubeSense is served over HTTPS (the Secure cookie flag requires it) and root_url matches the URL the browser actually uses |