Add Keystone v3 support
Change-Id: I5bb974064f0980a3f599eae3e2ba86b405f917ac Closes-Bug: 1585708
This commit is contained in:
parent
05379af68b
commit
7fa6639ab3
|
@ -79,6 +79,8 @@ class IdentityServiceContext(context.IdentityServiceContext):
|
|||
ctxt['admin_token'] = \
|
||||
relation_get('admin_token', unit, relid)
|
||||
|
||||
if cmp_pkgrevno('radosgw', "10.2.0") >= 0:
|
||||
ctxt['auth_keystone_v3_supported'] = True
|
||||
ctxt['auth_type'] = 'keystone'
|
||||
ctxt['user_roles'] = config('operator-roles')
|
||||
ctxt['cache_size'] = config('cache-size')
|
||||
|
|
|
@ -31,7 +31,15 @@ log file = /var/log/ceph/radosgw.log
|
|||
rgw frontends = civetweb port={{ port }}
|
||||
{% if auth_type == 'keystone' %}
|
||||
rgw keystone url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
{% if auth_keystone_v3_supported and api_version == '3' -%}
|
||||
rgw keystone api version = 3
|
||||
rgw keystone admin user = {{ admin_user }}
|
||||
rgw keystone admin password = {{ admin_password }}
|
||||
rgw keystone admin domain = {{ admin_domain_name }}
|
||||
rgw keystone admin project = {{ admin_tenant_name }}
|
||||
{% else -%}
|
||||
rgw keystone admin token = {{ admin_token }}
|
||||
{% endif -%}
|
||||
rgw keystone accepted roles = {{ user_roles }}
|
||||
rgw keystone token cache size = {{ cache_size }}
|
||||
rgw keystone revocation interval = {{ revocation_check_interval }}
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
# limitations under the License.
|
||||
|
||||
import amulet
|
||||
import keystoneclient
|
||||
import subprocess
|
||||
import swiftclient
|
||||
import json
|
||||
import time
|
||||
from charmhelpers.contrib.openstack.amulet.deployment import (
|
||||
|
@ -184,10 +186,21 @@ class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
|
|||
description='demo tenant',
|
||||
enabled=True)
|
||||
self.keystone.roles.create(name=self.demo_role)
|
||||
self.keystone.users.create(name=self.demo_user,
|
||||
password='password',
|
||||
tenant_id=tenant.id,
|
||||
email='demo@demo.com')
|
||||
user = self.keystone.users.create(name=self.demo_user,
|
||||
password='password',
|
||||
tenant_id=tenant.id,
|
||||
email='demo@demo.com')
|
||||
|
||||
# Grant Member role to demo_user
|
||||
roles = [r._info for r in self.keystone.roles.list()]
|
||||
for r in roles:
|
||||
if r['name'].lower() == 'member':
|
||||
self.keystone_member_role_id = r['id']
|
||||
|
||||
self.keystone.roles.add_user_role(
|
||||
user=user.id,
|
||||
role=self.keystone_member_role_id,
|
||||
tenant=tenant.id)
|
||||
|
||||
# Authenticate demo user with keystone
|
||||
self.keystone_demo = u.authenticate_keystone_user(self.keystone,
|
||||
|
@ -211,6 +224,77 @@ class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
|
|||
password=ks_obj_rel['service_password'],
|
||||
tenant=ks_obj_rel['service_tenant'])
|
||||
|
||||
self.keystone_v3 = None
|
||||
|
||||
def _initialize_keystone_v3(self):
|
||||
u.log.debug('Initializing Keystone v3 tests...')
|
||||
if self.keystone_v3 is not None:
|
||||
u.log.debug('...allready initialized.')
|
||||
return
|
||||
|
||||
se_rels = [(self.keystone_sentry, 'ceph-radosgw:identity-service')]
|
||||
u.keystone_configure_api_version(se_rels, self, 3)
|
||||
|
||||
# Prepare Keystone Client with a domain scoped token for admin user
|
||||
self.keystone_v3 = u.authenticate_keystone(
|
||||
self.keystone_sentry.info['public-address'],
|
||||
'admin', 'openstack', api_version=3,
|
||||
user_domain_name='admin_domain', domain_name='admin_domain'
|
||||
)
|
||||
|
||||
# Create a demo domain, project and user
|
||||
self.demo_domain = 'demoDomain'
|
||||
self.demo_project = 'demoProject'
|
||||
|
||||
try:
|
||||
domain = self.keystone_v3.domains.create(
|
||||
self.demo_domain,
|
||||
description='Demo Domain',
|
||||
enabled=True,
|
||||
)
|
||||
except keystoneclient.exceptions.Conflict:
|
||||
u.log.debug('Domain {} already exists, proceeding.'
|
||||
''.format(self.demo_domain))
|
||||
|
||||
try:
|
||||
project = self.keystone_v3.projects.create(
|
||||
self.demo_project,
|
||||
domain,
|
||||
description='Demo Project',
|
||||
enabled=True,
|
||||
)
|
||||
except keystoneclient.exceptions.Conflict:
|
||||
u.log.debug('Project {} already exists in domain {}, proceeding.'
|
||||
''.format(self.demo_project, domain.name))
|
||||
|
||||
try:
|
||||
user = self.keystone_v3.users.create(
|
||||
self.demo_user,
|
||||
domain=domain.id,
|
||||
project=self.demo_project,
|
||||
password='password',
|
||||
email='demov3@demo.com',
|
||||
description='Demo v3',
|
||||
enabled=True,
|
||||
)
|
||||
except keystoneclient.exceptions.Conflict:
|
||||
u.log.debug('User {} already exists in domain {}, proceeding.'
|
||||
''.format(self.demo_user, domain.name))
|
||||
self.keystone_v3.roles.grant(self.keystone_member_role_id,
|
||||
user=user.id,
|
||||
project=project.id)
|
||||
|
||||
# Prepare Keystone Client with a project scoped token for demo user
|
||||
self.keystone_demo_v3 = u.authenticate_keystone(
|
||||
self.keystone_sentry.info['public-address'],
|
||||
self.demo_user, 'password', api_version=3,
|
||||
user_domain_name=self.demo_domain,
|
||||
project_domain_name=self.demo_domain,
|
||||
project_name=self.demo_project,
|
||||
)
|
||||
|
||||
u.log.debug('OK')
|
||||
|
||||
def test_100_ceph_processes(self):
|
||||
"""Verify that the expected service processes are running
|
||||
on each ceph unit."""
|
||||
|
@ -519,6 +603,69 @@ class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
|
|||
assert('content-type' in headers.keys())
|
||||
assert(containers == [])
|
||||
|
||||
def test_403_swift_keystone_auth(self, api_version=2):
|
||||
"""Check Swift Object Storage functionlaity"""
|
||||
u.log.debug('Check Swift Object Storage functionality (api_version={})'
|
||||
''.format(api_version))
|
||||
keystone_ip = self.keystone_sentry.info['public-address']
|
||||
base_ep = "http://{}:5000".format(keystone_ip.strip().decode('utf-8'))
|
||||
if api_version == 3:
|
||||
self._initialize_keystone_v3()
|
||||
ep = base_ep + '/v3'
|
||||
os_options = {
|
||||
'user_domain_name': self.demo_domain,
|
||||
'project_domain_name': self.demo_domain,
|
||||
'project_name': self.demo_project,
|
||||
}
|
||||
conn = swiftclient.client.Connection(
|
||||
authurl=ep,
|
||||
user=self.demo_user,
|
||||
key='password',
|
||||
os_options=os_options,
|
||||
auth_version=api_version,
|
||||
)
|
||||
else:
|
||||
ep = base_ep + '/v2.0'
|
||||
conn = swiftclient.client.Connection(
|
||||
authurl=ep,
|
||||
user=self.demo_user,
|
||||
key='password',
|
||||
tenant_name=self.demo_tenant,
|
||||
auth_version=api_version,
|
||||
)
|
||||
u.log.debug('Create container')
|
||||
container = 'demo-container'
|
||||
try:
|
||||
conn.put_container(container)
|
||||
except swiftclient.exceptions.ClientException as e:
|
||||
if api_version == 3 and e.http_status == 409:
|
||||
# Ceph RadosGW is currently configured with a global namespace
|
||||
# for container names. Make use of this to verify that we
|
||||
# cannot create a container with a name already taken by a
|
||||
# same username authenticated in different domain in the
|
||||
# previous run of this function. If / when we support per
|
||||
# tenant namespace this logic must be replaced.
|
||||
u.log.debug('v3 user not allowed to overwrite previously '
|
||||
'created container created by v2 user...OK')
|
||||
container = 'demo-container-v3'
|
||||
conn.put_container(container)
|
||||
else:
|
||||
raise(e)
|
||||
|
||||
resp_headers, containers = conn.get_account()
|
||||
if (len(containers) and 'name' in containers[0] and
|
||||
containers[0]['name'] == container):
|
||||
u.log.debug('OK')
|
||||
else:
|
||||
amulet.raise_status(amulet.FAIL, 'container not created {} {}'
|
||||
''.format(resp_headers, containers))
|
||||
|
||||
def test_403_swift_keystone_auth_v3(self):
|
||||
if self._get_openstack_release() >= self.trusty_liberty:
|
||||
self.test_403_swift_keystone_auth(api_version=3)
|
||||
else:
|
||||
u.log.debug('Skipping test for openstack_release < trusty_liberty')
|
||||
|
||||
def test_498_radosgw_cmds_exit_zero(self):
|
||||
"""Check basic functionality of radosgw cli commands against
|
||||
the ceph_radosgw unit."""
|
||||
|
@ -570,7 +717,6 @@ class CephRadosGwBasicDeployment(OpenStackAmuletDeployment):
|
|||
assert self._wait_on_action(action_id), "Resume action failed."
|
||||
assert u.status_get(unit)[0] == "active"
|
||||
u.log.debug('OK')
|
||||
# Note(beisner): need to add basic object store functional checks.
|
||||
|
||||
# FYI: No restart check as ceph services do not restart
|
||||
# when charm config changes, unless monitor count increases.
|
||||
|
|
|
@ -73,7 +73,7 @@ class IdentityServiceContextTest(CharmTestCase):
|
|||
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'log')
|
||||
def test_ids_ctxt(self, _log, _rids, _runits, _rget, _ctxt_comp,
|
||||
_format_ipv6_addr):
|
||||
_format_ipv6_addr, jewel_installed=False):
|
||||
self.test_config.set('operator-roles', 'Babel')
|
||||
self.test_config.set('cache-size', '42')
|
||||
self.test_config.set('revocation-check-interval', '7500000')
|
||||
|
@ -84,6 +84,9 @@ class IdentityServiceContextTest(CharmTestCase):
|
|||
_rids.return_value = 'rid1'
|
||||
_runits.return_value = 'runit'
|
||||
_ctxt_comp.return_value = True
|
||||
self.cmp_pkgrevno.return_value = -1
|
||||
if jewel_installed:
|
||||
self.cmp_pkgrevno.return_value = 0
|
||||
id_data = {
|
||||
'service_port': 9876,
|
||||
'service_host': '127.0.0.4',
|
||||
|
@ -114,8 +117,13 @@ class IdentityServiceContextTest(CharmTestCase):
|
|||
'service_protocol': 'http',
|
||||
'user_roles': 'Babel',
|
||||
}
|
||||
if jewel_installed:
|
||||
expect['auth_keystone_v3_supported'] = True
|
||||
self.assertEqual(expect, ids_ctxt())
|
||||
|
||||
def test_ids_ctxt_jewel(self):
|
||||
self.test_ids_ctxt(jewel_installed=True)
|
||||
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'format_ipv6_addr')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'context_complete')
|
||||
@patch.object(charmhelpers.contrib.openstack.context, 'relation_get')
|
||||
|
|
Loading…
Reference in New Issue