derailed/k9s · error

user is not authorized to view pod logs

Error message

user is not authorized to view pod logs

What it means

Pod.Logs authorizes get on the pods/log subresource (GVR pods:log) in the pod's namespace before opening the log stream. RBAC on pods does not imply pods/log — it is a separate subresource — so users who can read pods but were never granted the subresource are rejected here.

Source

Thrown at internal/dao/pod.go:159

			return res, fmt.Errorf("expecting interface map but got `%T", o)
		}
		if spec["nodeName"] == nodeName {
			res = append(res, &render.PodWithMetrics{Raw: u, MX: pmx[fqn]})
		}
	}

	return res, nil
}

// Logs fetch container logs for a given pod and container.
func (p *Pod) Logs(path string, opts *v1.PodLogOptions) (*restclient.Request, error) {
	ns, n := client.Namespaced(path)
	auth, err := p.Client().CanI(ns, client.NewGVR(client.PodGVR.String()+":log"), n, client.GetAccess)
	if err != nil {
		return nil, err
	}
	if !auth {
		return nil, fmt.Errorf("user is not authorized to view pod logs")
	}

	dial, err := p.Client().DialLogs()
	if err != nil {
		return nil, err
	}

	return dial.CoreV1().Pods(ns).GetLogs(n, opts), nil
}

// Containers returns all container names on pod.
func (p *Pod) Containers(path string, includeInit bool) ([]string, error) {
	pod, err := p.GetInstance(path)
	if err != nil {
		return nil, err
	}

	cc := make([]string, 0, len(pod.Spec.Containers)+len(pod.Spec.InitContainers))

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Extend the role: resources: ["pods", "pods/log"] verbs: ["get"]
  2. Verify: kubectl auth can-i get pods/log -n <namespace>
  3. Keep pods/log separate from pods/exec when designing least-privilege roles

Example fix

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-logs-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list"]
Defensive patterns

Strategy: validation

Validate before calling

ok, err := client.CanI(ns, "pods:log", podName, "get")
if err != nil { return err }
if !ok { return fmt.Errorf("no pods/log access in %s; ask for get on pods/log", ns) }

Try / catch

if _, err := podDAO.Logs(path, opts); err != nil {
    if strings.Contains(err.Error(), "not authorized to view pod logs") {
        // hide log actions for this user instead of retrying
    }
}

Prevention

When it happens

Trigger: CanI(ns, pods:log, <pod>, get) false — the role binds get/list on pods but never lists pods/log under resources.

Common situations: Hand-rolled minimal RBAC that forgets the subresource; viewer roles cloned from pod-read templates; break-glass debugging where the user can see pods but not their logs.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/da131aa03d3313bd. Report an issue: GitHub.