Skip to content
Snippets Groups Projects
_storage_server.py 3.62 KiB
Newer Older
  • Learn to ignore specific revisions
  • # Copyright 2019 PrivateStorage.io, LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    """
    A Tahoe-LAFS RIStorageServer-alike which authorizes writes and lease
    updates using a per-call token.
    
    
    This is the server part of a storage access protocol.  The client part is
    implemented in ``_storage_client.py``.
    
    from zope.interface import (
    
    )
    
    from twisted.python.components import (
        proxyForInterface,
    )
    
    from foolscap.constraint import (
        ByteStringConstraint,
    )
    from foolscap.api import (
        ListOf,
    
        Referenceable,
    
    from foolscap.ipb import (
        IReferenceable,
        IRemotelyCallable,
    )
    
    from foolscap.remoteinterface import (
        RemoteMethodSchema,
        RemoteInterface,
    )
    
    
    from allmydata.interfaces import (
        RIStorageServer,
    )
    
    MAXIMUM_TOKENS_PER_CALL = 10
    TOKEN_LENGTH = 97
    
    Token = ByteStringConstraint(maxLength=TOKEN_LENGTH, minLength=TOKEN_LENGTH)
    TokenList = ListOf(Token, maxLength=MAXIMUM_TOKENS_PER_CALL)
    
    
    def add_tokens(schema):
        """
        Add a ``tokens`` parameter to the given method schema.
    
        :param foolscap.remoteinterface.RemoteMethodSchema schema: An existing
            method schema to modify.
    
        :return foolscap.remoteinterface.RemoteMethodSchema: A schema like
            ``schema`` but with one additional required argument.
        """
        return add_arguments(schema, tokens=TokenList)
    
    
    
    def add_arguments(schema, **kwargs):
    
        new_kwargs = schema.argConstraints.copy()
    
        new_kwargs.update(kwargs)
        modified_schema = RemoteMethodSchema(**new_kwargs)
        return modified_schema
    
    
    
    class RITokenAuthorizedStorageServer(RemoteInterface):
        __remote_name__ = (
            "RITokenAuthorizedStorageServer.tahoe.privatestorage.io"
        )
    
        get_version = RIStorageServer["get_version"]
    
        allocate_buckets = add_tokens(RIStorageServer["allocate_buckets"])
    
        add_lease = add_tokens(RIStorageServer["add_lease"])
    
        renew_lease = add_tokens(RIStorageServer["renew_lease"])
    
        get_buckets = RIStorageServer["get_buckets"]
    
        slot_readv = RIStorageServer["slot_readv"]
    
        slot_testv_and_readv_and_writev = add_tokens(
            RIStorageServer["slot_testv_and_readv_and_writev"],
        )
    
        advise_corrupt_share = RIStorageServer["advise_corrupt_share"]
    
    
    
    
    @implementer_only(RITokenAuthorizedStorageServer, IReferenceable, IRemotelyCallable)
    
    class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer), Referenceable):
    
        def allocate_buckets(self, tokens, *a, **kw):
            self._validate_tokens(tokens)
            return super(SecureAccessTokenAuthorizerStorageServer, self).allocate_buckets(*a, **kw)
    
        def add_lease(self, tokens, *a, **kw):
            self._validate_tokens(tokens)
            return super(SecureAccessTokenAuthorizerStorageServer, self).add_lease(*a, **kw)
    
    
    # I don't understand why this is required.
    # SecureAccessTokenAuthorizerStorageServer is-a Referenceable.  It seems like
    # the built in adapter should take care of this case.
    from twisted.python.components import (
        registerAdapter,
    )
    from foolscap.referenceable import (
        ReferenceableSlicer,
    )
    from foolscap.ipb import (
        ISlicer,
    )
    registerAdapter(ReferenceableSlicer, SecureAccessTokenAuthorizerStorageServer, ISlicer)