Allow enforcing usage of "raw" definitions

Since the chage 72a6bc1ad1 was merged,
mistralclient tries to determine if the value passed in is a definition
file path name or file URI, or the actual definition.
However this behavior causes problem when the client is used in server
side and results in allowing access to server files or any contents
in internal servers.

This change introduces the new enforce_raw_definitions variable to
disable that fallback behavior and ensure that client treats input
as raw contents.

Related-Bug: #1931558
Change-Id: I47931bdf8bbccb940d4c98c47f16a6eef27c026a
This commit is contained in:
Takashi Kajinami 2021-07-15 23:06:40 +09:00
parent 18fff747b5
commit ab54cb9ae5
8 changed files with 49 additions and 36 deletions

View File

@ -19,6 +19,8 @@ from oslo_serialization import jsonutils
from keystoneauth1 import exceptions
from mistralclient import utils
urlparse = urllib.parse
@ -73,8 +75,15 @@ def extract_json(response, response_key):
class ResourceManager(object):
resource_class = None
def __init__(self, http_client):
def __init__(self, http_client, enforce_raw_definitions=False):
self.http_client = http_client
self.enforce_raw_definitions = enforce_raw_definitions
def get_contents_if_file(self, contents_or_file_name):
if self.enforce_raw_definitions:
return contents_or_file_name
else:
return utils.get_contents_if_file(contents_or_file_name)
def find(self, **kwargs):
return [i for i in self.list() if _check_items(i, kwargs.items())]

View File

@ -14,7 +14,6 @@
# limitations under the License.
from mistralclient.api import base
from mistralclient import utils
class Action(base.Resource):
@ -29,7 +28,7 @@ class ActionManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
url = '/actions?scope=%s' % scope
if namespace:
@ -56,7 +55,7 @@ class ActionManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._update(
url,
@ -101,7 +100,7 @@ class ActionManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._validate(
'/actions/validate',

View File

@ -41,10 +41,27 @@ _DEFAULT_MISTRAL_URL = "http://localhost:8989/v2"
class Client(object):
MANAGERS = {
'workbooks': workbooks.WorkbookManager,
'executions': executions.ExecutionManager,
'tasks': tasks.TaskManager,
'actions': actions.ActionManager,
'workflows': workflows.WorkflowManager,
'cron_triggers': cron_triggers.CronTriggerManager,
'event_triggers': event_triggers.EventTriggerManager,
'environments': environments.EnvironmentManager,
'action_executions': action_executions.ActionExecutionManager,
'services': services.ServiceManager,
'members': members.MemberManager,
'code_sources': code_sources.CodeSourceManager,
'dynamic_actions': dynamic_actions.DynamicActionManager,
}
def __init__(self, auth_type='keystone', **kwargs):
# We get the session at this point, as some instances of session
# objects might have mutexes that can't be deep-copied.
session = kwargs.pop('session', None)
enforce_raw_definitions = kwargs.pop('enforce_raw_definitions', False)
req = copy.deepcopy(kwargs)
mistral_url = req.get('mistral_url')
profile = req.get('profile')
@ -77,22 +94,6 @@ class Client(object):
http_client = httpclient.HTTPClient(mistral_url, session=session,
**req)
# Create all resource managers.
self.workbooks = workbooks.WorkbookManager(http_client)
self.executions = executions.ExecutionManager(http_client)
self.tasks = tasks.TaskManager(http_client)
self.actions = actions.ActionManager(http_client)
self.workflows = workflows.WorkflowManager(http_client)
self.cron_triggers = cron_triggers.CronTriggerManager(http_client)
self.event_triggers = event_triggers.EventTriggerManager(http_client)
self.environments = environments.EnvironmentManager(http_client)
self.action_executions = action_executions.ActionExecutionManager(
http_client
)
self.services = services.ServiceManager(http_client)
self.members = members.MemberManager(http_client)
self.code_sources = code_sources.CodeSourceManager(http_client)
self.dynamic_actions = dynamic_actions.DynamicActionManager(
http_client
)
for name, cls in self.MANAGERS.items():
setattr(self, name, cls(http_client, enforce_raw_definitions))

View File

@ -13,7 +13,6 @@
# limitations under the License.
from mistralclient.api import base
from mistralclient import utils
class CodeSource(base.Resource):
@ -27,7 +26,7 @@ class CodeSourceManager(base.ResourceManager):
self._ensure_not_empty(name=name, content=content)
# If the specified content is actually a file, read from it.
content = utils.get_contents_if_file(content)
content = self.get_contents_if_file(content)
return self._create(
'/code_sources?name=%s&scope=%s&namespace=%s' %
@ -41,7 +40,7 @@ class CodeSourceManager(base.ResourceManager):
self._ensure_not_empty(identifier=identifier, content=content)
# If the specified content is actually a file, read from it.
content = utils.get_contents_if_file(content)
content = self.get_contents_if_file(content)
return self._update(
'/code_sources?identifier=%s&scope=%s&namespace=%s' %

View File

@ -43,7 +43,7 @@ class EnvironmentManager(base.ResourceManager):
# read it's contents first.
if 'file' in kwargs:
file = kwargs['file']
kwargs = utils.load_content(utils.get_contents_if_file(file))
kwargs = utils.load_content(self.get_contents_if_file(file))
self._ensure_not_empty(name=kwargs.get('name', None),
variables=kwargs.get('variables', None))
@ -59,7 +59,7 @@ class EnvironmentManager(base.ResourceManager):
# read it's contents first.
if 'file' in kwargs:
file = kwargs['file']
kwargs = utils.load_content(utils.get_contents_if_file(file))
kwargs = utils.load_content(self.get_contents_if_file(file))
name = kwargs.get('name', None)
self._ensure_not_empty(name=name)

View File

@ -14,7 +14,6 @@
# limitations under the License.
from mistralclient.api import base
from mistralclient import utils
class Workbook(base.Resource):
@ -44,7 +43,7 @@ class WorkbookManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._create(
self._get_workbooks_url(None, namespace, scope),
@ -58,7 +57,7 @@ class WorkbookManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._update(
self._get_workbooks_url(None, namespace, scope),
@ -100,7 +99,7 @@ class WorkbookManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._validate(
'/workbooks/validate',

View File

@ -14,7 +14,6 @@
# limitations under the License.
from mistralclient.api import base
from mistralclient import utils
class Workflow(base.Resource):
@ -29,7 +28,7 @@ class WorkflowManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._create(
'/workflows?scope=%s&namespace=%s' % (scope, namespace),
@ -47,7 +46,7 @@ class WorkflowManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
is_iter_resp = True
response_key = 'workflows'
@ -106,7 +105,7 @@ class WorkflowManager(base.ResourceManager):
# If the specified definition is actually a file, read in the
# definition file
definition = utils.get_contents_if_file(definition)
definition = self.get_contents_if_file(definition)
return self._validate(
'/workflows/validate',

View File

@ -0,0 +1,7 @@
---
features:
- |
The new ``enforce_raw_definitions`` variable has been added to
the ``Client`` class and each ``ResourceManager`` class. This variable is
set to False by default. Setting this parameter to True enforces the client
to use ``definition`` passed in as raw content.