diff --git a/README.md b/README.md index 71190d2c..be9caeb1 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,11 @@ helm install my-release-name matrix --values values.yaml - Latest version of [Synapse](https://github.com/matrix-org/synapse) (the official homeserver edition of matrix) - Ingress definitions for federated Synapse (Matrix homeserver) and Element (frontend and CMS for matrix) -- Use (existing) Kubernetes Secrets for confidential data, such as passwords ### Optional Features +- Use (existing) Kubernetes Secrets for confidential data, such as passwords +- Use OIDC configs for SSO - Latest version of [Element](https://element.io/) - [Bitnami PostgreSQL subchart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) to deploy a cluster - needs some work to standardize though, so we also support external postgresql servers - [Coturn TURN server subchart](https://github.com/jessebot/coturn-chart) for VoIP calls diff --git a/charts/matrix/Chart.yaml b/charts/matrix/Chart.yaml index 71445aa0..3cd81e75 100644 --- a/charts/matrix/Chart.yaml +++ b/charts/matrix/Chart.yaml @@ -8,7 +8,7 @@ sources: type: application -version: 4.1.3 +version: 4.2.0 appVersion: v1.88.0 maintainers: diff --git a/charts/matrix/README.md b/charts/matrix/README.md index 27bfeec8..41c841f5 100644 --- a/charts/matrix/README.md +++ b/charts/matrix/README.md @@ -1,6 +1,6 @@ # matrix -![Version: 4.1.3](https://img.shields.io/badge/Version-4.1.3-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v1.88.0](https://img.shields.io/badge/AppVersion-v1.88.0-informational?style=flat-square) +![Version: 4.2.0](https://img.shields.io/badge/Version-4.2.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v1.88.0](https://img.shields.io/badge/AppVersion-v1.88.0-informational?style=flat-square) A Helm chart to deploy a Matrix homeserver stack into Kubernetes @@ -56,7 +56,7 @@ A Helm chart to deploy a Matrix homeserver stack into Kubernetes | bridges.irc.enabled | bool | `false` | Set to true to enable the IRC bridge | | bridges.irc.image.pullPolicy | string | `"IfNotPresent"` | | | bridges.irc.image.repository | string | `"matrixdotorg/matrix-appservice-irc"` | | -| bridges.irc.image.tag | string | `"release-1.0.0"` | | +| bridges.irc.image.tag | string | `"release-1.0.1"` | | | bridges.irc.presence | bool | `false` | Whether to enable presence (online/offline indicators). If presence is disabled for the homeserver (above), it should be disabled here too | | bridges.irc.replicaCount | int | `1` | | | bridges.irc.resources | object | `{}` | | @@ -231,6 +231,28 @@ A Helm chart to deploy a Matrix homeserver stack into Kubernetes | matrix.logging.rootLogLevel | string | `"WARNING"` | Root log level is the default log level for log outputs that don't have more specific settings. | | matrix.logging.sqlLogLevel | string | `"WARNING"` | beware: increasing this to DEBUG will make synapse log sensitive information such as access tokens. | | matrix.logging.synapseLogLevel | string | `"WARNING"` | The log level for the synapse server | +| matrix.oidc_config.authorization_endpoint | string | `"https://accounts.example.com/oauth2/auth"` | oauth2 authorization endpoint. Required if provider discovery disabled. | +| matrix.oidc_config.client_auth_method | string | `"client_secret_post"` | auth method to use when exchanging the token. Valid values are: 'client_secret_basic' (default), 'client_secret_post' and 'none'. | +| matrix.oidc_config.client_id | string | `"provided-by-your-issuer"` | oauth2 client id to use. Required if 'enabled' is true. | +| matrix.oidc_config.client_secret | string | `"provided-by-your-issuer"` | oauth2 client secret to use. Required if 'enabled' is true. | +| matrix.oidc_config.discover | bool | `true` | set to false to disable use of the OIDC discovery mechanism to discover endpoints. | +| matrix.oidc_config.enabled | bool | `false` | set to true to enable authorization against an OpenID Connect server | +| matrix.oidc_config.existingSecret | string | `""` | existing secret to use for the OIDC config | +| matrix.oidc_config.issuer | string | `"https://accounts.example.com/"` | OIDC issuer. Used to validate tokens and (if discovery is enabled) to discover the provider's endpoints. Required if 'enabled' is true. | +| matrix.oidc_config.jwks_uri | string | `"https://accounts.example.com/.well-known/jwks.json"` | URI where to fetch the JWKS. Required if discovery is disabled and the "openid" scope is used. | +| matrix.oidc_config.scopes | list | `["openid","profile"]` | list of scopes to request. should normally include the "openid" scope. Defaults to ["openid"]. | +| matrix.oidc_config.secretKeys.authorization_endpoint | string | `"authorization_endpoint"` | key in secret with the authorization_endpoint if discovery is disabled | +| matrix.oidc_config.secretKeys.client_id | string | `"client_id"` | key in secret with the client_id | +| matrix.oidc_config.secretKeys.client_secret | string | `"client_secret"` | key in secret with the client_secret | +| matrix.oidc_config.secretKeys.issuer | string | `"issuer"` | key in secret with the issuer | +| matrix.oidc_config.secretKeys.jwks_uri | string | `"jwks_uri"` | key in secret with the if discovery is disabled and openid is scope | +| matrix.oidc_config.secretKeys.token_endpoint | string | `"token_endpoint"` | key in secret with the token_endpoint if discovery is disabled | +| matrix.oidc_config.secretKeys.userinfo_endpoint | string | `"userinfo_endpoint"` | key in secret with the userinfo_endpoint if discovery is disabled | +| matrix.oidc_config.skip_verification | bool | `false` | | +| matrix.oidc_config.token_endpoint | string | `"https://accounts.example.com/oauth2/token"` | the oauth2 token endpoint. Required if provider discovery is disabled. | +| matrix.oidc_config.user_mapping_provider.config.subject_claim | string | `"sub"` | name of the claim containing a unique identifier for user. Defaults to `sub`, which OpenID Connect compliant providers should provide. | +| matrix.oidc_config.user_mapping_provider.module | string | `"mapping_provider.OidcMappingProvider"` | The custom module's class. Uncomment to use a custom module. Default is 'synapse.handlers.oidc_handler.JinjaOidcMappingProvider'. github.com/matrix-org/synapse/blob/master/docs/sso_mapping_providers.md#openid-mapping-providers for information on implementing a custom mapping provider. example: module: mapping_provider.OidcMappingProvider | +| matrix.oidc_config.userinfo_endpoint | string | `"https://accounts.example.com/userinfo"` | the OIDC userinfo endpoint. Required if discovery is disabled and the "openid" scope is not requested. | | matrix.presence | bool | `true` | Set to false to disable presence (online/offline indicators) | | matrix.registration.allowGuests | bool | `false` | Allow users to join rooms as a guest | | matrix.registration.autoJoinRooms | list | `[]` | Rooms to automatically join all new users to | diff --git a/charts/matrix/templates/_helpers.tpl b/charts/matrix/templates/_helpers.tpl index 8f1d30ec..2e54a0ba 100644 --- a/charts/matrix/templates/_helpers.tpl +++ b/charts/matrix/templates/_helpers.tpl @@ -150,10 +150,21 @@ Helper function to get the coturn secret containing the sharedSecret {{/* Helper function to get the registration secret containing the sharedSecret */}} -{{- define "registration.secretName" -}} +{{- define "matrix.registration.secretName" -}} {{- if .Values.matrix.registration.existingSecret -}} {{ .Values.matrix.registration.existingSecret }} {{- else if or .Values.matrix.registration.sharedSecret .Values.matrix.registration.generateSharedSecret -}} {{ template "matrix.fullname" . }}-registration-secret {{- end }} {{- end }} + +{{/* +Helper function to get the registration secret containing the sharedSecret +*/}} +{{- define "matrix.oidc.secretName" -}} +{{- if .Values.matrix.odic_config.existingSecret -}} +{{ .Values.matrix.oidc_config.existingSecret }} +{{- else if .Values.matrix.oidc_config.sharedSecret -}} +{{ template "matrix.fullname" . }}-oidc-secret +{{- end }} +{{- end }} diff --git a/charts/matrix/templates/synapse/_homeserver.yaml b/charts/matrix/templates/synapse/_homeserver.yaml index 78f7d100..16948ab8 100644 --- a/charts/matrix/templates/synapse/_homeserver.yaml +++ b/charts/matrix/templates/synapse/_homeserver.yaml @@ -1498,60 +1498,23 @@ oidc_config: # Uncomment the following to enable authorization against an OpenID Connect # server. Defaults to false. # - #enabled: true + enabled: {{ .Values.matrix.oidc_config.enabled }} + {{- if .Values.matrix.oidc_config.enabled }} # Uncomment the following to disable use of the OIDC discovery mechanism to # discover endpoints. Defaults to true. - # - #discover: false - - # the OIDC issuer. Used to validate tokens and (if discovery is enabled) to - # discover the provider's endpoints. - # - # Required if 'enabled' is true. - # - #issuer: "https://accounts.example.com/" - - # oauth2 client id to use. - # - # Required if 'enabled' is true. - # - #client_id: "provided-by-your-issuer" - - # oauth2 client secret to use. - # - # Required if 'enabled' is true. - # - #client_secret: "provided-by-your-issuer" + discover: {{ .Values.matrix.oidc_config.discover }} # auth method to use when exchanging the token. # Valid values are 'client_secret_basic' (default), 'client_secret_post' and # 'none'. # - #client_auth_method: client_secret_post + client_auth_method: {{ .Values.matrix.oidc_config.client_auth_method }} # list of scopes to request. This should normally include the "openid" scope. # Defaults to ["openid"]. # - #scopes: ["openid", "profile"] - - # the oauth2 authorization endpoint. Required if provider discovery is disabled. - # - #authorization_endpoint: "https://accounts.example.com/oauth2/auth" - - # the oauth2 token endpoint. Required if provider discovery is disabled. - # - #token_endpoint: "https://accounts.example.com/oauth2/token" - - # the OIDC userinfo endpoint. Required if discovery is disabled and the - # "openid" scope is not requested. - # - #userinfo_endpoint: "https://accounts.example.com/userinfo" - - # URI where to fetch the JWKS. Required if discovery is disabled and the - # "openid" scope is used. - # - #jwks_uri: "https://accounts.example.com/.well-known/jwks.json" + scopes: {{ .Values.matrix.oidc_config.scopes }} # Uncomment to skip metadata verification. Defaults to false. # @@ -1559,7 +1522,7 @@ oidc_config: # compliant. # Avoid this in production. # - #skip_verification: true + skip_verification: {{ .Values.matrix.oidc_config.skip_verification }} # An external module can be provided here as a custom solution to mapping # attributes returned from a OIDC provider onto a matrix user. @@ -1571,7 +1534,7 @@ oidc_config: # See https://github.com/matrix-org/synapse/blob/master/docs/sso_mapping_providers.md#openid-mapping-providers # for information on implementing a custom mapping provider. # - #module: mapping_provider.OidcMappingProvider + module: {{ .Values.matrix.oidc_config.user_mapping_provider.module }} # Custom configuration values for the module. This section will be passed as # a Python dictionary to the user mapping provider module's `parse_config` @@ -1594,14 +1557,13 @@ oidc_config: # # This must be configured if using the default mapping provider. # -{{/* localpart_template: "{{ user.preferred_username }}"*/}} - + {{/* localpart_template: "{{ user.preferred_username }}"*/}} # Jinja2 template for the display name to set on first login. # # If unset, no displayname will be set. # -{{/* #display_name_template: "{{ user.given_name }} {{ user.last_name }}"*/}} - + {{/* #display_name_template: "{{ user.given_name }} {{ user.last_name }}"*/}} + {{- end }} # Enable CAS for registration and login. diff --git a/charts/matrix/templates/synapse/deployment.yaml b/charts/matrix/templates/synapse/deployment.yaml index c28f213a..e4e1cfad 100644 --- a/charts/matrix/templates/synapse/deployment.yaml +++ b/charts/matrix/templates/synapse/deployment.yaml @@ -99,9 +99,50 @@ spec: - name: REGISTRATION_SHARED_SECRET valueFrom: secretKeyRef: - name: {{ include "registration.secretName" . }} + name: {{ include "matrix.registration.secretName" . }} key: {{ .Values.matrix.registration.secretKey }} {{- end }} + {{- if .Values.matrix.oidc_config.enabled }} + - name: ISSUER + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.issuer }} + - name: CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.client_id }} + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.client_secret}} + {{- if not .Values.matrix.oidc_config.discover }} + - name: AUTH_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.authorization_endpoint }} + - name: TOKEN_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.token_endpoint }} + - name: USERINFO_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.userinfo_endpoint }} + {{- if eq .Values.matrix.oidc_config.scopes "openid" }} + - name: JWKS_URI + valueFrom: + secretKeyRef: + name: {{ include "matrix.oidc.secretName" . }} + key: {{ .Values.matrix.oidc_config.secretKeys.jwks_uri }} + {{- end }} + {{- end }} + {{- end }} command: - /bin/sh - -ec @@ -114,6 +155,16 @@ spec: {{- if or .Values.matrix.registration.existingSecret .Values.matrix.registration.sharedSecret .Values.matrix.registration.generateSharedSecret }} yq eval -i '.registration_shared_secret = env(REGISTRATION_SHARED_SECRET)' /data/homeserver.yaml && \ {{- end }} + {{- if .Values.matrix.oidc_config.enabled }} + yq eval -i '.oidc_config.issuer = env(ISSUER)' /data/homeserver.yaml && \ + yq eval -i '.oidc_config.client_id = env(CLIENT_ID)' /data/homeserver.yaml && \ + yq eval -i '.oidc_config.client_secret = env(CLIENT_SECRET)' /data/homeserver.yaml && \ + {{- if not .Values.matrix.oidc_config.discover }} + yq eval -i '.oidc_config.authorization_endpoint = env(AUTH_ENDPOINT)' /data/homeserver.yaml && \ + yq eval -i '.oidc_config.token_endpoint = env(TOKEN_ENDPOINT)' /data/homeserver.yaml && \ + yq eval -i '.oidc_config.userinfo_endpoint = env(USERINFO_ENDPOINT)' /data/homeserver.yaml && \ + {{- end }} + {{- end }} yq eval -i '.database.args.host = env(DATABASE_HOSTNAME)' /data/homeserver.yaml && \ yq eval -i '.database.args.database = env(DATABASE)' /data/homeserver.yaml && \ yq eval -i '.database.args.user = env(DATABASE_USERNAME)' /data/homeserver.yaml && \ diff --git a/charts/matrix/templates/synapse/oidc-config-secret.yaml b/charts/matrix/templates/synapse/oidc-config-secret.yaml new file mode 100644 index 00000000..f75d4687 --- /dev/null +++ b/charts/matrix/templates/synapse/oidc-config-secret.yaml @@ -0,0 +1,28 @@ +{{/* +if matrix.oidc_config.enabled is true, and matrix.oidc_config.existingSecret is not passed in, +then we create a secret to store the credentials without it being in a configmap in plaintext. +*/}} +{{- if and .Values.matrix.oidc_config.enabled (not .Values.matrix.oidc_config.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "matrix.fullname" . }}-oidc-secret + labels: + app.kubernetes.io/name: {{ include "matrix.name" . }} + helm.sh/chart: {{ include "matrix.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +type: Opaque +data: + issuer: {{ .Values.matrix.oidc_config.issuer | b64enc | quote }} + client_id: {{ .Values.matrix.oidc_config.client_id | b64enc | quote }} + client_secret: {{ .Values.matrix.oidc_config.client_secret | b64enc | quote }} + {{- if not .Values.matrix.oidc_config.discover }} + authorization_endpoint: {{ .Values.matrix.oidc_config.authorization_endpoint | b64enc | quote }} + token_endpoint: {{ .Values.matrix.oidc_config.token_endpoint | b64enc | quote }} + userinfo_endpoint: {{ .Values.matrix.oidc_config.userinfo_endpoint | b64enc | quote }} + {{- if eq .Values.matrix.oidc_config.scopes "openid" }} + jwks_uri: {{ .Values.matrix.oidc_config.jwks_uri | b64enc | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/matrix/values.yaml b/charts/matrix/values.yaml index 8ee3548c..911bfdbd 100644 --- a/charts/matrix/values.yaml +++ b/charts/matrix/values.yaml @@ -124,6 +124,99 @@ matrix: # -- Whether to allow token based registration requiresToken: false + # OpenID Connect integration. The following settings can be used to make Synapse + # use an OpenID Connect Provider for authentication, instead of its internal + # password database. + # ref: https://github.com/matrix-org/synapse/blob/master/docs/openid.md. + oidc_config: + # -- set to true to enable authorization against an OpenID Connect server + enabled: false + + # -- set to false to disable use of the OIDC discovery mechanism to + # discover endpoints. + discover: true + + # -- OIDC issuer. Used to validate tokens and (if discovery is enabled) to + # discover the provider's endpoints. Required if 'enabled' is true. + issuer: "https://accounts.example.com/" + + # -- oauth2 client id to use. Required if 'enabled' is true. + client_id: "provided-by-your-issuer" + + # -- oauth2 client secret to use. Required if 'enabled' is true. + client_secret: "provided-by-your-issuer" + + # -- auth method to use when exchanging the token. Valid values are: + # 'client_secret_basic' (default), 'client_secret_post' and 'none'. + client_auth_method: client_secret_post + + # -- list of scopes to request. should normally include the "openid" scope. + # Defaults to ["openid"]. + scopes: ["openid", "profile"] + + # -- oauth2 authorization endpoint. Required if provider discovery disabled. + authorization_endpoint: "https://accounts.example.com/oauth2/auth" + + # -- the oauth2 token endpoint. Required if provider discovery is disabled. + token_endpoint: "https://accounts.example.com/oauth2/token" + + # -- the OIDC userinfo endpoint. Required if discovery is disabled and the + # "openid" scope is not requested. + userinfo_endpoint: "https://accounts.example.com/userinfo" + + # -- URI where to fetch the JWKS. Required if discovery is disabled and the + # "openid" scope is used. + jwks_uri: "https://accounts.example.com/.well-known/jwks.json" + + # -- existing secret to use for the OIDC config + existingSecret: "" + + # keys in an existing secret to use for oidc config + secretKeys: + # -- key in secret with the issuer + issuer: "issuer" + # -- key in secret with the client_id + client_id: "client_id" + # -- key in secret with the client_secret + client_secret: "client_secret" + # -- key in secret with the authorization_endpoint if discovery is disabled + authorization_endpoint: "authorization_endpoint" + # -- key in secret with the token_endpoint if discovery is disabled + token_endpoint: "token_endpoint" + # -- key in secret with the userinfo_endpoint if discovery is disabled + userinfo_endpoint: "userinfo_endpoint" + # -- key in secret with the if discovery is disabled and openid is scope + jwks_uri: "jwks_uri" + + # set to false to skip metadata verification. Defaults to false. Use this if + # you are connecting to a provider that is not OpenID Connect compliant. + # Avoid this in production. + skip_verification: false + + # An external module can be provided here as a custom solution to mapping + # attributes returned from a OIDC provider onto a matrix user. + user_mapping_provider: + # -- The custom module's class. Uncomment to use a custom module. + # Default is 'synapse.handlers.oidc_handler.JinjaOidcMappingProvider'. + # + # github.com/matrix-org/synapse/blob/master/docs/sso_mapping_providers.md#openid-mapping-providers + # for information on implementing a custom mapping provider. + # example: + # module: mapping_provider.OidcMappingProvider + module: mapping_provider.OidcMappingProvider + + # Custom configuration values for the module. This section will be passed as + # a Python dictionary to the user mapping provider module's `parse_config` + # method. + # + # The examples below are intended for the default provider: they should be + # changed if using a custom provider. + # + config: + # -- name of the claim containing a unique identifier for user. Defaults + # to `sub`, which OpenID Connect compliant providers should provide. + subject_claim: "sub" + # Settings for the URL preview crawler urlPreviews: # -- Enable URL previews. WARN: Make sure to review default rules below to @@ -792,7 +885,7 @@ bridges: image: repository: "matrixdotorg/matrix-appservice-irc" - tag: "release-1.0.0" + tag: "release-1.0.1" pullPolicy: IfNotPresent replicaCount: 1 resources: {}