Use secure path join

Change-Id: If0eeef8b025b1f3be863728a8def81d944873ac5
Closes-bug: #1729214
This commit is contained in:
Stan Lagun 2017-11-01 00:11:48 -07:00
parent 52218ef398
commit de53ba8f9a
7 changed files with 64 additions and 24 deletions

View File

@ -10,10 +10,9 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import yaml
from murano.common.helpers import path
from murano.packages import exceptions
from murano.packages import package_base
@ -136,9 +135,9 @@ class CloudifyToscaPackage(package_base.PackageBase):
}
def _get_inputs_outputs(self):
path = os.path.join(
entry_point_path = path.secure_join(
self.source_directory, RESOURCES_DIR_NAME, self._entry_point)
with open(path) as blueprint:
with open(entry_point_path) as blueprint:
data = yaml.safe_load(blueprint)
return data.get('inputs') or {}, data.get('outputs') or {}

View File

@ -0,0 +1,33 @@
# Copyright (c) 2017 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.
import os.path
def secure_join(*parts):
"""Secure version of os.path.join(*parts)
Joins pathname components and ensures that with each join the result
is a subdirectory of the previous join
"""
new = prev = ""
for part in parts:
new = os.path.normpath(os.path.join(prev, part))
if len(new) <= len(prev) or prev != "" and not new.startswith(
prev + os.path.sep):
raise ValueError('path {0} is not allowed {1}'.format(
os.path.join(*parts), parts))
prev = new
return new

View File

@ -19,6 +19,7 @@ import sys
import six
import yaml
from murano.common.helpers import path
from murano.packages import exceptions
from murano.packages import package_base
@ -76,7 +77,8 @@ class HotPackage(package_base.PackageBase):
return self._translated_class, '<generated code>'
def _translate_class(self):
template_file = os.path.join(self._source_directory, 'template.yaml')
template_file = path.secure_join(
self._source_directory, 'template.yaml')
if not os.path.isfile(template_file):
raise exceptions.PackageClassLoadError(
@ -92,9 +94,8 @@ class HotPackage(package_base.PackageBase):
'Extends': 'io.murano.Application'
}
hot_envs_path = os.path.join(self._source_directory,
RESOURCES_DIR_NAME,
HOT_ENV_DIR_NAME)
hot_envs_path = path.secure_join(
self._source_directory, RESOURCES_DIR_NAME, HOT_ENV_DIR_NAME)
# if using hot environments, doing parameter validation with contracts
# will overwrite the parameters in the hot environment.
@ -190,9 +191,8 @@ class HotPackage(package_base.PackageBase):
@staticmethod
def _translate_files(source_directory):
hot_files_path = os.path.join(source_directory,
RESOURCES_DIR_NAME,
HOT_FILES_DIR_NAME)
hot_files_path = path.secure_join(
source_directory, RESOURCES_DIR_NAME, HOT_FILES_DIR_NAME)
return HotPackage._build_hot_resources(hot_files_path)
@ -202,7 +202,7 @@ class HotPackage(package_base.PackageBase):
if os.path.isdir(basedir):
for root, _, files in os.walk(os.path.abspath(basedir)):
for f in files:
full_path = os.path.join(root, f)
full_path = path.secure_join(root, f)
relative_path = os.path.relpath(full_path, basedir)
result.append(relative_path)
return result
@ -517,7 +517,8 @@ class HotPackage(package_base.PackageBase):
return app
def _translate_ui(self):
template_file = os.path.join(self._source_directory, 'template.yaml')
template_file = path.secure_join(
self._source_directory, 'template.yaml')
if not os.path.isfile(template_file):
raise exceptions.PackageClassLoadError(

View File

@ -22,6 +22,7 @@ import zipfile
import six
import yaml
from murano.common.helpers import path
from murano.common.plugins import package_types_loader
import murano.packages.exceptions as e
import murano.packages.hot_package
@ -76,14 +77,14 @@ def load_from_file(archive_path, target_dir=None, drop_dir=False):
shutil.rmtree(target_dir)
else:
for f in os.listdir(target_dir):
os.unlink(os.path.join(target_dir, f))
os.unlink(path.secure_join(target_dir, f))
def load_from_dir(source_directory, filename='manifest.yaml'):
if not os.path.isdir(source_directory) or not os.path.exists(
source_directory):
raise e.PackageLoadError('Invalid package directory')
full_path = os.path.join(source_directory, filename)
full_path = path.secure_join(source_directory, filename)
if not os.path.isfile(full_path):
raise e.PackageLoadError('Unable to find package manifest')

View File

@ -14,6 +14,7 @@
import os
from murano.common.helpers import path
from murano.packages import exceptions
from murano.packages import package_base
@ -34,7 +35,8 @@ class MuranoPlPackage(package_base.PackageBase):
@property
def ui(self):
full_path = os.path.join(self._source_directory, 'UI', self._ui_file)
full_path = path.secure_join(
self._source_directory, 'UI', self._ui_file)
if not os.path.isfile(full_path):
return None
with open(full_path, 'rb') as stream:
@ -49,7 +51,8 @@ class MuranoPlPackage(package_base.PackageBase):
raise exceptions.PackageClassLoadError(
name, 'Class not defined in package ' + self.full_name)
def_file = self._classes[name]
full_path = os.path.join(self._source_directory, 'Classes', def_file)
full_path = path.secure_join(
self._source_directory, 'Classes', def_file)
if not os.path.isfile(full_path):
raise exceptions.PackageClassLoadError(
name, 'File with class definition not found')

View File

@ -20,6 +20,8 @@ import zipfile
import six
from murano.common.helpers import path
class PackageType(object):
Library = 'Library'
@ -114,11 +116,11 @@ class Package(object):
raise NotImplementedError()
def _zip_dir(path, zip_file):
for root, _, files in os.walk(path):
def _zip_dir(base, zip_file):
for root, _, files in os.walk(base):
for f in files:
abs_path = os.path.join(root, f)
relative_path = os.path.relpath(abs_path, path)
abs_path = path.secure_join(root, f)
relative_path = os.path.relpath(abs_path, base)
zip_file.write(abs_path, relative_path)

View File

@ -22,6 +22,7 @@ import sys
import semantic_version
import six
from murano.common.helpers import path
from murano.common.i18n import _
from murano.packages import exceptions
from murano.packages import package
@ -119,13 +120,13 @@ class PackageBase(package.Package):
self._supplier.get('Logo'), 'supplier_logo.png', 'supplier logo')
def get_resource(self, name):
resources_dir = os.path.join(self._source_directory, 'Resources')
resources_dir = path.secure_join(self._source_directory, 'Resources')
if not os.path.exists(resources_dir):
os.makedirs(resources_dir)
return os.path.join(resources_dir, name)
return path.secure_join(resources_dir, name)
def _load_image(self, file_name, default_name, what_image):
full_path = os.path.join(
full_path = path.secure_join(
self._source_directory, file_name or default_name)
if not os.path.isfile(full_path) and not file_name:
return