summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Merritt <sam@swiftstack.com>2014-07-23 13:01:58 -0700
committerSamuel Merritt <sam@swiftstack.com>2014-07-24 14:38:53 -0700
commit4f2bb9f271e705ee5e7a357c9e5ec9384b4a690e (patch)
tree7664ba5676553c3a83b2994b97dd8475ea77b66b
parente788fd37dd2b21e308757ea4cf2ddf4e402a8137 (diff)
downloadswift-4f2bb9f271e705ee5e7a357c9e5ec9384b4a690e.tar.gz
Make swift-form-signature testable
Moved the body of bin/swift-form-signature into swift/cli/form_signature.py, like was done with swift-ring-builder and others. Added a couple basic tests; there's not 100% coverage, but it's better than the 0% coverage we had before. It's almost a straight forklift, but I changed exit() calls to return statements. Change-Id: Ie2f702c070da24d9cdface83b9e838e9e2965085
-rwxr-xr-xbin/swift-form-signature71
-rw-r--r--swift/cli/form_signature.py86
-rw-r--r--test/unit/cli/test_form_signature.py70
3 files changed, 160 insertions, 67 deletions
diff --git a/bin/swift-form-signature b/bin/swift-form-signature
index 91c76699f..15a077791 100755
--- a/bin/swift-form-signature
+++ b/bin/swift-form-signature
@@ -12,72 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import hmac
-from hashlib import sha1
-from os.path import basename
-from sys import argv, exit
-from time import time
+import sys
+import swift.cli.form_signature
-if __name__ == '__main__':
- if len(argv) != 7:
- prog = basename(argv[0])
- print 'Syntax: %s <path> <redirect> <max_file_size> ' \
- '<max_file_count> <seconds> <key>' % prog
- print
- print 'Where:'
- print ' <path> The prefix to use for form uploaded'
- print ' objects. For example:'
- print ' /v1/account/container/object_prefix_ would'
- print ' ensure all form uploads have that path'
- print ' prepended to the browser-given file name.'
- print ' <redirect> The URL to redirect the browser to after'
- print ' the uploads have completed.'
- print ' <max_file_size> The maximum file size per file uploaded.'
- print ' <max_file_count> The maximum number of uploaded files'
- print ' allowed.'
- print ' <seconds> The number of seconds from now to allow'
- print ' the form post to begin.'
- print ' <key> The X-Account-Meta-Temp-URL-Key for the'
- print ' account.'
- print
- print 'Example output:'
- print ' Expires: 1323842228'
- print ' Signature: 18de97e47345a82c4dbfb3b06a640dbb'
- exit(1)
- path, redirect, max_file_size, max_file_count, seconds, key = argv[1:]
- try:
- max_file_size = int(max_file_size)
- except ValueError:
- max_file_size = -1
- if max_file_size < 0:
- print 'Please use a <max_file_size> value greater than or equal to 0.'
- exit(1)
- try:
- max_file_count = int(max_file_count)
- except ValueError:
- max_file_count = 0
- if max_file_count < 1:
- print 'Please use a positive <max_file_count> value.'
- exit(1)
- try:
- expires = int(time() + int(seconds))
- except ValueError:
- expires = 0
- if expires < 1:
- print 'Please use a positive <seconds> value.'
- exit(1)
- parts = path.split('/', 4)
- # Must be four parts, ['', 'v1', 'a', 'c'], must be a v1 request, have
- # account and container values, and optionally have an object prefix.
- if len(parts) < 4 or parts[0] or parts[1] != 'v1' or not parts[2] or \
- not parts[3]:
- print '<path> must point to a container at least.'
- print 'For example: /v1/account/container'
- print ' Or: /v1/account/container/object_prefix'
- exit(1)
- sig = hmac.new(key, '%s\n%s\n%s\n%s\n%s' % (path, redirect, max_file_size,
- max_file_count, expires),
- sha1).hexdigest()
- print ' Expires:', expires
- print 'Signature:', sig
+if __name__ == "__main__":
+ sys.exit(swift.cli.form_signature.main(sys.argv))
diff --git a/swift/cli/form_signature.py b/swift/cli/form_signature.py
new file mode 100644
index 000000000..20452f36c
--- /dev/null
+++ b/swift/cli/form_signature.py
@@ -0,0 +1,86 @@
+# Copyright (c) 2010-2012 OpenStack Foundation
+# 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.
+
+"""
+Script for generating a form signature for use with FormPost middleware.
+"""
+import hmac
+from hashlib import sha1
+from os.path import basename
+from time import time
+
+
+def main(argv):
+ if len(argv) != 7:
+ prog = basename(argv[0])
+ print 'Syntax: %s <path> <redirect> <max_file_size> ' \
+ '<max_file_count> <seconds> <key>' % prog
+ print
+ print 'Where:'
+ print ' <path> The prefix to use for form uploaded'
+ print ' objects. For example:'
+ print ' /v1/account/container/object_prefix_ would'
+ print ' ensure all form uploads have that path'
+ print ' prepended to the browser-given file name.'
+ print ' <redirect> The URL to redirect the browser to after'
+ print ' the uploads have completed.'
+ print ' <max_file_size> The maximum file size per file uploaded.'
+ print ' <max_file_count> The maximum number of uploaded files'
+ print ' allowed.'
+ print ' <seconds> The number of seconds from now to allow'
+ print ' the form post to begin.'
+ print ' <key> The X-Account-Meta-Temp-URL-Key for the'
+ print ' account.'
+ print
+ print 'Example output:'
+ print ' Expires: 1323842228'
+ print ' Signature: 18de97e47345a82c4dbfb3b06a640dbb'
+ return 1
+ path, redirect, max_file_size, max_file_count, seconds, key = argv[1:]
+ try:
+ max_file_size = int(max_file_size)
+ except ValueError:
+ max_file_size = -1
+ if max_file_size < 0:
+ print 'Please use a <max_file_size> value greater than or equal to 0.'
+ return 1
+ try:
+ max_file_count = int(max_file_count)
+ except ValueError:
+ max_file_count = 0
+ if max_file_count < 1:
+ print 'Please use a positive <max_file_count> value.'
+ return 1
+ try:
+ expires = int(time() + int(seconds))
+ except ValueError:
+ expires = 0
+ if expires < 1:
+ print 'Please use a positive <seconds> value.'
+ return 1
+ parts = path.split('/', 4)
+ # Must be four parts, ['', 'v1', 'a', 'c'], must be a v1 request, have
+ # account and container values, and optionally have an object prefix.
+ if len(parts) < 4 or parts[0] or parts[1] != 'v1' or not parts[2] or \
+ not parts[3]:
+ print '<path> must point to a container at least.'
+ print 'For example: /v1/account/container'
+ print ' Or: /v1/account/container/object_prefix'
+ return 1
+ sig = hmac.new(key, '%s\n%s\n%s\n%s\n%s' % (path, redirect, max_file_size,
+ max_file_count, expires),
+ sha1).hexdigest()
+ print ' Expires:', expires
+ print 'Signature:', sig
+ return 0
diff --git a/test/unit/cli/test_form_signature.py b/test/unit/cli/test_form_signature.py
new file mode 100644
index 000000000..fa2c9da90
--- /dev/null
+++ b/test/unit/cli/test_form_signature.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2014 Samuel Merritt <sam@swiftstack.com>
+#
+# 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.
+
+import hashlib
+import hmac
+import mock
+import unittest
+from StringIO import StringIO
+
+from swift.cli import form_signature
+
+
+class TestFormSignature(unittest.TestCase):
+ def test_prints_signature(self):
+ the_time = 1406143563.020043
+ key = 'secret squirrel'
+ expires = 3600
+ path = '/v1/a/c/o'
+ redirect = 'https://example.com/done.html'
+ max_file_size = str(int(1024 * 1024 * 1024 * 3.14159)) # π GiB
+ max_file_count = '3'
+
+ expected_signature = hmac.new(
+ key,
+ "\n".join((
+ path, redirect, max_file_size, max_file_count,
+ str(int(the_time + expires)))),
+ hashlib.sha1).hexdigest()
+
+ out = StringIO()
+ with mock.patch('swift.cli.form_signature.time', lambda: the_time):
+ with mock.patch('sys.stdout', out):
+ exitcode = form_signature.main([
+ '/path/to/swift-form-signature',
+ path, redirect, max_file_size,
+ max_file_count, str(expires), key])
+
+ self.assertEqual(exitcode, 0)
+ self.assertTrue("Signature: %s" % expected_signature
+ in out.getvalue())
+ self.assertTrue("Expires: %d" % (the_time + expires,)
+ in out.getvalue())
+
+ def test_too_few_args(self):
+ out = StringIO()
+ with mock.patch('sys.stdout', out):
+ exitcode = form_signature.main([
+ '/path/to/swift-form-signature',
+ '/v1/a/c/o', '', '12', '34', '3600'])
+
+ self.assertNotEqual(exitcode, 0)
+ usage = 'Syntax: swift-form-signature <path>'
+ self.assertTrue(usage in out.getvalue())
+
+
+if __name__ == '__main__':
+ unittest.main()