Kubesense

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 upgrade against the deployment

Step 1: Add the custom SAML app

  1. In the Admin console, go to MenuAppsWeb and mobile apps
  2. Click Add appAdd custom SAML app
  3. On the App details page:
  4. Click Continue

Step 2: Download the IdP metadata

On the Google Identity Provider details page:

  1. Click Download metadata to save the IdP metadata XML file (e.g. GoogleIDPMetadata.xml)
  2. 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:

FieldValue
ACS URLhttps://<KUBESENSE_DOMAIN>/api/saml/acs
Entity IDhttps://<KUBESENSE_DOMAIN>/saml
Start URL (optional)https://<KUBESENSE_DOMAIN>/login
Signed responseLeave unchecked
Name ID formatEMAIL
Name IDBasic 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 attributeApp attribute
Primary emailemail
First namefirst_name
Last namelast_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.xml

That's it. The chart takes care of everything else:

  • kubesense-saml-secret Secret created on first install with a random 32-byte master key. Preserved across helm upgrade via lookup (no rotation, no churn).
  • API ConfigMap rendered with SAML_ENABLED, SAML_ENTITY_ID, SAML_ROOT_URL, SAML_IDP_METADATA_XML env vars (Viper reads them at startup).
  • API Deployment envFrom-wired to kubesense-saml-secret so SAML_KEY_ENCRYPTION_KEY is injected.
  • Webapp ConfigMap sets ENABLE_GOOGLE_SAML=true so 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_keys table. Restarts reuse the same key.

Configuration reference

values.yamlapi.saml

FieldRequiredDescription
enabledyesSet to true to render SAML resources and register /api/saml/* routes
rootUrlyesPublic HTTPS URL of the KubeSense deployment, e.g. https://kubesense.example.com
entityIdyesSP Entity ID — must match the Entity ID in Google admin (typically <rootUrl>/saml)
idpMetadataXmlone of twoInline IdP metadata XML (recommended)
idpMetadataUrlone of twoURL fetched at startup (discouraged — adds startup network dep)

Chart-managed Secrets

NamePurpose
kubesense-saml-secretHolds 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.

  1. In the Admin console, go to AppsWeb and mobile appsKubeSense
  2. Click User access
  3. Set Service status to ON for everyone (or for a specific OU)
  4. Click Save

Propagation can take up to a few minutes.

Step 7: Verify SSO

  1. Open https://<KUBESENSE_DOMAIN>/login in a private browser window
  2. Click Sign in with Google SAML
  3. Authenticate with your Google Workspace account
  4. You should land on the KubeSense dashboard

Rotate the IdP metadata

Google rotates SAML signing certificates from time to time. When that happens:

  1. In the Admin console, open the KubeSense SAML app
  2. Click Download metadata to get the new XML
  3. Replace api.saml.idpMetadataXml in your Helm values (or re-run --set-file)
  4. helm upgrade ... — the chart re-renders the API ConfigMap and the Deployment automatically rolls.

Troubleshooting

SymptomCauseFix
Endpoint doesn't exists on /api/saml/loginSAML disabled or init failedConfirm saml.enabled: true; check pod logs for SAML routes registered
503 SAML is not availableInit failed at startupCheck 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 GoogleApp not granted to userRe-do Step 6
SAML assertion validation failedGeneric message returned to clients on purpose; real reason in API logsCheck 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/acsFix ACS URL in Google admin
private_detail: "Audience does not match" (in logs)Entity ID mismatchMake 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-secretNew master key generated, can't decrypt old saml_sp_keys rowDELETE 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 /loginwebapp cannot read auth cookiesConfirm KubeSense is served over HTTPS (the Secure cookie flag requires it) and root_url matches the URL the browser actually uses