From a131f06e1299e21372f8f002c7959e54128be270 Mon Sep 17 00:00:00 2001 From: bobbyd0g <93697464+bobbyd0g@users.noreply.github.com> Date: Fri, 11 Feb 2022 09:01:40 -0500 Subject: [PATCH] Helm chart SSO support (#17205) * Add SAML support * move extAuth below essential components * Add CAS, PAM, LDAP support * Add WEB_DOMAIN and S3_ALIAS_HOST support * SAML defaults aligned * Bump chart version * SSO & WEB_DOMAIN support added * Add OIDC support * Correct typo * Notice for OIDC support Co-authored-by: Eugen Rochko --- chart/Chart.yaml | 2 +- chart/readme.md | 2 - chart/templates/configmap-env.yaml | 224 +++++++++++++++++++++++++++++ chart/values.yaml | 104 ++++++++++++++ 4 files changed, 329 insertions(+), 3 deletions(-) diff --git a/chart/Chart.yaml b/chart/Chart.yaml index 24676d74930..1687132acb0 100644 --- a/chart/Chart.yaml +++ b/chart/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.2.0 +version: 1.2.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/chart/readme.md b/chart/readme.md index 9f7a8895885..381037cc1ac 100644 --- a/chart/readme.md +++ b/chart/readme.md @@ -24,9 +24,7 @@ The variables that _must_ be configured are: Currently this chart does _not_ support: - Hidden services -- Single Sign-On - Swift -- configurations using `WEB_DOMAIN` # Upgrading diff --git a/chart/templates/configmap-env.yaml b/chart/templates/configmap-env.yaml index 701368e4987..5e0620998ac 100644 --- a/chart/templates/configmap-env.yaml +++ b/chart/templates/configmap-env.yaml @@ -21,6 +21,9 @@ data: ES_PORT: "9200" {{- end }} LOCAL_DOMAIN: {{ .Values.mastodon.local_domain }} + {{- if .Values.mastodon.web_domain }} + WEB_DOMAIN: {{ .Values.mastodon.web_domain }} + {{- end }} # https://devcenter.heroku.com/articles/tuning-glibc-memory-behavior MALLOC_ARENA_MAX: "2" NODE_ENV: "production" @@ -36,6 +39,9 @@ data: {{- if .Values.mastodon.s3.region }} S3_REGION: {{ .Values.mastodon.s3.region }} {{- end }} + {{- if .Values.mastodon.s3.alias_host }} + S3_ALIAS_HOST: {{ .Values.mastodon.s3.alias_host}} + {{- end }} {{- end }} {{- if .Values.mastodon.smtp.auth_method }} SMTP_AUTH_METHOD: {{ .Values.mastodon.smtp.auth_method }} @@ -77,3 +83,221 @@ data: SMTP_TLS: {{ .Values.mastodon.smtp.tls | quote }} {{- end }} STREAMING_CLUSTER_NUM: {{ .Values.mastodon.streaming.workers | quote }} + {{- if .Values.externalAuth.oidc.enabled }} + OIDC_ENABLED: {{ .Values.externalAuth.oidc.enabled | quote }} + OIDC_DISPLAY_NAME: {{ .Values.externalAuth.oidc.display_name }} + OIDC_ISSUER: {{ .Values.externalAuth.oidc.issuer }} + OIDC_DISCOVERY: {{ .Values.externalAuth.oidc.discovery | quote }} + OIDC_SCOPE: {{ .Values.externalAuth.oidc.scope | quote }} + OIDC_UID_FIELD: {{ .Values.externalAuth.oidc.uid_field }} + OIDC_CLIENT_ID: {{ .Values.externalAuth.oidc.client_id }} + OIDC_CLIENT_SECRET: {{ .Values.externalAuth.oidc.client_secret }} + OIDC_REDIRECT_URI: {{ .Values.externalAuth.oidc.redirect_uri }} + OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED: {{ .Values.externalAuth.oidc.assume_email_is_verified | quote }} + {{- if .Values.externalAuth.oidc.client_auth_method }} + OIDC_CLIENT_AUTH_METHOD: {{ .Values.externalAuth.oidc.client_auth_method }} + {{- end }} + {{- if .Values.externalAuth.oidc.response_type }} + OIDC_RESPONSE_TYPE: {{ .Values.externalAuth.oidc.response_type }} + {{- end }} + {{- if .Values.externalAuth.oidc.response_mode }} + OIDC_RESPONSE_MODE: {{ .Values.externalAuth.oidc.response_mode }} + {{- end }} + {{- if .Values.externalAuth.oidc.display }} + OIDC_DISPLAY: {{ .Values.externalAuth.oidc.display }} + {{- end }} + {{- if .Values.externalAuth.oidc.prompt }} + OIDC_PROMPT: {{ .Values.externalAuth.oidc.prompt }} + {{- end }} + {{- if .Values.externalAuth.oidc.send_nonce }} + OIDC_SEND_NONCE: {{ .Values.externalAuth.oidc.send_nonce }} + {{- end }} + {{- if .Values.externalAuth.oidc.send_scope_to_token_endpoint }} + OIDC_SEND_SCOPE_TO_TOKEN_ENDPOINT: {{ .Values.externalAuth.oidc.send_scope_to_token_endpoint | quote }} + {{- end }} + {{- if .Values.externalAuth.oidc.idp_logout_redirect_uri }} + OIDC_IDP_LOGOUT_REDIRECT_URI: {{ .Values.externalAuth.oidc.idp_logout_redirect_uri }} + {{- end }} + {{- if .Values.externalAuth.oidc.http_scheme }} + OIDC_HTTP_SCHEME: {{ .Values.externalAuth.oidc.http_scheme }} + {{- end }} + {{- if .Values.externalAuth.oidc.host }} + OIDC_HOST: {{ .Values.externalAuth.oidc.host }} + {{- end }} + {{- if .Values.externalAuth.oidc.port }} + OIDC_PORT: {{ .Values.externalAuth.oidc.port }} + {{- end }} + {{- if .Values.externalAuth.oidc.jwks_uri }} + OIDC_JWKS_URI: {{ .Values.externalAuth.oidc.jwks_uri }} + {{- end }} + {{- if .Values.externalAuth.oidc.auth_endpoint }} + OIDC_AUTH_ENDPOINT: {{ .Values.externalAuth.oidc.auth_endpoint }} + {{- end }} + {{- if .Values.externalAuth.oidc.token_endpoint }} + OIDC_TOKEN_ENDPOINT: {{ .Values.externalAuth.oidc.token_endpoint }} + {{- end }} + {{- if .Values.externalAuth.oidc.user_info_endpoint }} + OIDC_USER_INFO_ENDPOINT: {{ .Values.externalAuth.oidc.user_info_endpoint }} + {{- end }} + {{- if .Values.externalAuth.oidc.end_session_endpoint }} + OIDC_END_SESSION_ENDPOINT: {{ .Values.externalAuth.oidc.end_session_endpoint }} + {{- end }} + {{- end }} + {{- if .Values.externalAuth.saml.enabled }} + SAML_ENABLED: {{ .Values.externalAuth.saml.enabled | quote }} + SAML_ACS_URL: {{ .Values.externalAuth.saml.acs_url }} + SAML_ISSUER: {{ .Values.externalAuth.saml.issuer }} + SAML_IDP_SSO_TARGET_URL: {{ .Values.externalAuth.saml.idp_sso_target_url }} + SAML_IDP_CERT: {{ .Values.externalAuth.saml.idp_cert | quote }} + {{- if .Values.externalAuth.saml.idp_cert_fingerprint }} + SAML_IDP_CERT_FINGERPRINT: {{ .Values.externalAuth.saml.idp_cert_fingerprint | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.name_identifier_format }} + SAML_NAME_IDENTIFIER_FORMAT: {{ .Values.externalAuth.saml.name_identifier_format }} + {{- end }} + {{- if .Values.externalAuth.saml.cert }} + SAML_CERT: {{ .Values.externalAuth.saml.cert | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.private_key }} + SAML_PRIVATE_KEY: {{ .Values.externalAuth.saml.private_key | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.want_assertion_signed }} + SAML_SECURITY_WANT_ASSERTION_SIGNED: {{ .Values.externalAuth.saml.want_assertion_signed | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.want_assertion_encrypted }} + SAML_SECURITY_WANT_ASSERTION_ENCRYPTED: {{ .Values.externalAuth.saml.want_assertion_encrypted | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.assume_email_is_verified }} + SAML_SECURITY_ASSUME_EMAIL_IS_VERIFIED: {{ .Values.externalAuth.saml.assume_email_is_verified | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.uid_attribute }} + SAML_UID_ATTRIBUTE: {{ .Values.externalAuth.saml.uid_attribute }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.uid }} + SAML_ATTRIBUTES_STATEMENTS_UID: {{ .Values.externalAuth.saml.attributes_statements.uid | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.email }} + SAML_ATTRIBUTES_STATEMENTS_EMAIL: {{ .Values.externalAuth.saml.attributes_statements.email | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.full_name }} + SAML_ATTRIBUTES_STATEMENTS_FULL_NAME: {{ .Values.externalAuth.saml.attributes_statements.full_name | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.first_name }} + SAML_ATTRIBUTES_STATEMENTS_FIRST_NAME: {{ .Values.externalAuth.saml.attributes_statements.first_name | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.last_name }} + SAML_ATTRIBUTES_STATEMENTS_LAST_NAME: {{ .Values.externalAuth.saml.attributes_statements.last_name | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.verified }} + SAML_ATTRIBUTES_STATEMENTS_VERIFIED: {{ .Values.externalAuth.saml.attributes_statements.verified | quote }} + {{- end }} + {{- if .Values.externalAuth.saml.attributes_statements.verified_email }} + SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL: {{ .Values.externalAuth.saml.attributes_statements.verified_email | quote }} + {{- end }} + {{- end }} + {{- if .Values.externalAuth.oauth_global.oauth_redirect_at_sign_in }} + OAUTH_REDIRECT_AT_SIGN_IN: {{ .Values.externalAuth.oauth_global.oauth_redirect_at_sign_in | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.enabled }} + CAS_ENABLED: {{ .Values.externalAuth.cas.enabled | quote }} + CAS_URL: {{ .Values.externalAuth.cas.url }} + CAS_HOST: {{ .Values.externalAuth.cas.host }} + CAS_PORT: {{ .Values.externalAuth.cas.port }} + CAS_SSL: {{ .Values.externalAuth.cas.ssl | quote }} + {{- if .Values.externalAuth.cas.validate_url }} + CAS_VALIDATE_URL: {{ .Values.externalAuth.cas.validate_url }} + {{- end }} + {{- if .Values.externalAuth.cas.callback_url }} + CAS_CALLBACK_URL: {{ .Values.externalAuth.cas.callback_url }} + {{- end }} + {{- if .Values.externalAuth.cas.logout_url }} + CAS_LOGOUT_URL: {{ .Values.externalAuth.cas.logout_url }} + {{- end }} + {{- if .Values.externalAuth.cas.login_url }} + CAS_LOGIN_URL: {{ .Values.externalAuth.cas.login_url }} + {{- end }} + {{- if .Values.externalAuth.cas.uid_field }} + CAS_UID_FIELD: {{ .Values.externalAuth.cas.uid_field | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.ca_path }} + CAS_CA_PATH: {{ .Values.externalAuth.cas.ca_path }} + {{- end }} + {{- if .Values.externalAuth.cas.disable_ssl_verification }} + CAS_DISABLE_SSL_VERIFICATION: {{ .Values.externalAuth.cas.disable_ssl_verification | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.assume_email_is_verified }} + CAS_SECURITY_ASSUME_EMAIL_IS_VERIFIED: {{ .Values.externalAuth.cas.assume_email_is_verified | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.uid }} + CAS_UID_KEY: {{ .Values.externalAuth.cas.keys.uid | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.name }} + CAS_NAME_KEY: {{ .Values.externalAuth.cas.keys.name | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.email }} + CAS_EMAIL_KEY: {{ .Values.externalAuth.cas.keys.email | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.nickname }} + CAS_NICKNAME_KEY: {{ .Values.externalAuth.cas.keys.nickname | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.first_name }} + CAS_FIRST_NAME_KEY: {{ .Values.externalAuth.cas.keys.first_name | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.last_name }} + CAS_LAST_NAME_KEY: {{ .Values.externalAuth.cas.keys.last_name | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.location }} + CAS_LOCATION_KEY: {{ .Values.externalAuth.cas.keys.location | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.image }} + CAS_IMAGE_KEY: {{ .Values.externalAuth.cas.keys.image | quote }} + {{- end }} + {{- if .Values.externalAuth.cas.keys.phone }} + CAS_PHONE_KEY: {{ .Values.externalAuth.cas.keys.phone | quote }} + {{- end }} + {{- end }} + {{- if .Values.externalAuth.pam.enabled }} + PAM_ENABLED: {{ .Values.externalAuth.pam.enabled | quote }} + {{- if .Values.externalAuth.pam.email_domain }} + PAM_EMAIL_DOMAIN: {{ .Values.externalAuth.pam.email_domain }} + {{- end }} + {{- if .Values.externalAuth.pam.default_service }} + PAM_DEFAULT_SERVICE: {{ .Values.externalAuth.pam.default_service }} + {{- end }} + {{- if .Values.externalAuth.pam.controlled_service }} + PAM_CONTROLLED_SERVICE: {{ .Values.externalAuth.pam.controlled_service }} + {{- end }} + {{- end }} + {{- if .Values.externalAuth.ldap.enabled }} + LDAP_ENABLED: {{ .Values.externalAuth.ldap.enabled | quote }} + LDAP_HOST: {{ .Values.externalAuth.ldap.host }} + LDAP_PORT: {{ .Values.externalAuth.ldap.port }} + LDAP_METHOD: {{ .Values.externalAuth.ldap.method }} + {{- if .Values.externalAuth.ldap.base }} + LDAP_BASE: {{ .Values.externalAuth.ldap.base }} + {{- end }} + {{- if .Values.externalAuth.ldap.bind_on }} + LDAP_BIND_ON: {{ .Values.externalAuth.ldap.bind_on }} + {{- end }} + {{- if .Values.externalAuth.ldap.password }} + LDAP_PASSWORD: {{ .Values.externalAuth.ldap.password }} + {{- end }} + {{- if .Values.externalAuth.ldap.uid }} + LDAP_UID: {{ .Values.externalAuth.ldap.uid }} + {{- end }} + {{- if .Values.externalAuth.ldap.mail }} + LDAP_MAIL: {{ .Values.externalAuth.ldap.mail }} + {{- end }} + {{- if .Values.externalAuth.ldap.search_filter }} + LDAP_SEARCH_FILTER: {{ .Values.externalAuth.ldap.search_filter }} + {{- end }} + {{- if .Values.externalAuth.ldap.uid_conversion.enabled }} + LDAP_UID_CONVERSION_ENABLED: {{ .Values.externalAuth.ldap.uid_conversion.enabled | quote }} + {{- end }} + {{- if .Values.externalAuth.ldap.uid_conversion.search }} + LDAP_UID_CONVERSION_SEARCH: {{ .Values.externalAuth.ldap.uid_conversion.search }} + {{- end }} + {{- if .Values.externalAuth.ldap.uid_conversion.replace }} + LDAP_UID_CONVERSION_REPLACE: {{ .Values.externalAuth.ldap.uid_conversion.replace }} + {{- end }} + {{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml index dc476b1c513..54627854df8 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -27,6 +27,9 @@ mastodon: # available locales: https://github.com/tootsuite/mastodon/blob/master/config/application.rb#L43 locale: en local_domain: mastodon.local + # Use of WEB_DOMAIN requires careful consideration: https://docs.joinmastodon.org/admin/config/#federation + # You must redirect the path LOCAL_DOMAIN/.well-known/ to WEB_DOMAIN/.well-known/ as described + # web_domain: mastodon.example.com persistence: assets: # ReadWriteOnce is more widely supported than ReadWriteMany, but limits @@ -49,6 +52,8 @@ mastodon: endpoint: https://us-east-1.linodeobjects.com hostname: us-east-1.linodeobjects.com region: "" + # If you have a caching proxy, enter its base URL here. + alias_host: "" # these must be set manually; autogenerated keys are rotated on each upgrade secrets: secret_key_base: "" @@ -136,6 +141,105 @@ service: type: ClusterIP port: 80 +externalAuth: + oidc: + # OpenID Connect support is proposed in PR #16221 and awaiting merge. + enabled: false + # display_name: "example-label" + # issuer: https://login.example.space/auth/realms/example-space + # discovery: true + # scope: "openid,profile" + # uid_field: uid + # client_id: mastodon + # client_secret: SECRETKEY + # redirect_uri: https://example.com/auth/auth/openid_connect/callback + # assume_email_is_verified: true + # client_auth_method: + # response_type: + # response_mode: + # display: + # prompt: + # send_nonce: + # send_scope_to_token_endpoint: + # idp_logout_redirect_uri: + # http_scheme: + # host: + # port: + # jwks_uri: + # auth_endpoint: + # token_endpoint: + # user_info_endpoint: + # end_session_endpoint: + saml: + enabled: false + # acs_url: http://mastodon.example.com/auth/auth/saml/callback + # issuer: mastodon + # idp_sso_target_url: https://login.example.com/auth/realms/example/protocol/saml + # idp_cert: '-----BEGIN CERTIFICATE-----[your_cert_content]-----END CERTIFICATE-----' + # idp_cert_fingerprint: + # name_identifier_format: urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + # cert: + # private_key: + # want_assertion_signed: true + # want_assertion_encrypted: true + # assume_email_is_verified: true + # uid_attribute: "urn:oid:0.9.2342.19200300.100.1.1" + # attributes_statements: + # uid: "urn:oid:0.9.2342.19200300.100.1.1" + # email: "urn:oid:1.3.6.1.4.1.5923.1.1.1.6" + # full_name: "urn:oid:2.16.840.1.113730.3.1.241" + # first_name: "urn:oid:2.5.4.42" + # last_name: "urn:oid:2.5.4.4" + # verified: + # verified_email: + oauth_global: + # Force redirect local login to CAS. Does not function with SAML or LDAP. + oauth_redirect_at_sign_in: false + cas: + enabled: false + # url: https://sso.myserver.com + # host: sso.myserver.com + # port: 443 + # ssl: true + # validate_url: + # callback_url: + # logout_url: + # login_url: + # uid_field: 'user' + # ca_path: + # disable_ssl_verification: false + # assume_email_is_verified: true + # keys: + # uid: 'user' + # name: 'name' + # email: 'email' + # nickname: 'nickname' + # first_name: 'firstname' + # last_name: 'lastname' + # location: 'location' + # image: 'image' + # phone: 'phone' + pam: + enabled: false + # email_domain: example.com + # default_service: rpam + # controlled_service: rpam + ldap: + enabled: false + # host: myservice.namespace.svc + # port: 389 + # method: simple_tls + # base: + # bind_on: + # password: + # uid: cn + # mail: mail + # search_filter: "(|(%{uid}=%{email})(%{mail}=%{email}))" + # uid_conversion: + # enabled: true + # search: "., -" + # replace: _ + # https://github.com/tootsuite/mastodon/blob/master/Dockerfile#L88 # # if you manually change the UID/GID environment variables, ensure these values