kubectl access to troubleshoot your application in a customer’s cloud. This guide limits access to pod inspection and exec in app-system, with a 30-minute grant.
Just-in-time access means you hold no standing credentials for the environment. You request access when you need it, your customer approves it, and the access ends on its own when the window closes.
The example uses a support-debug permission set, a customer-prod environment, the app-system namespace, and an api installation. Substitute your own names.
Before you start
customer-prodrunning components that support permission sets. See provisioning prerequisites.- kubectl v1.31 or newer. Ryvn bridges pod exec, attach, and port-forward over WebSocket, and older kubectl negotiates SPDY instead.
app-systempresent in that environment’s cluster.
kube-system, add a separate permission with its own scope and rules.
Read the installation’s namespace instead of guessing it:
Step 1: Create the permission set
Environment administrator. A permission set is a named set of Kubernetes RBAC rules paired with a Ryvn scope.- CLI
- Dashboard
create on pods/exec, so that verb is the one the set needs.
Add pod logs only if your team needs them:
secrets, wildcards (*), or a cluster scope. Every rule you add applies for the full duration of every grant issued against the set.
Read back what you published:
Step 2: Require approval on the environment
Environment administrator. Set the environment’s Connect mode to by-request so no one reaches the cluster without an approved grant.- Dashboard
- GitOps
mode: default with a defaultPermissionSet) grants that one set without approval and follows its latest revision. Off (mode: off) blocks new access and revokes active grants. An environment that has never set connect keeps its previous role-derived behavior.Step 3: Request access
Request 30 minutes of access and include the reason:--reason is required. --duration defaults to 1 hour and cannot exceed 8 hours. An undecided request expires after 24 hours, which is a deadline for the decision, not the length of the access.
While an identical request is still pending, running the same command again returns that request instead of creating a second one. Change the reason or duration and you create a new request.
Check on it without re-requesting:
Step 4: Approve
Your customer approves in the dashboard Inbox, or under Environment → Access requests on their stack. Pending only lists what needs a decision; All requests and View grants show decisions already made. Each request shows the requester, the environment, the permission set and its revision, the requested duration, and the reason. Expand it to read the rules before deciding. Approval accepts exactly what was requested; there is no field for trimming the namespace or dropping a verb. To narrow it, deny the request and ask for a different permission set.- Dashboard
- CLI
kubectl command. A new request emits an access_request.pending notification to any Slack destination subscribed to that event.
Step 5: Connect and debug
Run the resume command the CLI printed. In the dashboard, use Copy resume command on your own pending request, or Copy connect command once it is approved. Both commands pin the org, so prefer them over retyping:-- <command> to run one command and exit instead.
-n app-system explicitly. Every request is authorized against the namespace it names, so a command in another namespace is denied, and so is a cluster-wide request such as kubectl get pods -A. A command without -n uses your current context’s namespace, which is denied when that namespace is outside the grant.
Reconnect as often as you need while the grant lasts. A single exec, attach, port-forward, or watch stream ends when the credential that opened it expires; run the command again for a new stream. Add --kubeconfig to write a context into ~/.kube/config for your own tooling; it stays pinned to this grant and its revision, and stops working when the grant ends or is revoked rather than falling back to the environment’s default access. A context written under default access instead follows the environment’s default permission set: when a newer revision is published, the next token refresh picks it up. Nothing is ever moved onto a revision it was not authorized under: a stream that is already open is closed when the proxy next re-checks it, and a command that still presents kubectl’s cached token from the old revision is refused with 401 Unauthorized (revision_superseded), which makes kubectl discard the cached token and mint again; the refused command is not replayed, and the next one opens under the current revision. Grant contexts are never refreshed this way: their denials stay 403.
kubectl attach and kubectl port-forward work the same way as exec. Ryvn forwards the request to the cluster exactly as kubectl sent it, so the cluster’s own RBAC decides: kubectl v1.31+ opens these WebSocket streams with an HTTP GET, which Kubernetes v1.31–v1.34 authorize as the get verb on pods/attach / pods/portforward, and Kubernetes v1.35+ additionally checks create on the same subresource. Grant both verbs on exactly the subresources you want to allow — the set in this guide has neither, so add a rule such as the one below before requesting. Do not widen the pods rule itself or the exec-only sets already in use. Port-forward over WebSocket also needs a cluster running Kubernetes v1.31 or newer; against an older cluster kubectl falls back to SPDY, which Ryvn refuses.
Step 6: Revoke access
Revoke your own grant when you are finished. Your customer can revoke any grant on their environment.access.renewal server configuration. Ryvn accepts the rules an environment last verified for a bounded validity window, and each connection is re-checked on a check interval inside that window. By default the window is six seconds, so a revocation or rule change takes effect within seconds, but a short agent or network hiccup can also interrupt access. Raising the window (up to five minutes, with checks about every thirty seconds) keeps access steady through brief outages, at the cost that a revocation can take up to the remaining window to reach a stream whose agent has gone quiet; a reachable agent still applies it on the next check. A grant’s own expiry and the credential’s lifetime are enforced independently of the window and never extend it.
The credential lifetime is the hub’s access.nativeCredentialTTL setting: 15 minutes unless configured, at most 8 hours, and never past the grant’s end for grant-backed access. A stream lives as long as the credential that opened it. Credentials are minted on demand by the kubeconfig’s exec plugin, one per kubectl refresh, so there is no single “session credential”: ryvn connect prints the grant deadline and notes how credentials are issued, labelling the expiry of its own preflight check credential (which kubectl never uses) as exactly that.
Review what happened afterwards:
Troubleshooting
Status stays approval_pending
Status stays approval_pending
ryvn connect returns the same request. Ask a developer or operator on the environment other than yourself to decide. Undecided requests expire after 24 hours.Approved, but connect returns materialization_pending
Approved, but connect returns materialization_pending
kubectl access is not enabled for this environment
kubectl access is not enabled for this environment
This request is outside the permission set granted to your session
This request is outside the permission set granted to your session
pods/log, or exec rules missing a verb. Check the pinned revision with ryvn describe permission-set support-debug --revision <revision-id>. Editing the set does not change a grant already approved.This session is not permitted to exec into pods
This session is not permitted to exec into pods
pods/exec rule lacks create, the verb exec requests are authorized against. Publish a revision granting create on pods/exec and request again.Exec requires WebSocket streaming
Exec requires WebSocket streaming
Access proxy is at pod stream capacity (ExecAtCapacity)
Access proxy is at pod stream capacity (ExecAtCapacity)
Retry-After; end an idle stream or wait a few seconds and run the command again. Long-running port-forwards count against the cap for as long as they stay open.Namespace not found, or forbidden despite matching the name
Namespace not found, or forbidden despite matching the name
ryvn describe installation api -e customer-prod. A namespaceNames scope grants nothing for a namespace that does not exist and is blocked for a namespace another Ryvn environment manages. allManagedNamespaces and namespaceSelector reach only namespaces Ryvn manages in the environment, so confirm the namespace is declared on the environment or used by an installation, and that namespaceFilter does not exclude it.ConfigMap writes: 'is a Ryvn Connect mailbox' or a native admission denial
ConfigMap writes: 'is a Ryvn Connect mailbox' or a native admission denial
create, update, patch, delete, or deletecollection on configmaps are ordinary application authority and are issued as written, including in the environment’s Ryvn system namespace. Two ConfigMaps in that namespace are Ryvn Connect’s internal mailboxes (access-intent-<environment-id> and access-activation-<environment-id>) and are protected by a cluster admission policy the agent installs and reads back: only the Ryvn agent may mutate them. If a revision names one of them in resourceNames, the revision publishes but the environment never materializes it: connect stays materialization_pending and the projection is blocked with is a Ryvn Connect mailbox; publish a revision without the name. If a kubectl write against one of them is refused with a ValidatingAdmissionPolicy denial, that is expected and unrelated to your grant. Other ConfigMaps in the same namespace, and ConfigMaps with the same names in other namespaces, are writable under your rules.Role and RoleBinding writes: what is issued, refused, or left behind
Role and RoleBinding writes: what is issued, refused, or left behind
create, update, patch, or delete on roles or rolebindings in rbac.authorization.k8s.io are issued as written for a namespace scope, and only after the environment’s agent has installed and read back the admission policies that protect Ryvn’s own RBAC objects. Until that readback succeeds the revision publishes but the environment does not materialize it (protection not yet observed); the agent retries on its own. Kubernetes’ escalation prevention still applies: you can only grant rights your grant already holds, so a Role adding secrets or a RoleBinding to cluster-admin is refused natively, and Ryvn-owned Roles and RoleBindings in the namespace are refused by admission. bind, escalate, impersonation, ServiceAccount tokens, and any write to clusterroles, clusterrolebindings, namespaces, CRDs, or admission policies are never issued; a revision that asks for them is blocked with UnsupportedDelegation. Reads (get, list, watch) on all four RBAC kinds stay available. Roles and RoleBindings you create or edit under such a grant are ordinary objects in the customer’s cluster: they remain after the grant expires or is revoked and are not rolled back by Ryvn. A RoleBinding you create or update under the grant may name only your own session subject (exactly one User, your session’s username): binding another user, a group, a ServiceAccount, or several subjects is refused by admission with a reason, so your rights cannot be handed to another holder that would keep them after your window closes. Bindings created by cluster administrators outside the grant are not restricted. Remove what you no longer need before the window closes.Multiple grants, or the wrong org or profile
Multiple grants, or the wrong org or profile
multiple_grants means more than one active grant applies; choose one with ryvn connect customer-prod --grant <grant-id>. If a permission set or environment appears not to exist, check ryvn auth status and pass --profile for the org that owns the environment.Related
- Deployment Approvals for the same review model applied to changes
- Access Policy for the roles that decide who may request, approve, and revoke
- Ryvn CLI for installation, profiles, and authentication