Kubernetes RBAC and NetworkPolicy Review
Kubernetes RBAC governs requests to Kubernetes API. NetworkPolicy selects Pod traffic, but works only when installed CNI enforces it. Review them together: compromised workload with broad API token and open egress crosses boundaries differently from workload with minimal Role and constrained traffic. Neither control proves application authorization or node hardening.
Start with identities and bindings
Export ServiceAccounts, Roles, ClusterRoles, RoleBindings, ClusterRoleBindings, namespace labels, and active workload manifests. Kubernetes guidance advises least privilege, avoiding wildcard permissions, and minimizing privileged token distribution. Identify every cluster-admin, wildcard verb, wildcard resource, impersonate, secret read, pod exec, and binding to broad groups.
| Boundary | Completed artifact | Evidence test | Owner | Pass / fail |
|---|---|---|---|---|
| Service account | workload-to-SA map | default SA not granted privilege | workload owner | each workload has intended identity |
| Namespace access | Role and RoleBinding export | kubectl auth can-i denies unnecessary verb | namespace owner | least privilege evidenced |
| Cluster access | ClusterRoleBinding register | scope justified; no broad accidental subject | cluster owner | binding reviewed |
| Ingress | default-deny policy plus allowed flows | unapproved Pod path blocked | network owner | intended caller only |
| Egress | default-deny policy plus DNS/service rules | unexpected destination blocked | network owner | required flow works |
Use Role and RoleBinding for namespace work. A ClusterRole can be bound through RoleBinding only within target namespace; ClusterRoleBinding grants its permissions cluster-wide. Do not bind application service account to cluster-admin to solve a deployment error. Replace it with exact API groups, resources, verbs, and names where resource names are stable.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata: { name: report-reader, namespace: payments }
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata: { name: report-reader, namespace: payments }
subjects:
- kind: ServiceAccount
name: reports
namespace: payments
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: report-reader
Record command, identity, namespace, expected result, actual result, and timestamp for authorization tests. Example fail: service account can list Secrets although workload has no need. Remediation means revised manifest, applied object export, denied retest, and owner—not “RBAC tightened.”
Default deny needs working dependencies
A NetworkPolicy selecting pods and declaring policyTypes: [Ingress, Egress] with no allow rules defaults selected pods to deny ingress and egress. First verify CNI supports NetworkPolicy; Kubernetes API acceptance alone is not evidence of enforcement. Inventory namespace, Pod labels, DNS resolver, dependencies, external endpoints, ports, and protocols before rollout.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: default-deny, namespace: payments }
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
Add narrow policies for known service callers and DNS. Test from matching and nonmatching pods, then preserve test output. NetworkPolicy combines applicable policies; it is not ordered firewall rules. Default-deny ingress without required frontend policy breaks callers. Default-deny egress without DNS allowance may break discovery. Do not use broad 0.0.0.0/0 as routine escape hatch; record why external access is needed and narrow it when provider and architecture allow.
Rollout and evidence
Apply policy first in a representative non-critical namespace when architecture allows. Capture before/after connection tests for API caller, worker, metrics, DNS, and intended external dependency. A failed dependency is evidence to refine an explicit allow rule, not reason to remove all egress controls. Record selected Pods, labels, namespace, CNI version, test command, observed result, and reviewer. Repeat after label, service, or CNI changes because selection can change without policy YAML changing.
Use short-lived projected service-account tokens where workload needs Kubernetes API access and disable token automount for workloads that do not. Confirm workloads reference intended service account rather than implicit default. Review controller-created Pods and Jobs too; they may inherit a privileged default unexpectedly. API audit logs can corroborate permission use, but absence of event is not proof that permission is unnecessary without considering collection scope.
Exceptions and deliverable
Exception requires affected namespace/workload, exact excessive permission or allowed flow, reason, compensating control, owner, approver, expiry, remediation, and retest date. Expired exception is fail. Deliver identity map, binding review, network-flow matrix, manifests, CNI enforcement evidence, pass/fail register, exceptions, and remediation tracker. Infrastructure testing can validate agreed cluster scope.
Worked case: namespace service account
Deploy test workload under named service account and request only listed API objects in its namespace. Expected output permits declared read action and denies secret read, cluster-scoped write, and same action in adjacent namespace. Capture API audit result and effective RoleBinding, then delete binding and verify access disappears. For NetworkPolicy, test allowed application path and denied cross-namespace path from real labeled pods; policy review must name DNS or egress dependencies instead of assuming deny behavior covers them.
Test label drift, default service account use, pod recreation, and emergency binding expiry. Closure record contains manifests, rendered policy, test pod identity, command outputs, audit references, and reviewer. Exceptions name namespace, verbs, resources, traffic peer, expiry, and independent removal check. Do not close from YAML reading alone; behavior under admission and runtime identity is evidence.
Operational handoff: platform owner inventories cluster add-ons needing egress and namespace labels. Application owner verifies service-account name in deployed pod, not manifest assumption. Rerun deny tests after chart or admission-controller change. Attach result to release record.
Final cluster check exercises deployed service account, namespace labels, and real pod network path rather than manifest intent alone. Expected result: required operations and traffic work while prohibited verbs and peers fail. Edge case: controller-created pods receive unexpected account or labels; inspect them after reconciliation. Close only when runtime audit and policy evidence identify same revision.