diff --git a/src/_secureaccesstokenauthorizer/_storage_server.py b/src/_secureaccesstokenauthorizer/_storage_server.py index fbae0c3f0b088139b56968df1dfc0888e9c07db2..3181f4e0008afb748257717e32d66d29264d6abe 100644 --- a/src/_secureaccesstokenauthorizer/_storage_server.py +++ b/src/_secureaccesstokenauthorizer/_storage_server.py @@ -118,6 +118,15 @@ def add_arguments(schema, kwargs): class RITokenAuthorizedStorageServer(RemoteInterface): + """ + An object which can store and retrieve shares, subject to token-based + authorization. + + This is much the same as ``allmydata.interfaces.RIStorageServer`` but + several of its methods take an additional ``tokens`` parameter. Clients + are expected to supply suitable tokens and only after the tokens have been + validated is service provided. + """ __remote_name__ = ( "RITokenAuthorizedStorageServer.tahoe.privatestorage.io" ) @@ -148,37 +157,86 @@ class RITokenAuthorizedStorageServer(RemoteInterface): # attributes on self and it's hard to avoid that. @attr.s(cmp=False) class SecureAccessTokenAuthorizerStorageServer(Referenceable): + """ + A class which wraps an ``RIStorageServer`` to insert token validity checks + before allowing certain functionality. + """ _original = attr.ib(validator=provides(RIStorageServer)) def _validate_tokens(self, tokens): - pass + """ + Check that all of the given tokens are valid. + + :raise InvalidToken: If any token in ``tokens`` is not valid. + + :return NoneType: If all of the tokens in ``tokens`` are valid. + + :note: This is yet to be implemented so it always returns ``None``. + """ + return None def remote_get_version(self): + """ + Pass through without token check to allow clients to learn about our + version and configuration in case it helps them decide how to behave. + """ return self._original.remote_get_version() def remote_allocate_buckets(self, tokens, *a, **kw): + """ + Pass through after a token check to ensure that clients can only allocate + storage for immutable shares if they present valid tokens. + """ self._validate_tokens(tokens) return self._original.remote_allocate_buckets(*a, **kw) def remote_get_buckets(self, storage_index): + """ + Pass through without token check to let clients read immutable shares as + long as those shares exist. + """ return self._original.remote_get_buckets(storage_index) def remote_add_lease(self, tokens, *a, **kw): + """ + Pass through after a token check to ensure clients can only extend the + duration of share storage if they present valid tokens. + """ self._validate_tokens(tokens) return self._original.remote_add_lease(*a, **kw) def remote_renew_lease(self, tokens, *a, **kw): + """ + Pass through after a token check to ensure clients can only extend the + duration of share storage if they present valid tokens. + """ self._validate_tokens(tokens) return self._original.remote_renew_lease(*a, **kw) def remote_advise_corrupt_share(self, *a, **kw): + """ + Pass through without a token check to let clients inform us of possible + issues with the system without incurring any cost to themselves. + """ return self._original.remote_advise_corrupt_share(*a, **kw) def remote_slot_testv_and_readv_and_writev(self, tokens, *a, **kw): + """ + Pass through after a token check to ensure clients can only allocate + storage for mutable shares if they present valid tokens. + + :note: This method can be used both to allocate storage and to rewrite + data in already-allocated storage. These cases may not be the + same from the perspective of token validation. + """ self._validate_tokens(tokens) return self._original.remote_slot_testv_and_readv_and_writev(*a, **kw) def remote_slot_readv(self, *a, **kw): + """ + Pass through without a token check to let clients read mutable shares as + long as those shares exist. + """ return self._original.remote_slot_readv(*a, **kw) # I don't understand why this is required.