You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(bff): introduce support of multiple auth methods (internal, user_token)
- Introduce auth-method flag (default: internal) to select auth strategy
- internal: uses pod service account (in-cluster) or current kubeconfig (local)
- user_token: uses bearer token from X-Forwarded-Access-Token header
- Implement separate SAR (internal) and SSAR (user_token) logic
- Clarify behavior and usage in README
Signed-off-by: Eder Ignatowicz <[email protected]>
Copy file name to clipboardExpand all lines: clients/ui/bff/README.md
+35-20Lines changed: 35 additions & 20 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ The main difference between the two docker compose files is that `-local` one bu
24
24
25
25
When shutting down the docker compose, you might want to clean-up the SQLite db file generated by ML Metadata, for example `./test/config/ml-metadata/metadata.sqlite.db`
26
26
27
-
# Development
27
+
##Development
28
28
29
29
Run the following command to build the BFF:
30
30
@@ -51,7 +51,7 @@ If you want to change the log level on deployment, add the LOG_LEVEL argument wh
51
51
make run LOG_LEVEL=DEBUG
52
52
```
53
53
54
-
# Building and Deploying
54
+
##Building and Deploying
55
55
56
56
Run the following command to build the BFF:
57
57
@@ -78,25 +78,25 @@ See the [OpenAPI specification](../api/openapi/mod-arch.yaml) for a complete lis
78
78
You will need to inject your requests with a `kubeflow-userid` header and namespace for authorization purposes.
79
79
80
80
When running the service with the mocked Kubernetes client (MOCK_K8S_CLIENT=true), the user `[email protected]` is preconfigured with the necessary RBAC permissions to perform these actions.
@@ -350,24 +351,38 @@ The mock Kubernetes environment is activated when the environment variable `MOCK
350
351
-`non-model-registry`: resides in the `kubeflow` namespace _without_ the label `component: model-registry`.
351
352
-`model-registry-dora`: resides in the `dora-namespace` namespace with the label `component: model-registry`.
352
353
353
-
#### 3. How BFF authorization works for kubeflow-userid and kubeflow-groups?
354
+
#### 3. Which Authentication methods are supported?
355
+
356
+
The BFF supports two authentication modes, selectable via the --auth-method flag or AUTH_METHOD environment variable (default: internal):
354
357
355
-
Authorization is performed using Kubernetes SubjectAccessReview (SAR), which validates user access to resources.
358
+
-`internal`: Uses the credentials of the running backend.
359
+
- If running inside the cluster, it uses the pod’s service account.
360
+
- If running locally (e.g. for development), it uses the current user's active kubeconfig context.
361
+
- In this mode, user identity is passed via the kubeflow-userid and optionally kubeflow-groups headers.
362
+
- This is the default mode and works well with mock clients and local testing.
363
+
-`user_token`: Uses a user-provided Bearer token for authentication.
364
+
- The token must be passed in the `X-Forwarded-Access-Token` header.
365
+
- Useful when the frontend is fronted by an auth proxy (e.g., Istio + OIDC) that injects a valid Kubernetes token.
356
366
357
-
-`kubeflow-userid`: Required header that specifies the user’s email. Access is checked directly for the user via SAR.
358
-
-`kubeflow-groups`: Optional header with a comma-separated list of groups. If the user does not have access, SAR checks group permissions using OR logic. If any group has access, the request is authorized.
359
367
360
-
Access to Model Registry List:
368
+
#### 4. How BFF authorization works?
361
369
362
-
- To list all model registries (/v1/model_registry), we perform a SAR check for get and list verbs on services within the specified namespace.
363
-
- If the user or any group has permission to get and list services in the namespace, the request is authorized.
370
+
Authorization is performed using Kubernetes access reviews, validating whether the user (or their groups) can perform certain actions.
371
+
There are two review mechanisms depending on the authentication mode:
372
+
- Internal mode (auth-method=internal):
373
+
Uses SubjectAccessReview (SAR) to check whether the impersonated user (from kubeflow-userid and kubeflow-groups headers) has the required permissions.
374
+
- User token mode (auth-method=user_token): Uses SelfSubjectAccessReview (SSAR), leveraging the Bearer token provided in the X-Forwarded-Access-Token header to check the current user's permissions directly.
364
375
365
-
Access to Specific Model Registry Endpoints:
376
+
##### Authorization logic
377
+
* Access to Model Registry List (/v1/model_registry):
378
+
- Checks for get and list on services in the target namespace.
379
+
- If the user (or groups, in internal mode) has permission, access is granted.
366
380
367
-
- For other endpoints (e.g., /v1/model_registry/{model_registry_id}/...), we perform a SAR check for get and list verbs on the specific service (identified by model_registry_id) within the namespace.
368
-
- If the user or any group has permission to get or list the specific service, the request is authorized.
381
+
* Access to Specific Model Registry Endpoints (/v1/model_registry/{model_registry_id}/...):
382
+
- Checks for get on the specific service (identified by model_registry_id) in the namespace.
383
+
- If authorized, access is granted.
369
384
370
-
#### 4. How do I allow CORS requests from other origins
385
+
#### 5. How do I allow CORS requests from other origins
371
386
372
387
When serving the UI directly from the BFF there is no need for any CORS headers to be served, by default they are turned off for security reasons.
flag.TextVar(&cfg.LogLevel, "log-level", parseLevel(getEnvAsString("LOG_LEVEL", "INFO")), "Sets server log level, possible values: error, warn, info, debug")
34
34
flag.Func("allowed-origins", "Sets allowed origins for CORS purposes, accepts a comma separated list of origins or * to allow all, default none", newOriginParser(&cfg.AllowedOrigins, getEnvAsString("ALLOWED_ORIGINS", "")))
35
+
flag.StringVar(&cfg.AuthMethod, "auth-method", "internal", "Authentication method (internal or user_token)")
0 commit comments