Skip to main content

Cluster permissions

Before deploying AI Gateway, ensure you have the appropriate RBAC permissions in your Kubernetes cluster. This section is written so your security team can pre-review the full permission surface before any install runs.

Bootstrap vs steady-state permissions​

There are two distinct permission scopes. Treat them differently in your security review.

PhaseWho needs itWhat it coversScopeWhen it's used
Bootstrap (one-time)The human or service account running aigateway deploy installCreating the target namespace (if absent), the Operator's ServiceAccount + Role + RoleBinding (skipped if a service account is provided in pool config), the API-auth Secret, the optional registry-credentials Secret, and the initial Operator DeploymentNamespace-scopedOnce per pool, at install. Can be revoked afterwards.
Steady-state (ongoing)The Operator's own ServiceAccountReconciling Armor, Redis (when auto-installed), ingress, HPAs, PDBs, leader-election leases, and MCP server deployments inside the pool's namespaceNamespace-scoped only (Role, not ClusterRole)Continuously, as the Operator runs

The Operator never needs cluster-admin. Once the bootstrap is complete, all reconciliation happens inside the pool's namespace.

For security review: generate the exact deployer Role manifest with aigateway cluster permissions --generate-role --namespace <ns> and share it with your platform/security team before scheduling the install.

What changes when you use a pool-provided ServiceAccount​

If you set Service Account on the pool (Basic Information tab) to a pre-provisioned SA name, the bootstrap path skips creating the Operator's ServiceAccount, Role, and RoleBinding. It only verifies that the ServiceAccount exists in the namespace and prints the RBAC rules the ServiceAccount must already have bound. That changes what the deployer (the principal running aigateway deploy install) needs:

Deployer permissionDefault (CLI creates ServiceAccount + RBAC)Pool-provided ServiceAccount
serviceaccounts create/update/patchRequiredNot required
rbac.authorization.k8s.io/roles create/update/patchRequiredNot required
rbac.authorization.k8s.io/rolebindings create/update/patchRequiredNot required
serviceaccounts getRequired (verify)Required (verify ServiceAccount exists)
Everything else in Deployer Permissions belowRequiredRequired

When you use a pool-provided ServiceAccount, the responsibility for binding the Operator's runtime Role to the ServiceAccount shifts to your platform team. Use the Operator runtime Role section below as the source of truth for what the ServiceAccount must be able to do.

Deployer Permissions​

These are the namespace-scoped permissions the deployer needs to run aigateway deploy install. This matches what aigateway cluster permissions --generate-role --namespace <ns> outputs.

Core workload resources​

ResourceAPI GroupVerbsPurpose
deploymentsappsget, list, watch, create, update, patch, deleteDeploy Operator, Armor, and SIEM components
statefulsetsappsget, list, watch, create, update, patch, deleteManage Redis (auto-install mode)
servicescoreget, list, watch, create, update, patch, deleteCreate service endpoints
secretscoreget, list, watch, create, update, patch, deleteManage API credentials and registry secrets
configmapscoreget, list, watch, create, update, patch, deleteStore configuration data
persistentvolumeclaimscoreget, list, watch, create, update, patch, deletePersistent storage for Redis (auto-install mode)
podscoreget, list, watchMonitor pod health and status
pods/execcorecreateOperator runtime operations
eventscoreget, listView Kubernetes events for troubleshooting

Scaling​

ResourceAPI GroupVerbsPurpose
horizontalpodautoscalersautoscalingget, list, watch, create, update, patch, deleteAuto-scale Armor and MCP deployments

Networking​

ResourceAPI GroupVerbsPurpose
ingressesnetworking.k8s.ioget, list, watch, create, update, patch, deleteExpose MCP servers externally

RBAC (required unless using a pool-provided ServiceAccount)​

ResourceAPI GroupVerbsPurpose
serviceaccountscoreget, create, update, patch (or just get with a pool-provided ServiceAccount)Create or verify the Operator's ServiceAccount
rolesrbac.authorization.k8s.ioget, create, update, patch (omitted with a pool-provided ServiceAccount)Create the Operator's Role
rolebindingsrbac.authorization.k8s.ioget, create, update, patch (omitted with a pool-provided ServiceAccount)Bind the Operator's Role to its ServiceAccount

Operator runtime Role​

The Operator's runtime Role is created automatically by the bootstrap step (or, when a pool-provided ServiceAccount is used, must be pre-bound by your platform team). It is broader than the deployer's permissions because it also covers what the Operator needs during steady-state reconciliation. The full set of rules is:

ResourceAPI GroupVerbsPurpose
pods, services, configmaps, secrets, persistentvolumeclaimscoreget, list, watch, create, update, patch, deleteManage Armor, Redis (auto-install), and MCP workloads + their config/state
eventscoreget, list, watchSurface cluster events into pool diagnostics
pods/execcorecreateOperator-side maintenance into pods
deployments, statefulsetsappsget, list, watch, create, update, patch, deleteManage Armor, Redis StatefulSet (auto-install), MCP Deployments
ingressesnetworking.k8s.ioget, list, watch, create, update, patch, deleteDefault ingress mode
horizontalpodautoscalersautoscalingget, list, watch, create, update, patch, deleteAuto-scale Armor and MCP deployments
poddisruptionbudgetspolicyget, list, watch, create, update, patch, deleteHA safeguards on Armor / Redis (auto-install) / MCP deployments
leasescoordination.k8s.ioget, list, watch, create, update, patch, deleteOperator leader election
gateways, virtualservicesnetworking.istio.ioget, list, watch, create, update, patch, deleteIstio ingress mode
ingressroutestraefik.ioget, list, watch, create, update, patch, deleteTraefik ingress mode
httproutesgateway.networking.k8s.ioget, list, watch, create, update, patch, deleteKubernetes Gateway API ingress mode
routesroute.openshift.ioget, list, watch, create, update, patch, deleteOpenShift routes

The four ingress-provider rules (Istio, Traefik, Gateway API, OpenShift) are granted unconditionally even if your pool currently uses a different mode. The Operator reads them at startup, and ingress mode can be changed later from the portal without re-rolling RBAC. Granting them on a cluster that doesn't have those CRDs installed is harmless — RBAC rules for absent resources are simply unused.

The bootstrap step creates this Role and a RoleBinding to the Operator's ServiceAccount. When you use a pool-provided ServiceAccount, you must create this Role yourself and bind it to your ServiceAccount before running aigateway deploy install — the CLI verifies the ServiceAccount exists but does not create or modify any RBAC for it.

Example Operator runtime Role (verified against a live aigw-operator Role; all four ingress-provider rules included because the CLI and Operator support all of them — keep the ones that match your ingress mode and comment out the rest if your platform team prefers a narrower manifest):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: aigw-operator
namespace: ai-gateway
rules:
# Core workload resources
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets", "persistentvolumeclaims"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# Scaling and high availability
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["policy"]
resources: ["poddisruptionbudgets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# --- Ingress: default (Kubernetes Ingress, includes AWS ALB / nginx / GKE / AKS / Azure App Gateway) ---
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# --- Ingress: Istio service mesh ---
- apiGroups: ["networking.istio.io"]
resources: ["gateways", "virtualservices"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# --- Ingress: Traefik ---
- apiGroups: ["traefik.io"]
resources: ["ingressroutes"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# --- Ingress: Kubernetes Gateway API ---
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["httproutes"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

# --- Ingress: OpenShift routes ---
- apiGroups: ["route.openshift.io"]
resources: ["routes"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

The bootstrap creates this Role with all ingress-provider rules included regardless of which mode your pool currently uses — that's the safest default (changing ingress mode later from the portal doesn't require re-rolling RBAC). If your platform team prefers a tighter manifest, comment out the rule groups for ingress providers you're not using; just remember to re-apply if you ever change the pool's ingress mode.

Bind the Role to your ServiceAccount:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: aigw-operator
namespace: ai-gateway
subjects:
- kind: ServiceAccount
name: <your-pool-service-account-name>
namespace: ai-gateway
roleRef:
kind: Role
name: aigw-operator
apiGroup: rbac.authorization.k8s.io

Checking Permissions​

Use the CLI to verify you have the required permissions:

# Check permissions for specific namespace
aigateway cluster permissions --namespace ai-gateway

# JSON output for automation
aigateway cluster permissions --namespace ai-gateway --json

Setting Up RBAC​

If you lack sufficient permissions, generate and apply the deployer Role:

Step 1: Generate the deployer Role

aigateway cluster permissions --generate-role --namespace ai-gateway > aigateway-deployer-role.yaml

Example output (verified against CLI v1.0.10):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: aigateway-deployer
namespace: ai-gateway
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["apps"]
resources: ["statefulsets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
- apiGroups: [""]
resources: ["events"]
verbs: ["get", "list"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["autoscaling"]
resources: ["horizontalpodautoscalers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["get", "create", "update", "patch"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["get", "create", "update", "patch"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["get", "create", "update", "patch"]

This is the deployer Role only — namespace-scoped, used to run aigateway deploy install. It does not include the Operator's runtime resources (policy/poddisruptionbudgets, coordination.k8s.io/leases, and the Istio/Traefik/Gateway-API/OpenShift ingress-provider resources). Those go in the separate Operator runtime Role, which the bootstrap creates automatically when it provisions the Operator's ServiceAccount.

If you provide a pre-existing ServiceAccount on the pool (set on the Basic Information tab), the bootstrap does not create or modify any Role/RoleBinding — you must construct the Operator runtime Role yourself based on the table in Operator runtime Role and bind it to your ServiceAccount before running aigateway deploy install.

Note: The CLI's emitted YAML uses unquoted flow-style verb lists (for example verbs: [get list watch ...]). That's valid syntactically in some YAML parsers but not in others — if kubectl apply rejects it, normalise the verbs into a quoted comma-separated list as shown above (verbs: ["get", "list", "watch", ...]). The semantics are identical.

Step 2: Create RoleBinding

Bind the Role to your user or service account:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: aigateway-deployer-binding
namespace: ai-gateway
subjects:
- kind: User
name: your-username@company.com # Replace with your username
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: aigateway-deployer
apiGroup: rbac.authorization.k8s.io

Step 3: Apply

kubectl apply -f aigateway-deployer-role.yaml
kubectl apply -f aigateway-deployer-rolebinding.yaml

For CI/CD: Use a ServiceAccount instead of User in the RoleBinding:

subjects:
- kind: ServiceAccount
name: aigateway-deployer
namespace: ai-gateway

Skipping Permission Checks​

Use the --skip-permission-checks flag if permission validation fails but you know you have the necessary permissions:

aigateway deploy install --skip-permission-checks

Warning: Only use this if you've verified your permissions. Deployment will fail if you lack required permissions.

What to share with your security team​

For a pre-install review, the artifacts to hand over are:

  • The deployer Role manifest — generate with aigateway cluster permissions --generate-role --namespace <ns> (see Setting Up RBAC for an example).
  • The Operator runtime Role — the table in Operator runtime Role lists everything the Operator's ServiceAccount gets bound to (created automatically by the bootstrap, or constructed manually when a pool-provided ServiceAccount is used).
  • The full set of manifests the Operator would apply — aigateway deploy install --dry-run --show-manifests. This is for review only, not a fork-and-maintain path; see Deployment Model.
  • The image list (or release path) for supply-chain review — see Mirroring images from your internal artifact registry on the pool's image fields.
  • The list of egress endpoints the Operator and Armor need to reach — see the egress allowlist.

Troubleshooting​

Common Issues:

IssueSolution
namespace not foundHave admin create namespace: kubectl create namespace ai-gateway
roles.rbac.authorization.k8s.io is forbiddenUse existing service account or ask admin to create RBAC resources
storageclasses is forbiddenUse --skip-permission-checks flag
Permissions not working after applying RoleVerify RoleBinding references correct user/namespace, wait for RBAC cache update

Tips​

  • Store credentials securely (use Kubernetes secrets, not plain text)
  • Use least-privilege RBAC (generate roles with aigateway cluster permissions --generate-role)
  • Enable TLS for all production deployments
  • Regularly rotate API credentials and registry secrets