SSO and RBAC are only officially supported on Kubecost Enterprise plans.
Kubecost supports single sign-on (SSO) and role-based access control (RBAC) with SAML 2.0. Kubecost works with most identity providers including Okta, Auth0, Microsoft Entra ID (formerly Azure AD), PingID, and KeyCloak.
User authentication (.Values.saml
): SSO provides a simple mechanism to restrict application access internally and externally
Pre-defined user roles (.Values.saml.rbac
):
admin
: Full control with permissions to manage users, configure model inputs, and application settings.
readonly
: User role with read-only permission.
editor
: Role can change and build alerts and reports, but cannot edit application settings and otherwise functions as read-only.
Custom access roles (filters.json): Limit users based on attributes or group membership to view a set of namespaces, clusters, or other aggregations
All SAML 2.0 providers also work. The above guides can be used as templates for what is required.
When SAML SSO is enabled in Kubecost, ports 9090 and 9003 of service/kubecost-cost-analyzer
will require authentication. Therefore user API requests will need to be authenticated with a token. The token can be obtained by logging into the Kubecost UI and copying the token from the browser’s local storage. Alternatively, a long-term token can be issued to users from your identity provider.
For admins, Kubecost additionally exposes an unauthenticated API on port 9004 of service/kubecost-cost-analyzer
.
You will be able to view your current SAML Group in the Kubecost UI by selecting Settings from the left navigation, then scrolling to 'SAML Group'. Your access level will be displayed in the 'Current SAML Group' box.
Disable SAML and confirm that the cost-analyzer
pod starts.
If step 1 is successful, but the pod is crashing or never enters the ready state when SAML is added, it is likely that there is panic loading or parsing SAML data.
kubectl logs deployment/kubecost-cost-analyzer -c cost-model -n kubecost
If you’re supplying the SAML from the address of an Identity Provider Server, curl
the SAML metadata endpoint from within the Kubecost pod and ensure that a valid XML EntityDescriptor is being returned and downloaded. The response should be in this format:
The URL returns a 404 error or returning HTML
Contact your SAML admin to find the URL on your identity provider that serves the raw XML file.
Returning an EntitiesDescriptor instead of an EntityDescriptor
Certain metadata URLs could potentially return an EntitiesDescriptor, instead of an EntityDescriptor. While Kubecost does not currently support using an EntitiesDescriptor, you can instead copy the EntityDescriptor into a new file you create called metadata.xml:
Download the XML from the metadata URL into a file called metadata.xml
Copy all the attributes from EntitiesDescriptor
to the EntityDescriptor
that are not present.
Remove the <EntitiesDescriptor>
tag from the beginning.
Remove the </EntitiesDescriptor>
from the end of the XML file.
You are left with data in a similar format to the example below:
Then, you can upload the EntityDescriptor to a secret in the same namespace as kubecost and use that directly.
kubectl create secret generic metadata-secret --from-file=./metadata.xml --namespace kubecost
To use this secret, in your helm values set metadataSecretName to the name of the secret created above, and set idpMetadataURL to the empty string:
Invalid NameID format
On Keycloak, if you receive an “Invalid NameID format” error, you should set the option “force nameid format” in Keycloak. See Keycloak docs for more details.
Users of CSI driver for storing SAML secret
For users who want to use CSI driver for storing SAML secret, we suggest this guide.
InvalidNameIDPolicy format
From a PingIdentity article:
An alternative solution is to add an attribute called "SAML_SP_NAME_QUALIFIER" to the connection's attribute contract with a TEXT value of the requested SPNameQualifier. When you do this, select the following for attribute name format:
urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
On the PingID side: specify an attribute contract “SAML_SP_NAME_QUALIFIER” with the format urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
.
On the Kubecost side: in your Helm values, set saml.nameIDFormat
to the same format set by PingID:
Make sure audienceURI
and appRootURL
match the entityID configured within PingFed.
SSO and RBAC are only officially supported on Kubecost Enterprise plans.
This guide will show you how to configure Kubecost integrations for SAML and RBAC with Microsoft Entra ID.
In the Azure Portal, go to the Microsoft Entra ID Overview page and select Enterprise applications in the left navigation underneath Manage.
On the Enterprise applications page, select New application.
On the Browse Microsoft Entra ID Gallery page, select Create your own application and select Create. The 'Create your own application window' opens.
Provide a custom name for your app. Then, select Integrate any other application you don't find in the gallery. Select Create.
Return to the Enterprise applications page from Step 1.2. Find and select your Enterprise application from the table.
Select Properties in the left navigation under Manage to begin editing the application. Start by updating the logo, then select Save. Feel free to use an official Kubecost logo.
Select Users and groups in the left navigation. Assign any users or groups you want to have access to Kubecost, then select Assign.
Select Single sign-on from the left navigation. In the 'Basic SAML Configuration' box, select Edit. Populate both the Identifier and Reply URL with the URL of your Kubecost environment without a trailing slash (ex: http://localhost:9090), then select Save. If your application is using OpenId Connect and OAuth, most of the SSO configuration will have already been completed.
(Optional) If you intend to use RBAC, you also need to add a group claim. Without leaving the SAML-based Sign-on page, select Edit next to Attributes & Claims. Select Add a group claim. Configure your group association, then select Save. The claim name will be used as the assertionName
value in the values-saml.yaml file.
On the SAML-based Sign-on page, in the SAML Certificates box, copy the login of 'App Federation Metadata Url' and add it to your values-saml.yaml as the value of idpMetadataURL
.
In the SAML Certificates box, select the Download link next to Certificate (Base64) to download the X.509 cert. Name the file myservice.cert.
Create a secret using the cert with the following command:
With your existing Helm install command, append -f values-saml.yaml
to the end.
At this point, test your SSO configuration to make sure it works before moving on to the next section. There is a Troubleshooting section at the end of this doc for help if you are experiencing problems.
The simplest form of RBAC in Kubecost is to have two groups: admin and read only. If your goal is to simply have these two groups, you do not need to configure filters. If you do not configure filters, this message in the logs is expected: file corruption: '%!s(MISSING)'
The values-saml.yaml file contains the admin
and readonly
groups in the RBAC section:
Remember the value of assertionName
needs to match the claim name given in Step 2.5 above.
Filters are used to give visibility to a subset of objects in Kubecost. RBAC filtering is capable can filter for any types as the Allocation API. Examples of the various filters available are these files:
These filters can be configured using groups or user attributes in your Entra ID directory. It is also possible to assign filters to specific users. The example below is using groups.
You can combine filtering with admin/read only rights, and it can be configured the same way. The same assertionName
and values will be used, as is the case in this example.
The values-saml.yaml file contains this customGroups
section for filtering:
The array of groups obtained during the authentication request will be matched to the subject key in the filters.yaml. See this example filters.json (linked above) to understand how your created groups will be formatted:
As an example, we will configure the following:
Admins will have full access to the Kubecost UI and have visibility to all resources
Kubecost users, by default, will not have visibility to any namespace and will be read only. If a group doesn't have access to any resources, the Kubecost UI may appear to be broken.
The dev-namespaces group will have read only access to the Kubecost UI and only have visibility to namespaces that are prefixed with dev-
or are exactly nginx-ingress
In the Entra ID left navigation, select Groups. Select New group to create a new group.
For Group type, select Security. Enter a name your group. For this demonstration, create groups for kubecost_users
, kubecost_admin
and kubecost_dev-namespaces
. By selecting No members selected, Azure will pull up a list of all users in your organization for you to add (you can add or remove members after creating the group also). Add all users to the kubecost_users
group, and the appropriate users to each of the other groups for testing. Kubecost admins will be part of both the read only kubecost_users
and kubecost_admin
groups. Kubecost will assign the most rights/least restrictions when there are conflicts.
When you are done, select Create at the bottom of the page. Repeat Steps 1-2 as needed for all groups.
Return to your created Enterprise application and select Users and groups from the left navigation. Select Add user/group. Select and add all relevant groups you created. Then select Assign at the bottom of the page to confirm.
Modify filters.json as depicted above.
Replace {group-object-id-a}
with the Object Id for kubecost_admin
Replace {group-object-id-b}
with the Object Id for kubecost_users
Replace {group-object-id-c}
with the Object Id for kubecost_dev-namespaces
Create the ConfigMap:
You can modify the ConfigMap without restarting any pods.
You can look at the logs on the cost-model container. This script is currently a work in progress.
When the group has been matched, you will see:
This is what a normal output looks like:
SSO and RBAC are only officially supported on Kubecost Enterprise plans.
This guide will show you how to configure Kubecost integrations for SSO and RBAC with Okta.
To enable SSO for Kubecost, this tutorial will show you how to create an application in Okta.
Go to the Okta admin dashboard (https://[your-subdomain]okta.com/admin/dashboard) and select Applications from the left navigation. On the Applications page, select Create App Integration > SAML 2.0 > Next.
On the 'Create SAML Integration' page, provide a name for your app. Feel free to also use this official Kubecost logo for the App logo field. Then, select Next.
Your SSO URL should be your application root URL followed by '/saml/acs', like: https://[your-kubecost-address].com/saml/acs
Your Audience URI (SP Entity ID) should be set to your application root without a trailing slash: https://[your-kubecost-address.com
(Optional) If you intend to use RBAC: under Group Attribute Statements, enter a name (ex: kubecost_group) and a filter based on your group naming standards (example Starts with kubecost_). Then, select Next.
Provide any feedback as needed, then select Finish.
Return to the Applications page, select your newly-created app, then select the Sign On tab. Copy the URL for Identity Provider metadata, and add that value to .Values.saml.idMetadataURL
in this values-saml.yaml file.
To fully configure SAML 2.0, select View Setup Instructions, download the X.509 certificate, and name the file myservice.cert.
Create a secret using the certificate with the following command:
kubectl create secret generic kubecost-okta --from-file myservice.cert --namespace kubecost
For configuring single app logout, read Okta's documentation on the subject. then, update the values.saml:redirectURL
value in your values.yaml file.
Use this Okta document to assign individuals or groups access to your Kubecost application.
Finally, add -f values-saml.yaml
to your Kubecost Helm upgrade command:
At this point, test your SSO to ensure it is working properly before moving on to the next section.
The simplest form of RBAC in Kubecost is to have two groups: admin
and readonly
. If your goal is to simply have these two groups, you do not need to configure filters. This will result in the logs message: file corruption: '%!s(MISSING)'
, but this is expected.
The values-saml.yaml file contains the admin
and readonly
groups in the RBAC section:
The assertionName: "kubecost_group"
value needs to match the name given in Step 5 of the Okta SSO Configuration section.
Filters are used to give visibility to a subset of objects in Kubecost. Examples of the various filters available are in filters.json and filters-examples.json. RBAC filtering is capable of all the same types of filtering features as that of the Allocation API.
It's possible to combine filtering with admin/readonly rights
These filters can be configured using groups or user attributes in your Okta directory. It is also possible to assign filters to specific users. The example below is using groups.
Filtering is configured very similarly to the admin/readonly above. The same group pattern match (kubecost_group) can be used for both, as is the case in this example:
The array of groups obtained during the authorization request will be matched to the subject key in the filters.json:
As an example, we will configure the following:
Admins will have full access to the Kubecost UI and have visibility to all resources
Kubecost users, by default, will not have visibility to any namespace and will be readonly
. If a group doesn't have access to any resources, the Kubecost UI may appear to be broken
The dev-namespaces group will have read only access to the Kubecost UI and only have visibility to namespaces that are prefixed with dev-
or are exactly nginx-ingress
Go to the Okta admin dashboard (https://[your-subdomain]okta.com/admin/dashboard) and select Directory > Groups from the left navigation. On the Groups page, select Add group.
Create groups for kubecost_users, kubecost_admin and kubecost_dev-namespaces by providing each value as the name with an optional description, then select Save. You will need to perform this step three times, one for each group.
Select each group, then select Assign people and add the appropriate users for testing. Select Done to confirm edits to a group. Kubecost admins will be part of both the read only kubecost_users and kubecost_admin groups. Kubecost will assign the most rights if there are conflicts.
Return to the Groups page. Select kubecost_users, then in the Applications tab, assign the Kubecost application. You do not need to assign the other kubecost_ groups to the Kubecost application because all users already have access in the kubecost_users group.
Modify filters.json as depicted above.
Create the ConfigMap using the following command:
You can modify the ConfigMap without restarting any pods.
Generate an X509 certificate and private key. Below is an example using OpenSSL:
openssl genpkey -algorithm RSA -out saml-encryption-key.pem -pkeyopt rsa_keygen_bits:2048
Generate a certificate signing request (CSR)
openssl req -new -key saml-encryption-key.pem -out request.csr
Request your organization's domain owner to sign the certificate, or generate a self-signed certificate:
openssl x509 -req -days 365 -in request.csr -signkey saml-encryption-key.pem -out saml-encryption-cert.cer
Go to your application, then under the General tab, edit the following SAML Settings:
Assertion Encryption: Encrypted
In the Encryption Algorithm box that appears, select AES256-CBC.
Select Browse Files in the Encryption Certificate field and upload an image file of your certifcate.
Create a secret with the certificate. The file name must be saml-encryption-cert.cer.
kubectl create secret generic kubecost-saml-cert --from-file saml-encryption-cert.cer --namespace kubecost
Create a secret with the private key. The file name must be saml-encryption-key.pem.
kubectl create secret generic kubecost-saml-decryption-key --from-file saml-encryption-key.pem --namespace kubecost
Pass the following values via Helm into your values.yaml:
You can view the logs on the cost-model container. In this example, the assumption is that the prefix for Kubecost groups is kubecost_
. This command is currently a work in progress.
kubectl logs deployment/kubecost-cost-analyzer -c cost-model --follow |grep -v -E 'resourceGroup|prometheus-server'|grep -i -E 'group|xmlname|saml|login|audience|kubecost_'
When the group has been matched, you will see:
This is what you should expect to see: