From d7ffb543336b53edfad8203ccd9ae7d4cba63ad9 Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Thu, 28 Jun 2018 16:56:33 -0400 Subject: [PATCH] Move tar filter to file, add tests for it --- config_app/config_endpoints/api/suconfig.py | 6 +++- .../config_endpoints/api/tar_config_loader.py | 16 ++-------- config_app/config_util/tar.py | 14 +++++++++ config_app/config_util/test/test_tar.py | 29 +++++++++++++++++++ .../download-tarball-modal.component.html | 14 +++++---- .../download-tarball-modal.css | 11 +++++-- .../js/core-config-setup/core-config-setup.js | 12 ++++---- util/config/validator.py | 9 ++++-- util/config/validators/validate_storage.py | 4 +++ 9 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 config_app/config_util/tar.py create mode 100644 config_app/config_util/test/test_tar.py diff --git a/config_app/config_endpoints/api/suconfig.py b/config_app/config_endpoints/api/suconfig.py index 9e17701ab..97bd2a39d 100644 --- a/config_app/config_endpoints/api/suconfig.py +++ b/config_app/config_endpoints/api/suconfig.py @@ -271,11 +271,15 @@ class SuperUserConfigValidate(ApiResource): # Note: This method is called to validate the database configuration before super users exists, # so we also allow it to be called if there is no valid registry configuration setup. Note that # this is also safe since this method does not access any information not given in the request. + + # We can skip localstorage validation, since we can't guarantee that this will be the same machine + # Q.E. will run under config = request.get_json()['config'] validator_context = ValidatorContext.from_app(app, config, request.get_json().get('password', ''), instance_keys=instance_keys, ip_resolver=ip_resolver, - config_provider=config_provider) + config_provider=config_provider, + skip_localstorage_validation=True) return validate_service_for_config(service, validator_context) diff --git a/config_app/config_endpoints/api/tar_config_loader.py b/config_app/config_endpoints/api/tar_config_loader.py index 011de5531..9cde0f68f 100644 --- a/config_app/config_endpoints/api/tar_config_loader.py +++ b/config_app/config_endpoints/api/tar_config_loader.py @@ -5,10 +5,10 @@ import tarfile from flask import request, make_response, send_file from data.database import configure -from util.config.validator import EXTRA_CA_DIRECTORY from config_app.c_app import app, config_provider from config_app.config_endpoints.api import resource, ApiResource, nickname +from config_app.config_util.tar import tarinfo_filter_partial @resource('/v1/configapp/initialization') class ConfigInitialization(ApiResource): @@ -17,7 +17,7 @@ class ConfigInitialization(ApiResource): """ @nickname('scStartNewConfig') - def get(self): + def post(self): config_provider.new_config_dir() return make_response('OK') @@ -37,22 +37,12 @@ class TarConfigLoader(ApiResource): # remove the initial trailing / from the prefix path, and add the last dir one tar_dir_prefix = config_path[1:] + '/' - def tarinfo_filter(tarinfo): - # remove leading directory info - tarinfo.name = tarinfo.name.replace(tar_dir_prefix, '') - - # ignore any directory that isn't the specified extra ca one: - if tarinfo.isdir() and not tarinfo.name == EXTRA_CA_DIRECTORY: - return None - - return tarinfo - temp = tempfile.NamedTemporaryFile() tar = tarfile.open(temp.name, mode="w|gz") for name in os.listdir(config_path): - tar.add(os.path.join(config_path, name), filter=tarinfo_filter) + tar.add(os.path.join(config_path, name), filter=tarinfo_filter_partial(tar_dir_prefix)) tar.close() diff --git a/config_app/config_util/tar.py b/config_app/config_util/tar.py new file mode 100644 index 000000000..379bdfae1 --- /dev/null +++ b/config_app/config_util/tar.py @@ -0,0 +1,14 @@ +from util.config.validator import EXTRA_CA_DIRECTORY + +def tarinfo_filter_partial(prefix): + def tarinfo_filter(tarinfo): + # remove leading directory info + tarinfo.name = tarinfo.name.replace(prefix, '') + + # ignore any directory that isn't the specified extra ca one: + if tarinfo.isdir() and not tarinfo.name == EXTRA_CA_DIRECTORY: + return None + + return tarinfo + + return tarinfo_filter diff --git a/config_app/config_util/test/test_tar.py b/config_app/config_util/test/test_tar.py new file mode 100644 index 000000000..432501e82 --- /dev/null +++ b/config_app/config_util/test/test_tar.py @@ -0,0 +1,29 @@ +import pytest + +from config_app.config_util.tar import tarinfo_filter_partial + +from util.config.validator import EXTRA_CA_DIRECTORY + +from test.fixtures import * + +class MockTarInfo: + def __init__(self, name, isdir): + self.name = name + self.isdir = lambda: isdir + + def __eq__(self, other): + return other is not None and self.name == other.name + +@pytest.mark.parametrize('prefix,tarinfo,expected', [ + # It should handle simple files + ('Users/sam/', MockTarInfo('Users/sam/config.yaml', False), MockTarInfo('config.yaml', False)), + # It should allow the extra CA dir + ('Users/sam/', MockTarInfo('Users/sam/%s' % EXTRA_CA_DIRECTORY, True), MockTarInfo('%s' % EXTRA_CA_DIRECTORY, True)), + # it should allow a file in that extra dir + ('Users/sam/', MockTarInfo('Users/sam/%s/cert.crt' % EXTRA_CA_DIRECTORY, False), MockTarInfo('%s/cert.crt' % EXTRA_CA_DIRECTORY, False)), + # it should not allow a directory that isn't the CA dir + ('Users/sam/', MockTarInfo('Users/sam/dirignore', True), None), +]) +def test_tarinfo_filter(prefix, tarinfo, expected): + partial = tarinfo_filter_partial(prefix) + assert partial(tarinfo) == expected diff --git a/config_app/js/components/download-tarball-modal/download-tarball-modal.component.html b/config_app/js/components/download-tarball-modal/download-tarball-modal.component.html index 89898455f..dfc95c578 100644 --- a/config_app/js/components/download-tarball-modal/download-tarball-modal.component.html +++ b/config_app/js/components/download-tarball-modal/download-tarball-modal.component.html @@ -8,15 +8,17 @@ -