Merge "Test to GET public-readable container's object"
diff --git a/tempest/openstack.py b/tempest/openstack.py
index e29ea8e..01b4cc1 100644
--- a/tempest/openstack.py
+++ b/tempest/openstack.py
@@ -22,33 +22,33 @@
from tempest.services.boto.clients import APIClientEC2
from tempest.services.boto.clients import ObjectClientS3
from tempest.services.compute.json.extensions_client import \
- ExtensionsClientJSON
+ ExtensionsClientJSON
from tempest.services.compute.json.flavors_client import FlavorsClientJSON
from tempest.services.compute.json.floating_ips_client import \
- FloatingIPsClientJSON
+ FloatingIPsClientJSON
from tempest.services.compute.json.images_client import ImagesClientJSON
from tempest.services.compute.json.limits_client import LimitsClientJSON
from tempest.services.compute.json.servers_client import ServersClientJSON
from tempest.services.compute.json.security_groups_client import \
- SecurityGroupsClientJSON
+ SecurityGroupsClientJSON
from tempest.services.compute.json.keypairs_client import KeyPairsClientJSON
from tempest.services.compute.json.quotas_client import QuotasClient
from tempest.services.compute.json.volumes_extensions_client import \
- VolumesExtensionsClientJSON
+ VolumesExtensionsClientJSON
from tempest.services.compute.json.console_output_client import \
- ConsoleOutputsClient
+ ConsoleOutputsClient
from tempest.services.compute.xml.extensions_client import ExtensionsClientXML
from tempest.services.compute.xml.flavors_client import FlavorsClientXML
from tempest.services.compute.xml.floating_ips_client import \
- FloatingIPsClientXML
+ FloatingIPsClientXML
from tempest.services.compute.xml.images_client import ImagesClientXML
from tempest.services.compute.xml.keypairs_client import KeyPairsClientXML
from tempest.services.compute.xml.limits_client import LimitsClientXML
from tempest.services.compute.xml.security_groups_client \
-import SecurityGroupsClientXML
+ import SecurityGroupsClientXML
from tempest.services.compute.xml.servers_client import ServersClientXML
from tempest.services.compute.xml.volumes_extensions_client import \
- VolumesExtensionsClientXML
+ VolumesExtensionsClientXML
from tempest.services.identity.json.admin_client import AdminClientJSON
from tempest.services.identity.json.admin_client import TokenClientJSON
from tempest.services.identity.xml.admin_client import AdminClientXML
@@ -60,6 +60,8 @@
from tempest.services.object_storage.object_client import ObjectClient
from tempest.services.volume.json.volumes_client import VolumesClientJSON
from tempest.services.volume.xml.volumes_client import VolumesClientXML
+from tempest.services.object_storage.object_client import \
+ ObjectClientCustomizedHeader
LOG = logging.getLogger(__name__)
@@ -191,6 +193,7 @@
self.object_client = ObjectClient(*client_args)
self.ec2api_client = APIClientEC2(*client_args)
self.s3_client = ObjectClientS3(*client_args)
+ self.custom_object_client = ObjectClientCustomizedHeader(*client_args)
class AltManager(Manager):
diff --git a/tempest/services/object_storage/object_client.py b/tempest/services/object_storage/object_client.py
index c8f63ef..5bf8de0 100644
--- a/tempest/services/object_storage/object_client.py
+++ b/tempest/services/object_storage/object_client.py
@@ -15,6 +15,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import httplib2
+import json
import re
from tempest.common.rest_client import RestClient
@@ -116,3 +118,44 @@
resp, body = self.copy(url, headers=headers)
return resp, body
+
+
+class ObjectClientCustomizedHeader(RestClient):
+
+ def __init__(self, config, username, password, auth_url, tenant_name=None):
+ super(ObjectClientCustomizedHeader, self).__init__(config, username,
+ password, auth_url,
+ tenant_name)
+ #Overwrites json-specific header encoding in RestClient
+ self.service = self.config.object_storage.catalog_type
+ self.format = 'json'
+
+ def request(self, method, url, headers=None, body=None, wait=None):
+ """A simple HTTP request interface."""
+ self.http_obj = httplib2.Http()
+ if headers is None:
+ headers = {}
+ if self.base_url is None:
+ self._set_auth()
+
+ req_url = "%s/%s" % (self.base_url, url)
+ resp, resp_body = self.http_obj.request(req_url, method,
+ headers=headers, body=body)
+ if resp.status in (401, 403):
+ try:
+ resp_body = json.loads(resp_body)
+ raise exceptions.Unauthorized(resp_body['error']['message'])
+ except ValueError:
+ pass
+ return resp, resp_body
+
+ def get_object(self, container, object_name, metadata=None):
+ """Retrieve object's data."""
+ headers = {}
+ if metadata:
+ for key in metadata:
+ headers[str(key)] = metadata[key]
+
+ url = "{0}/{1}".format(container, object_name)
+ resp, body = self.get(url, headers=headers)
+ return resp, body
diff --git a/tempest/tests/object_storage/base.py b/tempest/tests/object_storage/base.py
index 8edb3d2..f29798f 100644
--- a/tempest/tests/object_storage/base.py
+++ b/tempest/tests/object_storage/base.py
@@ -32,6 +32,7 @@
cls.container_client = cls.os.container_client
cls.account_client = cls.os.account_client
cls.config = cls.os.config
+ cls.custom_object_client = cls.os.custom_object_client
try:
cls.account_client.list_account_containers()
diff --git a/tempest/tests/object_storage/test_object_services.py b/tempest/tests/object_storage/test_object_services.py
index 3be2bee..807a99e 100644
--- a/tempest/tests/object_storage/test_object_services.py
+++ b/tempest/tests/object_storage/test_object_services.py
@@ -263,3 +263,36 @@
src_container_name)
resp, _ = self.container_client.delete_container(
dst_container_name)
+
+ @attr(type='smoke')
+ def test_access_object_without_using_creds(self):
+ """Make container public-readable, and access the object
+ anonymously, e.g. without using credentials"""
+
+ # Update Container Metadata to make public readable
+ headers = {'X-Container-Read': '.r:*,.rlistings'}
+ resp, body = \
+ self.container_client.update_container_metadata(
+ self.container_name, metadata=headers, metadata_prefix='')
+ self.assertIn(resp['status'], '204')
+
+ # Create Object
+ object_name = rand_name(name='Object')
+ data = arbitrary_string(size=len(object_name) * 1,
+ base_text=object_name)
+ resp, _ = self.object_client.create_object(self.container_name,
+ object_name, data)
+ self.assertEqual(resp['status'], '201')
+
+ # List container metadata
+ resp, _ = \
+ self.container_client.list_container_metadata(self.container_name)
+ self.assertEqual(resp['status'], '204')
+ self.assertIn('x-container-read', resp)
+ self.assertEqual(resp['x-container-read'], '.r:*,.rlistings')
+
+ # Trying to Get Object with empty Headers as it is public readable
+ resp, body = \
+ self.custom_object_client.get_object(self.container_name,
+ object_name, metadata={})
+ self.assertEqual(body, data)