Fix support for Keystone v3 API
Swift proxy is currently rejecting valid v3 tokens because it is failing to validate them due to its credentials being in the v2 format and missing domain information. This change examines the version of the API keystone has advertised down the identity-service relation and configures the proxy conf appropriately Change-Id: Id2215168ffbad1caf0e7203ded26c41913181306 Closes-Bug: 1624304
This commit is contained in:
		@@ -139,7 +139,7 @@ class SwiftIdentityContext(OSContextGenerator):
 | 
			
		||||
                'auth_port': config('keystone-auth-port'),
 | 
			
		||||
                'service_user': admin_user,
 | 
			
		||||
                'service_password': admin_password,
 | 
			
		||||
                'service_tenant': config('keystone-admin-tenant-name')
 | 
			
		||||
                'service_tenant': config('keystone-admin-tenant-name'),
 | 
			
		||||
            }
 | 
			
		||||
            ctxt.update(ks_auth)
 | 
			
		||||
 | 
			
		||||
@@ -168,7 +168,14 @@ class SwiftIdentityContext(OSContextGenerator):
 | 
			
		||||
                                                 unit, relid),
 | 
			
		||||
                    'admin_token': relation_get('admin_token',
 | 
			
		||||
                                                unit, relid),
 | 
			
		||||
                    'api_version': relation_get('api_version',
 | 
			
		||||
                                                unit, relid) or '2',
 | 
			
		||||
                }
 | 
			
		||||
                if ks_auth['api_version'] == '3':
 | 
			
		||||
                    ks_auth['admin_domain_id'] = relation_get(
 | 
			
		||||
                        '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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -82,9 +82,19 @@ operator_roles = {{ operator_roles }}
 | 
			
		||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
 | 
			
		||||
identity_uri = {{ auth_protocol }}://{{ keystone_host }}:{{ auth_port }}
 | 
			
		||||
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}
 | 
			
		||||
{% if api_version == '3' -%}
 | 
			
		||||
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 }}
 | 
			
		||||
{% else -%}
 | 
			
		||||
admin_tenant_name = {{ service_tenant }}
 | 
			
		||||
admin_user = {{ service_user }}
 | 
			
		||||
admin_password = {{ service_password }}
 | 
			
		||||
{% endif -%}
 | 
			
		||||
delay_auth_decision = {{ delay_auth_decision|lower }}
 | 
			
		||||
signing_dir = {{ signing_dir }}
 | 
			
		||||
cache = swift.cache
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,78 @@ with mock.patch('charmhelpers.core.hookenv.config'):
 | 
			
		||||
    import lib.swift_context as swift_context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SwiftIdentityContextTest(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    @mock.patch('lib.swift_context.relation_get')
 | 
			
		||||
    @mock.patch('lib.swift_context.related_units')
 | 
			
		||||
    @mock.patch('lib.swift_context.relation_ids')
 | 
			
		||||
    @mock.patch('lib.swift_context.IdentityServiceContext')
 | 
			
		||||
    @mock.patch('lib.swift_context.determine_api_port')
 | 
			
		||||
    @mock.patch('lib.swift_context.unit_get')
 | 
			
		||||
    @mock.patch('lib.swift_context.get_host_ip')
 | 
			
		||||
    @mock.patch('lib.swift_context.config')
 | 
			
		||||
    def test_context_api_v2(self, mock_config, mock_get_host_ip,
 | 
			
		||||
                            mock_unit_get, mock_determine_api_port,
 | 
			
		||||
                            mock_IdentityServiceContext, mock_relation_ids,
 | 
			
		||||
                            mock_related_units, mock_relation_get):
 | 
			
		||||
        _relinfo = {
 | 
			
		||||
            'auth_protocol': 'http',
 | 
			
		||||
            'service_protocol': 'http',
 | 
			
		||||
            'auth_host': 'kshost',
 | 
			
		||||
            'service_host': 'kshost',
 | 
			
		||||
            'auth_port': '5000',
 | 
			
		||||
            'service_username': 'svcuser',
 | 
			
		||||
            'service_password': 'svcpasswd',
 | 
			
		||||
            'service_tenant': 'svctenant',
 | 
			
		||||
            'service_port': 'svcport',
 | 
			
		||||
            'admin_token': 'token',
 | 
			
		||||
            'api_version': None,
 | 
			
		||||
        }
 | 
			
		||||
        mock_config.return_value = None
 | 
			
		||||
        mock_relation_ids.return_value = ['rid1']
 | 
			
		||||
        mock_related_units.return_value = ['ksunit/0']
 | 
			
		||||
        mock_relation_get.side_effect = lambda x, y, z: _relinfo[x]
 | 
			
		||||
        ctxt = swift_context.SwiftIdentityContext()
 | 
			
		||||
        self.assertEqual(ctxt()['api_version'], '2')
 | 
			
		||||
 | 
			
		||||
    @mock.patch('lib.swift_context.relation_get')
 | 
			
		||||
    @mock.patch('lib.swift_context.related_units')
 | 
			
		||||
    @mock.patch('lib.swift_context.relation_ids')
 | 
			
		||||
    @mock.patch('lib.swift_context.IdentityServiceContext')
 | 
			
		||||
    @mock.patch('lib.swift_context.determine_api_port')
 | 
			
		||||
    @mock.patch('lib.swift_context.unit_get')
 | 
			
		||||
    @mock.patch('lib.swift_context.get_host_ip')
 | 
			
		||||
    @mock.patch('lib.swift_context.config')
 | 
			
		||||
    def test_context_api_v3(self, mock_config, mock_get_host_ip,
 | 
			
		||||
                            mock_unit_get, mock_determine_api_port,
 | 
			
		||||
                            mock_IdentityServiceContext, mock_relation_ids,
 | 
			
		||||
                            mock_related_units, mock_relation_get):
 | 
			
		||||
        _relinfo = {
 | 
			
		||||
            'auth_protocol': 'http',
 | 
			
		||||
            'service_protocol': 'http',
 | 
			
		||||
            'auth_host': 'kshost',
 | 
			
		||||
            'service_host': 'kshost',
 | 
			
		||||
            'auth_port': '5000',
 | 
			
		||||
            'service_username': 'svcuser',
 | 
			
		||||
            'service_password': 'svcpasswd',
 | 
			
		||||
            'service_tenant': 'svctenant',
 | 
			
		||||
            'service_port': 'svcport',
 | 
			
		||||
            'admin_token': 'token',
 | 
			
		||||
            'api_version': '3',
 | 
			
		||||
            'admin_domain_id': 'admin_dom_id',
 | 
			
		||||
            'service_tenant_id': 'svc_tenant_id',
 | 
			
		||||
        }
 | 
			
		||||
        self.maxDiff = None
 | 
			
		||||
        mock_relation_ids.return_value = ['rid1']
 | 
			
		||||
        mock_related_units.return_value = ['ksunit/0']
 | 
			
		||||
        mock_relation_get.side_effect = lambda x, y, z: _relinfo[x]
 | 
			
		||||
        mock_config.return_value = None
 | 
			
		||||
        ctxt = swift_context.SwiftIdentityContext()
 | 
			
		||||
        self.assertEqual(ctxt()['api_version'], '3')
 | 
			
		||||
        self.assertEqual(ctxt()['admin_domain_id'], 'admin_dom_id')
 | 
			
		||||
        self.assertEqual(ctxt()['service_tenant_id'], 'svc_tenant_id')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SwiftContextTestCase(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    @mock.patch('lib.swift_context.config')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user