> ## Documentation Index
> Fetch the complete documentation index at: https://radarhq.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# RBAC under Cloud mode

> How a Cloud user's role becomes a Kubernetes identity. The cloud:owner / cloud:member / cloud:viewer groups, the X-Forwarded-* headers, and how to override the default ClusterRoleBindings.

When a Cloud user clicks into a cluster, the control plane injects their identity onto the request and the in-cluster Radar pod (running with `--auth-mode=proxy`) impersonates them on the K8s API. Per-user RBAC just works - via standard K8s impersonation, not a custom permission system.

## The header contract

For every request through the tunnel, the control plane:

1. **Strips inbound `X-Forwarded-*`** to prevent spoofing.
2. **Injects:**
   * `X-Forwarded-User: <user_id>` (e.g. `user_01HF...`)
   * `X-Forwarded-Groups: cloud:<role>,cloud:org:<org_id>,cloud:user:<user_id>`

`<role>` is one of `owner`, `member`, `viewer` - the user's [Cloud role](/docs/cloud/organizations#roles) in the org that owns the cluster.

The in-cluster Radar (under `RADAR_CLOUD_MODE=true`) is **forced** to `--auth-mode=proxy` with these header names pinned. The chart enforces this; you can't override it without un-cloud-mode-ing the in-cluster Radar.

## The default RBAC

The chart ships three ClusterRoleBindings out of the box:

| Cloud role | Impersonated as group | Bound to ClusterRole   |
| ---------- | --------------------- | ---------------------- |
| Owner      | `cloud:owner`         | `admin` (K8s built-in) |
| Member     | `cloud:member`        | `edit` (K8s built-in)  |
| Viewer     | `cloud:viewer`        | `view` (K8s built-in)  |

K8s itself decides what each ClusterRole permits. `view` is read-only for namespaced resources. `edit` adds writes. `admin` adds RBAC operations.

## Overriding the defaults

The chart's `cloud.defaultRbac.*` block lets you swap each binding:

```yaml theme={null}
# values.yaml for the in-cluster Radar
cloud:
  enabled: true
  url: wss://api.radarhq.io/agent
  clusterName: cl_xxx
  existingSecret: radar-cloud-token
  defaultRbac:
    create: true                       # set false to skip all three bindings
    owner: true                        # emit cloud:owner binding
    member: true
    viewer: true
    ownerClusterRole: cluster-admin    # ClusterRole each binding maps to
    memberClusterRole: edit
    viewerClusterRole: view
```

To **disable** a binding entirely (e.g. you want only owners to have access, no members or viewers):

```yaml theme={null}
cloud:
  defaultRbac:
    member: false
    viewer: false
```

Members and viewers will then hit 403s when they try to do anything in the cluster. The Cloud UI still shows the cluster in the list - it's the K8s API that's saying no.

## Per-user bindings

If you need finer control than role-level (e.g. specific user can edit deployments but only in `apps/*` namespaces), bind directly to the per-user group:

```yaml theme={null}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-apps-edit
  namespace: apps-prod
subjects:
  - kind: Group
    name: cloud:user:user_01HF...     # user_id from Settings → Tokens or audit log
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: edit
  apiGroup: rbac.authorization.k8s.io
```

Find a user's `user_id` in:

* The audit log row metadata.
* The user's PAT page (their own ID is shown at the top).
* Owner's view of **Settings → Organization → Members** (hover the row).

## Per-org bindings

Every request also carries `cloud:org:<org_id>` in the groups header. This is mostly useful for clusters that move between orgs - typically you wouldn't need to bind to it directly. But if you ever need "any user from this org can do X", that's the hook.

## Auditing what the in-cluster Radar did

K8s itself logs impersonated requests in `audit.k8s.io` if you've enabled the audit policy on the apiserver. The user ID and groups are present in the audit log entry, so you can correlate "user X did Y" against the Cloud audit log (which shows control-plane actions) and the K8s audit log (which shows in-cluster actions).

## Things to watch out for

* **Default `admin` is broad.** It can read Secrets, mutate RBAC, drain nodes. If you have non-admin owners, swap `cloud:owner` to a custom ClusterRole.
* **`view` doesn't see Secrets.** That's K8s `view` definition, not ours. If you want viewers to see Secret names without values, use a custom ClusterRole that grants `get/list` on `secrets` (which lets them see Secret data too - K8s doesn't have field-level RBAC). Since [Secret data is redacted by Radar](/docs/features/mcp#security-model) before display, this is usually safe but think it through.
* **Helm write needs more than `edit`.** Helm install / upgrade / rollback / uninstall need broad write access, including Secrets (Helm releases are Secrets). The chart's default `member → edit` is intentionally **not enough** for Helm writes; opt in via a custom binding if you want members to manage Helm.

## See also

* [Authentication](/docs/configuration/authentication) - how proxy / OIDC mode work generally.
* [Connecting a cluster](/docs/cloud/connect-cluster) - the chart values that enable cloud-mode.
* [Organizations & roles](/docs/cloud/organizations) - the role definitions that drive these groups.
