diff --git a/test/functional/__init__.py b/test/functional/__init__.py index 9e0ebe2b6c..1197f3f8da 100644 --- a/test/functional/__init__.py +++ b/test/functional/__init__.py @@ -92,15 +92,16 @@ normalized_urls = None # If no config was read, we will fall back to old school env vars swift_test_auth_version = None swift_test_auth = os.environ.get('SWIFT_TEST_AUTH') -swift_test_user = [os.environ.get('SWIFT_TEST_USER'), None, None, '', ''] -swift_test_key = [os.environ.get('SWIFT_TEST_KEY'), None, None, '', ''] -swift_test_tenant = ['', '', '', '', ''] -swift_test_perm = ['', '', '', '', ''] -swift_test_domain = ['', '', '', '', ''] -swift_test_user_id = ['', '', '', '', ''] -swift_test_tenant_id = ['', '', '', '', ''] +swift_test_user = [os.environ.get('SWIFT_TEST_USER'), None, None, '', '', ''] +swift_test_key = [os.environ.get('SWIFT_TEST_KEY'), None, None, '', '', ''] +swift_test_tenant = ['', '', '', '', '', ''] +swift_test_perm = ['', '', '', '', '', ''] +swift_test_domain = ['', '', '', '', '', ''] +swift_test_user_id = ['', '', '', '', '', ''] +swift_test_tenant_id = ['', '', '', '', '', ''] -skip, skip2, skip3, skip_service_tokens = False, False, False, False +skip, skip2, skip3, skip_service_tokens, skip_if_no_reseller_admin = \ + False, False, False, False, False orig_collate = '' insecure = False @@ -385,7 +386,11 @@ def in_process_setup(the_object_server=object_server): 'service_prefix': 'SERVICE', # For tempauth middleware. Update reseller_prefix 'reseller_prefix': 'AUTH, SERVICE', - 'SERVICE_require_group': 'service' + 'SERVICE_require_group': 'service', + # Reseller admin user (needs reseller_admin_role) + 'account6': 'test6', + 'username6': 'tester6', + 'password6': 'testing6' }) # If an env var explicitly specifies the proxy-server object_post_as_copy @@ -692,6 +697,10 @@ def setup_package(): swift_test_user[4] = config['username5'] swift_test_tenant[4] = config['account5'] swift_test_key[4] = config['password5'] + if 'username6' in config: + swift_test_user[5] = config['username6'] + swift_test_tenant[5] = config['account6'] + swift_test_key[5] = config['password6'] for _ in range(5): swift_test_perm[_] = swift_test_tenant[_] + ':' \ @@ -747,6 +756,16 @@ def setup_package(): % policy_specified) raise Exception('Failed to find specified policy %s' % policy_specified) + + global skip_if_no_reseller_admin + skip_if_no_reseller_admin = not all([not skip, swift_test_user[5], + swift_test_key[5], + swift_test_tenant[5]]) + if not skip and skip_if_no_reseller_admin: + print( + 'SKIPPING FUNCTIONAL TESTS DUE TO NO CONFIG FOR RESELLER ADMIN', + file=sys.stderr) + get_cluster_info() diff --git a/test/functional/test_access_control.py b/test/functional/test_access_control.py new file mode 100644 index 0000000000..7b6a68bd1b --- /dev/null +++ b/test/functional/test_access_control.py @@ -0,0 +1,1092 @@ +#!/usr/bin/python +# coding: UTF-8 + +# Copyright (c) 2015 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. + +import unittest +import uuid +from random import shuffle + +from nose import SkipTest +from swiftclient import get_auth, http_connection + +import test.functional as tf + + +def setUpModule(): + tf.setup_package() + + +def tearDownModule(): + tf.teardown_package() + + +TEST_CASE_FORMAT = ( + 'http_method', 'header', 'account_name', 'container_name', 'object_name', + 'prep_container_header', 'reseller_prefix', 'target_user_name', + 'auth_user_name', 'service_user_name', 'expected') +# http_method : HTTP methods such as PUT, GET, POST, HEAD and so on +# header : headers for a request +# account_name : Account name. Usually the name will be automatically +# created by keystone +# container_name : Container name. If 'UUID' is specified, a container +# name will be created automatically +# object_name : Object name. If 'UUID' is specified, a container +# name will be created automatically +# prep_container_header : headers which will be set on the container +# reseller_prefix : Reseller prefix that will be used for request url. +# Can be None or SERVICE to select the user account +# prefix or the service prefix respectively +# target_user_name : a user name which is used for getting the project id +# of the target +# auth_user_name : a user name which is used for getting a token for +# X-Auth_Token +# service_user_name : a user name which is used for getting a token for +# X-Service-Token +# expected : expected status code +# +# a combination of account_name, container_name and object_name +# represents a target. +# +------------+--------------+-----------+---------+ +# |account_name|container_name|object_name| target | +# +------------+--------------+-----------+---------+ +# | None | None | None | account | +# +------------+--------------+-----------+---------+ +# | None | 'UUID' | None |container| +# +------------+--------------+-----------+---------+ +# | None | 'UUID' | 'UUID' | object | +# +------------+--------------+-----------+---------+ +# +# The following users are required to run this functional test. +# No.6, tester6, is added for this test. +# +----+-----------+-------+---------+-------------+ +# |No. | Domain |Project|User name| Role | +# +----+-----------+-------+---------+-------------+ +# | 1 | default | test | tester | admin | +# +----+-----------+-------+---------+-------------+ +# | 2 | default | test2 | tester2 | admin | +# +----+-----------+-------+---------+-------------+ +# | 3 | default | test | tester3 | _member_ | +# +----+-----------+-------+---------+-------------+ +# | 4 |test-domain| test4 | tester4 | admin | +# +----+-----------+-------+---------+-------------+ +# | 5 | default | test5 | tester5 | service | +# +----+-----------+-------+---------+-------------+ +# | 6 | default | test | tester6 |ResellerAdmin| +# +----+-----------+-------+---------+-------------+ + +# A scenario of put for account, container and object with +# several roles. +RBAC_PUT = [ + ('PUT', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 201), + ('PUT', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 201), + ('PUT', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 201), + ('PUT', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 201), + ('PUT', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 201) +] + + +RBAC_PUT_WITH_SERVICE_PREFIX = [ + ('PUT', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 201), + ('PUT', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 401), + ('PUT', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 403), + ('PUT', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 201), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 401), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 403), + ('PUT', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 201), + ('PUT', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('PUT', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('PUT', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('PUT', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('PUT', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 201), + ('PUT', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('PUT', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 403), + ('PUT', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('PUT', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 401), +] + + +# A scenario of delete for account, container and object with +# several roles. +RBAC_DELETE = [ + ('DELETE', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 204), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 204), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 204), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 204), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 204) +] + + +RBAC_DELETE_WITH_SERVICE_PREFIX = [ + ('DELETE', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 204), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 401), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 401), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 403), + ('DELETE', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('DELETE', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('DELETE', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('DELETE', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('DELETE', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('DELETE', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('DELETE', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('DELETE', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 401) +] + + +# A scenario of get for account, container and object with +# several roles. +RBAC_GET = [ + ('GET', None, None, None, None, None, + None, 'tester', 'tester', None, 200), + ('GET', None, None, None, None, None, + None, 'tester', 'tester', 'tester', 200), + ('GET', None, None, None, None, None, + None, 'tester2', 'tester', None, 403), + ('GET', None, None, None, None, None, + None, 'tester4', 'tester', None, 403), + ('GET', None, None, None, None, None, + None, 'tester3', 'tester3', None, 403), + ('GET', None, None, None, None, None, + None, 'tester2', 'tester3', None, 403), + ('GET', None, None, None, None, None, + None, 'tester4', 'tester3', None, 403), + ('GET', None, None, None, None, None, + None, 'tester6', 'tester6', None, 200), + ('GET', None, None, None, None, None, + None, 'tester2', 'tester6', None, 200), + ('GET', None, None, None, None, None, + None, 'tester4', 'tester6', None, 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 200) +] + + +RBAC_GET_WITH_SERVICE_PREFIX = [ + ('GET', None, None, None, None, None, + None, 'tester', 'tester', 'tester5', 200), + ('GET', None, None, None, None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, None, None, None, + None, 'tester', None, 'tester5', 401), + ('GET', None, None, None, None, None, + None, 'tester5', 'tester5', None, 403), + ('GET', None, None, None, None, None, + None, 'tester2', 'tester5', None, 403), + ('GET', None, None, None, None, None, + None, 'tester4', 'tester5', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 200), + ('GET', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 401), + ('GET', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 403), + ('GET', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 200), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 401), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 403), + ('GET', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('GET', None, None, None, None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('GET', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('GET', None, None, None, None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('GET', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('GET', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('GET', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('GET', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('GET', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('GET', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('GET', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 403), + ('GET', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('GET', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 401) +] + + +# A scenario of head for account, container and object with +# several roles. +RBAC_HEAD = [ + ('HEAD', None, None, None, None, None, + None, 'tester', 'tester', None, 204), + ('HEAD', None, None, None, None, None, + None, 'tester', 'tester', 'tester', 204), + ('HEAD', None, None, None, None, None, + None, 'tester2', 'tester', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester4', 'tester', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester3', 'tester3', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester2', 'tester3', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester4', 'tester3', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester6', 'tester6', None, 204), + ('HEAD', None, None, None, None, None, + None, 'tester2', 'tester6', None, 204), + ('HEAD', None, None, None, None, None, + None, 'tester4', 'tester6', None, 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 204), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 200) +] + + +RBAC_HEAD_WITH_SERVICE_PREFIX = [ + ('HEAD', None, None, None, None, None, + None, 'tester', 'tester', 'tester5', 204), + ('HEAD', None, None, None, None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, None, None, None, + None, 'tester', None, 'tester5', 401), + ('HEAD', None, None, None, None, None, + None, 'tester5', 'tester5', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester2', 'tester5', None, 403), + ('HEAD', None, None, None, None, None, + None, 'tester4', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 204), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 401), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 401), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 403), + ('HEAD', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('HEAD', None, None, None, None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('HEAD', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('HEAD', None, None, None, None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('HEAD', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('HEAD', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('HEAD', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('HEAD', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('HEAD', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('HEAD', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('HEAD', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 401) +] + + +# A scenario of post for account, container and object with +# several roles. +RBAC_POST = [ + ('POST', None, None, None, None, None, + None, 'tester', 'tester', None, 204), + ('POST', None, None, None, None, None, + None, 'tester', 'tester', 'tester', 204), + ('POST', None, None, None, None, None, + None, 'tester2', 'tester', None, 403), + ('POST', None, None, None, None, None, + None, 'tester4', 'tester', None, 403), + ('POST', None, None, None, None, None, + None, 'tester3', 'tester3', None, 403), + ('POST', None, None, None, None, None, + None, 'tester2', 'tester3', None, 403), + ('POST', None, None, None, None, None, + None, 'tester4', 'tester3', None, 403), + ('POST', None, None, None, None, None, + None, 'tester6', 'tester6', None, 204), + ('POST', None, None, None, None, None, + None, 'tester2', 'tester6', None, 204), + ('POST', None, None, None, None, None, + None, 'tester4', 'tester6', None, 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 204), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 202), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 202), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 202), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 202), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 202) +] + + +RBAC_POST_WITH_SERVICE_PREFIX = [ + ('POST', None, None, None, None, None, + None, 'tester', 'tester', 'tester5', 204), + ('POST', None, None, None, None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, None, None, None, + None, 'tester', None, 'tester5', 401), + ('POST', None, None, None, None, None, + None, 'tester5', 'tester5', None, 403), + ('POST', None, None, None, None, None, + None, 'tester2', 'tester5', None, 403), + ('POST', None, None, None, None, None, + None, 'tester4', 'tester5', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 204), + ('POST', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 401), + ('POST', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 403), + ('POST', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 202), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 401), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 403), + ('POST', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('POST', None, None, None, None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('POST', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('POST', None, None, None, None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('POST', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 204), + ('POST', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 403), + ('POST', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('POST', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 401), + ('POST', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 202), + ('POST', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 403), + ('POST', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 403), + ('POST', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 403), + ('POST', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 401) +] + + +# A scenario of options for account, container and object with +# several roles. +RBAC_OPTIONS = [ + ('OPTIONS', None, None, None, None, None, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester2', 'tester', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester4', 'tester', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester3', 'tester3', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester2', 'tester3', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester4', 'tester3', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester6', 'tester6', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester2', 'tester6', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester4', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester2', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester4', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester3', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester2', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester4', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester6', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester2', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester4', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester3', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester3', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester6', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester6', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester6', None, 200), + ('OPTIONS', None, None, None, None, + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, None, None, + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, None, None, None, None, 'tester', 'tester', None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, None, None, + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, None, None, + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', None, None, None, 'tester', 'tester', None, 401), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', None, + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', 'tester', None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', None, + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 401), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', 'UUID', None, None, 'tester', 'tester', None, 401), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', 'UUID', + {"X-Container-Meta-Access-Control-Allow-Origin": "*"}, + None, 'tester', None, None, 200), + ('OPTIONS', + {"Origin": "http://localhost", "Access-Control-Request-Method": "GET"}, + None, 'UUID', 'UUID', + {"X-Container-Meta-Access-Control-Allow-Origin": "http://invalid.com"}, + None, 'tester', 'tester', None, 401) +] + + +RBAC_OPTIONS_WITH_SERVICE_PREFIX = [ + ('OPTIONS', None, None, None, None, None, + None, 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester', None, 'tester5', 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester5', 'tester5', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester2', 'tester5', None, 200), + ('OPTIONS', None, None, None, None, None, + None, 'tester4', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester', None, 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester5', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester2', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + None, 'tester4', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester', None, 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester5', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester2', 'tester5', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + None, 'tester4', 'tester5', None, 200), + ('OPTIONS', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, None, None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', None, 200), + ('OPTIONS', None, None, None, None, None, + 'SERVICE', 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, None, None, None, + 'SERVICE', 'tester', None, 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', None, None, + 'SERVICE', 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, 'UUID', None, None, + 'SERVICE', 'tester', None, 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester3', 'tester5', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', None, 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', 'tester', 'tester', 200), + ('OPTIONS', None, None, 'UUID', 'UUID', None, + 'SERVICE', 'tester', None, 'tester5', 200) +] + + +class SwiftClient(object): + _tokens = {} + + def __init__(self): + self._set_users() + self.auth_url = tf.swift_test_auth + self.insecure = tf.insecure + self.auth_version = tf.swift_test_auth_version + + def _set_users(self): + self.users = {} + for index in range(6): + self.users[tf.swift_test_user[index]] = { + 'account': tf.swift_test_tenant[index], + 'password': tf.swift_test_key[index], + 'domain': tf.swift_test_domain[index]} + + def _get_auth(self, user_name): + info = self.users.get(user_name) + if info is None: + return None, None + + os_options = {'user_domain_name': info['domain'], + 'project_domain_name': info['domain']} + authargs = dict(snet=False, tenant_name=info['account'], + auth_version=self.auth_version, os_options=os_options, + insecure=self.insecure) + storage_url, token = get_auth( + self.auth_url, user_name, info['password'], **authargs) + + return storage_url, token + + def auth(self, user_name): + storage_url, token = SwiftClient._tokens.get(user_name, (None, None)) + if not token: + SwiftClient._tokens[user_name] = self._get_auth(user_name) + storage_url, token = SwiftClient._tokens.get(user_name) + return storage_url, token + + def send_request(self, method, url, token=None, headers=None, + service_token=None): + headers = {} if headers is None else headers.copy() + headers.update({'Content-Type': 'application/json', + 'Accept': 'application/json'}) + if token: + headers['X-Auth-Token'] = token + if service_token: + headers['X-Service-Token'] = service_token + if self.insecure: + parsed, conn = http_connection(url, insecure=self.insecure) + else: + parsed, conn = http_connection(url) + + conn.request(method, parsed.path, headers=headers) + resp = conn.getresponse() + + return resp + + +class BaseTestAC(unittest.TestCase): + def setUp(self): + self.reseller_admin = tf.swift_test_user[5] + self.client = SwiftClient() + + def _create_resource_url(self, storage_url, account=None, + container=None, obj=None, reseller_prefix=None): + # e.g. + # storage_url = 'http://localhost/v1/AUTH_xxx' + # storage_url_list[:-1] is ['http:', '', 'localhost', 'v1'] + # storage_url_list[-1] is 'AUTH_xxx' + storage_url_list = storage_url.rstrip('/').split('/') + base_url = '/'.join(storage_url_list[:-1]) + + if account is None: + account = storage_url_list[-1] + if reseller_prefix == 'SERVICE': + # replace endpoint reseller prefix with service reseller prefix + i = (account.index('_') + 1) if '_' in account else 0 + account = tf.swift_test_service_prefix + account[i:] + + return '/'.join([part for part in (base_url, account, container, obj) + if part]) + + def _put_container(self, storage_url, token, test_case): + resource_url = self._create_resource_url( + storage_url, + test_case['account_name'], + test_case['container_name'], + reseller_prefix=test_case['reseller_prefix']) + self.created_resources.append(resource_url) + self.client.send_request('PUT', resource_url, token, + headers=test_case['prep_container_header']) + + def _put_object(self, storage_url, token, test_case): + resource_url = self._create_resource_url( + storage_url, + test_case['account_name'], + test_case['container_name'], + test_case['object_name'], + reseller_prefix=test_case['reseller_prefix']) + self.created_resources.append(resource_url) + self.client.send_request('PUT', resource_url, token) + + def _get_storage_url_and_token(self, storage_url_user, token_user): + storage_url, _junk = self.client.auth(storage_url_user) + _junk, token = self.client.auth(token_user) + + return storage_url, token + + def _prepare(self, test_case): + storage_url, reseller_token = self._get_storage_url_and_token( + test_case['target_user_name'], self.reseller_admin) + + if test_case['http_method'] in ('GET', 'POST', 'DELETE', 'HEAD', + 'OPTIONS'): + temp_test_case = test_case.copy() + if test_case['container_name'] is None: + # When the target is for account, dummy container will be + # created to create an account. This account is created by + # account_autocreate. + temp_test_case['container_name'] = uuid.uuid4().hex + self._put_container(storage_url, reseller_token, temp_test_case) + + if test_case['object_name']: + self._put_object(storage_url, reseller_token, test_case) + + elif test_case['http_method'] in ('PUT',): + if test_case['object_name']: + self._put_container(storage_url, reseller_token, test_case) + + def _execute(self, test_case): + storage_url, token = self._get_storage_url_and_token( + test_case['target_user_name'], test_case['auth_user_name']) + + service_user = test_case['service_user_name'] + service_token = (None if service_user is None + else self.client.auth(service_user)[1]) + + resource_url = self._create_resource_url( + storage_url, + test_case['account_name'], + test_case['container_name'], + test_case['object_name'], + test_case['reseller_prefix']) + + if test_case['http_method'] in ('PUT'): + self.created_resources.append(resource_url) + + resp = self.client.send_request(test_case['http_method'], + resource_url, + token, + headers=test_case['header'], + service_token=service_token) + + return resp.status + + def _cleanup(self): + _junk, reseller_token = self.client.auth(self.reseller_admin) + for resource_url in reversed(self.created_resources): + resp = self.client.send_request('DELETE', resource_url, + reseller_token) + self.assertIn(resp.status, (204, 404)) + + def _convert_data(self, data): + test_case = dict(zip(TEST_CASE_FORMAT, data)) + if test_case['container_name'] == 'UUID': + test_case['container_name'] = uuid.uuid4().hex + if test_case['object_name'] == 'UUID': + test_case['object_name'] = uuid.uuid4().hex + return test_case + + def _run_scenario(self, scenario): + for data in scenario: + test_case = self._convert_data(data) + self.created_resources = [] + try: + self._prepare(test_case) + result = self._execute(test_case) + self.assertEqual(test_case['expected'], + result, + 'Expected %s but got %s for test case %s' % + (test_case['expected'], result, test_case)) + finally: + self._cleanup() + + +class TestRBAC(BaseTestAC): + + def test_rbac(self): + if any((tf.skip, tf.skip2, tf.skip3, tf.skip_if_not_v3, + tf.skip_if_no_reseller_admin)): + raise SkipTest + scenario_rbac = RBAC_PUT + RBAC_DELETE + RBAC_GET +\ + RBAC_HEAD + RBAC_POST + RBAC_OPTIONS + shuffle(scenario_rbac) + self._run_scenario(scenario_rbac) + + def test_rbac_with_service_prefix(self): + if any((tf.skip, tf.skip2, tf.skip3, tf.skip_if_not_v3, + tf.skip_service_tokens, tf.skip_if_no_reseller_admin)): + raise SkipTest + scenario_rbac = RBAC_PUT_WITH_SERVICE_PREFIX +\ + RBAC_DELETE_WITH_SERVICE_PREFIX +\ + RBAC_GET_WITH_SERVICE_PREFIX +\ + RBAC_HEAD_WITH_SERVICE_PREFIX +\ + RBAC_POST_WITH_SERVICE_PREFIX +\ + RBAC_OPTIONS_WITH_SERVICE_PREFIX + shuffle(scenario_rbac) + self._run_scenario(scenario_rbac) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/functional/test_object.py b/test/functional/test_object.py index f559efb31a..f3b355ae13 100755 --- a/test/functional/test_object.py +++ b/test/functional/test_object.py @@ -71,6 +71,20 @@ class TestObject(unittest2.TestCase): resp = retry(put, name, use_account=use_account) resp.read() self.assertEqual(resp.status, 201) + + # With keystoneauth we need the accounts to have had the project + # domain id persisted as sysmeta prior to testing ACLs. This may + # not be the case if, for example, the account was created using + # a request with reseller_admin role, when project domain id may + # not have been known. So we ensure that the project domain id is + # in sysmeta by making a POST to the accounts using an admin role. + def post(url, token, parsed, conn): + conn.request('POST', parsed.path, '', {'X-Auth-Token': token}) + return check_response(conn) + resp = retry(post, use_account=use_account) + resp.read() + self.assertEqual(resp.status, 204) + return name def tearDown(self): diff --git a/test/functional/tests.py b/test/functional/tests.py index 7f9ef3ea3c..0615bf924a 100644 --- a/test/functional/tests.py +++ b/test/functional/tests.py @@ -1108,6 +1108,15 @@ class TestFileEnv(object): cls.file_size = 128 + # With keystoneauth we need the accounts to have had the project + # domain id persisted as sysmeta prior to testing ACLs. This may + # not be the case if, for example, the account was created using + # a request with reseller_admin role, when project domain id may + # not have been known. So we ensure that the project domain id is + # in sysmeta by making a POST to the accounts using an admin role. + cls.account.update_metadata() + cls.account2.update_metadata() + class TestFileDev(Base): env = TestFileEnv diff --git a/test/sample.conf b/test/sample.conf index 3cf3609e59..a5db328784 100644 --- a/test/sample.conf +++ b/test/sample.conf @@ -58,6 +58,12 @@ password3 = testing3 # account contains an underscore. #service_prefix = SERVICE +# Sixth user is required for access control tests. +# Account must have a role for reseller_admin_role(keystoneauth). +#account6 = test +#username6 = tester6 +#password6 = testing6 + collate = C # Only necessary if a pre-existing server uses self-signed certificate