Skip to main content

Create Administrative Boundaries Between Resources Using

More Info:

Namespaces provide administrative and security boundaries between sets of resources. Create dedicated namespaces to segregate workloads and apply scoped RBAC controls.

Risk Level

Low

Address

Security

Compliance Standards

  • CIS EKS

Triage and Remediation

Remediation

Manual Steps
  1. Inventory current namespaces and their workloads

    • Run on: any machine with kubectl access
    • Command:
      kubectl get namespaces
      kubectl get all --all-namespaces
    • Review whether business-critical, shared, and system workloads are clearly separated (e.g., kube-system, kube-public, provider-managed namespaces vs. your own application namespaces).
  2. Identify workloads running in default or shared namespaces

    • Run on: any machine with kubectl access
    • Command:
      kubectl get all -n default
      kubectl get all -n kube-system
      kubectl get all -n kube-public
      kubectl get all -n kube-node-lease
    • Determine which of these are your application workloads (not system or add-ons) and whether they should be isolated into dedicated namespaces (e.g., per team, environment, or application).
  3. Design a namespace strategy and plan moves

    • Decide target namespaces (e.g., team-a-prod, team-a-dev, shared-tools) and which workloads must be isolated for security, access control, or quota reasons.
    • For each workload in an inappropriate namespace, plan:
      • Target namespace name
      • Matching RBAC scope (ServiceAccounts, Roles, RoleBindings)
      • Any NetworkPolicies or ResourceQuotas/LimitRanges to apply.
  4. Create or update namespaces and associated policies

    • Run on: any machine with kubectl access
    • Command (example – adjust names and labels to your design):
      kubectl create namespace team-a-prod
      kubectl label namespace team-a-prod env=prod team=team-a --overwrite
    • Optionally add baseline policies per namespace, for example:
      # Example Role scoped to the namespace
      cat <<'EOF' | kubectl apply -f -
      apiVersion: rbac.authorization.k8s.io/v1
      kind: Role
      metadata:
      name: app-readonly
      namespace: team-a-prod
      rules:
      - apiGroups: [""]
      resources: ["pods","services","configmaps","secrets"]
      verbs: ["get","list","watch"]
      EOF
  5. Migrate workloads into their dedicated namespaces

    • Run on: any machine with kubectl access
    • Export and re-apply manifests into the new namespaces (update metadata.namespace):
      # Example: export a deployment currently in default namespace
      kubectl get deploy my-app -n default -o yaml > my-app.yaml
      sed -i 's/namespace: default/namespace: team-a-prod/' my-app.yaml
      kubectl apply -f my-app.yaml
      kubectl delete deploy my-app -n default
    • Ensure related objects (Services, ConfigMaps, Secrets, ServiceAccounts, Roles/RoleBindings, NetworkPolicies) are also created in the target namespace and references are updated.
  6. Verify namespace boundaries and workload placement

    • Run on: any machine with kubectl access
    • Commands:
      kubectl get namespaces --show-labels
      kubectl get all --all-namespaces
    • Confirm that:
      • Non-system workloads are no longer running in default or system namespaces unless explicitly intended.
      • Workloads are grouped into appropriate dedicated namespaces that align with your administrative and security boundaries.
Using kubectl
# 1. List all namespaces and their age
# Run on: any machine with kubectl access
kubectl get namespaces -o wide

What to look for (possible issues):

  • Only default, kube-system, kube-public, and kube-node-lease exist, but many workloads run in default.
  • Very old default namespace with many unrelated workloads suggests no logical separation.

# 2. See which namespaces workloads are running in (workloads only)
kubectl get deploy,sts,ds,job,cronjob,svc,ingress --all-namespaces

What to look for:

  • Multiple unrelated applications (e.g., payments, logging, demo, staging, prod) all in the same namespace (often default).
  • Shared namespace between system components and business apps.

# 3. List all pods with labels to infer logical groupings
kubectl get pods --all-namespaces --show-labels

What to look for:

  • Labels like app=payments, env=prod, team=ml, etc., all in one namespace instead of being grouped into separate namespaces by environment, team, or function.
  • No clear correlation between labels and namespace boundaries.

# 4. Inspect RBAC bindings and where they apply
kubectl get rolebinding,clusterrolebinding --all-namespaces -o wide

What to look for:

  • Overuse of ClusterRoleBinding granting broad roles (e.g., cluster-admin) instead of namespace-scoped RoleBinding.
  • Critical or sensitive workloads in namespaces that share wide RBAC bindings with unrelated workloads.

# 5. For a specific namespace, inspect its RBAC in detail
NAMESPACE=default # replace with namespace under review
kubectl get role,rolebinding -n "${NAMESPACE}" -o yaml
kubectl get pods,svc,deploy,sts,ds,job,cronjob,ingress -n "${NAMESPACE}" -o yaml

What to look for:

  • A namespace mixing:
    • different environments (dev/test/prod),
    • different business domains (payments, analytics, logging),
    • different teams or tenants, all with similar RBAC permissions.
  • Lack of any dedicated namespaces for components that clearly should be isolated (e.g., security tools, logging, monitoring, prod workloads).

# 6. Identify workloads still running in the default namespace
kubectl get all -n default

What to look for:

  • Long-lived application workloads or critical services in default instead of a dedicated namespace (e.g., payments-prod, team-a-dev, logging, monitoring).

# 7. (Optional) Show namespace labels/annotations that may indicate intended boundaries
kubectl get ns -o yaml

What to look for:

  • Important logical groups (tenant, team, env, data-sensitivity) present only as labels but not used to define actual namespace boundaries (e.g., multiple teams or envs mixed in one namespace despite labels suggesting separation is desired).

If these commands show that unrelated teams, environments, or sensitivity levels are mixed in the same namespaces, or that most workloads live in default, the cluster likely lacks appropriate administrative boundaries and requires a human-designed namespace model and migration plan.

Automation
#!/usr/bin/env bash
# Assess namespace usage to review administrative boundaries
# Run on: any machine with kubectl access and cluster-wide read permissions

set -euo pipefail

echo "=== 1) List all namespaces with age and labels (for grouping/ownership) ==="
kubectl get ns --show-labels -o wide

echo
echo "=== 2) Workloads per namespace (Pods, Deployments, StatefulSets, DaemonSets, Jobs, CronJobs) ==="
for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'); do
echo
echo "----- Namespace: ${ns} -----"
kubectl get pods,deploy,sts,ds,job,cronjob -n "${ns}" 2>/dev/null || echo " (no core workloads or no permission)"
done

echo
echo "=== 3) ServiceAccounts and their usage per namespace ==="
for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'); do
echo
echo "----- Namespace: ${ns} -----"
echo "- ServiceAccounts:"
kubectl get sa -n "${ns}" -o wide 2>/dev/null || echo " (no serviceaccounts or no permission)"
echo
echo "- Pods and their ServiceAccounts:"
kubectl get pods -n "${ns}" -o custom-columns='NAMESPACE:.metadata.namespace,POD:.metadata.name,SA:.spec.serviceAccountName' 2>/dev/null \
|| echo " (no pods or no permission)"
done

echo
echo "=== 4) Cluster-wide RBAC resources referencing namespaces ==="
echo
echo "- ClusterRoles (cluster-scoped permissions):"
kubectl get clusterrole
echo
echo "- ClusterRoleBindings (who has cluster-scoped permissions):"
kubectl get clusterrolebinding -o wide

echo
echo "=== 5) Namespaced RBAC per namespace ==="
for ns in $(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'); do
echo
echo "----- Namespace: ${ns} -----"
echo "- Roles:"
kubectl get role -n "${ns}" -o wide 2>/dev/null || echo " (no Roles or no permission)"
echo
echo "- RoleBindings:"
kubectl get rolebinding -n "${ns}" -o wide 2>/dev/null || echo " (no RoleBindings or no permission)"
done

echo
echo "=== 6) High-privilege bindings (cluster-admin or similar) by subject and namespace ==="
# Cluster-admin via ClusterRoleBinding
echo
echo "- ClusterRoleBindings that grant 'cluster-admin':"
kubectl get clusterrolebinding -o json \
| jq -r '
.items[]
| select(.roleRef.kind=="ClusterRole" and .roleRef.name=="cluster-admin")
| "Binding: \(.metadata.name)\n Subjects:\n" +
( .subjects[]?
| " - kind: \(.kind), name: \(.name), namespace: \(.namespace // "-")"
)
' || echo "jq not installed; skip detailed view (install jq to see more detail)"

# Detect RoleBindings that refer to high-privilege ClusterRoles (by name pattern)
echo
echo "- RoleBindings that reference ClusterRoles (potential cross-namespace high privilege):"
kubectl get rolebinding --all-namespaces -o json \
| jq -r '
.items[]
| select(.roleRef.kind=="ClusterRole")
| "Namespace: \(.metadata.namespace), RoleBinding: \(.metadata.name), ClusterRoleRef: \(.roleRef.name)"
' || echo "jq not installed; skip this check"

echo
echo "=== 7) Pods running in core / shared namespaces (kube-system, default, kube-public) ==="
for ns in default kube-system kube-public; do
echo
echo "----- Namespace: ${ns} -----"
kubectl get pods -n "${ns}" -o wide 2>/dev/null || echo " (namespace not found or no pods)"
done

echo
echo "=== 8) Summary hint (manual review required) ==="
cat <<'EOF'
Manual review guidance (what output indicates a potential problem):

1) From section 1:
- Workloads concentrated heavily in 'default' or other shared/core namespaces
instead of being grouped into dedicated application or team namespaces.
- Lack of meaningful labels (e.g., missing team/app/env/owner labels) that would
indicate clear administrative ownership of namespaces.

2) From section 2:
- Multiple unrelated applications or teams sharing the same namespace.
- System components and tenant workloads mixed in the same namespace.

3) From section 3:
- Many pods in a namespace sharing a single broad ServiceAccount instead of
more granular ServiceAccounts per application or function.

4) From sections 4 and 6:
- Frequent or broad use of 'cluster-admin' via ClusterRoleBindings (especially
bound to users/groups that should be limited to specific namespaces).
- RoleBindings that reference ClusterRoles across namespaces, implying
potentially unnecessary cluster-wide privileges for namespace-scoped users.

5) From section 5:
- Namespaces with workloads but no namespace-scoped Roles/RoleBindings,
relying solely on cluster-scoped RBAC (weakens namespace boundaries).

6) From section 7:
- Tenant or application workloads running in 'kube-system', 'kube-public',
or 'default' instead of dedicated namespaces.

Use these findings to decide where to:
- Introduce new namespaces to separate teams, environments, or applications.
- Tighten RBAC so users and ServiceAccounts have access only to their namespaces.
EOF