From f1fb7040bc3dd5ae626fa24a5160a3ee02cecd62 Mon Sep 17 00:00:00 2001
From: Jean-Paul Calderone <exarkun@twistedmatrix.com>
Date: Sat, 15 Jun 2019 20:14:34 -0400
Subject: [PATCH] start of a plugin implementation

---
 src/_secureaccesstokenauthorizer/__init__.py  |  8 ++
 src/_secureaccesstokenauthorizer/_plugin.py   | 47 ++++++++++
 .../_storage_server.py                        | 86 +++++++++++++++++++
 .../plugins/secureaccesstokenauthorizer.py    |  6 ++
 4 files changed, 147 insertions(+)
 create mode 100644 src/_secureaccesstokenauthorizer/_plugin.py
 create mode 100644 src/_secureaccesstokenauthorizer/_storage_server.py

diff --git a/src/_secureaccesstokenauthorizer/__init__.py b/src/_secureaccesstokenauthorizer/__init__.py
index 4990b68..51b6aad 100644
--- a/src/_secureaccesstokenauthorizer/__init__.py
+++ b/src/_secureaccesstokenauthorizer/__init__.py
@@ -13,3 +13,11 @@
 # limitations under the License.
 
 __version__ = "0.0"
+
+from ._storage_server import (
+    SecureAccessTokenAuthorizerStorageServer,
+)
+
+from ._plugin import (
+    SecureAccessTokenAuthorizer,
+)
diff --git a/src/_secureaccesstokenauthorizer/_plugin.py b/src/_secureaccesstokenauthorizer/_plugin.py
new file mode 100644
index 0000000..57a8286
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/_plugin.py
@@ -0,0 +1,47 @@
+# 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.
+
+"""
+The Twisted plugin that glues the Secure Access Token system into
+Tahoe-LAFS.
+"""
+
+from zope.interface import (
+    implementer,
+)
+
+from allmydata.interfaces import (
+    IFoolscapStoragePlugin,
+)
+
+from . import (
+    SecureAccessTokenAuthorizerStorageServer,
+)
+
+@implementer(IFoolscapStoragePlugin)
+class SecureAccessTokenAuthorizer(object):
+    """
+    A storage plugin which provides a token-based access control mechanism on
+    top of the Tahoe-LAFS built-in storage server interface.
+    """
+    name = u"privatestorageio-satauthz-v1"
+
+    def get_storage_server(self, configuration, get_anonymous_storage_server):
+        return SecureAccessTokenAuthorizerStorageServer(
+            get_anonymous_storage_server(),
+            **configuration,
+        )
+
+    def get_storage_client(self, configuration, announcement):
+        raise NotImplementedError()
diff --git a/src/_secureaccesstokenauthorizer/_storage_server.py b/src/_secureaccesstokenauthorizer/_storage_server.py
new file mode 100644
index 0000000..aa5032f
--- /dev/null
+++ b/src/_secureaccesstokenauthorizer/_storage_server.py
@@ -0,0 +1,86 @@
+# 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.
+"""
+
+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 = dict(**zip(schema.argumentNames, schema.argConstraints))
+    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(RITokenAuthorizedStorageServer)
+class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer)):
+    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)
diff --git a/src/twisted/plugins/secureaccesstokenauthorizer.py b/src/twisted/plugins/secureaccesstokenauthorizer.py
index 4fa53c2..de01bbe 100644
--- a/src/twisted/plugins/secureaccesstokenauthorizer.py
+++ b/src/twisted/plugins/secureaccesstokenauthorizer.py
@@ -15,3 +15,9 @@
 """
 A drop-in to supply plugins to the Twisted plugin system.
 """
+
+from _secureaccesstokenauthorizer import (
+    SecureAccessTokenAuthorizer,
+)
+
+storage_server = SecureAccessTokenAuthorizer()
-- 
GitLab