fix(backend): inject user identity header in scheduled-workflow-controller for multi-user auth#13472
fix(backend): inject user identity header in scheduled-workflow-controller for multi-user auth#13472jaewak wants to merge 14 commits into
Conversation
In multi-user mode, the scheduled-workflow-controller calls CreateRun via gRPC to the API server. Previously, only an Authorization: Bearer <token> header was attached (when a service-account token file was present). The API server's HTTPHeaderAuthenticator also requires a user identity header (e.g. kubeflow-userid), and rejects the request with 'Unauthenticated: Request header error: there is no user identity header' when the token volume is not mounted. This commit adds two new CLI flags to the controller: --userIdentityHeader: the header name (e.g. kubeflow-userid) --userIdentityValue: the value to set (e.g. the controller SA identity) When both are set, the controller injects the header into the gRPC outgoing metadata alongside the existing Bearer token. Both flags default to empty strings, making the feature fully opt-in -- existing single-user deployments are unaffected. The multi-user kustomize deployment patch is updated to pass these flags using the controller's own service account identity, derived from the pod namespace via the downward API. Signed-off-by: jaewak <jaewan.0907@gmail.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Hi @jaewak. Thanks for your PR. I'm waiting for a kubeflow member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR adds configurable user-identity metadata injection to the ScheduledWorkflow controller so it can authenticate to the Pipelines API in multi-user mode using a specified identity header/value.
Changes:
- Add
--userIdentityHeader/--userIdentityValueflags and pass them into the controller. - Inject the configured identity metadata into outgoing gRPC requests when creating runs.
- Update the multi-user scheduled-workflow deployment patch to set the flags using the controller pod namespace, and add unit tests covering header injection behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| manifests/kustomize/base/installs/multi-user/scheduled-workflow/deployment-patch.yaml | Configures the controller pod to derive its namespace and pass identity args for multi-user authorization. |
| backend/src/crd/controller/scheduledworkflow/main.go | Adds CLI flags for identity header/value and wires them into controller construction. |
| backend/src/crd/controller/scheduledworkflow/controller.go | Stores identity config on the controller and appends it to outgoing gRPC metadata. |
| backend/src/crd/controller/scheduledworkflow/controller_auth_header_test.go | Adds tests validating identity metadata injection and coexistence with bearer token auth. |
Address review feedback on the user identity injection: - Normalize the configured userIdentityHeader to lowercase and validate it against gRPC metadata key rules in NewController, failing fast at startup instead of risking failed requests during reconciliation. - Clarify the --userIdentityHeader/--userIdentityValue flag help to state that the value is injected as outgoing gRPC metadata (not an HTTP header). - Add unit tests for the key normalization/validation helper and for NewController rejecting a malformed key. Signed-off-by: jaewak <jaewan.0907@gmail.com>
The multi-user deployment patch set the user identity flags via the pod spec 'args' field. The controller image has no ENTRYPOINT and invokes the binary through its CMD (a shell that maps env vars to flags), so setting 'args' replaced the entire CMD and the container tried to exec '--userIdentityHeader=...' as the binary, crash-looping with: exec: "--userIdentityHeader=kubeflow-userid": executable file not found in $PATH Follow the existing convention instead: expose the configuration as the USER_IDENTITY_HEADER / USER_IDENTITY_VALUE env vars and map them to the --userIdentityHeader / --userIdentityValue flags in the Dockerfile CMD. The multi-user patch now sets those env vars (defaulting to empty, so single-user deployments remain unaffected). Signed-off-by: jaewak <jaewan.0907@gmail.com>
|
@jaewak: Cannot trigger testing until a trusted user reviews the PR and leaves an DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Signed-off-by: jaewak <jaewan.0907@gmail.com>
Description of your changes:
Problem
In multi-user mode, the scheduled-workflow-controller calls
CreateRunvia gRPC to the API server when "Always use latest pipeline version" is enabled on a recurring run. The controller attaches anAuthorization: Bearer <token>header (when an SA token volume is mounted), but it never sets the user identity header (e.g.kubeflow-userid).The API server's
HTTPHeaderAuthenticatorrequires this header and rejects the request with:This was masked in clusters that mount a service-account token volume (where
TokenReviewAuthenticatorsucceeds), but customers without that volume see recurring runs silently fail to create child runs.Solution
Add two new opt-in CLI flags to the scheduled-workflow-controller:
--userIdentityHeaderkubeflow-userid)""(disabled)--userIdentityValue""(disabled)When both flags are set, the controller injects the key/value into the outgoing gRPC metadata alongside the existing Bearer token. When either is empty, nothing is injected — preserving backward compatibility for single-user deployments.
The configured key is normalized to lowercase and validated against gRPC metadata key rules at controller startup, so a malformed
--userIdentityHeaderfails fast with a clear error instead of causing failed requests during reconciliation.The multi-user kustomize deployment patch is updated to pass these flags using the controller's own service account identity, derived from the pod's namespace via the Kubernetes downward API.
Changes
backend/src/crd/controller/scheduledworkflow/controller.go— AddeduserIdentityHeader/userIdentityValuefields to theControllerstruct; wired intoNewController(which now normalizes and validates the key, failing fast on an invalid one); inject the key/value into outgoing gRPC metadata insubmitNewWorkflowIfNotAlreadySubmittedafter the existing Bearer token block.backend/src/crd/controller/scheduledworkflow/main.go— Addedflag.StringVarregistrations for the two new flags (help text clarifies the value is injected as outgoing gRPC metadata); passed toNewController.manifests/kustomize/base/installs/multi-user/scheduled-workflow/deployment-patch.yaml— AddedNAMESPACE_SELFenv var (downward API) andargs:with--userIdentityHeader=kubeflow-useridand--userIdentityValue=system:serviceaccount:$(NAMESPACE_SELF):ml-pipeline-scheduledworkflow.backend/src/crd/controller/scheduledworkflow/controller_auth_header_test.go(new) — Unit tests covering:Authorization: Bearertoken.NewControllerrejecting a malformed key.Checklist: