From 7390eb2ed03681424e205ed796bb9e424566c5cf Mon Sep 17 00:00:00 2001 From: Mateusz Mandera Date: Wed, 29 Jan 2025 12:48:22 +0800 Subject: [PATCH] zilencer: Rename registration takeover to registration transfer. This is the final naming that we want, compared to the naming we merged in #32399. Includes renaming the API endpoints, but that should be fine as the original PR was just merged and this isn't deployed anywhere. --- zerver/lib/remote_server.py | 4 +- zerver/management/commands/register_server.py | 16 ++++---- zerver/tests/test_push_notifications.py | 38 +++++++++---------- zerver/views/push_notifications.py | 2 +- zilencer/auth.py | 6 +-- zilencer/urls.py | 8 ++-- zilencer/views.py | 34 ++++++++--------- zproject/default_settings.py | 2 +- zproject/urls.py | 4 +- 9 files changed, 57 insertions(+), 57 deletions(-) diff --git a/zerver/lib/remote_server.py b/zerver/lib/remote_server.py index 524b1f4d8c..7b5b4d62b7 100644 --- a/zerver/lib/remote_server.py +++ b/zerver/lib/remote_server.py @@ -493,11 +493,11 @@ def maybe_enqueue_audit_log_upload(realm: Realm) -> None: SELF_HOSTING_REGISTRATION_TAKEOVER_CHALLENGE_TOKEN_REDIS_KEY = ( - "self_hosting_domain_takeover_challenge_verify" + "self_hosting_domain_transfer_challenge_verify" ) -def prepare_for_registration_takeover_challenge(verification_secret: str) -> str: +def prepare_for_registration_transfer_challenge(verification_secret: str) -> str: access_token = secrets.token_urlsafe(32) data_to_store = {"verification_secret": verification_secret, "access_token": access_token} redis_client.set( diff --git a/zerver/management/commands/register_server.py b/zerver/management/commands/register_server.py index 12ade08434..de67a9ec57 100644 --- a/zerver/management/commands/register_server.py +++ b/zerver/management/commands/register_server.py @@ -13,7 +13,7 @@ from typing_extensions import override from zerver.lib.management import ZulipBaseCommand, check_config from zerver.lib.remote_server import ( PushBouncerSession, - prepare_for_registration_takeover_challenge, + prepare_for_registration_transfer_challenge, send_json_to_push_bouncer, send_server_data_to_push_bouncer, ) @@ -41,7 +41,7 @@ class Command(ZulipBaseCommand): help="Automatically rotate your server's zulip_org_key", ) action.add_argument( - "--registration-takeover", + "--registration-transfer", action="store_true", help="Overwrite pre-existing registration for the hostname", ) @@ -114,8 +114,8 @@ class Command(ZulipBaseCommand): # enough about what happened. return - if options["registration_takeover"]: - org_id, org_key = self.do_registration_takeover_flow(hostname) + if options["registration_transfer"]: + org_id, org_key = self.do_registration_transfer_flow(hostname) # We still want to proceed with a regular request to the registration endpoint, # as it'll update the registration with new information such as the contact email. request["zulip_org_id"] = org_id @@ -154,24 +154,24 @@ class Command(ZulipBaseCommand): ) print("Mobile Push Notification Service registration successfully updated!") - if options["registration_takeover"]: + if options["registration_transfer"]: print() print( "Make sure to restart the server next by running /home/zulip/deployments/current/scripts/restart-server " "so that the new credentials are reloaded." ) - def do_registration_takeover_flow(self, hostname: str) -> tuple[str, str]: + def do_registration_transfer_flow(self, hostname: str) -> tuple[str, str]: params = {"hostname": hostname} response = self._request_push_notification_bouncer_url( - "/api/v1/remotes/server/register/takeover", params + "/api/v1/remotes/server/register/transfer", params ) verification_secret = response.json()["verification_secret"] print( "Received a verification secret from the service. Preparing to serve it at the verification URL." ) - token_for_push_bouncer = prepare_for_registration_takeover_challenge(verification_secret) + token_for_push_bouncer = prepare_for_registration_transfer_challenge(verification_secret) print("Sending ACK to the service and awaiting completion of verification...") response = self._request_push_notification_bouncer_url( diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index 72665171c7..71019bd148 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -75,7 +75,7 @@ from zerver.lib.remote_server import ( PushNotificationBouncerServerError, build_analytics_data, get_realms_info_for_push_bouncer, - prepare_for_registration_takeover_challenge, + prepare_for_registration_transfer_challenge, record_push_notifications_recently_working, redis_client, send_server_data_to_push_bouncer, @@ -111,7 +111,7 @@ from zerver.models.scheduled_jobs import NotificationTriggers from zerver.models.streams import get_stream from zilencer.auth import ( REMOTE_SERVER_TAKEOVER_TOKEN_VALIDITY_SECONDS, - generate_registration_takeover_verification_secret, + generate_registration_transfer_verification_secret, ) from zilencer.lib.remote_counts import MissingDataError from zilencer.models import RemoteZulipServerAuditLog @@ -5364,7 +5364,7 @@ class PushBouncerSignupTest(ZulipTestCase): "A server with hostname example.com already exists. " "If you control the hostname " "and want to transfer the registration to this server, you can run manage.py register_server " - "with the --registration-takeover flag.", + "with the --registration-transfer flag.", ) def test_register_contact_email_validation_rules(self) -> None: @@ -5433,13 +5433,13 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): server = RemoteZulipServer.objects.get(uuid=self.zulip_org_id) result = self.client_post( - "/api/v1/remotes/server/register/takeover", {"hostname": self.hostname} + "/api/v1/remotes/server/register/transfer", {"hostname": self.hostname} ) self.assert_json_success(result) data = result.json() verification_secret = data["verification_secret"] - access_token = prepare_for_registration_takeover_challenge(verification_secret) + access_token = prepare_for_registration_transfer_challenge(verification_secret) # First we query the host's endpoint for serving the verification_secret. result = self.client_post(f"/api/v1/zulip-services/verify/{access_token}/") self.assert_json_success(result) @@ -5469,7 +5469,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): self.assertNotEqual(new_key, self.zulip_org_key) self.assertEqual( mock_log.output, - ["INFO:zilencer.views:verify_registration_takeover:host:example.com|success"], + ["INFO:zilencer.views:verify_registration_transfer:host:example.com|success"], ) # Verify the registration got updated accordingly. @@ -5485,7 +5485,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): @override_settings( RATE_LIMITING=True, ABSOLUTE_USAGE_LIMITS_BY_ENDPOINT={ - "verify_registration_takeover_challenge_ack_endpoint": [(10, 2)] + "verify_registration_transfer_challenge_ack_endpoint": [(10, 2)] }, ) @responses.activate @@ -5521,7 +5521,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): self.assertEqual( mock_log.output, [ - "WARNING:zilencer.views:Rate limit exceeded for verify_registration_takeover_challenge_ack_endpoint" + "WARNING:zilencer.views:Rate limit exceeded for verify_registration_transfer_challenge_ack_endpoint" ], ) @@ -5548,7 +5548,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): self.assert_json_error(result, "The verification secret is malformed") with time_machine.travel(time_now, tick=False): - verification_secret = generate_registration_takeover_verification_secret(self.hostname) + verification_secret = generate_registration_transfer_verification_secret(self.hostname) responses.get( "https://example.com/api/v1/zulip-services/verify/sometoken/", json={"verification_secret": verification_secret}, @@ -5568,7 +5568,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): time_machine.travel(time_now, tick=False), mock.patch("zilencer.auth.REMOTE_SERVER_TAKEOVER_TOKEN_SALT", "foo"), ): - verification_secret = generate_registration_takeover_verification_secret(self.hostname) + verification_secret = generate_registration_transfer_verification_secret(self.hostname) responses.get( "https://example.com/api/v1/zulip-services/verify/sometoken/", json={"verification_secret": verification_secret}, @@ -5582,7 +5582,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): # Make sure a valid verification secret for one hostname does not work for another. with time_machine.travel(time_now, tick=False): - verification_secret = generate_registration_takeover_verification_secret( + verification_secret = generate_registration_transfer_verification_secret( "different.example.com" ) responses.get( @@ -5616,7 +5616,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): self.assertEqual( mock_log.output, [ - "INFO:zilencer.views:verify_registration_takeover:host:example.com|secret_not_prepared" + "INFO:zilencer.views:verify_registration_transfer:host:example.com|secret_not_prepared" ], ) @@ -5633,7 +5633,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): ) self.assert_json_error(result, "Error response received from the host: 403") self.assertIn( - "verify_registration_takeover:host:example.com|exception:", mock_log.output[0] + "verify_registration_transfer:host:example.com|exception:", mock_log.output[0] ) # SSLError: @@ -5649,7 +5649,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): ) self.assert_json_error(result, "SSL error occurred while communicating with the host.") self.assertIn( - "verify_registration_takeover:host:example.com|exception:", mock_log.output[0] + "verify_registration_transfer:host:example.com|exception:", mock_log.output[0] ) # ConnectionError: @@ -5667,7 +5667,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): result, "Connection error occurred while communicating with the host." ) self.assertIn( - "verify_registration_takeover:host:example.com|exception:", mock_log.output[0] + "verify_registration_transfer:host:example.com|exception:", mock_log.output[0] ) # Timeout: @@ -5683,7 +5683,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): ) self.assert_json_error(result, "The request timed out while communicating with the host.") self.assertIn( - "verify_registration_takeover:host:example.com|exception:", mock_log.output[0] + "verify_registration_transfer:host:example.com|exception:", mock_log.output[0] ) # Generic RequestException: @@ -5699,12 +5699,12 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): ) self.assert_json_error(result, "An error occurred while communicating with the host.") self.assertIn( - "verify_registration_takeover:host:example.com|exception:", mock_log.output[0] + "verify_registration_transfer:host:example.com|exception:", mock_log.output[0] ) def test_initiate_flow_for_unregistered_domain(self) -> None: result = self.client_post( - "/api/v1/remotes/server/register/takeover", + "/api/v1/remotes/server/register/transfer", {"hostname": "unregistered.example.com"}, ) self.assert_json_error(result, "unregistered.example.com not yet registered") @@ -5715,7 +5715,7 @@ class RegistrationTakeoverFlowTest(ZulipTestCase): ) self.assert_json_error(result, "Verification secret not prepared") - valid_access_token = prepare_for_registration_takeover_challenge(verification_secret="foo") + valid_access_token = prepare_for_registration_transfer_challenge(verification_secret="foo") result = self.client_get( f"/api/v1/zulip-services/verify/{valid_access_token}/", ) diff --git a/zerver/views/push_notifications.py b/zerver/views/push_notifications.py index a8e2b4b82e..be2046be29 100644 --- a/zerver/views/push_notifications.py +++ b/zerver/views/push_notifications.py @@ -247,7 +247,7 @@ class VerificationSecretNotPreparedError(JsonableError): @typed_endpoint_without_parameters -def self_hosting_registration_takeover_challenge_verify( +def self_hosting_registration_transfer_challenge_verify( request: HttpRequest, access_token: str ) -> HttpResponse: json_data = redis_client.get( diff --git a/zilencer/auth.py b/zilencer/auth.py index 3dc75c2441..4800039ee7 100644 --- a/zilencer/auth.py +++ b/zilencer/auth.py @@ -40,17 +40,17 @@ logger = logging.getLogger(__name__) ParamT = ParamSpec("ParamT") -REMOTE_SERVER_TAKEOVER_TOKEN_SALT = "remote_server_takeover" +REMOTE_SERVER_TAKEOVER_TOKEN_SALT = "remote_server_transfer" REMOTE_SERVER_TAKEOVER_TOKEN_VALIDITY_SECONDS = 10 -def generate_registration_takeover_verification_secret(hostname: str) -> str: +def generate_registration_transfer_verification_secret(hostname: str) -> str: signer = TimestampSigner(salt=REMOTE_SERVER_TAKEOVER_TOKEN_SALT) secret = base64.b16encode(signer.sign(hostname).encode()).decode() return secret -def validate_registration_takeover_verification_secret(secret: str, hostname: str) -> None: +def validate_registration_transfer_verification_secret(secret: str, hostname: str) -> None: signer = TimestampSigner(salt=REMOTE_SERVER_TAKEOVER_TOKEN_SALT) try: signed_data = base64.b16decode(secret).decode() diff --git a/zilencer/urls.py b/zilencer/urls.py index 4fab2d99f5..1aed48313d 100644 --- a/zilencer/urls.py +++ b/zilencer/urls.py @@ -13,10 +13,10 @@ from zilencer.views import ( remote_server_notify_push, remote_server_post_analytics, remote_server_send_test_notification, - take_over_remote_server_registration, + transfer_remote_server_registration, unregister_all_remote_push_devices, unregister_remote_push_device, - verify_registration_takeover_challenge_ack_endpoint, + verify_registration_transfer_challenge_ack_endpoint, ) i18n_urlpatterns: Any = [] @@ -30,10 +30,10 @@ push_bouncer_patterns = [ remote_server_path("remotes/push/test_notification", POST=remote_server_send_test_notification), # Push signup doesn't use the REST API, since there's no auth. path("remotes/server/register", register_remote_server), - path("remotes/server/register/takeover", take_over_remote_server_registration), + path("remotes/server/register/transfer", transfer_remote_server_registration), path( "remotes/server/register/verify_challenge", - verify_registration_takeover_challenge_ack_endpoint, + verify_registration_transfer_challenge_ack_endpoint, ), remote_server_path("remotes/server/deactivate", POST=deactivate_remote_server), # For receiving table data used in analytics and billing diff --git a/zilencer/views.py b/zilencer/views.py index d822b204dc..81d07766d6 100644 --- a/zilencer/views.py +++ b/zilencer/views.py @@ -80,8 +80,8 @@ from zerver.models.realms import DisposableEmailError from zerver.views.push_notifications import validate_token from zilencer.auth import ( InvalidZulipServerKeyError, - generate_registration_takeover_verification_secret, - validate_registration_takeover_verification_secret, + generate_registration_transfer_verification_secret, + validate_registration_transfer_verification_secret, ) from zilencer.lib.remote_counts import MissingDataError from zilencer.models import ( @@ -162,13 +162,13 @@ def validate_hostname_or_raise_error(hostname: str) -> None: @csrf_exempt @require_post @typed_endpoint -def take_over_remote_server_registration(request: HttpRequest, *, hostname: str) -> HttpResponse: +def transfer_remote_server_registration(request: HttpRequest, *, hostname: str) -> HttpResponse: validate_hostname_or_raise_error(hostname) if not RemoteZulipServer.objects.filter(hostname=hostname).exists(): raise JsonableError(_("{hostname} not yet registered").format(hostname=hostname)) - verification_secret = generate_registration_takeover_verification_secret(hostname) + verification_secret = generate_registration_transfer_verification_secret(hostname) return json_success( request, data={ @@ -263,7 +263,7 @@ def register_remote_server( _( "A server with hostname {hostname} already exists. If you control the hostname " "and want to transfer the registration to this server, you can run manage.py register_server " - "with the --registration-takeover flag." + "with the --registration-transfer flag." ).format(hostname=hostname) ) @@ -295,11 +295,11 @@ def register_remote_server( return json_success(request, data={"created": created}) -class RegistrationTakeOverVerificationSession(OutgoingSession): +class RegistrationTransferVerificationSession(OutgoingSession): def __init__(self) -> None: # The generous timeout and retries here are likely to be unnecessary; a functional Zulip server should # respond instantly. - super().__init__(role="verify_registration_takeover_challenge", timeout=5, max_retries=3) + super().__init__(role="verify_registration_transfer_challenge", timeout=5, max_retries=3) class EndpointUsageRateLimitError(JsonableError): @@ -309,7 +309,7 @@ class EndpointUsageRateLimitError(JsonableError): @csrf_exempt @typed_endpoint -def verify_registration_takeover_challenge_ack_endpoint( +def verify_registration_transfer_challenge_ack_endpoint( request: HttpRequest, *, hostname: str, @@ -334,13 +334,13 @@ def verify_registration_takeover_challenge_ack_endpoint( # attacker to fill up the bucket here, and issues can be handled adequately by # manual intervention. if settings.RATE_LIMITING: - rate_limit_endpoint_absolute("verify_registration_takeover_challenge_ack_endpoint") + rate_limit_endpoint_absolute("verify_registration_transfer_challenge_ack_endpoint") except RateLimitedError: # This rate limit being hit means we've either set the limits too low for legitimate use, # or the endpoint is being spammed. Ideally, we want this endpoint to always be operational # so this deserves logging a warning. logger.warning( - "Rate limit exceeded for verify_registration_takeover_challenge_ack_endpoint" + "Rate limit exceeded for verify_registration_transfer_challenge_ack_endpoint" ) raise EndpointUsageRateLimitError( _( @@ -354,7 +354,7 @@ def verify_registration_takeover_challenge_ack_endpoint( except RemoteZulipServer.DoesNotExist: raise JsonableError(_("Registration not found for this hostname")) - session = RegistrationTakeOverVerificationSession() + session = RegistrationTransferVerificationSession() url = urljoin(f"https://{hostname}", f"/api/v1/zulip-services/verify/{access_token}/") exception_and_error_message: tuple[Exception, str] | None = None @@ -362,8 +362,8 @@ def verify_registration_takeover_challenge_ack_endpoint( response = session.get(url) response.raise_for_status() except requests.exceptions.HTTPError as e: - if check_takeover_challenge_response_secret_not_prepared(e.response): - logger.info("verify_registration_takeover:host:%s|secret_not_prepared", hostname) + if check_transfer_challenge_response_secret_not_prepared(e.response): + logger.info("verify_registration_transfer:host:%s|secret_not_prepared", hostname) raise JsonableError(_("The host reported it has no verification secret.")) error_message = _("Error response received from the host: {status_code}").format( @@ -385,14 +385,14 @@ def verify_registration_takeover_challenge_ack_endpoint( if exception_and_error_message is not None: exception, error_message = exception_and_error_message - logger.info("verify_registration_takeover:host:%s|exception:%s", hostname, exception) + logger.info("verify_registration_transfer:host:%s|exception:%s", hostname, exception) raise JsonableError(error_message) data = response.json() verification_secret = data["verification_secret"] - validate_registration_takeover_verification_secret(verification_secret, hostname) + validate_registration_transfer_verification_secret(verification_secret, hostname) - logger.info("verify_registration_takeover:host:%s|success", hostname) + logger.info("verify_registration_transfer:host:%s|success", hostname) new_secret_key = get_random_string(RemoteZulipServer.API_KEY_LENGTH) with transaction.atomic(durable=True): remote_server.api_key = new_secret_key @@ -410,7 +410,7 @@ def verify_registration_takeover_challenge_ack_endpoint( ) -def check_takeover_challenge_response_secret_not_prepared(response: requests.Response) -> bool: +def check_transfer_challenge_response_secret_not_prepared(response: requests.Response) -> bool: secret_not_prepared = False try: secret_not_prepared = ( diff --git a/zproject/default_settings.py b/zproject/default_settings.py index 6eeaad2ae5..72e3e0ca3c 100644 --- a/zproject/default_settings.py +++ b/zproject/default_settings.py @@ -343,7 +343,7 @@ RATE_LIMITING_RULES: dict[str, list[tuple[int, int]]] = {} # only, so we don't need a nice overriding system for them like we do # for RATE_LIMITING_RULES. ABSOLUTE_USAGE_LIMITS_BY_ENDPOINT = { - "verify_registration_takeover_challenge_ack_endpoint": [ + "verify_registration_transfer_challenge_ack_endpoint": [ # 30 requests per day (86400, 30), ], diff --git a/zproject/urls.py b/zproject/urls.py index 5074acea5e..5523c041a8 100644 --- a/zproject/urls.py +++ b/zproject/urls.py @@ -102,7 +102,7 @@ from zerver.views.push_notifications import ( self_hosting_auth_json_endpoint, self_hosting_auth_not_configured, self_hosting_auth_redirect_endpoint, - self_hosting_registration_takeover_challenge_verify, + self_hosting_registration_transfer_challenge_verify, send_test_push_notification_api, ) from zerver.views.reactions import add_reaction, remove_reaction @@ -872,7 +872,7 @@ urls += [ urls += [ path( "api/v1/zulip-services/verify//", - self_hosting_registration_takeover_challenge_verify, + self_hosting_registration_transfer_challenge_verify, ), ]