Merge "Rework service broker authorization process"
This commit is contained in:
@@ -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'
|
||||
|
Reference in New Issue
Block a user