diff --git a/src/_zkapauthorizer/lease_maintenance.py b/src/_zkapauthorizer/lease_maintenance.py index 8a3a0956660984a5eb1b5d05cf8fb04759f6870d..6d15951d6411f9861d4358b6043e66342c5c38e7 100644 --- a/src/_zkapauthorizer/lease_maintenance.py +++ b/src/_zkapauthorizer/lease_maintenance.py @@ -55,6 +55,8 @@ from allmydata.interfaces import ( from allmydata.util.hashutil import ( file_renewal_secret_hash, bucket_renewal_secret_hash, + file_cancel_secret_hash, + bucket_cancel_secret_hash, ) from .controller import ( @@ -165,6 +167,7 @@ def renew_leases( storage_indexes = yield iter_storage_indexes(visit_assets) renewal_secret = secret_holder.get_renewal_secret() + cancel_secret = secret_holder.get_cancel_secret() servers = list( server.get_storage_server() for server @@ -176,6 +179,7 @@ def renew_leases( yield renew_leases_on_server( min_lease_remaining, renewal_secret, + cancel_secret, storage_indexes, server, activity, @@ -189,6 +193,7 @@ def renew_leases( def renew_leases_on_server( min_lease_remaining, renewal_secret, + cancel_secret, storage_indexes, server, activity, @@ -202,8 +207,9 @@ def renew_leases_on_server( :param timedelta min_lease_remaining: The minimum amount of time remaining to allow on a lease without renewing it. - :param renewal_secret: A seed for the renewal secret hash calculation for - any leases which need to be renewed. + :param renewal_secret: See ``renew_lease``. + + :param cancel_secret: See ``renew_lease``. :param list[bytes] storage_indexes: The storage indexes to check. @@ -230,16 +236,19 @@ def renew_leases_on_server( # All shares have the same lease information. stat = stat_dict.popitem()[1] if needs_lease_renew(min_lease_remaining, stat, now): - yield renew_lease(renewal_secret, storage_index, server) + yield renew_lease(renewal_secret, cancel_secret, storage_index, server) -def renew_lease(renewal_secret, storage_index, server): +def renew_lease(renewal_secret, cancel_secret, storage_index, server): """ Renew the lease on the shares in one storage index on one server. :param renewal_secret: A seed for the renewal secret hash calculation for any leases which need to be renewed. + :param cancel_secret: A seed for the cancel secret hash calculation for + any leases which need to be renewed. + :param bytes storage_index: The storage index to operate on. :param StorageServer server: The storage server to operate on. @@ -254,9 +263,19 @@ def renew_lease(renewal_secret, storage_index, server): ), server.get_lease_seed(), ) - return server.renew_lease( + cancel_secret = bucket_cancel_secret_hash( + file_cancel_secret_hash( + cancel_secret, + storage_index, + ), + server.get_lease_seed(), + ) + # Use add_lease to add a new lease *or* renew an existing one with a + # matching renew secret. + return server.add_lease( storage_index, renew_secret, + cancel_secret, ) diff --git a/src/_zkapauthorizer/tests/test_lease_maintenance.py b/src/_zkapauthorizer/tests/test_lease_maintenance.py index 48d690359ebf43e38587f13af728751bb5a4eb5c..654f7eb679205bb97593bdd19fd933e8104c556d 100644 --- a/src/_zkapauthorizer/tests/test_lease_maintenance.py +++ b/src/_zkapauthorizer/tests/test_lease_maintenance.py @@ -160,7 +160,7 @@ class DummyStorageServer(object): def get_lease_seed(self): return self.lease_seed - def renew_lease(self, storage_index, renew_secret): + def add_lease(self, storage_index, renew_secret, cancel_secret): self.buckets[storage_index].lease_expiration = ( self.clock.seconds() + timedelta(days=31).total_seconds() )