From 6ed3d526156947783e94ab442e3a74967bbc74bd Mon Sep 17 00:00:00 2001 From: DQ Date: Fri, 30 Aug 2019 13:40:49 +0800 Subject: [PATCH] Fix: prepare permission issue 1. recursivele change ownership for all prepare dir 2. database file permission fix Signed-off-by: DQ --- make/photon/prepare/g.py | 2 +- make/photon/prepare/utils/cert.py | 15 +++++++-- make/photon/prepare/utils/chart.py | 23 +++++++------ make/photon/prepare/utils/core.py | 12 ++++--- make/photon/prepare/utils/db.py | 2 +- make/photon/prepare/utils/misc.py | 48 ++++++++++++++++++++------- make/photon/prepare/utils/registry.py | 4 ++- 7 files changed, 73 insertions(+), 33 deletions(-) diff --git a/make/photon/prepare/g.py b/make/photon/prepare/g.py index 229f61a54..14ec20975 100644 --- a/make/photon/prepare/g.py +++ b/make/photon/prepare/g.py @@ -19,7 +19,7 @@ templates_dir = "/usr/src/app/templates" config_dir = '/config' data_dir = '/data' secret_dir = '/secret' -secret_key_dir='/secret/keys' +secret_key_dir = '/secret/keys' old_private_key_pem_path = Path('/config/core/private_key.pem') old_crt_path = Path('/config/registry/root.crt') diff --git a/make/photon/prepare/utils/cert.py b/make/photon/prepare/utils/cert.py index 8be25a8fd..3ba42861a 100644 --- a/make/photon/prepare/utils/cert.py +++ b/make/photon/prepare/utils/cert.py @@ -4,8 +4,11 @@ from pathlib import Path from subprocess import DEVNULL from functools import wraps -from .misc import mark_file -from .misc import generate_random_string +from g import DEFAULT_GID, DEFAULT_UID +from .misc import ( + mark_file, + generate_random_string, + check_permission) SSL_CERT_PATH = os.path.join("/etc/cert", "server.crt") SSL_CERT_KEY_PATH = os.path.join("/etc/cert", "server.key") @@ -101,4 +104,10 @@ def prepare_ca( mark_file(root_crt_path) else: shutil.move(old_crt_path, root_crt_path) - shutil.move(old_private_key_pem_path, private_key_pem_path) \ No newline at end of file + shutil.move(old_private_key_pem_path, private_key_pem_path) + + if not check_permission(root_crt_path, uid=DEFAULT_UID, gid=DEFAULT_GID): + os.chown(root_crt_path, DEFAULT_UID, DEFAULT_GID) + + if not check_permission(private_key_pem_path, uid=DEFAULT_UID, gid=DEFAULT_GID): + os.chown(private_key_pem_path, DEFAULT_UID, DEFAULT_GID) \ No newline at end of file diff --git a/make/photon/prepare/utils/chart.py b/make/photon/prepare/utils/chart.py index ace5e7acf..d3f1d1faa 100644 --- a/make/photon/prepare/utils/chart.py +++ b/make/photon/prepare/utils/chart.py @@ -1,17 +1,19 @@ import os, shutil -from g import templates_dir, config_dir +from g import templates_dir, config_dir, data_dir, DEFAULT_UID, DEFAULT_GID from .jinja import render_jinja +from .misc import prepare_dir -chartm_temp_dir = os.path.join(templates_dir, "chartserver") -chartm_env_temp = os.path.join(chartm_temp_dir, "env.jinja") +chart_museum_temp_dir = os.path.join(templates_dir, "chartserver") +chart_museum_env_temp = os.path.join(chart_museum_temp_dir, "env.jinja") -chartm_config_dir = os.path.join(config_dir, "chartserver") -chartm_env = os.path.join(config_dir, "chartserver", "env") +chart_museum_config_dir = os.path.join(config_dir, "chartserver") +chart_museum_env = os.path.join(config_dir, "chartserver", "env") + +chart_museum_data_dir = os.path.join(data_dir, 'chart_storage') def prepare_chartmuseum(config_dict): - core_secret = config_dict['core_secret'] redis_host = config_dict['redis_host'] redis_port = config_dict['redis_port'] redis_password = config_dict['redis_password'] @@ -19,9 +21,8 @@ def prepare_chartmuseum(config_dict): storage_provider_name = config_dict['storage_provider_name'] storage_provider_config_map = config_dict['storage_provider_config'] - if not os.path.isdir(chartm_config_dir): - print ("Create config folder: %s" % chartm_config_dir) - os.makedirs(chartm_config_dir) + prepare_dir(chart_museum_data_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) + prepare_dir(chart_museum_config_dir) # process redis info cache_store = "redis" @@ -94,8 +95,8 @@ def prepare_chartmuseum(config_dict): all_storage_provider_configs = ('\n').join(storage_provider_config_options) render_jinja( - chartm_env_temp, - chartm_env, + chart_museum_env_temp, + chart_museum_env, cache_store=cache_store, cache_redis_addr=cache_redis_addr, cache_redis_password=cache_redis_password, diff --git a/make/photon/prepare/utils/core.py b/make/photon/prepare/utils/core.py index 5da6fc6fa..ca6ff7ed8 100644 --- a/make/photon/prepare/utils/core.py +++ b/make/photon/prepare/utils/core.py @@ -1,6 +1,6 @@ import shutil, os -from g import config_dir, templates_dir +from g import config_dir, templates_dir, data_dir, DEFAULT_GID, DEFAULT_UID from utils.misc import prepare_dir, generate_random_string from utils.jinja import render_jinja @@ -10,8 +10,14 @@ core_conf_env = os.path.join(config_dir, "core", "env") core_conf_template_path = os.path.join(templates_dir, "core", "app.conf.jinja") core_conf = os.path.join(config_dir, "core", "app.conf") +ca_download_dir = os.path.join(data_dir, 'ca_download') +psc_dir = os.path.join(data_dir, 'psc') + + def prepare_core(config_dict, with_notary, with_clair, with_chartmuseum): - prepare_core_config_dir() + prepare_dir(psc_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) + prepare_dir(ca_download_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) + prepare_dir(core_config_dir) # Render Core # set cache for chart repo server # default set 'memory' mode, if redis is configured then set to 'redis' @@ -32,8 +38,6 @@ def prepare_core(config_dict, with_notary, with_clair, with_chartmuseum): # Copy Core app.conf copy_core_config(core_conf_template_path, core_conf) -def prepare_core_config_dir(): - prepare_dir(core_config_dir) def copy_core_config(core_templates_path, core_config_path): shutil.copyfile(core_templates_path, core_config_path) diff --git a/make/photon/prepare/utils/db.py b/make/photon/prepare/utils/db.py index 30b7e050d..eb88360e0 100644 --- a/make/photon/prepare/utils/db.py +++ b/make/photon/prepare/utils/db.py @@ -10,7 +10,7 @@ db_conf_env = os.path.join(config_dir, "db", "env") database_data_path = os.path.join(data_dir, 'database') def prepare_db(config_dict): - prepare_dir(database_data_path, uid=PG_UID, gid=PG_GID) + prepare_dir(database_data_path, uid=PG_UID, gid=PG_GID, mode=0o700) prepare_dir(db_config_dir) render_jinja( db_env_template_path, diff --git a/make/photon/prepare/utils/misc.py b/make/photon/prepare/utils/misc.py index e7b62faff..5ced50799 100644 --- a/make/photon/prepare/utils/misc.py +++ b/make/photon/prepare/utils/misc.py @@ -1,9 +1,10 @@ import os import string import random +from pathlib import Path from g import DEFAULT_UID, DEFAULT_GID -from pathlib import Path + # To meet security requirement # By default it will change file mode to 0600, and make the owner of the file to 10000:10000 @@ -78,19 +79,18 @@ def generate_random_string(length): return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length)) -def prepare_config_dir(root, *name): - absolute_path = os.path.join(root, *name) - if not os.path.exists(absolute_path): - os.makedirs(absolute_path) - return absolute_path - def prepare_dir(root: str, *args, **kwargs) -> str: gid, uid = kwargs.get('gid'), kwargs.get('uid') absolute_path = Path(os.path.join(root, *args)) if absolute_path.is_file(): raise Exception('Path exists and the type is regular file') mode = kwargs.get('mode') or 0o755 - absolute_path.mkdir(mode, parents=True, exist_ok=True) + + # we need make sure this dir has the right permission + if not absolute_path.exists(): + absolute_path.mkdir(mode=mode, parents=True) + elif not check_permission(absolute_path, mode=mode): + absolute_path.chmod(mode) # if uid or gid not None, then change the ownership of this dir if not(gid is None and uid is None): @@ -99,7 +99,10 @@ def prepare_dir(root: str, *args, **kwargs) -> str: uid = dir_uid if gid is None: gid = dir_gid - os.chown(absolute_path, uid, gid) + # We decide to recursively chown only if the dir is not owned by correct user + # to save time if the dir is extremely large + if not check_permission(absolute_path, uid, gid): + recursive_chown(absolute_path, uid, gid) return str(absolute_path) @@ -113,6 +116,27 @@ def delfile(src): except Exception as e: print(e) elif os.path.isdir(src): - for item in os.listdir(src): - itemsrc = os.path.join(src, item) - delfile(itemsrc) \ No newline at end of file + for dir_name in os.listdir(src): + dir_path = os.path.join(src, dir_name) + delfile(dir_path) + + +def recursive_chown(path, uid, gid): + os.chown(path, uid, gid) + for root, dirs, files in os.walk(path): + for d in dirs: + os.chown(os.path.join(root, d), uid, gid) + for f in files: + os.chown(os.path.join(root, f), uid, gid) + + +def check_permission(path: str, uid:int = None, gid:int = None, mode:int = None): + if not isinstance(path, Path): + path = Path(path) + if uid is not None and uid != path.stat().st_uid: + return False + if gid is not None and gid != path.stat().st_gid: + return False + if mode is not None and (path.stat().st_mode - mode) % 0o1000 != 0: + return False + return True diff --git a/make/photon/prepare/utils/registry.py b/make/photon/prepare/utils/registry.py index 2a3512d9b..564a39111 100644 --- a/make/photon/prepare/utils/registry.py +++ b/make/photon/prepare/utils/registry.py @@ -1,6 +1,6 @@ import os, copy -from g import config_dir, templates_dir, DEFAULT_GID, DEFAULT_UID +from g import config_dir, templates_dir, DEFAULT_GID, DEFAULT_UID, data_dir from utils.misc import prepare_dir from utils.jinja import render_jinja @@ -8,6 +8,7 @@ from utils.jinja import render_jinja registry_config_dir = os.path.join(config_dir, "registry") registry_config_template_path = os.path.join(templates_dir, "registry", "config.yml.jinja") registry_conf = os.path.join(config_dir, "registry", "config.yml") +registry_data_dir = os.path.join(data_dir, 'registry') levels_map = { 'debug': 'debug', @@ -18,6 +19,7 @@ levels_map = { } def prepare_registry(config_dict): + prepare_dir(registry_data_dir, uid=DEFAULT_UID, gid=DEFAULT_GID) prepare_dir(registry_config_dir) storage_provider_info = get_storage_provider_info(