diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-08-06 12:44:25 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-08-06 12:44:25 +0000 |
commit | c28749abb05135b80e38ae119d57a5fea2948342 (patch) | |
tree | 2e0e87ef7266314886b1e08cff1e222b59583c38 | |
parent | 560e578dfc8f58db4bbeaf19f4a9c39854d9f875 (diff) | |
parent | 4f2bb9f271e705ee5e7a357c9e5ec9384b4a690e (diff) | |
download | swift-c28749abb05135b80e38ae119d57a5fea2948342.tar.gz |
Merge "Make swift-form-signature testable"
-rwxr-xr-x | bin/swift-form-signature | 71 | ||||
-rw-r--r-- | swift/cli/form_signature.py | 86 | ||||
-rw-r--r-- | test/unit/cli/test_form_signature.py | 70 |
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() |