From d997beb03367b3cc3b6c8c0c31b465dcbbefcad6 Mon Sep 17 00:00:00 2001 From: Sarah Asad Date: Tue, 19 May 2026 15:17:28 -0700 Subject: [PATCH 1/2] support k8s setting --- .../resource/pythonvirtualenvironment/PveResource.scala | 8 +++----- .../virtual-environment/virtual-environment.service.ts | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/amber/src/main/scala/org/apache/texera/web/resource/pythonvirtualenvironment/PveResource.scala b/amber/src/main/scala/org/apache/texera/web/resource/pythonvirtualenvironment/PveResource.scala index 4d810678cc5..2f60da2c712 100644 --- a/amber/src/main/scala/org/apache/texera/web/resource/pythonvirtualenvironment/PveResource.scala +++ b/amber/src/main/scala/org/apache/texera/web/resource/pythonvirtualenvironment/PveResource.scala @@ -36,12 +36,10 @@ class PveResource { @GET @Path("/system") @Produces(Array(MediaType.APPLICATION_JSON)) - def getSystemPackages: util.Map[String, util.List[String]] = { + def getSystemPackages( + @QueryParam("isLocal") isLocal: Boolean + ): util.Map[String, util.List[String]] = { try { - - // TODO: Support Kubernetes environment handling - val isLocal = true - val systemPkgs = PveManager.getSystemPackages(isLocal).toList.asJava diff --git a/frontend/src/app/workspace/service/virtual-environment/virtual-environment.service.ts b/frontend/src/app/workspace/service/virtual-environment/virtual-environment.service.ts index 7788cba2701..72129dbce64 100644 --- a/frontend/src/app/workspace/service/virtual-environment/virtual-environment.service.ts +++ b/frontend/src/app/workspace/service/virtual-environment/virtual-environment.service.ts @@ -50,7 +50,7 @@ export class WorkflowPveService { } getSystemPackages(isLocal: boolean): Observable { - const params = this.buildBaseParams(); + const params = this.buildBaseParams().set("isLocal", isLocal.toString()); return this.http.get("/pve/system", { params }); } From 661a04ce7847dac249b4bfa3323bb0c275ffdcf8 Mon Sep 17 00:00:00 2001 From: Sarah Asad Date: Tue, 19 May 2026 15:20:58 -0700 Subject: [PATCH 2/2] add gateway routing --- .../resource/AccessControlResource.scala | 21 +++++++++++++++++-- bin/k8s/templates/gateway-routes.yaml | 14 +++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/access-control-service/src/main/scala/org/apache/texera/service/resource/AccessControlResource.scala b/access-control-service/src/main/scala/org/apache/texera/service/resource/AccessControlResource.scala index 0cd52f49194..c48be41af26 100644 --- a/access-control-service/src/main/scala/org/apache/texera/service/resource/AccessControlResource.scala +++ b/access-control-service/src/main/scala/org/apache/texera/service/resource/AccessControlResource.scala @@ -43,6 +43,14 @@ object AccessControlResource extends LazyLogging { private val wsapiWorkflowWebsocket: Regex = """.*/wsapi/workflow-websocket.*""".r private val apiExecutionsStats: Regex = """.*/api/executions/[0-9]+/stats/[0-9]+.*""".r private val apiExecutionsResultExport: Regex = """.*/api/executions/result/export.*""".r + // PVE REST + websocket endpoints, all per-computing-unit. The REST route + // appears as bare /pve/... to ext-authz (the gateway's URLRewrite to /api/pve + // runs after ext_authz), while websocket traffic comes in as /wsapi/pve/... + private val pveRoute: Regex = """.*/(?:api/|wsapi/)?pve(?:/.*)?""".r + + // Path patterns whose cuid lives in the URL path rather than the query string. + private val pvePvesCuidPath: Regex = """.*/pve/pves/([0-9]+).*""".r + private val pvePackagesCuidPath: Regex = """.*/pve/([0-9]+)/[^/]+/packages/.+""".r /** * Authorize the request based on the path and headers. @@ -60,7 +68,8 @@ object AccessControlResource extends LazyLogging { logger.info(s"Authorizing request for path: $path") path match { - case wsapiWorkflowWebsocket() | apiExecutionsStats() | apiExecutionsResultExport() => + case wsapiWorkflowWebsocket() | apiExecutionsStats() | apiExecutionsResultExport() | + pveRoute() => checkComputingUnitAccess(uriInfo, headers, bodyOpt) case _ => logger.warn(s"No authorization logic for path: $path. Denying access.") @@ -95,7 +104,15 @@ object AccessControlResource extends LazyLogging { qToken.orElse(hToken).orElse(bToken).getOrElse("") } logger.info(s"token extracted from request $token") - val cuid = queryParams.getOrElse("cuid", "") + // Some PVE endpoints carry the cuid in the URL path (e.g. DELETE /pve/pves/{cuid}) instead of + // the query string, so fall back to extracting it from the path when missing from the query. + val cuid = queryParams.get("cuid").filter(_.nonEmpty).getOrElse { + uriInfo.getPath match { + case pvePvesCuidPath(c) => c + case pvePackagesCuidPath(c) => c + case _ => "" + } + } val cuidInt = try { cuid.toInt diff --git a/bin/k8s/templates/gateway-routes.yaml b/bin/k8s/templates/gateway-routes.yaml index 55dc40f581a..ab53c184e83 100644 --- a/bin/k8s/templates/gateway-routes.yaml +++ b/bin/k8s/templates/gateway-routes.yaml @@ -118,6 +118,20 @@ spec: - group: gateway.envoyproxy.io kind: Backend name: texera-dynamic-backend + - matches: + - path: + type: PathPrefix + value: /pve + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: /api/pve + backendRefs: + - group: gateway.envoyproxy.io + kind: Backend + name: texera-dynamic-backend --- # MinIO Route {{- if .Values.minio.gateway.enabled }}