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

# Security and RBAC

> Every permission Mixpeek asks for in your cluster, and how to verify the claim yourself

One namespace. This page is the whole ask, with the verbs written out.

## What gets created

Applying the install kit creates six objects, all namespaced:

* one `ServiceAccount` (`mixpeek-submitter`)
* two `Role`s and their `RoleBinding`s
* one `ResourceQuota`

You can read every object in about five minutes.

## The short answer, for a security review

|                                              | Does Mixpeek install one?                                                                                                                                     |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CustomResourceDefinitions                    | **No.** Mixpeek defines no CRDs. KubeRay's three are the prerequisite below                                                                                   |
| Operators                                    | **No.** Mixpeek runs no operator or controller of its own                                                                                                     |
| ClusterRoles or ClusterRoleBindings          | **No**                                                                                                                                                        |
| Admission webhooks, mutating or validating   | **No.** Mixpeek registers nothing in the admission chain, so your own admission and scheduling policy applies to our pods with nothing of ours in front of it |
| Aggregated API servers, `APIService` objects | **No**                                                                                                                                                        |
| Anything outside the granted namespace       | **No**                                                                                                                                                        |

There is exactly one cluster-scoped prerequisite and it is not ours to install.

## The one cluster-scoped prerequisite

KubeRay is cluster-scoped, and there is no namespace-only way to install it.
Measured on kuberay-operator 1.5.1: **3 CustomResourceDefinitions**
(`rayclusters`, `rayjobs`, `rayservices`) and **5 ClusterRoles with 1
ClusterRoleBinding**. CRDs and ClusterRoles are cluster-scoped by definition.

The distinction that matters to a security review is lifetime:

|                                    | Scope         | Frequency             | Who normally holds it |
| ---------------------------------- | ------------- | --------------------- | --------------------- |
| Installing KubeRay                 | Cluster       | Once, then on upgrade | You                   |
| Everything Mixpeek does after that | One namespace | Continuous            | Mixpeek               |

Most customers reading this page already run KubeRay, in which case there is
nothing to grant. Where you do not, your platform team installs it once with a
published Helm command, and the steady-state ask is unchanged.

You can also grant it to us, and some customers prefer to. The permissions are
`customresourcedefinitions`, `clusterroles` and `clusterrolebindings`, all
`create`. The trade is straightforward: holding it yourself means a Mixpeek
release that requires a newer KubeRay waits for your change window.

<Note>
  On GKE these permissions are separable, which is worth knowing if you are
  scoping a custom role. An identity can hold
  `container.customResourceDefinitions.create` and not
  `container.clusterRoles.create`, so a check that reads only the CRD verb reports
  the grant as held on a cluster where the install will fail halfway. The
  qualification suite checks all three.
</Note>

## The two Roles, in full

### `rayjob-manager`: submitting batch work

| API group | Resources        | Verbs                                               |
| --------- | ---------------- | --------------------------------------------------- |
| `ray.io`  | `rayjobs`        | `create`, `get`, `list`, `watch`, `delete`, `patch` |
| core      | `secrets`        | `get`, `list`                                       |
| core      | `resourcequotas` | `get`, `list`                                       |
| core      | `services`       | `list`                                              |

`resourcequotas` is read so batches can be sized to fit under your quota rather
than discovering it by rejection. `services` is listed to resolve the Ray head.

### `ray-autoscaler-generation-stable`: letting Ray scale its own workers

| API group | Resources     | Verbs                           |
| --------- | ------------- | ------------------------------- |
| core      | `pods`        | `get`, `list`, `watch`, `patch` |
| core      | `pods/resize` | `patch`                         |
| `ray.io`  | `rayclusters` | `get`, `patch`                  |

This is Ray's own autoscaler, not Mixpeek code. `pods/resize` is in-place vertical
scaling, available from Kubernetes 1.33; on older clusters the rule is inert and
Ray falls back to replacing pods.

<Note>
  The binding is named for a generation-stable subject on purpose. KubeRay creates
  a new ServiceAccount per cluster generation, so a name-bound Role breaks on the
  first `RayService` swap and the symptom is that worker scale-up silently stops.
  If you intend to share this namespace with your own workloads, tell us and we
  will pin the generation instead.
</Note>

## What Mixpeek does not ask for

No `ClusterRole`. No cluster-scoped read of any kind. No ability to create
namespaces, read other namespaces, or touch nodes.

Verify it rather than believing it:

```bash theme={null}
kubectl auth can-i --list \
  --as=system:serviceaccount:mixpeek:mixpeek-submitter -n mixpeek
```

The qualification suite's `rbac-minimal-sa` row asserts five verbs we need and
five we must not have, including `create clusterroles`, `create namespaces`,
`delete nodes`, and creating RayJobs in a namespace other than ours. It fails if
any of the five forbidden answers `yes`.

<Warning>
  `kubectl auth can-i --as` requires impersonation rights. If you run it as an
  identity that cannot impersonate, every answer comes back `no` and the output
  reads like a clean bill of health. Check that you got a mix of answers.
</Warning>

## A disclosure we would rather you heard from us

**`get`/`list` on `rayjobs` currently also reads Mixpeek credentials.** Our batch
RayJob CRs carry credential-shaped environment variables as inline values on their
container specs, so anyone holding `rayjob-manager` can read them out of the CR.

The verbs are genuinely required for batch to work. The problem is what the CR
contains, and it is ours. It is tracked, being fixed in two phases (deliver via
`envFrom` from a Secret, then remove the inline values), and the qualification
suite **fails** on `Security/rayjob-cr-secrets` until it is done.

**How long the exposure lasts.** Batch RayJob CRs are submitted with
`ttlSecondsAfterFinished: 120`, so a finished job's CR self-deletes two minutes
after it completes. What is readable is in-flight and just-finished jobs, rather
than an accumulating pile of credential-bearing objects.

## Network policy

`networkpolicy.yaml` ships as a **template with the endpoints blank**, and is
deliberately not applied by default. An incomplete egress policy does not fail at
apply time; it fails hours later, in the middle of a batch, as a timeout that
looks like something else.

That leaves a third outcome, where you apply the kit, it works, and the policy is
never revisited. So the qualification suite reports whether *any* NetworkPolicy
governs the namespace. It is a **warning** rather than a failure, since running
without one is a legitimate choice on a flat internal cluster. The point is that
deciding against a policy and forgetting about it stop looking identical.

The suite also distinguishes a policy that exists from a policy that governs *our*
pods. One carrying a `podSelector` that matches something else leaves our
workloads exactly as open as none at all, while still counting as one.

## Using a namespace that is not `mixpeek`

Two edits before your first apply: the `namespace:` line in `kustomization.yaml`,
and the Group subject `system:serviceaccounts:mixpeek` in
`role-ray-autoscaler.yaml`, which kustomize does not rewrite.

Then `kubectl apply -k .` with no `-n`. Passing `-n` instead does not work:
kustomize stamps every object with the pinned namespace and kubectl refuses the
mismatch object by object.
