From 0b61dd0b3160e41cd53f7067ae8d2a26aaa484ce Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Thu, 4 Jun 2026 10:47:06 -0600 Subject: [PATCH 1/6] feat(engine_core): support remote Azure DevOps organization for config retrieval --- .../src/applications/runner_engine_core.py | 53 ++++++++++++++++++- .../driven_adapters/azure/azure_devops.py | 24 ++++++--- .../applications/test_runner_engine_core.py | 12 +++++ .../azuredevopscore/test_azure_devops.py | 29 ++-------- 4 files changed, 85 insertions(+), 33 deletions(-) diff --git a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py index 64fa38c26..c760f675c 100755 --- a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py @@ -260,6 +260,35 @@ def get_inputs_from_cli(args): required=False, help="Address of the Docker daemon to connect to." ) + parser.add_argument( + "--use_remote_org", + choices=["true", "false"], + type=str, + required=False, + default="false", + help="Set to true to use remote organization integration." + ) + parser.add_argument( + "--remote_org", + type=str, + required=False, + default='', + help="Remote organization name (required if --use_remote_org is set)." + ) + parser.add_argument( + "--remote_pat", + type=str, + required=False, + default='', + help="Remote personal access token (required if --use_remote_org is set)." + ) + parser.add_argument( + "--remote_proj", + type=str, + required=False, + default='', + help="Remote project name (required if --use_remote_org is set)." + ) TOOLS = { "engine_iac": ["checkov", "kics", "kubescape"], @@ -274,6 +303,17 @@ def get_inputs_from_cli(args): args = parser.parse_args() + if args.use_remote_org == "true": + missing = [] + if not args.remote_org: + missing.append("--remote_org") + if not args.remote_pat: + missing.append("--remote_pat") + if not args.remote_proj: + missing.append("--remote_proj") + if missing: + parser.error(f"When --use_remote_org is set, the following arguments are required: {', '.join(missing)}") + if args.module in TOOLS and args.tool: allowed_tools = TOOLS[args.module] if allowed_tools is None: @@ -307,11 +347,16 @@ def get_inputs_from_cli(args): "dast_file_path": args.dast_file_path, "context": args.context, "docker_address": args.docker_address, + "use_remote_org": args.use_remote_org, + "remote_org": args.remote_org, + "remote_pat": args.remote_pat, + "remote_proj": args.remote_proj, } def application_core(): tb = True + devops_platform_gateway = None try: # Get inputs from CLI args = get_inputs_from_cli(sys.argv[1:]) @@ -343,7 +388,13 @@ def application_core(): # Activate traceback config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] + args["remote_config_repo"], + "/engine_core/ConfigTool.json", + args["remote_config_branch"], + use_remote_org=args["use_remote_org"] == "true", + remote_org=args["remote_org"], + remote_pat=args["remote_pat"], + remote_proj=args["remote_proj"] ) tb = config_tool.get("TRACEBACK", False) diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py index 0263b7927..255717da4 100644 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py @@ -25,15 +25,23 @@ @dataclass class AzureDevops(DevopsPlatformGateway): - def get_remote_config(self, repository, path, branch=""): - - base_compact_remote_config_url = ( - f"https://{SystemVariables.System_TeamFoundationCollectionUri.value().rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" - f".visualstudio.com/{SystemVariables.System_TeamProject.value()}/_git/" - f"{repository}?path={path}" - ) + def get_remote_config(self, repository, path, branch="", use_remote_org=False, remote_org="", remote_pat="", remote_proj=""): + base_compact_remote_config_url = '' + if use_remote_org: + base_compact_remote_config_url = ( + f"https://{remote_org.rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" + f".visualstudio.com/{remote_proj}/_git/{repository}?path={path}" + ) + pat = remote_pat + else: + base_compact_remote_config_url = ( + f"https://{SystemVariables.System_TeamFoundationCollectionUri.value().rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" + f".visualstudio.com/{SystemVariables.System_TeamProject.value()}/_git/" + f"{repository}?path={path}" + ) + pat = SystemVariables.System_AccessToken.value() utils_azure = AzureDevopsApi( - personal_access_token=SystemVariables.System_AccessToken.value(), + personal_access_token=pat, compact_remote_config_url=base_compact_remote_config_url, ) connection = utils_azure.get_azure_connection() diff --git a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py index f64c6865a..50ffec0d3 100644 --- a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py @@ -118,6 +118,10 @@ def test_get_inputs_from_cli(mock_parse_args): mock_args.token_license_analyzer = None mock_args.use_license_analyzer = "false" mock_args.docker_address = "unix:///var/run/docker.sock" + mock_args.use_remote_org = "false" + mock_args.remote_org = "" + mock_args.remote_pat = "" + mock_args.remote_proj = "" # Mock the parse_args method mock_parse_args.return_value = mock_args @@ -151,6 +155,10 @@ def test_get_inputs_from_cli(mock_parse_args): "token_license_analyzer": None, "use_license_analyzer": "false", "docker_address": "unix:///var/run/docker.sock", + "use_remote_org": "false", + "remote_org": "", + "remote_pat": "", + "remote_proj": "", } @@ -281,6 +289,10 @@ def test_application_core_exception_block( "dast_file_path": None, "context": "false", "docker_address": None, + "use_remote_org": "false", + "remote_org": "", + "remote_pat": "", + "remote_proj": "", } mock_get_inputs_from_cli.return_value = mock_args mock_init_engine_core.side_effect = Exception("simulated error") diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py index 37026b98a..71549fa0f 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py @@ -8,30 +8,26 @@ class TestAzureDevops(unittest.TestCase): + @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.AzureDevopsApi', autospec=True) @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.SystemVariables', autospec=True) def test_get_remote_config(self, mock_system_variables, mock_azure_devops_api): - azure_devops = AzureDevops() - # Set up mock values for SystemVariables mock_system_variables.System_TeamFoundationCollectionUri.value.return_value = "System_TeamFoundationCollectionUri" - # Mock the AzureDevopsApi class mock_azure_devops_api_instance = MagicMock() mock_azure_devops_api_instance.get_azure_connection.return_value = "MockedConnection" mock_azure_devops_api_instance.get_remote_json_config.return_value = {'key': 'value'} mock_azure_devops_api.return_value = mock_azure_devops_api_instance - remote_config_repo = "my_repo" remote_config_path = "my_path" - result = azure_devops.get_remote_config(remote_config_repo, remote_config_path) - + # Llamar con los nuevos argumentos + result = azure_devops.get_remote_config(remote_config_repo, remote_config_path, use_remote_org=False, remote_org="", remote_pat="", remote_proj="") assert result == {"key": "value"} def test_message(self): azure_devops = AzureDevops() - assert azure_devops.message("succeeded", "message") == "##[section]message" assert azure_devops.message("info", "message") == "##[command]message" assert azure_devops.message("warning", "message") == "##[warning]message" @@ -39,7 +35,6 @@ def test_message(self): def test_result_pipeline(self): azure_devops = AzureDevops() - assert azure_devops.result_pipeline("failed") == "##vso[task.complete result=Failed;]DONE" assert azure_devops.result_pipeline("succeeded") == "##vso[task.complete result=Succeeded;]DONE" @@ -47,12 +42,10 @@ def test_result_pipeline(self): @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.BuildVariables', autospec=True) def test_get_source_code_management_uri(self, mock_build_variables, mock_system_variables): azure_devops = AzureDevops() - mock_system_variables.System_TeamFoundationCollectionUri.value.return_value = "System_TeamFoundationCollectionUri" mock_system_variables.System_TeamProject.value.return_value = "Build_Project_Name" mock_build_variables.Build_Repository_Name.value.return_value = "Build_Repository_Name" mock_build_variables.Build_Repository_Provider.value.return_value = "tfsgit" - assert azure_devops.get_source_code_management_uri() == "System_TeamFoundationCollectionUriBuild_Project_Name/_git/Build_Repository_Name" @@ -60,55 +53,42 @@ def test_get_source_code_management_uri(self, mock_build_variables, mock_system_ @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.BuildVariables', autospec=True) def test_get_build_pipeline_execution_url(self, mock_build_variables, mock_system_variables): azure_devops = AzureDevops() - mock_system_variables.System_TeamFoundationCollectionUri.value.return_value = "System_TeamFoundationCollectionUri" mock_system_variables.System_TeamProject.value.return_value = "Build_Project_Name" mock_build_variables.Build_BuildId.value.return_value = "Build_BuildId" - - assert azure_devops.get_build_pipeline_execution_url() == "System_TeamFoundationCollectionUriBuild_Project_Name/_build?buildId=Build_BuildId" + @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.SystemVariables', autospec=True) @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.BuildVariables', autospec=True) @mock.patch('devsecops_engine_tools.engine_core.src.infrastructure.driven_adapters.azure.azure_devops.ReleaseVariables', autospec=True) def test_get_variable(self, mock_release_variables, mock_build_variables, mock_system_variables): azure_devops = AzureDevops() - # Mock the BuildVariables class mock_build_variables.Build_SourceBranchName.value.return_value = "Build_SourceBranchName" mock_build_variables.Build_BuildNumber.value.return_value = "Build_BuildNumber" mock_build_variables.Build_BuildId.value.return_value = "Build_BuildId" mock_build_variables.Build_SourceVersion.value.return_value = "Build_SourceVersion" mock_build_variables.Build_SourceBranch.value.return_value = "Build_SourceBranch" - # Mock the ReleaseVariables class mock_release_variables.Environment.value.return_value = "Environment" mock_release_variables.Release_Releaseid.value.return_value = "Release_ReleaseId" - # Mock the SystemVariables class mock_system_variables.System_AccessToken.value.return_value = "System_AccessToken" - result = azure_devops.get_variable("branch_name") assert result == "Build_SourceBranchName" - result = azure_devops.get_variable("build_id") assert result == "Build_BuildNumber" - result = azure_devops.get_variable("build_execution_id") assert result == "Build_BuildId" - result = azure_devops.get_variable("commit_hash") assert result == "Build_SourceVersion" - result = azure_devops.get_variable("environment") assert result == "Environment" - result = azure_devops.get_variable("release_id") assert result == "Release_ReleaseId" - result = azure_devops.get_variable("branch_tag") assert result == "Build_SourceBranch" - result = azure_devops.get_variable("access_token") assert result == "System_AccessToken" @@ -236,5 +216,6 @@ def test_get_source_code_management_uri_value_error_returns_none(self, mock_buil self.assertIsNone(result) + if __name__ == '__main__': unittest.main() \ No newline at end of file From 017539ce46a9189079b3f0c4f1401689e4b79445 Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Thu, 18 Jun 2026 17:38:18 -0600 Subject: [PATCH 2/6] feat(engine_core): support remote AZ organization for config retrieval --- .../src/applications/runner_engine_core.py | 68 ++++++------------- .../entry_points/entry_point_core.py | 9 ++- .../entry_points/test_entry_point_core.py | 10 ++- .../runner_engine_integrations.py | 17 +++++ .../entry_points/entry_point_integrations.py | 9 ++- 5 files changed, 61 insertions(+), 52 deletions(-) diff --git a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py index c760f675c..bd2afdc4b 100755 --- a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py @@ -37,6 +37,8 @@ import sys import argparse import traceback +import os +import json from devsecops_engine_tools.engine_utilities.dependency_track.infrastructure.driver_adapters.dependency_track import DependencyTrack from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger from devsecops_engine_tools.engine_utilities import settings @@ -64,6 +66,20 @@ def parse_with_choices(value): return parse_with_choices +def build_remote_context(): + organization = os.environ.get("DET_REMOTE_ORG", "") + project = os.environ.get("DET_REMOTE_PROJ", "") + token = os.environ.get("DET_REMOTE_TOKEN", "") + github_repository = os.environ.get("DET_GITHUB_REPOSITORY", "") + + return { + "organization": organization, + "project": project, + "token": token, + "github_repository": github_repository, + } + + def get_inputs_from_cli(args): parser = argparse.ArgumentParser() parser.add_argument( @@ -260,36 +276,6 @@ def get_inputs_from_cli(args): required=False, help="Address of the Docker daemon to connect to." ) - parser.add_argument( - "--use_remote_org", - choices=["true", "false"], - type=str, - required=False, - default="false", - help="Set to true to use remote organization integration." - ) - parser.add_argument( - "--remote_org", - type=str, - required=False, - default='', - help="Remote organization name (required if --use_remote_org is set)." - ) - parser.add_argument( - "--remote_pat", - type=str, - required=False, - default='', - help="Remote personal access token (required if --use_remote_org is set)." - ) - parser.add_argument( - "--remote_proj", - type=str, - required=False, - default='', - help="Remote project name (required if --use_remote_org is set)." - ) - TOOLS = { "engine_iac": ["checkov", "kics", "kubescape"], "engine_secret": ["trufflehog", "gitleaks", "all_tools"], @@ -303,17 +289,6 @@ def get_inputs_from_cli(args): args = parser.parse_args() - if args.use_remote_org == "true": - missing = [] - if not args.remote_org: - missing.append("--remote_org") - if not args.remote_pat: - missing.append("--remote_pat") - if not args.remote_proj: - missing.append("--remote_proj") - if missing: - parser.error(f"When --use_remote_org is set, the following arguments are required: {', '.join(missing)}") - if args.module in TOOLS and args.tool: allowed_tools = TOOLS[args.module] if allowed_tools is None: @@ -347,10 +322,6 @@ def get_inputs_from_cli(args): "dast_file_path": args.dast_file_path, "context": args.context, "docker_address": args.docker_address, - "use_remote_org": args.use_remote_org, - "remote_org": args.remote_org, - "remote_pat": args.remote_pat, - "remote_proj": args.remote_proj, } @@ -360,6 +331,8 @@ def application_core(): try: # Get inputs from CLI args = get_inputs_from_cli(sys.argv[1:]) + remote_context = build_remote_context() + args["remote_context"] = remote_context # Define driven adapters for gateways vulnerability_management_gateway = DefectDojoPlatform() @@ -391,10 +364,7 @@ def application_core(): args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"], - use_remote_org=args["use_remote_org"] == "true", - remote_org=args["remote_org"], - remote_pat=args["remote_pat"], - remote_proj=args["remote_proj"] + remote_context=remote_context, ) tb = config_tool.get("TRACEBACK", False) diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py index bf64a6a29..765ed3e6b 100644 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py @@ -27,8 +27,15 @@ def init_engine_core( license_tool_gateway: any, args: any ): + remote_context = args.get("remote_context", { + "organization": args.get("remote_org", ""), + "project": args.get("remote_proj", ""), + "token": args.get("remote_token", ""), + "github_repository": args.get("remote_config_repo", ""), + }) + config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] + args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"], remote_context=remote_context ) Printers.print_logo_tool(config_tool["BANNER"]) diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py index aa7d4cc98..70d946855 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py @@ -65,7 +65,15 @@ def test_init_engine_core( # Assert that the function calls were made with the expected arguments mock_remote_config_source_gateway.get_remote_config.assert_called_once_with( - "https://github.com/example/repo", "/engine_core/ConfigTool.json", "" + "https://github.com/example/repo", + "/engine_core/ConfigTool.json", + "", + remote_context={ + "organization": "", + "project": "", + "token": "", + "github_repository": "https://github.com/example/repo" + }, ) mock_handle_scan.return_value.process.assert_called_once_with( { diff --git a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py index d3cc58f64..2da78cf76 100755 --- a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py +++ b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py @@ -24,12 +24,27 @@ ) import sys import argparse +import os from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger from devsecops_engine_tools.engine_utilities import settings from devsecops_engine_tools.version import version logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger() + +def build_remote_context(): + organization = os.environ.get("DET_REMOTE_ORG", "") + project = os.environ.get("DET_REMOTE_PROJ", "") + token = os.environ.get("DET_REMOTE_TOKEN", "") + github_repository = os.environ.get("DET_GITHUB_REPOSITORY", "") + + return { + "organization": organization, + "project": project, + "token": token, + "github_repository": github_repository, + } + def validate_integration_requirements(args): integration = args.get("integration") missing_args = [] @@ -189,6 +204,8 @@ def get_inputs_from_cli(args): def runner_engine_integrations(): try: args = get_inputs_from_cli(sys.argv[1:]) + remote_context = build_remote_context() + args["remote_context"] = remote_context if not args["remote_config_source"]: args["remote_config_source"] = args["platform_devops"] diff --git a/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py b/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py index ef2a38feb..626087ee3 100644 --- a/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py +++ b/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py @@ -18,8 +18,15 @@ def init_engine_integrations( metrics_manager_gateway, args, ): + remote_context = args.get("remote_context", { + "organization": args.get("remote_org", ""), + "project": args.get("remote_proj", ""), + "token": args.get("remote_token", ""), + "github_repository": args.get("remote_config_repo", ""), + }) + config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] + args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"], remote_context=remote_context ) Printers.print_logo_tool(config_tool["BANNER"]) From 027e33aaadbe249fc06d1d89045b243bb332a5f9 Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Thu, 18 Jun 2026 17:42:14 -0600 Subject: [PATCH 3/6] feat(engine_core): support remote AZ organization for config retrieval --- .../model/gateway/devops_platform_gateway.py | 8 +++++- .../src/domain/usecases/handle_risk.py | 3 +++ .../driven_adapters/azure/azure_devops.py | 26 ++++++++----------- .../driven_adapters/github/github_actions.py | 12 ++++++--- .../runtime_local/runtime_local.py | 2 +- .../applications/test_runner_engine_core.py | 16 ++---------- .../azuredevopscore/test_azure_devops.py | 2 +- 7 files changed, 34 insertions(+), 35 deletions(-) diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py index 065f94fac..a454ae3f5 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py @@ -3,7 +3,13 @@ class DevopsPlatformGateway(metaclass=ABCMeta): @abstractmethod - def get_remote_config(self, repository, path, branch): + def get_remote_config( + self, + repository, + path, + branch="", + **kwargs, + ): "get_remote_config" @abstractmethod diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py index 4c644f108..e0930a5a9 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py @@ -91,6 +91,7 @@ def _exclude_services(self, dict_args, pipeline_name, service_list): dict_args["remote_config_repo"], "engine_risk/Exclusions.json", dict_args["remote_config_branch"], + remote_context=dict_args.get("remote_context", {}), ) if ( pipeline_name in risk_exclusions @@ -133,11 +134,13 @@ def process(self, dict_args: any, remote_config: any): dict_args["remote_config_repo"], "engine_risk/ConfigTool.json", dict_args["remote_config_branch"], + remote_context=dict_args.get("remote_context", {}), ) risk_exclusions = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/Exclusions.json", dict_args["remote_config_branch"], + remote_context=dict_args.get("remote_context", {}), ) pipeline_name = self.devops_platform_gateway.get_variable("pipeline_name") definition_name = self.devops_platform_gateway.get_variable("definition_name") diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py index 255717da4..d23990ea3 100644 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py @@ -25,21 +25,17 @@ @dataclass class AzureDevops(DevopsPlatformGateway): - def get_remote_config(self, repository, path, branch="", use_remote_org=False, remote_org="", remote_pat="", remote_proj=""): - base_compact_remote_config_url = '' - if use_remote_org: - base_compact_remote_config_url = ( - f"https://{remote_org.rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" - f".visualstudio.com/{remote_proj}/_git/{repository}?path={path}" - ) - pat = remote_pat - else: - base_compact_remote_config_url = ( - f"https://{SystemVariables.System_TeamFoundationCollectionUri.value().rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" - f".visualstudio.com/{SystemVariables.System_TeamProject.value()}/_git/" - f"{repository}?path={path}" - ) - pat = SystemVariables.System_AccessToken.value() + def get_remote_config(self, repository, path, branch="", **kwargs): + remote_context = kwargs.get("remote_context") or {} + organization = remote_context.get("organization") or SystemVariables.System_TeamFoundationCollectionUri.value() + project = remote_context.get("project") or SystemVariables.System_TeamProject.value() + pat = remote_context.get("token") or SystemVariables.System_AccessToken.value() + + base_compact_remote_config_url = ( + f"https://{organization.rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" + f".visualstudio.com/{project}/_git/{repository}?path={path}" + ) + utils_azure = AzureDevopsApi( personal_access_token=pat, compact_remote_config_url=base_compact_remote_config_url, diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py index cda9940d3..d3deb40ef 100755 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py @@ -24,14 +24,20 @@ class GithubActions(DevopsPlatformGateway): ICON_FAIL = "\u2718" ICON_SUCCESS = "\u2714" - def get_remote_config(self, repository, path, branch=""): + def get_remote_config(self, repository, path, branch="", **kwargs): + remote_context = kwargs.get("remote_context") or {} + token = remote_context.get("token") or SystemVariables.github_access_token.value() + github_repository = remote_context.get("github_repository") or SystemVariables.github_repository.value() + + # Accept both owner/repo and full URL formats. + if github_repository.startswith("https://") or github_repository.startswith("http://"): + github_repository = github_repository.rstrip("/").split("github.com/")[-1] - github_repository = SystemVariables.github_repository.value() split = github_repository.split("/") owner = split[0] utils_github = GithubApi() - git_client = utils_github.get_github_connection(SystemVariables.github_access_token.value()) + git_client = utils_github.get_github_connection(token) json_config = utils_github.get_remote_json_config(git_client, owner, repository, path, branch) return json_config diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py index 4507dd8f8..bb4bda91e 100755 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py @@ -18,7 +18,7 @@ class RuntimeLocal(DevopsPlatformGateway): ICON_SUCCESS = "\u2714" - def get_remote_config(self, repository, path, branch=""): + def get_remote_config(self, repository, path, branch="", **kwargs): remote_config_path = f"{repository}/{path}" with open(remote_config_path, 'r', encoding='utf-8') as f: diff --git a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py index 50ffec0d3..56667b12d 100644 --- a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py @@ -118,10 +118,6 @@ def test_get_inputs_from_cli(mock_parse_args): mock_args.token_license_analyzer = None mock_args.use_license_analyzer = "false" mock_args.docker_address = "unix:///var/run/docker.sock" - mock_args.use_remote_org = "false" - mock_args.remote_org = "" - mock_args.remote_pat = "" - mock_args.remote_proj = "" # Mock the parse_args method mock_parse_args.return_value = mock_args @@ -154,11 +150,7 @@ def test_get_inputs_from_cli(mock_parse_args): "token_engine_code": None, "token_license_analyzer": None, "use_license_analyzer": "false", - "docker_address": "unix:///var/run/docker.sock", - "use_remote_org": "false", - "remote_org": "", - "remote_pat": "", - "remote_proj": "", + "docker_address": "unix:///var/run/docker.sock" } @@ -288,11 +280,7 @@ def test_application_core_exception_block( "image_to_scan": None, "dast_file_path": None, "context": "false", - "docker_address": None, - "use_remote_org": "false", - "remote_org": "", - "remote_pat": "", - "remote_proj": "", + "docker_address": None } mock_get_inputs_from_cli.return_value = mock_args mock_init_engine_core.side_effect = Exception("simulated error") diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py index 71549fa0f..88aec6ddb 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py @@ -23,7 +23,7 @@ def test_get_remote_config(self, mock_system_variables, mock_azure_devops_api): remote_config_repo = "my_repo" remote_config_path = "my_path" # Llamar con los nuevos argumentos - result = azure_devops.get_remote_config(remote_config_repo, remote_config_path, use_remote_org=False, remote_org="", remote_pat="", remote_proj="") + result = azure_devops.get_remote_config(remote_config_repo, remote_config_path) assert result == {"key": "value"} def test_message(self): From 689cc101627e710803a23375e5e5fa22eee80c7f Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Mon, 22 Jun 2026 15:29:02 -0600 Subject: [PATCH 4/6] feat(engine_core): support remote AZ organization for config retrieval --- .../src/applications/runner_engine_core.py | 19 +------------------ .../model/gateway/devops_platform_gateway.py | 3 +-- .../src/domain/usecases/handle_risk.py | 9 +++------ .../driven_adapters/azure/azure_devops.py | 10 +++++----- .../driven_adapters/github/github_actions.py | 8 ++++---- .../entry_points/entry_point_core.py | 9 +-------- .../entry_points/test_entry_point_core.py | 8 +------- .../runner_engine_integrations.py | 15 --------------- .../entry_points/entry_point_integrations.py | 9 +-------- 9 files changed, 17 insertions(+), 73 deletions(-) diff --git a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py index bd2afdc4b..921e6aceb 100755 --- a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py @@ -66,20 +66,6 @@ def parse_with_choices(value): return parse_with_choices -def build_remote_context(): - organization = os.environ.get("DET_REMOTE_ORG", "") - project = os.environ.get("DET_REMOTE_PROJ", "") - token = os.environ.get("DET_REMOTE_TOKEN", "") - github_repository = os.environ.get("DET_GITHUB_REPOSITORY", "") - - return { - "organization": organization, - "project": project, - "token": token, - "github_repository": github_repository, - } - - def get_inputs_from_cli(args): parser = argparse.ArgumentParser() parser.add_argument( @@ -331,8 +317,6 @@ def application_core(): try: # Get inputs from CLI args = get_inputs_from_cli(sys.argv[1:]) - remote_context = build_remote_context() - args["remote_context"] = remote_context # Define driven adapters for gateways vulnerability_management_gateway = DefectDojoPlatform() @@ -363,8 +347,7 @@ def application_core(): config_tool = remote_config_source_gateway.get_remote_config( args["remote_config_repo"], "/engine_core/ConfigTool.json", - args["remote_config_branch"], - remote_context=remote_context, + args["remote_config_branch"] ) tb = config_tool.get("TRACEBACK", False) diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py index a454ae3f5..05982563b 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py @@ -7,8 +7,7 @@ def get_remote_config( self, repository, path, - branch="", - **kwargs, + branch="" ): "get_remote_config" diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py index e0930a5a9..7ab0aae2c 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py @@ -90,8 +90,7 @@ def _exclude_services(self, dict_args, pipeline_name, service_list): risk_exclusions = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/Exclusions.json", - dict_args["remote_config_branch"], - remote_context=dict_args.get("remote_context", {}), + dict_args["remote_config_branch"] ) if ( pipeline_name in risk_exclusions @@ -133,14 +132,12 @@ def process(self, dict_args: any, remote_config: any): risk_config = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/ConfigTool.json", - dict_args["remote_config_branch"], - remote_context=dict_args.get("remote_context", {}), + dict_args["remote_config_branch"] ) risk_exclusions = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/Exclusions.json", - dict_args["remote_config_branch"], - remote_context=dict_args.get("remote_context", {}), + dict_args["remote_config_branch"] ) pipeline_name = self.devops_platform_gateway.get_variable("pipeline_name") definition_name = self.devops_platform_gateway.get_variable("definition_name") diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py index d23990ea3..5beb8d7f1 100644 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/azure/azure_devops.py @@ -1,3 +1,4 @@ +import os from dataclasses import dataclass from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import ( DevopsPlatformGateway, @@ -25,11 +26,10 @@ @dataclass class AzureDevops(DevopsPlatformGateway): - def get_remote_config(self, repository, path, branch="", **kwargs): - remote_context = kwargs.get("remote_context") or {} - organization = remote_context.get("organization") or SystemVariables.System_TeamFoundationCollectionUri.value() - project = remote_context.get("project") or SystemVariables.System_TeamProject.value() - pat = remote_context.get("token") or SystemVariables.System_AccessToken.value() + def get_remote_config(self, repository, path, branch=""): + organization = os.environ.get("DET_REMOTE_ORG") or SystemVariables.System_TeamFoundationCollectionUri.value() + project = os.environ.get("DET_REMOTE_PROJ") or SystemVariables.System_TeamProject.value() + pat = os.environ.get("DET_REMOTE_TOKEN") or SystemVariables.System_AccessToken.value() base_compact_remote_config_url = ( f"https://{organization.rstrip('/').split('/')[-1].replace('.visualstudio.com','')}" diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py index d3deb40ef..2bae6a4c8 100755 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/github/github_actions.py @@ -1,3 +1,4 @@ +import os from dataclasses import dataclass from devsecops_engine_tools.engine_core.src.domain.model.gateway.devops_platform_gateway import ( DevopsPlatformGateway, @@ -24,10 +25,9 @@ class GithubActions(DevopsPlatformGateway): ICON_FAIL = "\u2718" ICON_SUCCESS = "\u2714" - def get_remote_config(self, repository, path, branch="", **kwargs): - remote_context = kwargs.get("remote_context") or {} - token = remote_context.get("token") or SystemVariables.github_access_token.value() - github_repository = remote_context.get("github_repository") or SystemVariables.github_repository.value() + def get_remote_config(self, repository, path, branch=""): + token = os.environ.get("DET_REMOTE_TOKEN") or SystemVariables.github_access_token.value() + github_repository = os.environ.get("DET_GITHUB_REPOSITORY") or SystemVariables.github_repository.value() # Accept both owner/repo and full URL formats. if github_repository.startswith("https://") or github_repository.startswith("http://"): diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py index 765ed3e6b..bf64a6a29 100644 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/entry_points/entry_point_core.py @@ -27,15 +27,8 @@ def init_engine_core( license_tool_gateway: any, args: any ): - remote_context = args.get("remote_context", { - "organization": args.get("remote_org", ""), - "project": args.get("remote_proj", ""), - "token": args.get("remote_token", ""), - "github_repository": args.get("remote_config_repo", ""), - }) - config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"], remote_context=remote_context + args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] ) Printers.print_logo_tool(config_tool["BANNER"]) diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py index 70d946855..412fbd84e 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py @@ -67,13 +67,7 @@ def test_init_engine_core( mock_remote_config_source_gateway.get_remote_config.assert_called_once_with( "https://github.com/example/repo", "/engine_core/ConfigTool.json", - "", - remote_context={ - "organization": "", - "project": "", - "token": "", - "github_repository": "https://github.com/example/repo" - }, + "" ) mock_handle_scan.return_value.process.assert_called_once_with( { diff --git a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py index 2da78cf76..1bfa37d20 100755 --- a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py +++ b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py @@ -32,19 +32,6 @@ logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger() -def build_remote_context(): - organization = os.environ.get("DET_REMOTE_ORG", "") - project = os.environ.get("DET_REMOTE_PROJ", "") - token = os.environ.get("DET_REMOTE_TOKEN", "") - github_repository = os.environ.get("DET_GITHUB_REPOSITORY", "") - - return { - "organization": organization, - "project": project, - "token": token, - "github_repository": github_repository, - } - def validate_integration_requirements(args): integration = args.get("integration") missing_args = [] @@ -204,8 +191,6 @@ def get_inputs_from_cli(args): def runner_engine_integrations(): try: args = get_inputs_from_cli(sys.argv[1:]) - remote_context = build_remote_context() - args["remote_context"] = remote_context if not args["remote_config_source"]: args["remote_config_source"] = args["platform_devops"] diff --git a/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py b/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py index 626087ee3..ef2a38feb 100644 --- a/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py +++ b/tools/devsecops_engine_tools/engine_integrations/src/infrastructure/entry_points/entry_point_integrations.py @@ -18,15 +18,8 @@ def init_engine_integrations( metrics_manager_gateway, args, ): - remote_context = args.get("remote_context", { - "organization": args.get("remote_org", ""), - "project": args.get("remote_proj", ""), - "token": args.get("remote_token", ""), - "github_repository": args.get("remote_config_repo", ""), - }) - config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"], remote_context=remote_context + args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] ) Printers.print_logo_tool(config_tool["BANNER"]) From 925e04f180769cb4e167e9a16c632170fa9a4e41 Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Mon, 22 Jun 2026 15:37:50 -0600 Subject: [PATCH 5/6] feat(engine_core): support remote AZ organization for config retrieval --- .../engine_core/src/applications/runner_engine_core.py | 6 +----- .../src/domain/model/gateway/devops_platform_gateway.py | 7 +------ .../engine_core/src/domain/usecases/handle_risk.py | 6 +++--- .../driven_adapters/runtime_local/runtime_local.py | 2 +- .../test/applications/test_runner_engine_core.py | 4 ++-- .../driven_adapters/azuredevopscore/test_azure_devops.py | 2 +- .../infrastructure/entry_points/test_entry_point_core.py | 4 +--- .../src/applications/runner_engine_integrations.py | 2 -- 8 files changed, 10 insertions(+), 23 deletions(-) diff --git a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py index 921e6aceb..8b0e25b84 100755 --- a/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/src/applications/runner_engine_core.py @@ -37,8 +37,6 @@ import sys import argparse import traceback -import os -import json from devsecops_engine_tools.engine_utilities.dependency_track.infrastructure.driver_adapters.dependency_track import DependencyTrack from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger from devsecops_engine_tools.engine_utilities import settings @@ -345,9 +343,7 @@ def application_core(): # Activate traceback config_tool = remote_config_source_gateway.get_remote_config( - args["remote_config_repo"], - "/engine_core/ConfigTool.json", - args["remote_config_branch"] + args["remote_config_repo"], "/engine_core/ConfigTool.json", args["remote_config_branch"] ) tb = config_tool.get("TRACEBACK", False) diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py index 05982563b..1c71e7bac 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py @@ -3,12 +3,7 @@ class DevopsPlatformGateway(metaclass=ABCMeta): @abstractmethod - def get_remote_config( - self, - repository, - path, - branch="" - ): + def get_remote_config(self, repository, path, branch=""): "get_remote_config" @abstractmethod diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py index 7ab0aae2c..4c644f108 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/usecases/handle_risk.py @@ -90,7 +90,7 @@ def _exclude_services(self, dict_args, pipeline_name, service_list): risk_exclusions = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/Exclusions.json", - dict_args["remote_config_branch"] + dict_args["remote_config_branch"], ) if ( pipeline_name in risk_exclusions @@ -132,12 +132,12 @@ def process(self, dict_args: any, remote_config: any): risk_config = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/ConfigTool.json", - dict_args["remote_config_branch"] + dict_args["remote_config_branch"], ) risk_exclusions = self.remote_config_source_gateway.get_remote_config( dict_args["remote_config_repo"], "engine_risk/Exclusions.json", - dict_args["remote_config_branch"] + dict_args["remote_config_branch"], ) pipeline_name = self.devops_platform_gateway.get_variable("pipeline_name") definition_name = self.devops_platform_gateway.get_variable("definition_name") diff --git a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py index bb4bda91e..4507dd8f8 100755 --- a/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py +++ b/tools/devsecops_engine_tools/engine_core/src/infrastructure/driven_adapters/runtime_local/runtime_local.py @@ -18,7 +18,7 @@ class RuntimeLocal(DevopsPlatformGateway): ICON_SUCCESS = "\u2714" - def get_remote_config(self, repository, path, branch="", **kwargs): + def get_remote_config(self, repository, path, branch=""): remote_config_path = f"{repository}/{path}" with open(remote_config_path, 'r', encoding='utf-8') as f: diff --git a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py index 56667b12d..f64c6865a 100644 --- a/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/applications/test_runner_engine_core.py @@ -150,7 +150,7 @@ def test_get_inputs_from_cli(mock_parse_args): "token_engine_code": None, "token_license_analyzer": None, "use_license_analyzer": "false", - "docker_address": "unix:///var/run/docker.sock" + "docker_address": "unix:///var/run/docker.sock", } @@ -280,7 +280,7 @@ def test_application_core_exception_block( "image_to_scan": None, "dast_file_path": None, "context": "false", - "docker_address": None + "docker_address": None, } mock_get_inputs_from_cli.return_value = mock_args mock_init_engine_core.side_effect = Exception("simulated error") diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py index 88aec6ddb..7591798a0 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/driven_adapters/azuredevopscore/test_azure_devops.py @@ -22,7 +22,7 @@ def test_get_remote_config(self, mock_system_variables, mock_azure_devops_api): mock_azure_devops_api.return_value = mock_azure_devops_api_instance remote_config_repo = "my_repo" remote_config_path = "my_path" - # Llamar con los nuevos argumentos + result = azure_devops.get_remote_config(remote_config_repo, remote_config_path) assert result == {"key": "value"} diff --git a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py index 412fbd84e..aa7d4cc98 100644 --- a/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py +++ b/tools/devsecops_engine_tools/engine_core/test/infrastructure/entry_points/test_entry_point_core.py @@ -65,9 +65,7 @@ def test_init_engine_core( # Assert that the function calls were made with the expected arguments mock_remote_config_source_gateway.get_remote_config.assert_called_once_with( - "https://github.com/example/repo", - "/engine_core/ConfigTool.json", - "" + "https://github.com/example/repo", "/engine_core/ConfigTool.json", "" ) mock_handle_scan.return_value.process.assert_called_once_with( { diff --git a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py index 1bfa37d20..d3cc58f64 100755 --- a/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py +++ b/tools/devsecops_engine_tools/engine_integrations/src/applications/runner_engine_integrations.py @@ -24,14 +24,12 @@ ) import sys import argparse -import os from devsecops_engine_tools.engine_utilities.utils.logger_info import MyLogger from devsecops_engine_tools.engine_utilities import settings from devsecops_engine_tools.version import version logger = MyLogger.__call__(**settings.SETTING_LOGGER).get_logger() - def validate_integration_requirements(args): integration = args.get("integration") missing_args = [] From 9933c91d9ff1c5e4b5030de7f35ed193d412b6fd Mon Sep 17 00:00:00 2001 From: Guillermo Josue Hernandez Andrade Date: Tue, 23 Jun 2026 08:57:45 -0600 Subject: [PATCH 6/6] feat(engine_core): support remote AZ organization for config retrieval --- docs/Docusaurus/docs/modules/engine_core.md | 33 +++++++++++++++++++ .../model/gateway/devops_platform_gateway.py | 2 +- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/Docusaurus/docs/modules/engine_core.md b/docs/Docusaurus/docs/modules/engine_core.md index a6dd7cefd..1aa7a7c7e 100644 --- a/docs/Docusaurus/docs/modules/engine_core.md +++ b/docs/Docusaurus/docs/modules/engine_core.md @@ -715,6 +715,39 @@ devsecops-engine-tools \ --image_to_scan myimage:latest ``` +## Remote Config Environment Variables + +These variables are used to resolve authentication and repository context when loading remote configuration files. + +```bash +DET_REMOTE_ORG="my-azure-organization" +DET_REMOTE_PROJ="my-azure-project" +DET_REMOTE_TOKEN="***" +DET_GITHUB_REPOSITORY="owner/repository" +``` + +- **DET_REMOTE_ORG** + - **Use:** Azure DevOps organization used to build the remote config URL. + - **Applies to:** `--remote_config_source azure`. + - **Fallback if missing:** `System.TeamFoundationCollectionUri`. + +- **DET_REMOTE_PROJ** + - **Use:** Azure DevOps project used in the remote config URL path. + - **Applies to:** `--remote_config_source azure`. + - **Fallback if missing:** `System.TeamProject`. + +- **DET_REMOTE_TOKEN** + - **Use:** Token to authenticate against the remote config source. + - **Applies to:** `--remote_config_source azure` and `--remote_config_source github`. + - **Fallback if missing:** + - Azure: `System.AccessToken`. + - GitHub: `github.access.token`. + +- **DET_GITHUB_REPOSITORY** + - **Use:** GitHub repository context used to resolve owner/repository (accepts `owner/repo` or full GitHub URL). + - **Applies to:** `--remote_config_source github`. + - **Fallback if missing:** `github.repository`. + ## Extensibility - New tools and modules can be added by extending the adapters and use cases. diff --git a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py index 1c71e7bac..065f94fac 100644 --- a/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py +++ b/tools/devsecops_engine_tools/engine_core/src/domain/model/gateway/devops_platform_gateway.py @@ -3,7 +3,7 @@ class DevopsPlatformGateway(metaclass=ABCMeta): @abstractmethod - def get_remote_config(self, repository, path, branch=""): + def get_remote_config(self, repository, path, branch): "get_remote_config" @abstractmethod