Merge "Make tempurl command check for valid object path"
This commit is contained in:
@@ -1240,17 +1240,17 @@ def st_tempurl(parser, args, thread_manager):
|
|||||||
|
|
||||||
parsed = urlparse(path)
|
parsed = urlparse(path)
|
||||||
|
|
||||||
try:
|
|
||||||
seconds = int(seconds)
|
|
||||||
except ValueError:
|
|
||||||
thread_manager.error('Seconds must be an integer')
|
|
||||||
return
|
|
||||||
if method.upper() not in ['GET', 'PUT', 'HEAD', 'POST', 'DELETE']:
|
if method.upper() not in ['GET', 'PUT', 'HEAD', 'POST', 'DELETE']:
|
||||||
thread_manager.print_msg('WARNING: Non default HTTP method %s for '
|
thread_manager.print_msg('WARNING: Non default HTTP method %s for '
|
||||||
'tempurl specified, possibly an error' %
|
'tempurl specified, possibly an error' %
|
||||||
method.upper())
|
method.upper())
|
||||||
path = generate_temp_url(parsed.path, seconds, key, method,
|
try:
|
||||||
absolute=options['absolute_expiry'])
|
path = generate_temp_url(parsed.path, seconds, key, method,
|
||||||
|
absolute=options['absolute_expiry'])
|
||||||
|
except ValueError as err:
|
||||||
|
thread_manager.error(err)
|
||||||
|
return
|
||||||
|
|
||||||
if parsed.scheme and parsed.netloc:
|
if parsed.scheme and parsed.netloc:
|
||||||
url = "%s://%s%s" % (parsed.scheme, parsed.netloc, path)
|
url = "%s://%s%s" % (parsed.scheme, parsed.netloc, path)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -68,14 +68,20 @@ def generate_temp_url(path, seconds, key, method, absolute=False):
|
|||||||
|
|
||||||
:param path: The full path to the Swift object. Example:
|
:param path: The full path to the Swift object. Example:
|
||||||
/v1/AUTH_account/c/o.
|
/v1/AUTH_account/c/o.
|
||||||
:param seconds: The amount of time in seconds the temporary URL will
|
:param seconds: If absolute is False then this specifies the amount of time
|
||||||
be valid for.
|
in seconds for which the temporary URL will be valid. If absolute is
|
||||||
|
True then this specifies an absolute time at which the temporary URL
|
||||||
|
will expire.
|
||||||
:param key: The secret temporary URL key set on the Swift
|
:param key: The secret temporary URL key set on the Swift
|
||||||
cluster. To set a key, run 'swift post -m
|
cluster. To set a key, run 'swift post -m
|
||||||
"Temp-URL-Key: <substitute tempurl key here>"'
|
"Temp-URL-Key: <substitute tempurl key here>"'
|
||||||
:param method: A HTTP method, typically either GET or PUT, to allow
|
:param method: A HTTP method, typically either GET or PUT, to allow
|
||||||
for this temporary URL.
|
for this temporary URL.
|
||||||
:raises: ValueError if seconds is not a positive integer
|
:param absolute: if True then the seconds parameter is interpreted as an
|
||||||
|
absolute Unix time, otherwise seconds is interpreted as a relative time
|
||||||
|
offset from current time.
|
||||||
|
:raises: ValueError if seconds is not a positive integer or path is not to
|
||||||
|
an object.
|
||||||
:raises: TypeError if seconds is not an integer
|
:raises: TypeError if seconds is not an integer
|
||||||
:return: the path portion of a temporary URL
|
:return: the path portion of a temporary URL
|
||||||
"""
|
"""
|
||||||
@@ -94,6 +100,10 @@ def generate_temp_url(path, seconds, key, method, absolute=False):
|
|||||||
else:
|
else:
|
||||||
path_for_body = path
|
path_for_body = path
|
||||||
|
|
||||||
|
parts = path_for_body.split('/', 4)
|
||||||
|
if len(parts) != 5 or parts[0] or not all(parts[1:]):
|
||||||
|
raise ValueError('path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
standard_methods = ['GET', 'PUT', 'HEAD', 'POST', 'DELETE']
|
standard_methods = ['GET', 'PUT', 'HEAD', 'POST', 'DELETE']
|
||||||
if method.upper() not in standard_methods:
|
if method.upper() not in standard_methods:
|
||||||
logger = logging.getLogger("swiftclient")
|
logger = logging.getLogger("swiftclient")
|
||||||
|
|||||||
@@ -1402,7 +1402,7 @@ class TestShell(unittest.TestCase):
|
|||||||
"secret_key"]
|
"secret_key"]
|
||||||
swiftclient.shell.main(argv)
|
swiftclient.shell.main(argv)
|
||||||
temp_url.assert_called_with(
|
temp_url.assert_called_with(
|
||||||
'/v1/AUTH_account/c/o', 60, 'secret_key', 'GET', absolute=False)
|
'/v1/AUTH_account/c/o', "60", 'secret_key', 'GET', absolute=False)
|
||||||
|
|
||||||
@mock.patch('swiftclient.shell.generate_temp_url', return_value='')
|
@mock.patch('swiftclient.shell.generate_temp_url', return_value='')
|
||||||
def test_absolute_expiry_temp_url(self, temp_url):
|
def test_absolute_expiry_temp_url(self, temp_url):
|
||||||
@@ -1410,7 +1410,7 @@ class TestShell(unittest.TestCase):
|
|||||||
"secret_key", "--absolute"]
|
"secret_key", "--absolute"]
|
||||||
swiftclient.shell.main(argv)
|
swiftclient.shell.main(argv)
|
||||||
temp_url.assert_called_with(
|
temp_url.assert_called_with(
|
||||||
'/v1/AUTH_account/c/o', 60, 'secret_key', 'GET', absolute=True)
|
'/v1/AUTH_account/c/o', "60", 'secret_key', 'GET', absolute=True)
|
||||||
|
|
||||||
def test_temp_url_output(self):
|
def test_temp_url_output(self):
|
||||||
argv = ["", "tempurl", "GET", "60", "/v1/a/c/o",
|
argv = ["", "tempurl", "GET", "60", "/v1/a/c/o",
|
||||||
@@ -1428,6 +1428,18 @@ class TestShell(unittest.TestCase):
|
|||||||
expected = "http://saio:8080%s" % expected
|
expected = "http://saio:8080%s" % expected
|
||||||
self.assertEqual(expected, output.out)
|
self.assertEqual(expected, output.out)
|
||||||
|
|
||||||
|
def test_temp_url_error_output(self):
|
||||||
|
expected = 'path must be full path to an object e.g. /v1/a/c/o\n'
|
||||||
|
for bad_path in ('/v1/a/c', 'v1/a/c/o', '/v1/a/c/', '/v1/a//o',
|
||||||
|
'http://saio/v1/a/c', 'http://v1/a/c/o'):
|
||||||
|
argv = ["", "tempurl", "GET", "60", bad_path,
|
||||||
|
"secret_key", "--absolute"]
|
||||||
|
with CaptureOutput(suppress_systemexit=True) as output:
|
||||||
|
swiftclient.shell.main(argv)
|
||||||
|
self.assertEqual(expected, output.err,
|
||||||
|
'Expected %r but got %r for path %r' %
|
||||||
|
(expected, output.err, bad_path))
|
||||||
|
|
||||||
@mock.patch('swiftclient.service.Connection')
|
@mock.patch('swiftclient.service.Connection')
|
||||||
def test_capabilities(self, connection):
|
def test_capabilities(self, connection):
|
||||||
argv = ["", "capabilities"]
|
argv = ["", "capabilities"]
|
||||||
|
|||||||
@@ -180,6 +180,32 @@ class TestTempURL(unittest.TestCase):
|
|||||||
self.assertEqual(exc_manager.exception.args[0],
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
'seconds must be a positive integer')
|
'seconds must be a positive integer')
|
||||||
|
|
||||||
|
def test_generate_temp_url_bad_path(self):
|
||||||
|
with self.assertRaises(ValueError) as exc_manager:
|
||||||
|
u.generate_temp_url('/v1/a/c', 60, self.key, self.method)
|
||||||
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
|
'path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError) as exc_manager:
|
||||||
|
u.generate_temp_url('v1/a/c/o', 60, self.key, self.method)
|
||||||
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
|
'path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError) as exc_manager:
|
||||||
|
u.generate_temp_url('blah/v1/a/c/o', 60, self.key, self.method)
|
||||||
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
|
'path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError) as exc_manager:
|
||||||
|
u.generate_temp_url('/v1//c/o', 60, self.key, self.method)
|
||||||
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
|
'path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError) as exc_manager:
|
||||||
|
u.generate_temp_url('/v1/a/c/', 60, self.key, self.method)
|
||||||
|
self.assertEqual(exc_manager.exception.args[0],
|
||||||
|
'path must be full path to an object e.g. /v1/a/c/o')
|
||||||
|
|
||||||
|
|
||||||
class TestTempURLUnicodePathAndKey(TestTempURL):
|
class TestTempURLUnicodePathAndKey(TestTempURL):
|
||||||
url = u'/v1/\u00e4/c/\u00f3'
|
url = u'/v1/\u00e4/c/\u00f3'
|
||||||
|
|||||||
Reference in New Issue
Block a user