From e81e50853b598a299599ed733e5c4671cfc6babc Mon Sep 17 00:00:00 2001
From: Itamar Turner-Trauring <itamar@futurefoundries.com>
Date: Fri, 1 Mar 2013 13:58:10 -0500
Subject: [PATCH] Sketch of working Google Cloud Storage authentication, with
 some demo code.

---
 .../backends/cloud/googlestorage/__init__.py  |  3 +
 .../googlestorage/googlestorage_container.py  | 89 +++++++++++++++++++
 2 files changed, 92 insertions(+)
 create mode 100644 src/allmydata/storage/backends/cloud/googlestorage/__init__.py
 create mode 100644 src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py

diff --git a/src/allmydata/storage/backends/cloud/googlestorage/__init__.py b/src/allmydata/storage/backends/cloud/googlestorage/__init__.py
new file mode 100644
index 00000000..6b2f9c1c
--- /dev/null
+++ b/src/allmydata/storage/backends/cloud/googlestorage/__init__.py
@@ -0,0 +1,3 @@
+from allmydata.storage.backends.cloud.googlestorage.googlestorage_container import configure_googlestorage_container
+
+configure_container = configure_googlestorage_container
diff --git a/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py b/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py
new file mode 100644
index 00000000..aa337dc4
--- /dev/null
+++ b/src/allmydata/storage/backends/cloud/googlestorage/googlestorage_container.py
@@ -0,0 +1,89 @@
+"""
+This requires the oauth2client library:
+
+http://code.google.com/p/google-api-python-client/downloads/list
+"""
+
+import httplib2
+
+from twisted.internet.defer import DeferredLock
+from twisted.internet.threads import deferToThread
+
+from oauth2client.client import SignedJwtAssertionCredentials
+
+from zope.interface import implements
+
+from allmydata.util import log
+from allmydata.node import InvalidValueError
+from allmydata.storage.backends.cloud.cloud_common import IContainer, \
+     CloudServiceError, ContainerItem, ContainerListing, ContainerRetryMixin, \
+     HTTPClientMixin
+
+
+def configure_googlestorage_container(*args):
+    """
+    Configure the Google Cloud Storage container.
+    """
+
+
+class AuthenticationClient(object):
+    """
+    Retrieve access tokens for the Google Storage API, using OAuth 2.0.
+
+    See https://developers.google.com/accounts/docs/OAuth2ServiceAccount for
+    more details.
+    """
+
+    def __init__(self, account_name, private_key, private_key_password='notasecret'):
+        self.credentials = SignedJwtAssertionCredentials(
+            account_name, private_key,
+            "https://www.googleapis.com/auth/devstorage.read_write",
+            private_key_password = private_key_password,
+            )
+        self._need_first_auth = True
+        self._lock = DeferredLock()
+
+    def get_authorization_header(self):
+        """
+        Return a Deferred that fires with the value to use for the
+        Authorization header in HTTP requests.
+        """
+        def refreshIfNecessary():
+            if self._need_first_auth or self.credentials.access_token_expired:
+                self._need_first_auth = False
+                return deferToThread(self.credentials.refresh, httplib2.Http())
+        d = self._lock.run(refreshIfNecessary)
+
+        def refreshed(ignore):
+            headers = {}
+            self.credentials.apply(headers)
+            return headers['Authorization']
+        d.addCallback(refreshed)
+        return d
+
+
+class GoogleStorageContainer(HTTPClientMixin, ContainerRetryMixin):
+    implements(IContainer)
+
+    USER_AGENT = "Tahoe-LAFS Google Storage client"
+
+    def __init__(self, auth_client, bucket_name, override_reactor=None):
+        pass
+
+
+if __name__ == '__main__':
+    from twisted.internet import reactor
+    from twisted.web.client import getPage
+    import sys
+    auth = AuthenticationClient(sys.argv[1], file(sys.argv[2]).read())
+    def println(result):
+        print result
+        reactor.stop()
+    def gotAuth(value):
+        return getPage("https://storage.googleapis.com/",
+                       headers={"Authorization": value,
+                                "x-goog-api-version": "2",
+                                "x-goog-project-id": sys.argv[3]}).addCallback(println)
+    auth.get_authorization_header().addCallback(gotAuth)
+    reactor.run()
+
-- 
2.45.2