diff --git a/cost-analyzer/templates/_helpers.tpl b/cost-analyzer/templates/_helpers.tpl index a62f7ef54..be12b73b9 100755 --- a/cost-analyzer/templates/_helpers.tpl +++ b/cost-analyzer/templates/_helpers.tpl @@ -157,6 +157,15 @@ will result in failure. Users are asked to select one of the two presently-avail {{- end -}} {{- end -}} +{{/* +RBAC exclusivity check: make sure either simple RBAC or RBAC Teams is configured, not both +*/}} +{{- define "rbacCheck" -}} + {{- if and (or (.Values.saml).groups (.Values.oidc).groups) (.Values.teams).teamsConfig -}} + {{- fail "\nSimple RBAC and RBAC Teams are mutually exclusive. Please specify only one." -}} + {{- end -}} +{{- end -}} + {{/* Federated Storage source contents check. Either the Secret must be specified or the JSON, not both. */}} @@ -1005,6 +1014,14 @@ Begin Kubecost 2.0 templates {{- end }} {{- end }} {{- end }} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + - name: kubecost-rbac-secret + mountPath: /var/configs/kubecost-rbac-secret + {{- end }} + {{- if eq (include "rbacTeamsConfigEnabled" .) "true" }} + - name: kubecost-rbac-teams-config + mountPath: /var/configs/rbac-teams-configs + {{- end }} {{- if .Values.global.integrations.postgres.enabled }} - name: postgres-creds mountPath: /var/configs/integrations/postgres-creds @@ -1161,6 +1178,20 @@ Begin Kubecost 2.0 templates - name: OIDC_SKIP_ONLINE_VALIDATION value: {{ (quote .Values.oidc.skipOnlineTokenValidation) | default (quote false) }} {{- end}} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + {{- if .Values.oidc.enabled }} + - name: OIDC_RBAC_TEAMS_ENABLED + value: "true" + {{- end }} + {{- if .Values.saml.enabled }} + - name: SAML_RBAC_TEAMS_ENABLED + value: "true" + {{- end }} + {{- end }} + {{- if eq (include "rbacTeamsConfigEnabled" .) "true" }} + - name: RBAC_TEAMS_HELM_CONFIG_PATH + value: "/var/configs/rbac-teams-configs/rbac-teams-configs.json" + {{- end }} {{- if .Values.kubecostAggregator }} {{- if .Values.kubecostAggregator.collections }} {{- if (((.Values.kubecostAggregator).collections).cache) }} @@ -1202,9 +1233,11 @@ Begin Kubecost 2.0 templates value: {{ .Values.saml.redirectURL }} {{- end}} {{- if .Values.saml.rbac.enabled }} + {{- if eq (include "rbacTeamsEnabled" .) "false" }} - name: SAML_RBAC_ENABLED value: "true" {{- end }} + {{- end }} {{- if and .Values.saml.encryptionCertSecret .Values.saml.decryptionKeySecret }} - name: SAML_RESPONSE_ENCRYPTED value: "true" @@ -1357,8 +1390,8 @@ SSO enabled flag for nginx configmap {{- end -}} {{/* -To use the Kubecost built-in Teams UI RBAC< you must enable SSO and RBAC and not specify any groups. -Groups is only used when using external RBAC. +To use the Kubecost built-in RBAC Teams UI, you must enable SSO and RBAC and not specify any groups. +Groups is only used when using simple RBAC. */}} {{- define "rbacTeamsEnabled" -}} {{- if or (.Values.saml).enabled (.Values.oidc).enabled -}} @@ -1376,6 +1409,18 @@ Groups is only used when using external RBAC. {{- end -}} {{- end -}} +{{- define "rbacTeamsConfigEnabled" -}} + {{- if eq (include "rbacTeamsEnabled" .) "true" -}} + {{- if or (.Values.teams).teamsConfig (.Values.teams).teamsConfigMapName -}} + {{- printf "true" -}} + {{- else -}} + {{- printf "false" -}} + {{- end }} + {{- else -}} + {{- printf "false" -}} + {{- end }} +{{- end }} + {{/* Backups configured flag for nginx configmap */}} diff --git a/cost-analyzer/templates/aggregator-statefulset.yaml b/cost-analyzer/templates/aggregator-statefulset.yaml index 2ccc0c502..595781bb1 100644 --- a/cost-analyzer/templates/aggregator-statefulset.yaml +++ b/cost-analyzer/templates/aggregator-statefulset.yaml @@ -164,6 +164,20 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + - name: kubecost-rbac-secret + secret: + secretName: kubecost-rbac-secret + {{- end }} + {{- if eq (include "rbacTeamsConfigEnabled" .) "true" }} + - name: kubecost-rbac-teams-config + configMap: + {{- if .Values.teams.teamsConfigMapName }} + name: {{ .Values.teams.teamsConfigMapName }} + {{- else }} + name: kubecost-rbac-teams-config + {{- end }} + {{- end }} {{- if .Values.global.integrations.postgres.enabled }} - name: postgres-creds secret: diff --git a/cost-analyzer/templates/cost-analyzer-deployment-template.yaml b/cost-analyzer/templates/cost-analyzer-deployment-template.yaml index 48068445c..3630cc106 100644 --- a/cost-analyzer/templates/cost-analyzer-deployment-template.yaml +++ b/cost-analyzer/templates/cost-analyzer-deployment-template.yaml @@ -280,6 +280,20 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + - name: kubecost-rbac-secret + secret: + secretName: kubecost-rbac-secret + {{- end }} + {{- if eq (include "rbacTeamsConfigEnabled" .) "true" }} + - name: kubecost-rbac-teams-config + configMap: + {{- if .Values.teams.teamsConfigMapName }} + name: {{ .Values.teams.teamsConfigMapName }} + {{- else }} + name: kubecost-rbac-teams-config + {{- end }} + {{- end }} {{- if .Values.extraVolumes }} # Extra volume(s) {{- toYaml .Values.extraVolumes | nindent 8 }} @@ -737,6 +751,10 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + - name: kubecost-rbac-secret + mountPath: /var/configs/kubecost-rbac-secret + {{- end }} env: - name: CONTAINER_IMAGE_TAG value: {{ include "cost-model.imagetag" . }} @@ -780,8 +798,8 @@ spec: value: {{ .Values.assetReportConfigmapName }} {{- end }} {{- if .Values.cloudCostReportConfigmapName }} - - name: CLOUD_COST_REPORT_CONFIGMAP_NAME - value: {{ .Values.cloudCostReportConfigmapName }} + - name: CLOUD_COST_REPORT_CONFIGMAP_NAME + value: {{ .Values.cloudCostReportConfigmapName }} {{- end }} {{- if .Values.savedReportConfigmapName }} - name: SAVED_REPORT_CONFIGMAP_NAME @@ -1000,7 +1018,7 @@ spec: {{- else}} - name: ADVANCED_NETWORK_STATS value: "false" - {{- end}} + {{- end }} {{- end }} {{- end }} {{- end }} @@ -1009,7 +1027,7 @@ spec: value: "true" - name: OIDC_SKIP_ONLINE_VALIDATION value: {{ (quote .Values.oidc.skipOnlineTokenValidation) | default (quote false) }} - {{- end}} + {{- end }} {{- if .Values.saml }} {{- if .Values.saml.enabled }} - name: SAML_ENABLED @@ -1039,15 +1057,27 @@ spec: value: {{ .Values.saml.redirectURL }} {{- end}} {{- if .Values.saml.rbac.enabled }} + {{- if eq (include "rbacTeamsEnabled" .) "false" }} - name: SAML_RBAC_ENABLED value: "true" {{- end }} + {{- end }} {{- if and .Values.saml.encryptionCertSecret .Values.saml.decryptionKeySecret }} - name: SAML_RESPONSE_ENCRYPTED value: "true" {{- end}} {{- end }} {{- end }} + {{- if eq (include "rbacTeamsEnabled" .) "true" }} + {{- if .Values.oidc.enabled }} + - name: OIDC_RBAC_TEAMS_ENABLED + value: "true" + {{- end }} + {{- if .Values.saml.enabled }} + - name: SAML_RBAC_TEAMS_ENABLED + value: "true" + {{- end }} + {{- end }} {{- if and (.Values.prometheus.server.global.external_labels.cluster_id) (not .Values.prometheus.server.clusterIDConfigmap) }} - name: CLUSTER_ID value: {{ .Values.prometheus.server.global.external_labels.cluster_id }} diff --git a/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml b/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml index e25f2352b..9ea5e901e 100755 --- a/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml +++ b/cost-analyzer/templates/cost-analyzer-frontend-config-map-template.yaml @@ -966,6 +966,54 @@ data: proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } + location = /model/rbac/teams { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/teams; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location = /model/rbac/team { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/team; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location = /model/rbac/roles { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/roles; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location = /model/rbac/role { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/role; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location = /model/rbac/currentTeams { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/currentTeams; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + location = /model/rbac/currentPermissions { + proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; + proxy_pass http://aggregator/rbac/currentPermissions; + proxy_redirect off; + proxy_set_header Connection ""; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } location = /model/debug/orchestrator { proxy_read_timeout {{ .Values.kubecostFrontend.timeoutSeconds | default 300 }}; proxy_pass http://aggregator/debug/orchestrator; diff --git a/cost-analyzer/templates/kubecost-rbac-secret-template.yaml b/cost-analyzer/templates/kubecost-rbac-secret-template.yaml new file mode 100644 index 000000000..4f2116035 --- /dev/null +++ b/cost-analyzer/templates/kubecost-rbac-secret-template.yaml @@ -0,0 +1,18 @@ +{{- if eq (include "rbacTeamsEnabled" .) "true" }} +apiVersion: v1 +kind: Secret +type: Opaque +metadata: + name: kubecost-rbac-secret + namespace: {{ .Release.Namespace }} + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} +stringData: + key: + {{- if .Values.oidc.enabled }} + {{ .Values.oidc.authSecret | default (randAlphaNum 32 | quote) }} + {{- end }} + {{- if .Values.saml.enabled }} + {{ .Values.saml.authSecret | default (randAlphaNum 32 | quote) }} + {{- end }} +{{- end }} diff --git a/cost-analyzer/templates/kubecost-rbac-teams-configmap-template.yaml b/cost-analyzer/templates/kubecost-rbac-teams-configmap-template.yaml new file mode 100644 index 000000000..02a43815e --- /dev/null +++ b/cost-analyzer/templates/kubecost-rbac-teams-configmap-template.yaml @@ -0,0 +1,13 @@ +{{- if eq (include "rbacTeamsConfigEnabled" .) "true" }} +{{- if not .Values.teams.teamsConfigMapName }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: "kubecost-rbac-teams-config" + namespace: {{ .Release.Namespace }} + labels: + {{- include "cost-analyzer.commonLabels" . | nindent 4 }} +data: + rbac-teams-configs.json: '{{ toJson .Values.rbacTeams.teamsConfig }}' +{{- end }} +{{- end }} \ No newline at end of file diff --git a/cost-analyzer/values.yaml b/cost-analyzer/values.yaml index dd735726c..1166bb988 100644 --- a/cost-analyzer/values.yaml +++ b/cost-analyzer/values.yaml @@ -423,6 +423,44 @@ oidc: # claimValues: # - "editor" +# teams: + # teamsConfigMapName: kubecost-rbac-teams-config # Name of the ConfigMap containing the teams configuration, if manually created, which overrides any other configured teams + # teamsConfig: # Values-defined teams configuration, if teamsConfigMapName is not set, which will override UI-configured teams + # - id: '' + # name: helm-team + # roles: + # - id: '' + # name: helm-role + # description: helm configrured role + # pages: + # showOverview: true + # showAllocation: true + # showAsset: true + # showCloudCost: true + # showClusters: true + # showExternalCosts: true + # showNetwork: true + # showCollections: true + # showReports: true + # showInsights: true + # showActions: true + # showAlerts: true + # showBudgets: true + # showAnomalies: true + # showEfficiency: true + # showSettings: true + # permissions: admin + # routes: [] + # allocationFilters: + # - key: cluster + # operator: ":" + # value: cluster-one + # assetFilters: [] + # cloudCostFilters: [] + # claims: + # NameID: email@domain.com + + ## Adds the HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables to all ## containers. Typically used in environments that have firewall rules which ## prevent kubecost from accessing cloud provider resources.