Working on secure DB access (part 3)
* Moving method get_project_id() to services/security.py Change-Id: Id4a166a754c1eda24280e7454530339b43243cb3
This commit is contained in:
parent
14a7b44bb0
commit
9fcbfbe2f9
@ -23,7 +23,7 @@ from sqlalchemy import event
|
|||||||
from sqlalchemy.ext import declarative
|
from sqlalchemy.ext import declarative
|
||||||
from sqlalchemy.orm import attributes
|
from sqlalchemy.orm import attributes
|
||||||
|
|
||||||
from mistral.db import v2 as db_base
|
from mistral.services import security
|
||||||
|
|
||||||
|
|
||||||
def _generate_unicode_uuid():
|
def _generate_unicode_uuid():
|
||||||
@ -90,11 +90,11 @@ class MistralSecureModelBase(MistralModelBase):
|
|||||||
__abstract__ = True
|
__abstract__ = True
|
||||||
|
|
||||||
scope = sa.Column(sa.String(80), default='private')
|
scope = sa.Column(sa.String(80), default='private')
|
||||||
project_id = sa.Column(sa.String(80), default=db_base.get_project_id)
|
project_id = sa.Column(sa.String(80), default=security.get_project_id)
|
||||||
|
|
||||||
|
|
||||||
def _set_project_id(target, value, oldvalue, initiator):
|
def _set_project_id(target, value, oldvalue, initiator):
|
||||||
return db_base.get_project_id()
|
return security.get_project_id()
|
||||||
|
|
||||||
|
|
||||||
def register_secure_model_hooks():
|
def register_secure_model_hooks():
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
# Copyright 2014 - 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 oslo.config import cfg
|
|
||||||
|
|
||||||
from mistral import context as auth_context
|
|
||||||
|
|
||||||
|
|
||||||
# Make sure to import 'auth_enable' option before using it.
|
|
||||||
cfg.CONF.import_opt('auth_enable', 'mistral.config', group='pecan')
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
DEFAULT_PROJECT_ID = "<default-project>"
|
|
||||||
|
|
||||||
|
|
||||||
def get_project_id():
|
|
||||||
if CONF.pecan.auth_enable and auth_context.has_ctx():
|
|
||||||
return auth_context.ctx().project_id
|
|
||||||
else:
|
|
||||||
return DEFAULT_PROJECT_ID
|
|
@ -21,11 +21,10 @@ from oslo.db import exception as db_exc
|
|||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from mistral.db.sqlalchemy import base as b
|
from mistral.db.sqlalchemy import base as b
|
||||||
from mistral.db import v2 as db_base
|
|
||||||
from mistral.db.v2.sqlalchemy import models
|
from mistral.db.v2.sqlalchemy import models
|
||||||
from mistral import exceptions as exc
|
from mistral import exceptions as exc
|
||||||
from mistral.openstack.common import log as logging
|
from mistral.openstack.common import log as logging
|
||||||
|
from mistral.services import security
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
@ -94,7 +93,7 @@ def _get_collection_sorted_by_name(model, **kwargs):
|
|||||||
query = b.model_query(model)
|
query = b.model_query(model)
|
||||||
|
|
||||||
proj = query.filter_by(
|
proj = query.filter_by(
|
||||||
project_id=db_base.get_project_id(),
|
project_id=security.get_project_id(),
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
public = query.filter_by(scope='public', **kwargs)
|
public = query.filter_by(scope='public', **kwargs)
|
||||||
@ -106,7 +105,7 @@ def _get_collection_sorted_by_time(model, **kwargs):
|
|||||||
query = b.model_query(model)
|
query = b.model_query(model)
|
||||||
|
|
||||||
return query.filter_by(
|
return query.filter_by(
|
||||||
project_id=db_base.get_project_id(),
|
project_id=security.get_project_id(),
|
||||||
**kwargs
|
**kwargs
|
||||||
).order_by(model.created_at).all()
|
).order_by(model.created_at).all()
|
||||||
|
|
||||||
@ -114,7 +113,7 @@ def _get_collection_sorted_by_time(model, **kwargs):
|
|||||||
def _get_db_object_by_name(model, name):
|
def _get_db_object_by_name(model, name):
|
||||||
query = b.model_query(model)
|
query = b.model_query(model)
|
||||||
|
|
||||||
private = query.filter_by(name=name, project_id=db_base.get_project_id())
|
private = query.filter_by(name=name, project_id=security.get_project_id())
|
||||||
public = query.filter_by(name=name, scope='public')
|
public = query.filter_by(name=name, scope='public')
|
||||||
|
|
||||||
return private.union(public).first()
|
return private.union(public).first()
|
||||||
@ -123,7 +122,7 @@ def _get_db_object_by_name(model, name):
|
|||||||
def _get_db_object_by_id(model, id):
|
def _get_db_object_by_id(model, id):
|
||||||
query = b.model_query(model)
|
query = b.model_query(model)
|
||||||
|
|
||||||
return query.filter_by(id=id, project_id=db_base.get_project_id()).first()
|
return query.filter_by(id=id, project_id=security.get_project_id()).first()
|
||||||
|
|
||||||
|
|
||||||
# Workbooks.
|
# Workbooks.
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
import copy
|
import copy
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from mistral.db import v2 as db_base
|
|
||||||
from mistral.db.v2 import api as db_api
|
from mistral.db.v2 import api as db_api
|
||||||
from mistral.engine1 import base
|
from mistral.engine1 import base
|
||||||
from mistral.engine1 import commands
|
from mistral.engine1 import commands
|
||||||
@ -194,7 +193,6 @@ class DefaultEngine(base.Engine):
|
|||||||
'output': {},
|
'output': {},
|
||||||
'context': copy.copy(wf_input) or {},
|
'context': copy.copy(wf_input) or {},
|
||||||
'parent_task_id': params.get('parent_task_id'),
|
'parent_task_id': params.get('parent_task_id'),
|
||||||
'project_id': db_base.get_project_id()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
data_flow.add_openstack_data_to_context(wf_db, exec_db.context)
|
data_flow.add_openstack_data_to_context(wf_db, exec_db.context)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright 2013 - Mirantis, Inc.
|
# Copyright 2015 - Mirantis, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
from mistral.db.v2 import api as db_api
|
from mistral.db.v2 import api as db_api
|
||||||
from mistral import exceptions as exc
|
from mistral import exceptions as exc
|
||||||
from mistral.services import security
|
|
||||||
from mistral.workbook import parser as spec_parser
|
from mistral.workbook import parser as spec_parser
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +79,4 @@ def _get_action_values(action_spec, definition, scope):
|
|||||||
'scope': scope
|
'scope': scope
|
||||||
}
|
}
|
||||||
|
|
||||||
security.add_project_id(values, scope)
|
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
@ -16,17 +16,31 @@
|
|||||||
|
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from mistral import context
|
from mistral import context as auth_ctx
|
||||||
from mistral.utils.openstack import keystone
|
from mistral.utils.openstack import keystone
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
# Make sure to import 'auth_enable' option before using it.
|
||||||
|
# TODO(rakhmerov): Try to find a better solution.
|
||||||
|
CONF.import_opt('auth_enable', 'mistral.config', group='pecan')
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_PROJECT_ID = "<default-project>"
|
||||||
|
|
||||||
|
|
||||||
|
def get_project_id():
|
||||||
|
if CONF.pecan.auth_enable and auth_ctx.has_ctx():
|
||||||
|
return auth_ctx.ctx().project_id
|
||||||
|
else:
|
||||||
|
return DEFAULT_PROJECT_ID
|
||||||
|
|
||||||
|
|
||||||
def create_trust():
|
def create_trust():
|
||||||
client = keystone.client()
|
client = keystone.client()
|
||||||
|
|
||||||
ctx = context.ctx()
|
ctx = auth_ctx.ctx()
|
||||||
|
|
||||||
trustee_id = keystone.client_for_admin(
|
trustee_id = keystone.client_for_admin(
|
||||||
CONF.keystone_authtoken.admin_tenant_name).user_id
|
CONF.keystone_authtoken.admin_tenant_name).user_id
|
||||||
@ -53,13 +67,13 @@ def create_context(trust_id, project_id):
|
|||||||
if CONF.pecan.auth_enable:
|
if CONF.pecan.auth_enable:
|
||||||
client = keystone.client_for_trusts(trust_id)
|
client = keystone.client_for_trusts(trust_id)
|
||||||
|
|
||||||
return context.MistralContext(
|
return auth_ctx.MistralContext(
|
||||||
user_id=client.user_id,
|
user_id=client.user_id,
|
||||||
project_id=project_id,
|
project_id=project_id,
|
||||||
auth_token=client.auth_token
|
auth_token=client.auth_token
|
||||||
)
|
)
|
||||||
|
|
||||||
return context.MistralContext(
|
return auth_ctx.MistralContext(
|
||||||
user_id=None,
|
user_id=None,
|
||||||
project_id=None,
|
project_id=None,
|
||||||
auth_token=None,
|
auth_token=None,
|
||||||
@ -75,13 +89,6 @@ def delete_trust(workbook):
|
|||||||
keystone_client.trusts.delete(workbook.trust_id)
|
keystone_client.trusts.delete(workbook.trust_id)
|
||||||
|
|
||||||
|
|
||||||
def add_project_id(secure_object_values, scope='private'):
|
|
||||||
if cfg.CONF.pecan.auth_enable and scope == 'private':
|
|
||||||
secure_object_values.update({
|
|
||||||
'project_id': context.ctx().project_id
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def add_trust_id(secure_object_values):
|
def add_trust_id(secure_object_values):
|
||||||
if cfg.CONF.pecan.auth_enable:
|
if cfg.CONF.pecan.auth_enable:
|
||||||
secure_object_values.update({
|
secure_object_values.update({
|
||||||
|
@ -17,7 +17,6 @@ import datetime
|
|||||||
|
|
||||||
from mistral.db.v1 import api as db_api_v1
|
from mistral.db.v1 import api as db_api_v1
|
||||||
from mistral.db.v2 import api as db_api_v2
|
from mistral.db.v2 import api as db_api_v2
|
||||||
from mistral.services import security
|
|
||||||
from mistral.workbook import parser as spec_parser
|
from mistral.workbook import parser as spec_parser
|
||||||
|
|
||||||
|
|
||||||
@ -100,8 +99,6 @@ def create_cron_trigger(name, pattern, workflow_name, workflow_input,
|
|||||||
'scope': 'private'
|
'scope': 'private'
|
||||||
}
|
}
|
||||||
|
|
||||||
security.add_project_id(values)
|
|
||||||
|
|
||||||
trig = db_api_v2.create_cron_trigger(values)
|
trig = db_api_v2.create_cron_trigger(values)
|
||||||
|
|
||||||
return trig
|
return trig
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright 2013 - Mirantis, Inc.
|
# Copyright 2015 - Mirantis, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@ -22,8 +22,6 @@ from mistral.workbook import parser as spec_parser
|
|||||||
|
|
||||||
|
|
||||||
def create_workbook_v1(values, scope='private'):
|
def create_workbook_v1(values, scope='private'):
|
||||||
security.add_project_id(values, scope)
|
|
||||||
|
|
||||||
return db_api_v1.workbook_create(values)
|
return db_api_v1.workbook_create(values)
|
||||||
|
|
||||||
|
|
||||||
@ -115,6 +113,4 @@ def _get_workbook_values(wb_spec, definition, scope):
|
|||||||
'scope': scope
|
'scope': scope
|
||||||
}
|
}
|
||||||
|
|
||||||
security.add_project_id(values, scope)
|
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
@ -70,7 +70,6 @@ def _get_workflow_values(wf_spec, definition, scope):
|
|||||||
'scope': scope
|
'scope': scope
|
||||||
}
|
}
|
||||||
|
|
||||||
security.add_project_id(values, scope)
|
|
||||||
security.add_trust_id(values)
|
security.add_trust_id(values)
|
||||||
|
|
||||||
return values
|
return values
|
||||||
|
@ -79,8 +79,6 @@ class TestWorkbooksController(base.FunctionalTest):
|
|||||||
|
|
||||||
@mock.patch.object(db_api, "workbook_create",
|
@mock.patch.object(db_api, "workbook_create",
|
||||||
mock.MagicMock(side_effect=exceptions.DBDuplicateEntry))
|
mock.MagicMock(side_effect=exceptions.DBDuplicateEntry))
|
||||||
@mock.patch("mistral.services.security.add_project_id",
|
|
||||||
mock.MagicMock(return_value=None))
|
|
||||||
def test_post_dup(self):
|
def test_post_dup(self):
|
||||||
resp = self.app.post_json('/v1/workbooks', WORKBOOKS[0],
|
resp = self.app.post_json('/v1/workbooks', WORKBOOKS[0],
|
||||||
expect_errors=True)
|
expect_errors=True)
|
||||||
|
@ -21,9 +21,9 @@ import datetime
|
|||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from mistral import context as auth_context
|
from mistral import context as auth_context
|
||||||
from mistral.db import v2 as db_base
|
|
||||||
from mistral.db.v2.sqlalchemy import api as db_api
|
from mistral.db.v2.sqlalchemy import api as db_api
|
||||||
from mistral import exceptions as exc
|
from mistral import exceptions as exc
|
||||||
|
from mistral.services import security
|
||||||
from mistral.tests import base as test_base
|
from mistral.tests import base as test_base
|
||||||
|
|
||||||
|
|
||||||
@ -335,8 +335,8 @@ class WorkflowTest(SQLAlchemyTest):
|
|||||||
fetched0 = db_api.load_workflow(created0.name)
|
fetched0 = db_api.load_workflow(created0.name)
|
||||||
fetched1 = db_api.load_workflow(created1.name)
|
fetched1 = db_api.load_workflow(created1.name)
|
||||||
|
|
||||||
self.assertEqual(db_base.get_project_id(), fetched0.project_id)
|
self.assertEqual(security.get_project_id(), fetched0.project_id)
|
||||||
self.assertEqual(db_base.get_project_id(), fetched1.project_id)
|
self.assertEqual(security.get_project_id(), fetched1.project_id)
|
||||||
|
|
||||||
fetched = db_api.get_workflows()
|
fetched = db_api.get_workflows()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user