Skip to content

Commit

Permalink
Fix Keystone v3 auth for swift-proxy
Browse files Browse the repository at this point in the history
No need for refresh of proxy-server.conf template for Mitaka. Update
template for Kilo and later to make use of domain_name and project_name
parameters instead of domain_id and project_id parameters.

The current template sets up auth to user in default domain
but project in service domain. This does not work with service
domain layout.

Do not request configured operator_roles roles from Keystone. From
which roles swift-proxy should accept requests are still configured
in proxy-server.conf, but requesting and setting up these roles for
the s3_swift user in Keystone is incorrect behaviour.

Register required relation data for identity-service immediatelly when
relation to 'identity-service' exists. Do not postpone registration
until context is complete which may cause the swift-proxy unit marking
itself ready while still being in a unconfigured state.

Add tests to verify configuration and operation of swift-proxy when
using Keystone v3 auth.

Change-Id: I8bf182a9256f96af50e4cc37505d9c0ca3d62e47
Closes-Bug: 1646765
  • Loading branch information
fnordahl committed Dec 8, 2016
1 parent c4cd069 commit 7c24ae8
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 20 deletions.
3 changes: 1 addition & 2 deletions hooks/swift_hooks.py
Expand Up @@ -194,15 +194,14 @@ def keystone_joined(relid=None):
public_url = ('%s:%s/v1/AUTH_$(tenant_id)s' %
(canonical_url(CONFIGS, PUBLIC), port))
region = config('region')
roles = config('operator-roles')

s3_public_url = ('%s:%s' %
(canonical_url(CONFIGS, PUBLIC), port))
s3_internal_url = ('%s:%s' %
(canonical_url(CONFIGS, INTERNAL), port))
s3_admin_url = '%s:%s' % (canonical_url(CONFIGS, ADMIN), port)

relation_set(requested_roles=roles, relation_id=relid,
relation_set(relation_id=relid,
region=None, public_url=None,
internal_url=None, admin_url=None, service=None,
swift_service='swift', swift_region=region,
Expand Down
8 changes: 5 additions & 3 deletions lib/swift_context.py
Expand Up @@ -14,7 +14,6 @@
from charmhelpers.contrib.openstack.context import (
OSContextGenerator,
ApacheSSLContext as SSLContext,
context_complete,
IdentityServiceContext,
)
from charmhelpers.contrib.hahelpers.cluster import (
Expand Down Expand Up @@ -183,8 +182,11 @@ def __call__(self):
'admin_domain_id', unit, relid)
ks_auth['service_tenant_id'] = relation_get(
'service_tenant_id', unit, relid)
if context_complete(ks_auth):
ctxt.update(ks_auth)
ks_auth['admin_domain_name'] = relation_get(
'service_domain', unit, relid)
ks_auth['admin_tenant_name'] = relation_get(
'service_tenant', unit, relid)
ctxt.update(ks_auth)

if config('prefer-ipv6'):
for key in ['keystone_host', 'service_host']:
Expand Down
6 changes: 3 additions & 3 deletions templates/kilo/proxy-server.conf
Expand Up @@ -87,9 +87,9 @@ auth_plugin = password
auth_url = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}
username = {{ service_user }}
password = {{ service_password }}
user_domain_name = default
project_id = {{ service_tenant_id }}
project_domain_id = {{ admin_domain_id }}
project_domain_name = {{ admin_domain_name }}
user_domain_name = {{ admin_domain_name }}
project_name = {{ admin_tenant_name }}
{% else -%}
admin_tenant_name = {{ service_tenant }}
admin_user = {{ service_user }}
Expand Down
92 changes: 82 additions & 10 deletions tests/basic_deployment.py
Expand Up @@ -14,6 +14,7 @@

import amulet
import swiftclient
import time

from charmhelpers.contrib.openstack.amulet.deployment import (
OpenStackAmuletDeployment
Expand Down Expand Up @@ -275,7 +276,6 @@ def test_200_swift_proxy_identity_service_relation(self):
's3_internal_url': u.valid_url,
's3_admin_url': u.valid_url,
'private-address': u.valid_ip,
'requested_roles': 'Member,Admin',
}

ret = u.validate_relation_data(unit, relation, expected)
Expand Down Expand Up @@ -386,9 +386,10 @@ def test_300_swift_config(self):
message = "swift config error: {}".format(ret)
amulet.raise_status(amulet.FAIL, msg=message)

def test_302_proxy_server_config(self):
def test_302_proxy_server_config(self, auth_api_version='2.0'):
"""Verify the data in the proxy-server config file."""
u.log.debug('Checking swift proxy-server config...')
u.log.debug("Checking swift proxy-server config auth_api_version={}..."
"".format(auth_api_version))
unit = self.swift_proxy_sentry
conf = '/etc/swift/proxy-server.conf'
keystone_relation = self.keystone_sentry.relation(
Expand Down Expand Up @@ -453,26 +454,45 @@ def test_302_proxy_server_config(self):
auth_protocol,
auth_host,
keystone_relation['service_port']),
'admin_tenant_name': keystone_relation['service_tenant'],
'admin_user': keystone_relation['service_username'],
'admin_password': keystone_relation['service_password'],
'delay_auth_decision': 'true',
'signing_dir': '/var/cache/swift',
'cache': 'swift.cache'
},
'filter:swift3': {'use': 'egg:swift3#swift3'}
}
if auth_api_version == '2.0':
expected['filter:authtoken'].update({
'admin_tenant_name': keystone_relation['service_tenant'],
'admin_user': keystone_relation['service_username'],
'admin_password': keystone_relation['service_password'],
})

if self._get_openstack_release() >= self.trusty_kilo:
# Kilo and later
expected['filter:authtoken'].update({
'paste.filter_factory': 'keystonemiddleware.auth_token:'
'filter_factory',
'identity_uri': '{}://{}:{}'.format(
auth_protocol,
auth_host,
keystone_relation['auth_port']),
})
if auth_api_version == '3':
expected['filter:authtoken'].update({
'auth_url': '{}://{}:{}'.format(
auth_protocol,
auth_host,
keystone_relation['auth_port']),
'auth_plugin': 'password',
'username': keystone_relation['service_username'],
'password': keystone_relation['service_password'],
'project_domain_name': keystone_relation['service_domain'],
'user_domain_name': keystone_relation['service_domain'],
'project_name': keystone_relation['service_tenant'],
})
else:
expected['filter:authtoken'].update({
'identity_uri': '{}://{}:{}'.format(
auth_protocol,
auth_host,
keystone_relation['auth_port']),
})
expected['filter:s3token'] = {
# No section commonality with J and earlier
'paste.filter_factory': 'keystonemiddleware.s3_token'
Expand Down Expand Up @@ -553,6 +573,58 @@ def test_400_swift_backed_image_create(self):
u.delete_resource(self.glance.images, img_id, msg="glance image")
u.log.info('OK')

def _set_auth_api_version(self, api_version, retry_count=5):
"""Change Keystone preferred-api-version, wait for: propagation to
relation data, update of service configuration file and restart of
services on swift-proxy unit."""
configs = {'keystone': {'preferred-api-version': api_version}}
super(SwiftProxyBasicDeployment, self)._configure_services(configs)
mtime = u.get_sentry_time(self.swift_proxy_sentry)
for i in range(retry_count, -1, -1):
ks_gl_rel = self.keystone_sentry.relation(
'identity-service', 'glance:identity-service')
ks_sw_rel = self.keystone_sentry.relation(
'identity-service', 'swift-proxy:identity-service')
if not (ks_gl_rel['api_version'] == api_version and
ks_sw_rel['api_version'] == api_version):
u.log.info("change of api_version not propagated yet "
"retries left: '%d' "
"glance:identity-service api_version: '%s' "
"swift-proxy:identity-service api_version: '%s' "
% (i,
ks_gl_rel['api_version'],
ks_sw_rel['api_version']))
u.log.info("sleeping %d seconds..." % i)
time.sleep(i)
elif not u.validate_service_config_changed(
self.swift_proxy_sentry,
mtime,
'swift-proxy-server',
'/etc/swift/proxy-server.conf',
sleep_time=i):
msg = "swift-proxy-server didn't restart after change of "\
"api_version"
amulet.raise_status(amulet.FAIL, msg=msg)
else:
return True
return False

def test_keystone_v3(self):
"""Verify that the service is configured and operates correctly when
using Keystone v3 auth."""
os_release = self._get_openstack_release_string()
if os_release < 'kilo':
u.log.info('Skipping test, {} < kilo'.format(os_release))
return
u.log.info('Checking that service is configured and operate correctly '
'when using Keystine v3 auth...')
if not self._set_auth_api_version('3'):
msg = "Unable to set auth_api_version to '3'"
amulet.raise_status(amulet.FAIL, msg=msg)
return
self.test_302_proxy_server_config(auth_api_version='3')
self.test_400_swift_backed_image_create()

def test_900_restart_on_config_change(self):
"""Verify that the specified services are restarted when the config
is changed."""
Expand Down
3 changes: 3 additions & 0 deletions unit_tests/test_swift_context.py
Expand Up @@ -81,6 +81,7 @@ def test_context_api_v3(self, mock_config, mock_get_host_ip,
'auth_port': '5000',
'service_username': 'svcuser',
'service_password': 'svcpasswd',
'service_domain': 'service_domain',
'service_tenant': 'svctenant',
'service_port': 'svcport',
'admin_token': 'token',
Expand All @@ -97,6 +98,8 @@ def test_context_api_v3(self, mock_config, mock_get_host_ip,
self.assertEqual(ctxt()['api_version'], '3')
self.assertEqual(ctxt()['admin_domain_id'], 'admin_dom_id')
self.assertEqual(ctxt()['service_tenant_id'], 'svc_tenant_id')
self.assertEqual(ctxt()['admin_domain_name'], 'service_domain')
self.assertEqual(ctxt()['admin_tenant_name'], 'svctenant')


class SwiftContextTestCase(unittest.TestCase):
Expand Down
2 changes: 0 additions & 2 deletions unit_tests/test_swift_hooks.py
Expand Up @@ -106,7 +106,6 @@ def foo(key=None):
public_url=None,
region=None,
relation_id=None,
requested_roles='Operator,Monitor',
s3_admin_url='http://swift-proxy:1234',
s3_internal_url='http://swift-proxy:1234',
s3_public_url='http://swift-proxy:1234',
Expand Down Expand Up @@ -163,7 +162,6 @@ def foo(key=None):
public_url=None,
region=None,
relation_id=None,
requested_roles='Operator,Monitor',
s3_admin_url='http://swift-proxy:1234',
s3_internal_url='http://swift-proxy:1234',
s3_public_url='http://public.example.com:1234',
Expand Down

0 comments on commit 7c24ae8

Please sign in to comment.