From 0c5ddf1f6a45ac4abbab02c3eebc024d20932f5e Mon Sep 17 00:00:00 2001 From: mihaTrajbaric <26118837+mihaTrajbaric@users.noreply.github.com> Date: Mon, 17 Jan 2022 12:09:12 +0100 Subject: [PATCH] Add password masking --- .../api/controllers/default_controller.py | 8 ++- .../api/service/image_builder_service.py | 51 ++++++++++++++++--- src/image_builder/api/settings/settings.py | 9 +++- .../api/util/image_builder_util.py | 1 + 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/image_builder/api/controllers/default_controller.py b/src/image_builder/api/controllers/default_controller.py index ffde235..14ceca7 100644 --- a/src/image_builder/api/controllers/default_controller.py +++ b/src/image_builder/api/controllers/default_controller.py @@ -5,7 +5,7 @@ from image_builder.api.log import get_logger from image_builder.api.openapi.models import BuildParams, Invocation, BuildingStarted from image_builder.api.service.invocation_service import InvocationService -from image_builder.api.service.image_builder_service import validate +from image_builder.api.service.image_builder_service import validate, mask_password_inv logger = get_logger(__name__) invocation_service = InvocationService() @@ -23,7 +23,11 @@ def get_status(invocation_id): inv = invocation_service.load_invocation(invocation_id) if not inv: return f"Invocation with ID {invocation_id} not found", 404 - return inv, 200 + try: + return mask_password_inv(inv), 200 + except Exception as e: + logger.error(e) + return inv, 200 def post_build(): diff --git a/src/image_builder/api/service/image_builder_service.py b/src/image_builder/api/service/image_builder_service.py index c6934bc..ef1d7e8 100644 --- a/src/image_builder/api/service/image_builder_service.py +++ b/src/image_builder/api/service/image_builder_service.py @@ -32,13 +32,52 @@ def validate(data: BuildParams): return True, "" +def mask_password_inv(inv: Invocation): + """ + replaces all password values with '****' + """ + if inv.build_params.target.registry.password: + inv.build_params.target.registry.password = '****' + + if inv.build_params.source.git_repo: + if inv.build_params.source.git_repo.password: + inv.build_params.source.git_repo.password = '****' + + if inv.build_params.source.dockerfile: + if inv.build_params.source.dockerfile.password: + inv.build_params.source.dockerfile.password = '****' + + return inv + + +def mask_password(obj: dict): + """ + replaces all password values with '****' + """ + + def replace_in_dict(obj_dict, key, replace_value): + for k, v in obj_dict.items(): + if isinstance(v, dict): + obj_dict[k] = replace_in_dict(v, key, replace_value) + elif isinstance(v, list): + obj_dict[k] = replace_in_list(v, key, replace_value) + if key in obj_dict: + obj_dict[key] = replace_value + return obj_dict + + def replace_in_list(obj_list, key, replace_value): + for i, item in enumerate(obj_list): + if isinstance(item, dict): + obj_list[i] = replace_in_dict(item, key, replace_value) + elif isinstance(item, list): + obj_list[i] = replace_in_list(item, key, replace_value) + return obj_list + + return replace_in_dict(obj, 'password', '****') + + def transform_build_params(data: BuildParams): build_params = data.to_dict() - # if not build_params['target']['registry']: - # logger.debug(f'Changing registry_ip to {Settings.registry_ip}') - # build_params['target']['registry'] = dict(url=Settings.registry_ip) - # else: - # logger.debug(f"Registry_ip={build_params['target']['registry']['url']}") def remove_none_dict(_dict: dict): dict_keys = list(_dict.keys()) @@ -68,7 +107,7 @@ def build_image(inv: Invocation): opera_storage = Storage.create(".opera") service_template = PurePath(workdir) / "docker_image_definition.yaml" build_params = transform_build_params(inv.build_params) - logger.info(json.dumps(build_params)) + logger.info(json.dumps(mask_password(build_params))) opera_deploy(service_template, build_params, opera_storage, verbose_mode=False, num_workers=1, delete_existing_state=True) return opera_outputs(opera_storage) diff --git a/src/image_builder/api/settings/settings.py b/src/image_builder/api/settings/settings.py index 595a705..aec5dbb 100644 --- a/src/image_builder/api/settings/settings.py +++ b/src/image_builder/api/settings/settings.py @@ -1,6 +1,7 @@ import json import os from pathlib import Path +import copy from image_builder.api.log import get_logger @@ -38,12 +39,16 @@ def load_settings(): 'connect_timeout': int(os.getenv("IMAGEBUILDER_DATABASE_TIMEOUT", '3')) } + # prepare sql_config for printing + __debug_sql_config = copy.deepcopy(Settings.sql_config) + __debug_sql_config['password'] = '****' + logger.debug(json.dumps({ "oicd_config": { "introspection_endpoint": Settings.oidc_introspection_endpoint_uri, "client_id": Settings.oidc_client_id, - "client_secret": Settings.oidc_client_secret, + "client_secret": Settings.oidc_client_secret if Settings.oidc_client_secret == "" else "****", }, "auth_api_key": Settings.apiKey, - "sql_config": Settings.sql_config, + "sql_config": __debug_sql_config, }, indent=2)) diff --git a/src/image_builder/api/util/image_builder_util.py b/src/image_builder/api/util/image_builder_util.py index e834cc2..57af86f 100644 --- a/src/image_builder/api/util/image_builder_util.py +++ b/src/image_builder/api/util/image_builder_util.py @@ -3,6 +3,7 @@ from contextlib import contextmanager from pathlib import Path from uuid import UUID +from datetime import datetime @contextmanager