Fix API incompatibility in update_metadata()

A major security fix[1] has been back-ported to icehouse branch in
upstream Swift. This fix changes the method signature of one of the
methods that we override, namely "update_metadata()". The method
signature of the same method in gluster-swift has been adjusted
accordingly. However, the entire fix itself has NOT been backported
as the implementations are different and due to time constraints.

[1]: https://review.openstack.org/#/c/126645/

Running unit tests in icehouse branch fails with:
AttributeError: 'VersionInfo' object has no attribute 'semantic_version'
Installing testtools package seems to be a good workaround for now.

Also fixed pep8 issues and removed duplicate gswauth unit tests.

Change-Id: I61d635ca5f47eb37f5275297c262f2bfe41de1fa
Signed-off-by: Prashanth Pai <ppai@redhat.com>
This commit is contained in:
Prashanth Pai
2015-08-05 14:49:33 +05:30
parent 2beeef64da
commit 2842e8236a
10 changed files with 31 additions and 4613 deletions

View File

@@ -42,9 +42,9 @@ class PkgInfo(object):
return '%s-dev' % (self.canonical_version,)
###
### Change the Package version here
###
#
# Change the Package version here
#
_pkginfo = PkgInfo('1.13.1', '2', 'gluster_swift', False)
__version__ = _pkginfo.pretty_version
__canonical_version__ = _pkginfo.canonical_version

View File

@@ -195,7 +195,7 @@ class DiskCommon(object):
except FileOrDirNotFoundError:
return True
def update_metadata(self, metadata):
def update_metadata(self, metadata, validate_metadata=False):
assert self.metadata, "Valid container/account metadata should have " \
"been created by now"
if metadata:

View File

@@ -241,7 +241,7 @@ class Swauth(object):
version, rest = split_path(env.get('PATH_INFO', ''),
1, 2, True)
except ValueError:
version, rest = None, None
rest = None
if rest and rest.startswith(self.reseller_prefix):
# Handle anonymous access to accounts I'm the definitive
# auth for.
@@ -693,7 +693,7 @@ class Swauth(object):
return HTTPBadRequest(request=req)
try:
new_services = json.loads(req.body)
except ValueError, err:
except ValueError as err:
return HTTPBadRequest(body=str(err))
# Get the current services information
path = quote('/v1/%s/%s/.services' % (self.auth_account, account))
@@ -1405,7 +1405,7 @@ class Swauth(object):
memcache_key,
(self.itoken_expires,
'%s,.reseller_admin,%s' % (self.metadata_volume,
self.auth_account)),
self.auth_account)),
timeout=self.token_life)
return self.itoken
@@ -1589,19 +1589,20 @@ class Swauth(object):
if getattr(req, 'client_disconnect', False) or \
getattr(response, 'client_disconnect', False):
status_int = 499
self.logger.info(
' '.join(quote(str(x)) for x in (client or '-',
req.remote_addr or '-', strftime('%d/%b/%Y/%H/%M/%S', gmtime()),
req.method, the_request, req.environ['SERVER_PROTOCOL'],
status_int, req.referer or '-', req.user_agent or '-',
req.headers.get(
'x-auth-token',
req.headers.get('x-auth-admin-user', '-')),
getattr(req, 'bytes_transferred', 0) or '-',
getattr(response, 'bytes_transferred', 0) or '-',
req.headers.get('etag', '-'),
req.headers.get('x-trans-id', '-'), logged_headers or '-',
trans_time)))
self.logger.info(' '.join(quote(str(x)) for x in
(client or '-',
req.remote_addr or '-', strftime('%d/%b/%Y/%H/%M/%S',
gmtime()),
req.method, the_request,
req.environ['SERVER_PROTOCOL'], status_int,
req.referer or '-', req.user_agent or '-',
req.headers.get('x-auth-token', req.headers.get(
'x-auth-admin-user', '-')),
getattr(req, 'bytes_transferred', 0) or '-',
getattr(response, 'bytes_transferred', 0) or '-',
req.headers.get('etag', '-'),
req.headers.get('x-trans-id', '-'), logged_headers
or '-', trans_time)))
def filter_factory(global_conf, **local_conf):

View File

@@ -1,6 +0,0 @@
# See http://code.google.com/p/python-nose/issues/detail?id=373
# The code below enables nosetests to work with i18n _() blocks
import __builtin__
setattr(__builtin__, '_', lambda x: x)

View File

@@ -1,63 +0,0 @@
# 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.
#
# Pablo Llopis 2011
import unittest
from swauth import authtypes
class TestPlaintext(unittest.TestCase):
def setUp(self):
self.auth_encoder = authtypes.Plaintext()
def test_plaintext_encode(self):
enc_key = self.auth_encoder.encode('keystring')
self.assertEquals('plaintext:keystring', enc_key)
def test_plaintext_valid_match(self):
creds = 'plaintext:keystring'
match = self.auth_encoder.match('keystring', creds)
self.assertEquals(match, True)
def test_plaintext_invalid_match(self):
creds = 'plaintext:other-keystring'
match = self.auth_encoder.match('keystring', creds)
self.assertEquals(match, False)
class TestSha1(unittest.TestCase):
def setUp(self):
self.auth_encoder = authtypes.Sha1()
self.auth_encoder.salt = 'salt'
def test_sha1_encode(self):
enc_key = self.auth_encoder.encode('keystring')
self.assertEquals('sha1:salt$d50dc700c296e23ce5b41f7431a0e01f69010f06',
enc_key)
def test_sha1_valid_match(self):
creds = 'sha1:salt$d50dc700c296e23ce5b41f7431a0e01f69010f06'
match = self.auth_encoder.match('keystring', creds)
self.assertEquals(match, True)
def test_sha1_invalid_match(self):
creds = 'sha1:salt$deadbabedeadbabedeadbabec0ffeebadc0ffeee'
match = self.auth_encoder.match('keystring', creds)
self.assertEquals(match, False)
if __name__ == '__main__':
unittest.main()

View File

@@ -834,9 +834,9 @@ class DiskFile(object):
child = stack.pop() if stack else None
return True, newmd
# Exists, but as a file
#raise DiskFileError('DiskFile.put(): directory creation failed'
# ' since the target, %s, already exists as'
# ' a file' % df._data_file)
# raise DiskFileError('DiskFile.put(): directory creation failed'
# ' since the target, %s, already exists as'
# ' a file' % df._data_file)
@contextmanager
def create(self, size=None):

View File

@@ -692,7 +692,7 @@ class TestObjectExpirer(TestCase):
x = expirer.ObjectExpirer({})
x.swift.make_request = mock.MagicMock()
x.delete_actual_object(name, timestamp)
x.swift.make_request.assert_called_once()
self.assertTrue(x.swift.make_request.called)
self.assertEqual(x.swift.make_request.call_args[0][1],
'/v1/' + urllib.quote(name))

View File

@@ -18,9 +18,14 @@ setenv = VIRTUAL_ENV={envdir}
NOSE_COVER_BRANCHES=1
NOSE_COVER_PACKAGE=gluster
deps =
https://launchpad.net/swift/icehouse/1.13.1/+download/swift-1.13.1.tar.gz
git+https://github.com/openstack/swift.git@icehouse-eol
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
# Just having testtools package installed fixes some dependency issue
# https://github.com/swiftstack/vagrant-swift-all-in-one/issues/19
# pip needs a good dependency resolver :/
testtools
flake8
changedir = {toxinidir}/test/unit
commands = nosetests -v {posargs}