Rework service broker authorization process
Now we can use keystonemiddleware and murano context middleware for requests from outside OpenStack so we don't need to recreate keystoneclient for each request and can easily get token from the request headers. That makes authorization proccess a lot easier in terms of source code. Change-Id: If937501074b85d43921fdb108f8af3babeded828 Closes-Bug: #1512254
This commit is contained in:
parent
b985627eaa
commit
c508be37a2
@ -1,5 +1,5 @@
|
||||
[pipeline:cloudfoundry]
|
||||
pipeline = cloudfoundryapi
|
||||
pipeline = request_id ssl ext_context authtoken context cloudfoundryapi
|
||||
|
||||
[pipeline:murano]
|
||||
pipeline = request_id ssl versionnegotiation faultwrap authtoken context rootapp
|
||||
|
@ -1,28 +0,0 @@
|
||||
# Copyright (c) 2015 Mirantis, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from keystoneclient.v3 import client
|
||||
from oslo_config import cfg
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def authenticate(user, password, tenant=None):
|
||||
project_name = tenant or CONF.cfapi.tenant
|
||||
keystone = client.Client(username=user,
|
||||
password=password,
|
||||
project_name=project_name,
|
||||
auth_url=CONF.cfapi.auth_url.replace(
|
||||
'v2.0', 'v3'))
|
||||
return keystone
|
@ -12,7 +12,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import base64
|
||||
import json
|
||||
import uuid
|
||||
|
||||
@ -20,13 +19,10 @@ import muranoclient.client as client
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import six
|
||||
from webob import exc
|
||||
from webob import response
|
||||
|
||||
from murano.api.v1.cloudfoundry import auth as keystone_auth
|
||||
from murano.common.i18n import _LI
|
||||
from murano.common import wsgi
|
||||
from murano import context
|
||||
from murano.db.catalog import api as db_api
|
||||
from murano.db.services import cf_connections as db_cf
|
||||
|
||||
@ -64,21 +60,6 @@ class Controller(object):
|
||||
srv['plans'] = [plan]
|
||||
return srv
|
||||
|
||||
def _check_auth(self, req, tenant=None):
|
||||
auth = req.headers.get('Authorization', None)
|
||||
if auth is None:
|
||||
raise exc.HTTPUnauthorized(explanation='Bad credentials')
|
||||
|
||||
auth_info = auth.split(' ')[1]
|
||||
auth_decoded = base64.b64decode(auth_info)
|
||||
user = auth_decoded.split(':')[0]
|
||||
password = auth_decoded.split(':')[1]
|
||||
if tenant:
|
||||
keystone = keystone_auth.authenticate(user, password, tenant)
|
||||
else:
|
||||
keystone = keystone_auth.authenticate(user, password)
|
||||
return (user, password, keystone)
|
||||
|
||||
def _make_service(self, name, package, plan_id):
|
||||
id = uuid.uuid4().hex
|
||||
|
||||
@ -94,13 +75,9 @@ class Controller(object):
|
||||
return None
|
||||
|
||||
def list(self, req):
|
||||
user, _, keystone = self._check_auth(req)
|
||||
# Once we get here we were authorized by keystone
|
||||
token = keystone.auth_token
|
||||
|
||||
ctx = context.RequestContext(user=user, tenant='', auth_token=token)
|
||||
|
||||
packages = db_api.package_search({'type': 'application'}, ctx,
|
||||
packages = db_api.package_search({'type': 'application'},
|
||||
req.context,
|
||||
catalog=True)
|
||||
services = []
|
||||
for package in packages:
|
||||
@ -135,19 +112,13 @@ class Controller(object):
|
||||
try:
|
||||
tenant = db_cf.get_tenant_for_org(org_guid)
|
||||
except AttributeError:
|
||||
# FIXME(Kezar): need to find better way to get tenant
|
||||
tenant = CONF.cfapi.tenant
|
||||
tenant = req.headers['X-Project-Id']
|
||||
db_cf.set_tenant_for_org(org_guid, tenant)
|
||||
LOG.info(_LI("Cloud Foundry {org_id} mapped to tenant "
|
||||
"{tenant_name}").format(org_id=org_guid,
|
||||
tenant_name=tenant))
|
||||
|
||||
# Now as we have all parameters we can try to auth user in actual
|
||||
# tenant
|
||||
|
||||
user, _, keystone = self._check_auth(req, tenant)
|
||||
# Once we get here we were authorized by keystone
|
||||
token = keystone.auth_token
|
||||
token = req.headers['X-Auth-Token']
|
||||
m_cli = muranoclient(token)
|
||||
try:
|
||||
environment_id = db_cf.get_environment_for_space(space_guid)
|
||||
@ -160,11 +131,7 @@ class Controller(object):
|
||||
.format(space_id=space_guid,
|
||||
environment_id=environment_id))
|
||||
|
||||
LOG.debug('Keystone endpoint: {0}'.format(keystone.auth_ref))
|
||||
tenant_id = keystone.project_id
|
||||
ctx = context.RequestContext(user=user, tenant=tenant_id)
|
||||
|
||||
package = db_api.package_get(service_id, ctx)
|
||||
package = db_api.package_get(service_id, req.context)
|
||||
LOG.debug('Adding service {name}'.format(name=package.name))
|
||||
|
||||
service = self._make_service(space_guid, package, plan_id)
|
||||
@ -198,10 +165,7 @@ class Controller(object):
|
||||
|
||||
service_id = service.service_id
|
||||
environment_id = service.environment_id
|
||||
tenant = service.tenant
|
||||
_, _, keystone = self._check_auth(req, tenant)
|
||||
# Once we get here we were authorized by keystone
|
||||
token = keystone.auth_token
|
||||
token = req.headers['X-Auth-Token']
|
||||
m_cli = muranoclient(token)
|
||||
|
||||
session_id = create_session(m_cli, environment_id)
|
||||
@ -217,10 +181,7 @@ class Controller(object):
|
||||
|
||||
service_id = db_service.service_id
|
||||
environment_id = db_service.environment_id
|
||||
tenant = db_service.tenant
|
||||
_, _, keystone = self._check_auth(req, tenant)
|
||||
# Once we get here we were authorized by keystone
|
||||
token = keystone.auth_token
|
||||
token = req.headers['X-Auth-Token']
|
||||
m_cli = muranoclient(token)
|
||||
|
||||
session_id = create_session(m_cli, environment_id)
|
||||
@ -250,10 +211,7 @@ class Controller(object):
|
||||
def get_last_operation(self, req, instance_id):
|
||||
service = db_cf.get_service_for_instance(instance_id)
|
||||
env_id = service.environment_id
|
||||
tenant = service.tenant
|
||||
_, _, keystone = self._check_auth(req, tenant)
|
||||
# Once we get here we were authorized by keystone
|
||||
token = keystone.auth_token
|
||||
token = req.headers["X-Auth-Token"]
|
||||
m_cli = muranoclient(token)
|
||||
|
||||
# NOTE(starodubcevna): we can track only environment status. it's
|
||||
@ -276,6 +234,7 @@ class Controller(object):
|
||||
|
||||
|
||||
def muranoclient(token_id):
|
||||
# TODO(starodubcevna): I guess it can be done better.
|
||||
endpoint = "http://{murano_host}:{murano_port}".format(
|
||||
murano_host=CONF.bind_host, murano_port=CONF.bind_port)
|
||||
insecure = False
|
||||
|
@ -29,12 +29,12 @@ class TestController(base.MuranoTestCase):
|
||||
|
||||
self.request = mock.MagicMock()
|
||||
self.request.headers = {'Authorization': 'Basic {encoded}'.format(
|
||||
encoded=base64.b64encode('test:test'))}
|
||||
encoded=base64.b64encode('test:test')), 'X-Auth-Token': 'foo-bar',
|
||||
'X-Project-Id': 'bar-baz'}
|
||||
|
||||
@mock.patch('murano.common.policy.check_is_admin')
|
||||
@mock.patch('murano.db.catalog.api.package_search')
|
||||
@mock.patch('murano.api.v1.cloudfoundry.auth.authenticate')
|
||||
def test_list(self, mock_auth, mock_db_search, mock_policy):
|
||||
def test_list(self, mock_db_search, mock_policy):
|
||||
|
||||
pkg0 = mock.MagicMock()
|
||||
pkg0.id = 'xxx'
|
||||
@ -64,8 +64,7 @@ class TestController(base.MuranoTestCase):
|
||||
@mock.patch('murano.db.services.cf_connections.set_instance_for_service')
|
||||
@mock.patch('murano.db.services.cf_connections.get_environment_for_space')
|
||||
@mock.patch('murano.db.services.cf_connections.get_tenant_for_org')
|
||||
@mock.patch('murano.api.v1.cloudfoundry.auth.authenticate')
|
||||
def test_provision_from_scratch(self, mock_auth, mock_get_tenant,
|
||||
def test_provision_from_scratch(self, mock_get_tenant,
|
||||
mock_get_environment, mock_is, mock_client,
|
||||
mock_package, mock_policy):
|
||||
|
||||
@ -93,8 +92,7 @@ class TestController(base.MuranoTestCase):
|
||||
@mock.patch('murano.db.services.cf_connections.set_tenant_for_org')
|
||||
@mock.patch('murano.db.services.cf_connections.get_environment_for_space')
|
||||
@mock.patch('murano.db.services.cf_connections.get_tenant_for_org')
|
||||
@mock.patch('murano.api.v1.cloudfoundry.auth.authenticate')
|
||||
def test_provision_existent(self, mock_auth, mock_get_tenant,
|
||||
def test_provision_existent(self, mock_get_tenant,
|
||||
mock_get_environment, mock_set_tenant,
|
||||
mock_set_environment, mock_is, mock_client,
|
||||
mock_package, mock_policy):
|
||||
@ -116,9 +114,8 @@ class TestController(base.MuranoTestCase):
|
||||
self.assertIsInstance(resp, response.Response)
|
||||
|
||||
@mock.patch('murano.api.v1.cloudfoundry.cfapi.muranoclient')
|
||||
@mock.patch('murano.api.v1.cloudfoundry.auth.authenticate')
|
||||
@mock.patch('murano.db.services.cf_connections.get_service_for_instance')
|
||||
def test_deprovision(self, mock_get_si, mock_auth, mock_client):
|
||||
def test_deprovision(self, mock_get_si, mock_client):
|
||||
service = mock.MagicMock()
|
||||
service.service_id = '111-111'
|
||||
service.tenant_id = '222-222'
|
||||
@ -131,8 +128,7 @@ class TestController(base.MuranoTestCase):
|
||||
|
||||
@mock.patch('murano.api.v1.cloudfoundry.cfapi.muranoclient')
|
||||
@mock.patch('murano.db.services.cf_connections.get_service_for_instance')
|
||||
@mock.patch('murano.api.v1.cloudfoundry.auth.authenticate')
|
||||
def test_bind(self, mock_auth, mock_get_si, mock_client):
|
||||
def test_bind(self, mock_get_si, mock_client):
|
||||
service = mock.MagicMock()
|
||||
service.service_id = '111-111'
|
||||
service.tenant_id = '222-222'
|
||||
|
Loading…
Reference in New Issue
Block a user