Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.")
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 14 additions & 0 deletions bin/k8s/templates/gateway-routes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class WorkflowPveService {
}

getSystemPackages(isLocal: boolean): Observable<PackageResponse> {
const params = this.buildBaseParams();
const params = this.buildBaseParams().set("isLocal", isLocal.toString());
return this.http.get<PackageResponse>("/pve/system", { params });
}

Expand Down
Loading