Add selfhosted authorization documentation#873
Add selfhosted authorization documentation#873mhotan wants to merge 6 commits intopeeter/selfhosted-docsfrom
Conversation
Covers the three authorization modes: - Noop: no enforcement (default, development/small teams) - External: customer-provided gRPC authorization server - UserClouds: Union built-in RBAC Includes architecture diagram, trade-offs comparison, Helm and Terraform configuration examples, observability metrics/alerts reference, verification steps, and troubleshooting guide. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Deploying docs with
|
| Latest commit: |
61e40a4
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://9d591fc5.docs-dog.pages.dev |
| Branch Preview URL: | https://mike-selfhosted-authorizatio.docs-dog.pages.dev |
## Summary Centralizes authorization configuration in the controlplane helm chart so all deployment modes (Noop, External, UserClouds) are configured through values overlays rather than hardcoded logic. ### Key Changes **TypeAuthorizer routing defaults:** - All non-authorizer services default to `TypeAuthorizer` with `authorizerClient.grpcConfig` pointing directly to the authorizer service over plaintext gRPC - The authorizer service itself defaults to `TypeNoop` with documented examples for External and UserClouds backends **Config refactor:** - Replace bare `authorizerEndpoint` string with structured `authorizerClient` containing `grpcConfig` (host, insecure, etc.) and `forwardHeaders` - Merge ingress auth annotations from #293 into base values **Remove global.AUTHZ_TYPE:** - Remove the forced Noop override in `_helpers.tpl` that stomped on values overlays when `AUTHZ_TYPE != "union"` - Remove `AUTHZ_TYPE` global variable — authorization is now purely values-driven - Gate union-authz sidecar (UserClouds) templates on `services.authorizer.configMap.authorizer.type == "UserClouds"` instead of separate enable flag **Observability (Phases 4-5):** - Add 6 dashboard panels to the Authorizer row: Mode stat, External Backend Latency, External Errors by gRPC Code, Fail-Open Activations, Decisions by Action, Error Attribution - Add 3 PrometheusRule alerts: ExternalErrors (warning), FailOpenActive (critical), HighDenyRate (warning) - Add recording rule for external error rate **Service template:** - Add `grpc-native` port for services with `connectPort` (exposes native gRPC alongside Connect) ### Release Notes **Authorization configuration is now values-driven.** The `global.AUTHZ_TYPE` variable has been removed. Authorization mode is configured solely through `services.authorizer.configMap.authorizer.type` (`"Noop"`, `"External"`, or `"UserClouds"`). If you previously set `global.AUTHZ_TYPE: "union"` in your values overlay, migrate to: ```yaml services: authorizer: configMap: authorizer: type: "UserClouds" ``` The `protectedIngressAnnotationsGrpc` auth annotations (from #293) are now included in the base chart defaults. ### Related PRs - cloud [#14943](unionai/cloud#14943) — TypeExternal authorizer backend (merged) - docs [#873](unionai/unionai-docs#873) — Selfhosted authorization documentation ## Test plan - [x] `make generate-expected && make test` passes - [x] `helm template` renders correct configs for ext-authz environment - [x] Deployed to ext-authz staging — all services running, ListRuns working - [x] Verified authorizer configmap renders `type: External` with `externalClient` - [x] Dashboard panels and recording rule render in template output - [x] Alerts render when `monitoring.alerting.enabled: true` - [ ] Verify existing BYOC deployments (TypeUserClouds path) are unaffected 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Add Prerequisites section linking to authentication, mapping OAuth apps to identity types and required JWT claims - Add External authorization server requirements: gRPC contract, identity resolution, complete actions table, service account permissions for Apps 3/4/5 with warnings about what breaks - Rename UserClouds to Union (built-in RBAC) in user-facing text, note legacy config value with future rename planned - Reference implementation noted as non-generic example - Use namespace placeholders in kubectl commands - Expand troubleshooting with service-account-specific scenarios Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ences - Replace internal service names (flyteadmin, executions, etc.) with generic labels in architecture diagram - Remove union-authz service name from user-facing text - Use placeholders for service endpoints and namespaces - Fix diagram alignment and stray code fence Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
||
| {{< key product_name >}} self-hosted deployments support configurable authorization backends to control who can perform which actions on platform resources. The authorization mode determines how access control decisions are made for API requests from the console, CLI, and SDK. | ||
|
|
||
| Unlike serverless and BYOC deployments where {{< key product_name >}} manages RBAC for you, **self-hosted deployments let you choose the authorization model** that fits your organization's security requirements. |
There was a problem hiding this comment.
Unlike serverless and BYOC deployments
It was my understanding that we're quietly shutting down serverless. Do we need to mention it here?
| | Claim | Values | Used for | | ||
| | ---------------------- | ------------------------------------- | ------------------------------------------------------ | | ||
| | `sub` | User's internal ID or app's client ID | Primary identity for authorization decisions | | ||
| | `identitytype` | `"user"` or `"app"` | Distinguishes human users from service accounts | |
There was a problem hiding this comment.
technically no longer a requirement with the external identity type, but definitely a nice to have when not using an external authorization impl
| | `preferred_username` | User login or app client ID | Identity injection ("Owned By" display in the console) | | ||
|
|
||
| > [!WARNING] | ||
| > Without the `identitytype` claim, the authorizer cannot distinguish users from applications. This may cause all requests to be misclassified or denied. See [Authentication — Authorization server setup]({{< relref "authentication#authorization-server-setup" >}}) for claim configuration details. |
There was a problem hiding this comment.
again, only true if not using the external authz impl
| | OAuth App | # | Token `sub` claim | Identity type | Purpose in authorization | | ||
| | ------------------ | - | ------------------- | ------------- | ----------------------------------------- | | ||
| | Browser login | 1 | User's internal ID | `user` | End-user console/UI actions | | ||
| | CLI | 2 | User's internal ID | `user` | End-user CLI actions | |
There was a problem hiding this comment.
nit but maybe not worth elaborating, you can log in with the cli using app creds too
| | ------------------ | - | ------------------- | ------------- | ----------------------------------------- | | ||
| | Browser login | 1 | User's internal ID | `user` | End-user console/UI actions | | ||
| | CLI | 2 | User's internal ID | `user` | End-user CLI actions | | ||
| | Service-to-service | 3 | App's client ID | `app` | Internal controlplane calls through NGINX | |
There was a problem hiding this comment.
are 3) onwards internal apps? is it worth distinguishing them here?
|
|
||
| ## Architecture | ||
|
|
||
| All controlplane services route authorization decisions through a centralized **authorizer service**. The authorizer service delegates to a configurable backend: |
There was a problem hiding this comment.
This is all external facing, right? How conservative do we want to be with leaking private implementation details?
| The authorizer service resolves the caller's identity before forwarding to your server. Identity arrives through two channels: | ||
|
|
||
| 1. **gRPC metadata headers** (`authorization` / `flyte-authorization`) — forwarded to your server if configured in `forwardHeaders`. Contains the raw JWT/OIDC token. Your server can decode the JWT payload to read claims (`sub`, `identitytype`, `email`, `groups`, etc.) without signature verification — the token has already been validated by the controlplane's auth middleware. | ||
| 2. **`AuthorizeRequest.identity` protobuf field** — a structured identity set by the authorizer service. Contains `user_id.subject`, `application_id.subject`, or `external_identity.subject` + `external_identity.token`. |
There was a problem hiding this comment.
I'd put this first, it's the recommended field to use
|
|
||
| | OAuth App | # | Subject (`sub` claim) | Required permissions | | ||
| | ------------------ | - | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | Service-to-service | 3 | `INTERNAL_CLIENT_ID` value | `VIEW_FLYTE_INVENTORY`, `VIEW_FLYTE_EXECUTIONS`, `CREATE_FLYTE_EXECUTIONS`, `MANAGE_CLUSTER` | |
There was a problem hiding this comment.
Is this really all this requires? internally i think we have an expanded permission set
| A [Python reference implementation](https://github.com/unionai/cloud/tree/main/examples/external-authz-server) is available as an example. It demonstrates: | ||
|
|
||
| - Extracting identity from forwarded JWT metadata headers | ||
| - Falling back to the proto `Identity` field when no JWT is present |
There was a problem hiding this comment.
still not a fan of this recommendation :)
|
|
||
| ### Reference implementation | ||
|
|
||
| A [Python reference implementation](https://github.com/unionai/cloud/tree/main/examples/external-authz-server) is available as an example. It demonstrates: |
There was a problem hiding this comment.
this is a link to the private repo, right?
| # Expected: Authorization decisions with identity and action details | ||
| ``` | ||
|
|
||
| 5. **Verify service account access:** Check that internal platform operations are working by navigating the console and triggering a workflow execution. Monitor the external server logs for requests from the service account subjects (Apps 3, 4, 5). |
There was a problem hiding this comment.
I'd also check triggering an execution from the CLI for the non-browser flow
Summary
Content
The page covers:
authorization_modevariable configurationRelated PRs
🤖 Generated with Claude Code