gcloud 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. data.tar.gz.sig +2 -3
  2. data/CHANGELOG +4 -0
  3. data/LICENSE +674 -0
  4. data/Manifest +111 -0
  5. data/README.md +4 -3
  6. data/bin/gcutil +53 -0
  7. data/gcloud.gemspec +4 -3
  8. data/packages/gcutil-1.7.1/CHANGELOG +197 -0
  9. data/packages/gcutil-1.7.1/LICENSE +202 -0
  10. data/packages/gcutil-1.7.1/VERSION +1 -0
  11. data/packages/gcutil-1.7.1/gcutil +53 -0
  12. data/packages/gcutil-1.7.1/lib/google_api_python_client/LICENSE +23 -0
  13. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/__init__.py +1 -0
  14. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/discovery.py +743 -0
  15. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/errors.py +123 -0
  16. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/ext/__init__.py +0 -0
  17. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/http.py +1443 -0
  18. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/mimeparse.py +172 -0
  19. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/model.py +385 -0
  20. data/packages/gcutil-1.7.1/lib/google_api_python_client/apiclient/schema.py +303 -0
  21. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/__init__.py +1 -0
  22. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/anyjson.py +32 -0
  23. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/appengine.py +528 -0
  24. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/client.py +1139 -0
  25. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/clientsecrets.py +105 -0
  26. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/crypt.py +244 -0
  27. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/django_orm.py +124 -0
  28. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/file.py +107 -0
  29. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/locked_file.py +343 -0
  30. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/multistore_file.py +379 -0
  31. data/packages/gcutil-1.7.1/lib/google_api_python_client/oauth2client/tools.py +174 -0
  32. data/packages/gcutil-1.7.1/lib/google_api_python_client/uritemplate/__init__.py +147 -0
  33. data/packages/gcutil-1.7.1/lib/google_apputils/LICENSE +202 -0
  34. data/packages/gcutil-1.7.1/lib/google_apputils/google/__init__.py +3 -0
  35. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/__init__.py +3 -0
  36. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/app.py +356 -0
  37. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/appcommands.py +783 -0
  38. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/basetest.py +1260 -0
  39. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/datelib.py +421 -0
  40. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/debug.py +60 -0
  41. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/file_util.py +181 -0
  42. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/resources.py +67 -0
  43. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/run_script_module.py +217 -0
  44. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/setup_command.py +159 -0
  45. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/shellutil.py +49 -0
  46. data/packages/gcutil-1.7.1/lib/google_apputils/google/apputils/stopwatch.py +204 -0
  47. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/__init__.py +0 -0
  48. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper.py +140 -0
  49. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auth_helper_test.py +149 -0
  50. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth.py +130 -0
  51. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/auto_auth_test.py +75 -0
  52. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds.py +128 -0
  53. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/basic_cmds_test.py +111 -0
  54. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base.py +1808 -0
  55. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/command_base_test.py +1651 -0
  56. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta13.json +2851 -0
  57. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/compute/v1beta14.json +3361 -0
  58. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds.py +342 -0
  59. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/disk_cmds_test.py +474 -0
  60. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds.py +344 -0
  61. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/firewall_cmds_test.py +231 -0
  62. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/flags_cache.py +274 -0
  63. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil +89 -0
  64. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/gcutil_logging.py +69 -0
  65. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds.py +262 -0
  66. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/image_cmds_test.py +172 -0
  67. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds.py +1506 -0
  68. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/instance_cmds_test.py +1904 -0
  69. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds.py +91 -0
  70. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/kernel_cmds_test.py +56 -0
  71. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds.py +106 -0
  72. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/machine_type_cmds_test.py +59 -0
  73. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata.py +96 -0
  74. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_lib.py +357 -0
  75. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/metadata_test.py +84 -0
  76. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_api.py +420 -0
  77. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/mock_metadata.py +58 -0
  78. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds.py +824 -0
  79. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/move_cmds_test.py +307 -0
  80. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds.py +178 -0
  81. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/network_cmds_test.py +133 -0
  82. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds.py +181 -0
  83. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/operation_cmds_test.py +196 -0
  84. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/path_initializer.py +38 -0
  85. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds.py +173 -0
  86. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/project_cmds_test.py +111 -0
  87. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes.py +61 -0
  88. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/scopes_test.py +50 -0
  89. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds.py +276 -0
  90. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/snapshot_cmds_test.py +260 -0
  91. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys.py +266 -0
  92. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/ssh_keys_test.py +128 -0
  93. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/table_formatter.py +563 -0
  94. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool.py +188 -0
  95. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/thread_pool_test.py +88 -0
  96. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils.py +208 -0
  97. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/utils_test.py +193 -0
  98. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version.py +17 -0
  99. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker.py +246 -0
  100. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/version_checker_test.py +271 -0
  101. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds.py +151 -0
  102. data/packages/gcutil-1.7.1/lib/google_compute_engine/gcutil/zone_cmds_test.py +60 -0
  103. data/packages/gcutil-1.7.1/lib/httplib2/LICENSE +21 -0
  104. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/__init__.py +1630 -0
  105. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/cacerts.txt +714 -0
  106. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/iri2uri.py +110 -0
  107. data/packages/gcutil-1.7.1/lib/httplib2/httplib2/socks.py +438 -0
  108. data/packages/gcutil-1.7.1/lib/iso8601/LICENSE +20 -0
  109. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/__init__.py +1 -0
  110. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/iso8601.py +102 -0
  111. data/packages/gcutil-1.7.1/lib/iso8601/iso8601/test_iso8601.py +111 -0
  112. data/packages/gcutil-1.7.1/lib/python_gflags/AUTHORS +2 -0
  113. data/packages/gcutil-1.7.1/lib/python_gflags/LICENSE +28 -0
  114. data/packages/gcutil-1.7.1/lib/python_gflags/gflags.py +2862 -0
  115. data/packages/gcutil-1.7.1/lib/python_gflags/gflags2man.py +544 -0
  116. data/packages/gcutil-1.7.1/lib/python_gflags/gflags_validators.py +187 -0
  117. metadata +118 -5
  118. metadata.gz.sig +0 -0
@@ -0,0 +1,105 @@
1
+ # Copyright (C) 2011 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """Utilities for reading OAuth 2.0 client secret files.
16
+
17
+ A client_secrets.json file contains all the information needed to interact with
18
+ an OAuth 2.0 protected service.
19
+ """
20
+
21
+
22
+
23
+
24
+ from anyjson import simplejson
25
+
26
+ # Properties that make a client_secrets.json file valid.
27
+ TYPE_WEB = 'web'
28
+ TYPE_INSTALLED = 'installed'
29
+
30
+ VALID_CLIENT = {
31
+ TYPE_WEB: {
32
+ 'required': [
33
+ 'client_id',
34
+ 'client_secret',
35
+ 'redirect_uris',
36
+ 'auth_uri',
37
+ 'token_uri'],
38
+ 'string': [
39
+ 'client_id',
40
+ 'client_secret'
41
+ ]
42
+ },
43
+ TYPE_INSTALLED: {
44
+ 'required': [
45
+ 'client_id',
46
+ 'client_secret',
47
+ 'redirect_uris',
48
+ 'auth_uri',
49
+ 'token_uri'],
50
+ 'string': [
51
+ 'client_id',
52
+ 'client_secret'
53
+ ]
54
+ }
55
+ }
56
+
57
+ class Error(Exception):
58
+ """Base error for this module."""
59
+ pass
60
+
61
+
62
+ class InvalidClientSecretsError(Error):
63
+ """Format of ClientSecrets file is invalid."""
64
+ pass
65
+
66
+
67
+ def _validate_clientsecrets(obj):
68
+ if obj is None or len(obj) != 1:
69
+ raise InvalidClientSecretsError('Invalid file format.')
70
+ client_type = obj.keys()[0]
71
+ if client_type not in VALID_CLIENT.keys():
72
+ raise InvalidClientSecretsError('Unknown client type: %s.' % client_type)
73
+ client_info = obj[client_type]
74
+ for prop_name in VALID_CLIENT[client_type]['required']:
75
+ if prop_name not in client_info:
76
+ raise InvalidClientSecretsError(
77
+ 'Missing property "%s" in a client type of "%s".' % (prop_name,
78
+ client_type))
79
+ for prop_name in VALID_CLIENT[client_type]['string']:
80
+ if client_info[prop_name].startswith('[['):
81
+ raise InvalidClientSecretsError(
82
+ 'Property "%s" is not configured.' % prop_name)
83
+ return client_type, client_info
84
+
85
+
86
+ def load(fp):
87
+ obj = simplejson.load(fp)
88
+ return _validate_clientsecrets(obj)
89
+
90
+
91
+ def loads(s):
92
+ obj = simplejson.loads(s)
93
+ return _validate_clientsecrets(obj)
94
+
95
+
96
+ def loadfile(filename):
97
+ try:
98
+ fp = file(filename, 'r')
99
+ try:
100
+ obj = simplejson.load(fp)
101
+ finally:
102
+ fp.close()
103
+ except IOError:
104
+ raise InvalidClientSecretsError('File not found: "%s"' % filename)
105
+ return _validate_clientsecrets(obj)
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/python2.4
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2011 Google Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ import base64
19
+ import hashlib
20
+ import logging
21
+ import time
22
+
23
+ from OpenSSL import crypto
24
+ from anyjson import simplejson
25
+
26
+
27
+ CLOCK_SKEW_SECS = 300 # 5 minutes in seconds
28
+ AUTH_TOKEN_LIFETIME_SECS = 300 # 5 minutes in seconds
29
+ MAX_TOKEN_LIFETIME_SECS = 86400 # 1 day in seconds
30
+
31
+
32
+ class AppIdentityError(Exception):
33
+ pass
34
+
35
+
36
+ class Verifier(object):
37
+ """Verifies the signature on a message."""
38
+
39
+ def __init__(self, pubkey):
40
+ """Constructor.
41
+
42
+ Args:
43
+ pubkey, OpenSSL.crypto.PKey, The public key to verify with.
44
+ """
45
+ self._pubkey = pubkey
46
+
47
+ def verify(self, message, signature):
48
+ """Verifies a message against a signature.
49
+
50
+ Args:
51
+ message: string, The message to verify.
52
+ signature: string, The signature on the message.
53
+
54
+ Returns:
55
+ True if message was singed by the private key associated with the public
56
+ key that this object was constructed with.
57
+ """
58
+ try:
59
+ crypto.verify(self._pubkey, signature, message, 'sha256')
60
+ return True
61
+ except:
62
+ return False
63
+
64
+ @staticmethod
65
+ def from_string(key_pem, is_x509_cert):
66
+ """Construct a Verified instance from a string.
67
+
68
+ Args:
69
+ key_pem: string, public key in PEM format.
70
+ is_x509_cert: bool, True if key_pem is an X509 cert, otherwise it is
71
+ expected to be an RSA key in PEM format.
72
+
73
+ Returns:
74
+ Verifier instance.
75
+
76
+ Raises:
77
+ OpenSSL.crypto.Error if the key_pem can't be parsed.
78
+ """
79
+ if is_x509_cert:
80
+ pubkey = crypto.load_certificate(crypto.FILETYPE_PEM, key_pem)
81
+ else:
82
+ pubkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key_pem)
83
+ return Verifier(pubkey)
84
+
85
+
86
+ class Signer(object):
87
+ """Signs messages with a private key."""
88
+
89
+ def __init__(self, pkey):
90
+ """Constructor.
91
+
92
+ Args:
93
+ pkey, OpenSSL.crypto.PKey, The private key to sign with.
94
+ """
95
+ self._key = pkey
96
+
97
+ def sign(self, message):
98
+ """Signs a message.
99
+
100
+ Args:
101
+ message: string, Message to be signed.
102
+
103
+ Returns:
104
+ string, The signature of the message for the given key.
105
+ """
106
+ return crypto.sign(self._key, message, 'sha256')
107
+
108
+ @staticmethod
109
+ def from_string(key, password='notasecret'):
110
+ """Construct a Signer instance from a string.
111
+
112
+ Args:
113
+ key: string, private key in P12 format.
114
+ password: string, password for the private key file.
115
+
116
+ Returns:
117
+ Signer instance.
118
+
119
+ Raises:
120
+ OpenSSL.crypto.Error if the key can't be parsed.
121
+ """
122
+ pkey = crypto.load_pkcs12(key, password).get_privatekey()
123
+ return Signer(pkey)
124
+
125
+
126
+ def _urlsafe_b64encode(raw_bytes):
127
+ return base64.urlsafe_b64encode(raw_bytes).rstrip('=')
128
+
129
+
130
+ def _urlsafe_b64decode(b64string):
131
+ # Guard against unicode strings, which base64 can't handle.
132
+ b64string = b64string.encode('ascii')
133
+ padded = b64string + '=' * (4 - len(b64string) % 4)
134
+ return base64.urlsafe_b64decode(padded)
135
+
136
+
137
+ def _json_encode(data):
138
+ return simplejson.dumps(data, separators = (',', ':'))
139
+
140
+
141
+ def make_signed_jwt(signer, payload):
142
+ """Make a signed JWT.
143
+
144
+ See http://self-issued.info/docs/draft-jones-json-web-token.html.
145
+
146
+ Args:
147
+ signer: crypt.Signer, Cryptographic signer.
148
+ payload: dict, Dictionary of data to convert to JSON and then sign.
149
+
150
+ Returns:
151
+ string, The JWT for the payload.
152
+ """
153
+ header = {'typ': 'JWT', 'alg': 'RS256'}
154
+
155
+ segments = [
156
+ _urlsafe_b64encode(_json_encode(header)),
157
+ _urlsafe_b64encode(_json_encode(payload)),
158
+ ]
159
+ signing_input = '.'.join(segments)
160
+
161
+ signature = signer.sign(signing_input)
162
+ segments.append(_urlsafe_b64encode(signature))
163
+
164
+ logging.debug(str(segments))
165
+
166
+ return '.'.join(segments)
167
+
168
+
169
+ def verify_signed_jwt_with_certs(jwt, certs, audience):
170
+ """Verify a JWT against public certs.
171
+
172
+ See http://self-issued.info/docs/draft-jones-json-web-token.html.
173
+
174
+ Args:
175
+ jwt: string, A JWT.
176
+ certs: dict, Dictionary where values of public keys in PEM format.
177
+ audience: string, The audience, 'aud', that this JWT should contain. If
178
+ None then the JWT's 'aud' parameter is not verified.
179
+
180
+ Returns:
181
+ dict, The deserialized JSON payload in the JWT.
182
+
183
+ Raises:
184
+ AppIdentityError if any checks are failed.
185
+ """
186
+ segments = jwt.split('.')
187
+
188
+ if (len(segments) != 3):
189
+ raise AppIdentityError(
190
+ 'Wrong number of segments in token: %s' % jwt)
191
+ signed = '%s.%s' % (segments[0], segments[1])
192
+
193
+ signature = _urlsafe_b64decode(segments[2])
194
+
195
+ # Parse token.
196
+ json_body = _urlsafe_b64decode(segments[1])
197
+ try:
198
+ parsed = simplejson.loads(json_body)
199
+ except:
200
+ raise AppIdentityError('Can\'t parse token: %s' % json_body)
201
+
202
+ # Check signature.
203
+ verified = False
204
+ for (keyname, pem) in certs.items():
205
+ verifier = Verifier.from_string(pem, True)
206
+ if (verifier.verify(signed, signature)):
207
+ verified = True
208
+ break
209
+ if not verified:
210
+ raise AppIdentityError('Invalid token signature: %s' % jwt)
211
+
212
+ # Check creation timestamp.
213
+ iat = parsed.get('iat')
214
+ if iat is None:
215
+ raise AppIdentityError('No iat field in token: %s' % json_body)
216
+ earliest = iat - CLOCK_SKEW_SECS
217
+
218
+ # Check expiration timestamp.
219
+ now = long(time.time())
220
+ exp = parsed.get('exp')
221
+ if exp is None:
222
+ raise AppIdentityError('No exp field in token: %s' % json_body)
223
+ if exp >= now + MAX_TOKEN_LIFETIME_SECS:
224
+ raise AppIdentityError(
225
+ 'exp field too far in future: %s' % json_body)
226
+ latest = exp + CLOCK_SKEW_SECS
227
+
228
+ if now < earliest:
229
+ raise AppIdentityError('Token used too early, %d < %d: %s' %
230
+ (now, earliest, json_body))
231
+ if now > latest:
232
+ raise AppIdentityError('Token used too late, %d > %d: %s' %
233
+ (now, latest, json_body))
234
+
235
+ # Check audience.
236
+ if audience is not None:
237
+ aud = parsed.get('aud')
238
+ if aud is None:
239
+ raise AppIdentityError('No aud field in token: %s' % json_body)
240
+ if aud != audience:
241
+ raise AppIdentityError('Wrong recipient, %s != %s: %s' %
242
+ (aud, audience, json_body))
243
+
244
+ return parsed
@@ -0,0 +1,124 @@
1
+ # Copyright (C) 2010 Google Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """OAuth 2.0 utilities for Django.
16
+
17
+ Utilities for using OAuth 2.0 in conjunction with
18
+ the Django datastore.
19
+ """
20
+
21
+
22
+
23
+ import oauth2client
24
+ import base64
25
+ import pickle
26
+
27
+ from django.db import models
28
+ from oauth2client.client import Storage as BaseStorage
29
+
30
+ class CredentialsField(models.Field):
31
+
32
+ __metaclass__ = models.SubfieldBase
33
+
34
+ def get_internal_type(self):
35
+ return "TextField"
36
+
37
+ def to_python(self, value):
38
+ if value is None:
39
+ return None
40
+ if isinstance(value, oauth2client.client.Credentials):
41
+ return value
42
+ return pickle.loads(base64.b64decode(value))
43
+
44
+ def get_db_prep_value(self, value, connection, prepared=False):
45
+ if value is None:
46
+ return None
47
+ return base64.b64encode(pickle.dumps(value))
48
+
49
+
50
+ class FlowField(models.Field):
51
+
52
+ __metaclass__ = models.SubfieldBase
53
+
54
+ def get_internal_type(self):
55
+ return "TextField"
56
+
57
+ def to_python(self, value):
58
+ if value is None:
59
+ return None
60
+ if isinstance(value, oauth2client.client.Flow):
61
+ return value
62
+ return pickle.loads(base64.b64decode(value))
63
+
64
+ def get_db_prep_value(self, value, connection, prepared=False):
65
+ if value is None:
66
+ return None
67
+ return base64.b64encode(pickle.dumps(value))
68
+
69
+
70
+ class Storage(BaseStorage):
71
+ """Store and retrieve a single credential to and from
72
+ the datastore.
73
+
74
+ This Storage helper presumes the Credentials
75
+ have been stored as a CredenialsField
76
+ on a db model class.
77
+ """
78
+
79
+ def __init__(self, model_class, key_name, key_value, property_name):
80
+ """Constructor for Storage.
81
+
82
+ Args:
83
+ model: db.Model, model class
84
+ key_name: string, key name for the entity that has the credentials
85
+ key_value: string, key value for the entity that has the credentials
86
+ property_name: string, name of the property that is an CredentialsProperty
87
+ """
88
+ self.model_class = model_class
89
+ self.key_name = key_name
90
+ self.key_value = key_value
91
+ self.property_name = property_name
92
+
93
+ def locked_get(self):
94
+ """Retrieve Credential from datastore.
95
+
96
+ Returns:
97
+ oauth2client.Credentials
98
+ """
99
+ credential = None
100
+
101
+ query = {self.key_name: self.key_value}
102
+ entities = self.model_class.objects.filter(**query)
103
+ if len(entities) > 0:
104
+ credential = getattr(entities[0], self.property_name)
105
+ if credential and hasattr(credential, 'set_store'):
106
+ credential.set_store(self)
107
+ return credential
108
+
109
+ def locked_put(self, credentials):
110
+ """Write a Credentials to the datastore.
111
+
112
+ Args:
113
+ credentials: Credentials, the credentials to store.
114
+ """
115
+ args = {self.key_name: self.key_value}
116
+ entity = self.model_class(**args)
117
+ setattr(entity, self.property_name, credentials)
118
+ entity.save()
119
+
120
+ def locked_delete(self):
121
+ """Delete Credentials from the datastore."""
122
+
123
+ query = {self.key_name: self.key_value}
124
+ entities = self.model_class.objects.filter(**query).delete()