Default value for `public_baseurl` (#11210)

We might as well use a default value for `public_baseurl` based on
`server_name` - in many cases, it will be correct.
This commit is contained in:
Richard van der Hoff 2021-11-08 14:13:10 +00:00 committed by GitHub
parent 556a488209
commit 86a497efaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 62 additions and 73 deletions

View File

@ -0,0 +1 @@
Calculate a default value for `public_baseurl` based on `server_name`.

View File

@ -91,6 +91,8 @@ pid_file: DATADIR/homeserver.pid
# Otherwise, it should be the URL to reach Synapse's client HTTP listener (see # Otherwise, it should be the URL to reach Synapse's client HTTP listener (see
# 'listeners' below). # 'listeners' below).
# #
# Defaults to 'https://<server_name>/'.
#
#public_baseurl: https://example.com/ #public_baseurl: https://example.com/
# Uncomment the following to tell other servers to send federation traffic on # Uncomment the following to tell other servers to send federation traffic on
@ -1265,7 +1267,7 @@ oembed:
# in on this server. # in on this server.
# #
# (By default, no suggestion is made, so it is left up to the client. # (By default, no suggestion is made, so it is left up to the client.
# This setting is ignored unless public_baseurl is also set.) # This setting is ignored unless public_baseurl is also explicitly set.)
# #
#default_identity_server: https://matrix.org #default_identity_server: https://matrix.org
@ -1290,8 +1292,6 @@ oembed:
# by the Matrix Identity Service API specification: # by the Matrix Identity Service API specification:
# https://matrix.org/docs/spec/identity_service/latest # https://matrix.org/docs/spec/identity_service/latest
# #
# If a delegate is specified, the config option public_baseurl must also be filled out.
#
account_threepid_delegates: account_threepid_delegates:
#email: https://example.com # Delegate email sending to example.com #email: https://example.com # Delegate email sending to example.com
#msisdn: http://localhost:8090 # Delegate SMS sending to this local process #msisdn: http://localhost:8090 # Delegate SMS sending to this local process
@ -1981,11 +1981,10 @@ sso:
# phishing attacks from evil.site. To avoid this, include a slash after the # phishing attacks from evil.site. To avoid this, include a slash after the
# hostname: "https://my.client/". # hostname: "https://my.client/".
# #
# If public_baseurl is set, then the login fallback page (used by clients # The login fallback page (used by clients that don't natively support the
# that don't natively support the required login flows) is whitelisted in # required login flows) is whitelisted in addition to any URLs in this list.
# addition to any URLs in this list.
# #
# By default, this list is empty. # By default, this list contains only the login fallback page.
# #
#client_whitelist: #client_whitelist:
# - https://riot.im/develop # - https://riot.im/develop

View File

@ -38,9 +38,6 @@ class ConsentURIBuilder:
def __init__(self, hs_config: HomeServerConfig): def __init__(self, hs_config: HomeServerConfig):
if hs_config.key.form_secret is None: if hs_config.key.form_secret is None:
raise ConfigError("form_secret not set in config") raise ConfigError("form_secret not set in config")
if hs_config.server.public_baseurl is None:
raise ConfigError("public_baseurl not set in config")
self._hmac_secret = hs_config.key.form_secret.encode("utf-8") self._hmac_secret = hs_config.key.form_secret.encode("utf-8")
self._public_baseurl = hs_config.server.public_baseurl self._public_baseurl = hs_config.server.public_baseurl

View File

@ -75,10 +75,6 @@ class AccountValidityConfig(Config):
self.account_validity_period * 10.0 / 100.0 self.account_validity_period * 10.0 / 100.0
) )
if self.account_validity_renew_by_email_enabled:
if not self.root.server.public_baseurl:
raise ConfigError("Can't send renewal emails without 'public_baseurl'")
# Load account validity templates. # Load account validity templates.
account_validity_template_dir = account_validity_config.get("template_dir") account_validity_template_dir = account_validity_config.get("template_dir")
if account_validity_template_dir is not None: if account_validity_template_dir is not None:

View File

@ -16,7 +16,7 @@ from typing import Any, List
from synapse.config.sso import SsoAttributeRequirement from synapse.config.sso import SsoAttributeRequirement
from ._base import Config, ConfigError from ._base import Config
from ._util import validate_config from ._util import validate_config
@ -35,14 +35,10 @@ class CasConfig(Config):
if self.cas_enabled: if self.cas_enabled:
self.cas_server_url = cas_config["server_url"] self.cas_server_url = cas_config["server_url"]
# The public baseurl is required because it is used by the redirect
# template.
public_baseurl = self.root.server.public_baseurl
if not public_baseurl:
raise ConfigError("cas_config requires a public_baseurl to be set")
# TODO Update this to a _synapse URL. # TODO Update this to a _synapse URL.
public_baseurl = self.root.server.public_baseurl
self.cas_service_url = public_baseurl + "_matrix/client/r0/login/cas/ticket" self.cas_service_url = public_baseurl + "_matrix/client/r0/login/cas/ticket"
self.cas_displayname_attribute = cas_config.get("displayname_attribute") self.cas_displayname_attribute = cas_config.get("displayname_attribute")
required_attributes = cas_config.get("required_attributes") or {} required_attributes = cas_config.get("required_attributes") or {}
self.cas_required_attributes = _parsed_required_attributes_def( self.cas_required_attributes = _parsed_required_attributes_def(

View File

@ -186,11 +186,6 @@ class EmailConfig(Config):
if not self.email_notif_from: if not self.email_notif_from:
missing.append("email.notif_from") missing.append("email.notif_from")
# public_baseurl is required to build password reset and validation links that
# will be emailed to users
if config.get("public_baseurl") is None:
missing.append("public_baseurl")
if missing: if missing:
raise ConfigError( raise ConfigError(
MISSING_PASSWORD_RESET_CONFIG_ERROR % (", ".join(missing),) MISSING_PASSWORD_RESET_CONFIG_ERROR % (", ".join(missing),)
@ -296,9 +291,6 @@ class EmailConfig(Config):
if not self.email_notif_from: if not self.email_notif_from:
missing.append("email.notif_from") missing.append("email.notif_from")
if config.get("public_baseurl") is None:
missing.append("public_baseurl")
if missing: if missing:
raise ConfigError( raise ConfigError(
"email.enable_notifs is True but required keys are missing: %s" "email.enable_notifs is True but required keys are missing: %s"

View File

@ -59,8 +59,6 @@ class OIDCConfig(Config):
) )
public_baseurl = self.root.server.public_baseurl public_baseurl = self.root.server.public_baseurl
if public_baseurl is None:
raise ConfigError("oidc_config requires a public_baseurl to be set")
self.oidc_callback_url = public_baseurl + "_synapse/client/oidc/callback" self.oidc_callback_url = public_baseurl + "_synapse/client/oidc/callback"
@property @property

View File

@ -45,17 +45,6 @@ class RegistrationConfig(Config):
account_threepid_delegates = config.get("account_threepid_delegates") or {} account_threepid_delegates = config.get("account_threepid_delegates") or {}
self.account_threepid_delegate_email = account_threepid_delegates.get("email") self.account_threepid_delegate_email = account_threepid_delegates.get("email")
self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn") self.account_threepid_delegate_msisdn = account_threepid_delegates.get("msisdn")
if (
self.account_threepid_delegate_msisdn
and not self.root.server.public_baseurl
):
raise ConfigError(
"The configuration option `public_baseurl` is required if "
"`account_threepid_delegate.msisdn` is set, such that "
"clients know where to submit validation tokens to. Please "
"configure `public_baseurl`."
)
self.default_identity_server = config.get("default_identity_server") self.default_identity_server = config.get("default_identity_server")
self.allow_guest_access = config.get("allow_guest_access", False) self.allow_guest_access = config.get("allow_guest_access", False)
@ -240,7 +229,7 @@ class RegistrationConfig(Config):
# in on this server. # in on this server.
# #
# (By default, no suggestion is made, so it is left up to the client. # (By default, no suggestion is made, so it is left up to the client.
# This setting is ignored unless public_baseurl is also set.) # This setting is ignored unless public_baseurl is also explicitly set.)
# #
#default_identity_server: https://matrix.org #default_identity_server: https://matrix.org
@ -265,8 +254,6 @@ class RegistrationConfig(Config):
# by the Matrix Identity Service API specification: # by the Matrix Identity Service API specification:
# https://matrix.org/docs/spec/identity_service/latest # https://matrix.org/docs/spec/identity_service/latest
# #
# If a delegate is specified, the config option public_baseurl must also be filled out.
#
account_threepid_delegates: account_threepid_delegates:
#email: https://example.com # Delegate email sending to example.com #email: https://example.com # Delegate email sending to example.com
#msisdn: http://localhost:8090 # Delegate SMS sending to this local process #msisdn: http://localhost:8090 # Delegate SMS sending to this local process

View File

@ -199,14 +199,11 @@ class SAML2Config(Config):
""" """
import saml2 import saml2
public_baseurl = self.root.server.public_baseurl
if public_baseurl is None:
raise ConfigError("saml2_config requires a public_baseurl to be set")
if self.saml2_grandfathered_mxid_source_attribute: if self.saml2_grandfathered_mxid_source_attribute:
optional_attributes.add(self.saml2_grandfathered_mxid_source_attribute) optional_attributes.add(self.saml2_grandfathered_mxid_source_attribute)
optional_attributes -= required_attributes optional_attributes -= required_attributes
public_baseurl = self.root.server.public_baseurl
metadata_url = public_baseurl + "_synapse/client/saml2/metadata.xml" metadata_url = public_baseurl + "_synapse/client/saml2/metadata.xml"
response_url = public_baseurl + "_synapse/client/saml2/authn_response" response_url = public_baseurl + "_synapse/client/saml2/authn_response"
return { return {

View File

@ -16,6 +16,7 @@ import itertools
import logging import logging
import os.path import os.path
import re import re
import urllib.parse
from textwrap import indent from textwrap import indent
from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union
@ -264,10 +265,44 @@ class ServerConfig(Config):
self.use_frozen_dicts = config.get("use_frozen_dicts", False) self.use_frozen_dicts = config.get("use_frozen_dicts", False)
self.serve_server_wellknown = config.get("serve_server_wellknown", False) self.serve_server_wellknown = config.get("serve_server_wellknown", False)
self.public_baseurl = config.get("public_baseurl") # Whether we should serve a "client well-known":
if self.public_baseurl is not None: # (a) at .well-known/matrix/client on our client HTTP listener
if self.public_baseurl[-1] != "/": # (b) in the response to /login
self.public_baseurl += "/" #
# ... which together help ensure that clients use our public_baseurl instead of
# whatever they were told by the user.
#
# For the sake of backwards compatibility with existing installations, this is
# True if public_baseurl is specified explicitly, and otherwise False. (The
# reasoning here is that we have no way of knowing that the default
# public_baseurl is actually correct for existing installations - many things
# will not work correctly, but that's (probably?) better than sending clients
# to a completely broken URL.
self.serve_client_wellknown = False
public_baseurl = config.get("public_baseurl")
if public_baseurl is None:
public_baseurl = f"https://{self.server_name}/"
logger.info("Using default public_baseurl %s", public_baseurl)
else:
self.serve_client_wellknown = True
if public_baseurl[-1] != "/":
public_baseurl += "/"
self.public_baseurl = public_baseurl
# check that public_baseurl is valid
try:
splits = urllib.parse.urlsplit(self.public_baseurl)
except Exception as e:
raise ConfigError(f"Unable to parse URL: {e}", ("public_baseurl",))
if splits.scheme not in ("https", "http"):
raise ConfigError(
f"Invalid scheme '{splits.scheme}': only https and http are supported"
)
if splits.query or splits.fragment:
raise ConfigError(
"public_baseurl cannot contain query parameters or a #-fragment"
)
# Whether to enable user presence. # Whether to enable user presence.
presence_config = config.get("presence") or {} presence_config = config.get("presence") or {}
@ -773,6 +808,8 @@ class ServerConfig(Config):
# Otherwise, it should be the URL to reach Synapse's client HTTP listener (see # Otherwise, it should be the URL to reach Synapse's client HTTP listener (see
# 'listeners' below). # 'listeners' below).
# #
# Defaults to 'https://<server_name>/'.
#
#public_baseurl: https://example.com/ #public_baseurl: https://example.com/
# Uncomment the following to tell other servers to send federation traffic on # Uncomment the following to tell other servers to send federation traffic on

View File

@ -101,13 +101,10 @@ class SSOConfig(Config):
# gracefully to the client). This would make it pointless to ask the user for # gracefully to the client). This would make it pointless to ask the user for
# confirmation, since the URL the confirmation page would be showing wouldn't be # confirmation, since the URL the confirmation page would be showing wouldn't be
# the client's. # the client's.
# public_baseurl is an optional setting, so we only add the fallback's URL to the login_fallback_url = (
# list if it's provided (because we can't figure out what that URL is otherwise). self.root.server.public_baseurl + "_matrix/static/client/login"
if self.root.server.public_baseurl: )
login_fallback_url = ( self.sso_client_whitelist.append(login_fallback_url)
self.root.server.public_baseurl + "_matrix/static/client/login"
)
self.sso_client_whitelist.append(login_fallback_url)
def generate_config_section(self, **kwargs): def generate_config_section(self, **kwargs):
return """\ return """\
@ -128,11 +125,10 @@ class SSOConfig(Config):
# phishing attacks from evil.site. To avoid this, include a slash after the # phishing attacks from evil.site. To avoid this, include a slash after the
# hostname: "https://my.client/". # hostname: "https://my.client/".
# #
# If public_baseurl is set, then the login fallback page (used by clients # The login fallback page (used by clients that don't natively support the
# that don't natively support the required login flows) is whitelisted in # required login flows) is whitelisted in addition to any URLs in this list.
# addition to any URLs in this list.
# #
# By default, this list is empty. # By default, this list contains only the login fallback page.
# #
#client_whitelist: #client_whitelist:
# - https://riot.im/develop # - https://riot.im/develop

View File

@ -537,10 +537,6 @@ class IdentityHandler:
except RequestTimedOutError: except RequestTimedOutError:
raise SynapseError(500, "Timed out contacting identity server") raise SynapseError(500, "Timed out contacting identity server")
# It is already checked that public_baseurl is configured since this code
# should only be used if account_threepid_delegate_msisdn is true.
assert self.hs.config.server.public_baseurl
# we need to tell the client to send the token back to us, since it doesn't # we need to tell the client to send the token back to us, since it doesn't
# otherwise know where to send it, so add submit_url response parameter # otherwise know where to send it, so add submit_url response parameter
# (see also MSC2078) # (see also MSC2078)

View File

@ -34,8 +34,7 @@ class WellKnownBuilder:
self._config = hs.config self._config = hs.config
def get_well_known(self) -> Optional[JsonDict]: def get_well_known(self) -> Optional[JsonDict]:
# if we don't have a public_baseurl, we can't help much here. if not self._config.server.serve_client_wellknown:
if self._config.server.public_baseurl is None:
return None return None
result = {"m.homeserver": {"base_url": self._config.server.public_baseurl}} result = {"m.homeserver": {"base_url": self._config.server.public_baseurl}}

View File

@ -65,7 +65,7 @@ class EmailPusherTests(HomeserverTestCase):
"notif_from": "test@example.com", "notif_from": "test@example.com",
"riot_base_url": None, "riot_base_url": None,
} }
config["public_baseurl"] = "aaa" config["public_baseurl"] = "http://aaa"
config["start_pushers"] = True config["start_pushers"] = True
hs = self.setup_test_homeserver(config=config) hs = self.setup_test_homeserver(config=config)

View File

@ -35,7 +35,6 @@ class ConsentResourceTestCase(unittest.HomeserverTestCase):
def make_homeserver(self, reactor, clock): def make_homeserver(self, reactor, clock):
config = self.default_config() config = self.default_config()
config["public_baseurl"] = "aaaa"
config["form_secret"] = "123abc" config["form_secret"] = "123abc"
# Make some temporary templates... # Make some temporary templates...

View File

@ -891,7 +891,6 @@ class AccountValidityRenewalByEmailTestCase(unittest.HomeserverTestCase):
"smtp_pass": None, "smtp_pass": None,
"notif_from": "test@example.com", "notif_from": "test@example.com",
} }
config["public_baseurl"] = "aaa"
self.hs = self.setup_test_homeserver(config=config) self.hs = self.setup_test_homeserver(config=config)