Backout changes for automatically calculating the public baseurl. (#9313)

This breaks some people's configurations (if their Client-Server API
is not accessed via port 443).
This commit is contained in:
Patrick Cloke 2021-02-11 11:16:54 -05:00 committed by GitHub
parent afa18f1baa
commit e40d88cff3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 97 additions and 41 deletions

1
changelog.d/9313.bugfix Normal file
View file

@ -0,0 +1 @@
Do not automatically calculate `public_baseurl` since it can be wrong in some situations.

View file

@ -74,10 +74,6 @@ 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).
# #
# If this is left unset, it defaults to 'https://<server_name>/'. (Note that
# that will not work unless you configure Synapse or a reverse-proxy to listen
# on port 443.)
#
#public_baseurl: https://example.com/ #public_baseurl: https://example.com/
# Set the soft limit on the number of file descriptors synapse can use # Set the soft limit on the number of file descriptors synapse can use
@ -1169,9 +1165,8 @@ account_validity:
# send an email to the account's email address with a renewal link. By # send an email to the account's email address with a renewal link. By
# default, no such emails are sent. # default, no such emails are sent.
# #
# If you enable this setting, you will also need to fill out the 'email' # If you enable this setting, you will also need to fill out the 'email' and
# configuration section. You should also check that 'public_baseurl' is set # 'public_baseurl' configuration sections.
# correctly.
# #
#renew_at: 1w #renew_at: 1w
@ -1262,7 +1257,8 @@ account_validity:
# The identity server which we suggest that clients should use when users log # The identity server which we suggest that clients should use when users log
# 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.)
# #
#default_identity_server: https://matrix.org #default_identity_server: https://matrix.org
@ -1287,6 +1283,8 @@ account_validity:
# 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
@ -1938,9 +1936,9 @@ 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/".
# #
# The login fallback page (used by clients that don't natively support the # If public_baseurl is set, then the login fallback page (used by clients
# required login flows) is automatically whitelisted in addition to any URLs # that don't natively support the required login flows) is whitelisted in
# in this list. # addition to any URLs in this list.
# #
# By default, this list is empty. # By default, this list is empty.
# #

View file

@ -42,6 +42,8 @@ class ConsentURIBuilder:
""" """
if hs_config.form_secret is None: if hs_config.form_secret is None:
raise ConfigError("form_secret not set in config") raise ConfigError("form_secret not set in config")
if hs_config.public_baseurl is None:
raise ConfigError("public_baseurl not set in config")
self._hmac_secret = hs_config.form_secret.encode("utf-8") self._hmac_secret = hs_config.form_secret.encode("utf-8")
self._public_baseurl = hs_config.public_baseurl self._public_baseurl = hs_config.public_baseurl

View file

@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from ._base import Config from ._base import Config, ConfigError
class CasConfig(Config): class CasConfig(Config):
@ -30,13 +30,15 @@ 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"]
public_base_url = cas_config.get("service_url") or self.public_baseurl
if public_base_url[-1] != "/": # The public baseurl is required because it is used by the redirect
public_base_url += "/" # template.
public_baseurl = self.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.
self.cas_service_url = ( self.cas_service_url = public_baseurl + "_matrix/client/r0/login/cas/ticket"
public_base_url + "_matrix/client/r0/login/cas/ticket"
)
self.cas_displayname_attribute = cas_config.get("displayname_attribute") self.cas_displayname_attribute = cas_config.get("displayname_attribute")
self.cas_required_attributes = cas_config.get("required_attributes") or {} self.cas_required_attributes = cas_config.get("required_attributes") or {}
else: else:

View file

@ -166,6 +166,11 @@ 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),)
@ -264,6 +269,9 @@ 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

@ -53,7 +53,10 @@ class OIDCConfig(Config):
"Multiple OIDC providers have the idp_id %r." % idp_id "Multiple OIDC providers have the idp_id %r." % idp_id
) )
self.oidc_callback_url = self.public_baseurl + "_synapse/client/oidc/callback" public_baseurl = self.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"
@property @property
def oidc_enabled(self) -> bool: def oidc_enabled(self) -> bool:

View file

@ -49,6 +49,10 @@ class AccountValidityConfig(Config):
self.startup_job_max_delta = self.period * 10.0 / 100.0 self.startup_job_max_delta = self.period * 10.0 / 100.0
if self.renew_by_email_enabled:
if "public_baseurl" not in synapse_config:
raise ConfigError("Can't send renewal emails without 'public_baseurl'")
template_dir = config.get("template_dir") template_dir = config.get("template_dir")
if not template_dir: if not template_dir:
@ -105,6 +109,13 @@ 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.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)
@ -227,9 +238,8 @@ class RegistrationConfig(Config):
# send an email to the account's email address with a renewal link. By # send an email to the account's email address with a renewal link. By
# default, no such emails are sent. # default, no such emails are sent.
# #
# If you enable this setting, you will also need to fill out the 'email' # If you enable this setting, you will also need to fill out the 'email' and
# configuration section. You should also check that 'public_baseurl' is set # 'public_baseurl' configuration sections.
# correctly.
# #
#renew_at: 1w #renew_at: 1w
@ -320,7 +330,8 @@ class RegistrationConfig(Config):
# The identity server which we suggest that clients should use when users log # The identity server which we suggest that clients should use when users log
# 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.)
# #
#default_identity_server: https://matrix.org #default_identity_server: https://matrix.org
@ -345,6 +356,8 @@ 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

@ -189,6 +189,8 @@ class SAML2Config(Config):
import saml2 import saml2
public_baseurl = self.public_baseurl public_baseurl = self.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)

View file

@ -161,11 +161,7 @@ class ServerConfig(Config):
self.print_pidfile = config.get("print_pidfile") self.print_pidfile = config.get("print_pidfile")
self.user_agent_suffix = config.get("user_agent_suffix") self.user_agent_suffix = config.get("user_agent_suffix")
self.use_frozen_dicts = config.get("use_frozen_dicts", False) self.use_frozen_dicts = config.get("use_frozen_dicts", False)
self.public_baseurl = config.get("public_baseurl") or "https://%s/" % ( self.public_baseurl = config.get("public_baseurl")
self.server_name,
)
if self.public_baseurl[-1] != "/":
self.public_baseurl += "/"
# Whether to enable user presence. # Whether to enable user presence.
self.use_presence = config.get("use_presence", True) self.use_presence = config.get("use_presence", True)
@ -321,6 +317,9 @@ class ServerConfig(Config):
# Always blacklist 0.0.0.0, :: # Always blacklist 0.0.0.0, ::
self.federation_ip_range_blacklist.update(["0.0.0.0", "::"]) self.federation_ip_range_blacklist.update(["0.0.0.0", "::"])
if self.public_baseurl is not None:
if self.public_baseurl[-1] != "/":
self.public_baseurl += "/"
self.start_pushers = config.get("start_pushers", True) self.start_pushers = config.get("start_pushers", True)
# (undocumented) option for torturing the worker-mode replication a bit, # (undocumented) option for torturing the worker-mode replication a bit,
@ -748,10 +747,6 @@ 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).
# #
# If this is left unset, it defaults to 'https://<server_name>/'. (Note that
# that will not work unless you configure Synapse or a reverse-proxy to listen
# on port 443.)
#
#public_baseurl: https://example.com/ #public_baseurl: https://example.com/
# Set the soft limit on the number of file descriptors synapse can use # Set the soft limit on the number of file descriptors synapse can use

View file

@ -64,6 +64,9 @@ 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
# list if it's provided (because we can't figure out what that URL is otherwise).
if self.public_baseurl:
login_fallback_url = self.public_baseurl + "_matrix/static/client/login" login_fallback_url = self.public_baseurl + "_matrix/static/client/login"
self.sso_client_whitelist.append(login_fallback_url) self.sso_client_whitelist.append(login_fallback_url)
@ -83,9 +86,9 @@ 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/".
# #
# The login fallback page (used by clients that don't natively support the # If public_baseurl is set, then the login fallback page (used by clients
# required login flows) is automatically whitelisted in addition to any URLs # that don't natively support the required login flows) is whitelisted in
# in this list. # addition to any URLs in this list.
# #
# By default, this list is empty. # By default, this list is empty.
# #

View file

@ -504,6 +504,10 @@ class IdentityHandler(BaseHandler):
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.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,6 +34,10 @@ class WellKnownBuilder:
self._config = hs.config self._config = hs.config
def get_well_known(self): def get_well_known(self):
# if we don't have a public_baseurl, we can't help much here.
if self._config.public_baseurl is None:
return None
result = {"m.homeserver": {"base_url": self._config.public_baseurl}} result = {"m.homeserver": {"base_url": self._config.public_baseurl}}
if self._config.default_identity_server: if self._config.default_identity_server:

View file

@ -17,7 +17,7 @@
import time import time
import urllib.parse import urllib.parse
from typing import TYPE_CHECKING, Callable, Iterable, Union from typing import TYPE_CHECKING, Callable, Iterable, Optional, Union
import jinja2 import jinja2
@ -74,14 +74,23 @@ def build_jinja_env(
return env return env
def _create_mxc_to_http_filter(public_baseurl: str) -> Callable: def _create_mxc_to_http_filter(
public_baseurl: Optional[str],
) -> Callable[[str, int, int, str], str]:
"""Create and return a jinja2 filter that converts MXC urls to HTTP """Create and return a jinja2 filter that converts MXC urls to HTTP
Args: Args:
public_baseurl: The public, accessible base URL of the homeserver public_baseurl: The public, accessible base URL of the homeserver
""" """
def mxc_to_http_filter(value, width, height, resize_method="crop"): def mxc_to_http_filter(
value: str, width: int, height: int, resize_method: str = "crop"
) -> str:
if not public_baseurl:
raise RuntimeError(
"public_baseurl must be set in the homeserver config to convert MXC URLs to HTTP URLs."
)
if value[0:6] != "mxc://": if value[0:6] != "mxc://":
return "" return ""

View file

@ -672,10 +672,12 @@ class CASTestCase(unittest.HomeserverTestCase):
self.redirect_path = "_synapse/client/login/sso/redirect/confirm" self.redirect_path = "_synapse/client/login/sso/redirect/confirm"
config = self.default_config() config = self.default_config()
config["public_baseurl"] = (
config.get("public_baseurl") or "https://matrix.goodserver.com:8448"
)
config["cas_config"] = { config["cas_config"] = {
"enabled": True, "enabled": True,
"server_url": CAS_SERVER, "server_url": CAS_SERVER,
"service_url": "https://matrix.goodserver.com:8448",
} }
cas_user_id = "username" cas_user_id = "username"

View file

@ -40,3 +40,12 @@ class WellKnownTests(unittest.HomeserverTestCase):
"m.identity_server": {"base_url": "https://testis"}, "m.identity_server": {"base_url": "https://testis"},
}, },
) )
def test_well_known_no_public_baseurl(self):
self.hs.config.public_baseurl = None
channel = self.make_request(
"GET", "/.well-known/matrix/client", shorthand=False
)
self.assertEqual(channel.code, 404)

View file

@ -159,6 +159,7 @@ def default_config(name, parse=False):
}, },
"rc_3pid_validation": {"per_second": 10000, "burst_count": 10000}, "rc_3pid_validation": {"per_second": 10000, "burst_count": 10000},
"saml2_enabled": False, "saml2_enabled": False,
"public_baseurl": None,
"default_identity_server": None, "default_identity_server": None,
"key_refresh_interval": 24 * 60 * 60 * 1000, "key_refresh_interval": 24 * 60 * 60 * 1000,
"old_signing_keys": {}, "old_signing_keys": {},