diff --git a/lib/galaxy/managers/jobs.py b/lib/galaxy/managers/jobs.py index 8a6195ba15f..6418967f3a5 100644 --- a/lib/galaxy/managers/jobs.py +++ b/lib/galaxy/managers/jobs.py @@ -79,6 +79,7 @@ from galaxy.model.index_filter_util import ( text_column_filter, ) from galaxy.model.scoped_session import galaxy_scoped_session +from galaxy.schema.credentials import CredentialsContext from galaxy.schema.schema import ( JobIndexQueryPayload, JobIndexSortByEnum, @@ -2186,6 +2187,9 @@ class JobSubmitter: target_history = request_context.history use_cached_jobs = request.use_cached_jobs rerun_remap_job_id = request.rerun_remap_job_id + credentials_context: Optional[CredentialsContext] = None + if request.credentials_context: + credentials_context = CredentialsContext(root=request.credentials_context) tool_state, new_hdas = self.dereference(request_context, tool, request, tool_request) to_materialize_list = [p for p in new_hdas if not p.request.deferred] for to_materialize in to_materialize_list: @@ -2201,6 +2205,7 @@ class JobSubmitter: history=target_history, use_cached_job=use_cached_jobs, rerun_remap_job_id=rerun_remap_job_id, + credentials_context=credentials_context, ) tool_request.state = ToolRequest.states.SUBMITTED sa_session.add(tool_request) diff --git a/lib/galaxy/schema/tasks.py b/lib/galaxy/schema/tasks.py index 8c6ef67e7f8..5d5f173d2dd 100644 --- a/lib/galaxy/schema/tasks.py +++ b/lib/galaxy/schema/tasks.py @@ -9,6 +9,7 @@ from pydantic import Field from galaxy.util.hash_util import HashFunctionNameEnum from . import PdfDocumentType +from .credentials import ServiceCredentialsContext from .schema import ( BcoGenerationParametersMixin, DatasetSourceType, @@ -186,3 +187,4 @@ class QueueJobs(Model): user: RequestUser # TODO: test anonymous users through this submission path use_cached_jobs: bool rerun_remap_job_id: Optional[int] # link to a job to rerun & remap + credentials_context: Optional[list[ServiceCredentialsContext]] = None # credential context for vault-based credential injection diff --git a/lib/galaxy/tools/actions/__init__.py b/lib/galaxy/tools/actions/__init__.py index 79890964b4b..15ae62e1599 100644 --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -972,6 +972,7 @@ class DefaultToolAction(ToolAction): if credentials_context is None: return + # Create database associations for vault-based credentials for service_context in credentials_context.root: association = JobCredentialsContextAssociation( job=job, diff --git a/lib/galaxy/webapps/galaxy/services/jobs.py b/lib/galaxy/webapps/galaxy/services/jobs.py index ffc3a054983..781c58a78d1 100644 --- a/lib/galaxy/webapps/galaxy/services/jobs.py +++ b/lib/galaxy/webapps/galaxy/services/jobs.py @@ -47,6 +47,7 @@ from galaxy.schema.schema import ( AsyncTaskResultSummary, JobIndexQueryPayload, ) +from galaxy.schema.credentials import ServiceCredentialsContext from galaxy.schema.tasks import ( QueueJobs, ToolSource, @@ -90,6 +91,9 @@ class JobRequest(BaseModel): default=None, title="rerun_remap_job_id", description="TODO" ) send_email_notification: bool = Field(default=False, title="Send Email Notification", description="TODO") + credentials_context: Optional[list[ServiceCredentialsContext]] = Field( + default=None, title="credentials_context", description="Credential context for tool execution." + ) class JobCreateResponse(BaseModel): @@ -286,6 +290,7 @@ class JobsService(ServiceBase): tool_request_id=tool_request_id, use_cached_jobs=job_request.use_cached_jobs or False, rerun_remap_job_id=job_request.rerun_remap_job_id, + credentials_context=job_request.credentials_context, ) result = queue_jobs.delay(request=task_request) return JobCreateResponse( diff --git a/lib/galaxy/webapps/galaxy/services/tools.py b/lib/galaxy/webapps/galaxy/services/tools.py index ef469889acb..c508b857e65 100644 --- a/lib/galaxy/webapps/galaxy/services/tools.py +++ b/lib/galaxy/webapps/galaxy/services/tools.py @@ -352,7 +352,7 @@ class ToolsService(ServiceBase): inputs.get("use_cached_job", "false") ) preferred_object_store_id = payload.get("preferred_object_store_id") - credentials_context = payload.get("credentials_context") + credentials_context_raw = payload.get("credentials_context") input_format = str(payload.get("input_format", "legacy")) if input_format not in get_args(InputFormatT): raise exceptions.RequestParameterInvalidException(f"input_format invalid {input_format}") @@ -360,6 +360,12 @@ class ToolsService(ServiceBase): if "data_manager_mode" in payload: incoming["__data_manager_mode"] = payload["data_manager_mode"] tags = payload.get("__tags") + + # Handle credentials_context + credentials_context: Optional[CredentialsContext] = None + if credentials_context_raw: + credentials_context = CredentialsContext(root=credentials_context_raw) + vars = tool.handle_input( trans, incoming, @@ -367,7 +373,7 @@ class ToolsService(ServiceBase): use_cached_job=use_cached_job, input_format=input_format, preferred_object_store_id=preferred_object_store_id, - credentials_context=CredentialsContext(root=credentials_context) if credentials_context else None, + credentials_context=credentials_context, tags=tags, )