Skip to main content

Create Administrative Boundaries Between Resources Using

More Info:

Use namespaces to isolate your Kubernetes objects.

Risk Level

Low

Address

Security

Compliance Standards

  • APRA CPS 234 (Australia)
  • BSI C5 (Germany)
  • Brazil LGPD
  • CCPA / CPRA (California)
  • CIS Critical Security Controls v8
  • CIS OKE
  • CMMC 2.0
  • CSA Cloud Controls Matrix v4
  • DPDPA
  • Digital Operational Resilience Act (EU)
  • Essential 8
  • ISO/IEC 27017
  • ISO/IEC 27018
  • ISO/IEC 27701
  • KSA PDPL
  • MAS Technology Risk Management (Singapore)
  • MITRE ATT&CK (Cloud)
  • NIST SP 800-171
  • NYDFS 23 NYCRR 500
  • SWIFT Customer Security Controls Framework
  • Sarbanes-Oxley IT General Controls
  • UK NCSC Cyber Assessment Framework

Triage and Remediation

Remediation

Manual Steps
  1. Inventory current namespaces and their workloads

    • On any machine with kubectl access:
      kubectl get namespaces
      kubectl get all --all-namespaces
    • Review which applications, environments (dev/test/prod), or teams are sharing the same namespace (especially default).
  2. Identify applications using shared or inappropriate namespaces

    • List objects in the default namespace (and any other obviously shared namespaces):
      kubectl get deploy,sts,ds,svc,ingress,cm,secret,sa,job,cronjob -n default
    • For each listed object, decide which logical boundary it belongs to (e.g., team, app, environment, or project).
  3. Define the desired namespace model and create namespaces

    • Decide on a small, clear set of namespaces that reflect administrative boundaries (e.g., team-a-prod, team-a-dev, payments, logging, etc.).
    • Create them:
      kubectl create namespace team-a-prod
      kubectl create namespace team-a-dev
      # Add more as needed, matching your chosen model
  4. Plan and migrate workloads into appropriate namespaces

    • Export existing manifests from shared namespaces for editing:
      kubectl get deploy,sts,ds,svc,ingress,cm,secret,sa,job,cronjob -n default -o yaml > /tmp/default-workloads.yaml
    • Edit /tmp/default-workloads.yaml and, for each object to be moved, set metadata.namespace to the appropriate target namespace.
    • Apply the updated manifests:
      kubectl apply -f /tmp/default-workloads.yaml
    • After confirming successful creation in the new namespace, delete the old instances from default:
      kubectl delete -f /tmp/default-workloads.yaml -n default --ignore-not-found
  5. Enforce use of namespaces for future deployments

    • Optionally create a simple namespace usage policy by documenting which namespace each team/app must use.
    • If you use GitOps or CI/CD, ensure manifests and Helm charts specify metadata.namespace (or Helm --namespace flag) rather than relying on default.
  6. Verify namespace-based separation

    • On any machine with kubectl access, confirm that application objects now reside in non-default, purpose-specific namespaces and that default is mostly empty or only contains intentional resources:
      kubectl get all --all-namespaces
      kubectl get all -n default
    • Confirm that applications belonging to different administrative boundaries are no longer sharing the same namespace unless explicitly intended.
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

  1. List all namespaces and basic metadata
kubectl get namespaces -o wide

Review points / potential problems:

  • Only default, kube-system, and a small number of clearly named namespaces exist, but many unrelated apps are deployed (see next steps) → suggests poor separation.
  • Business‑critical, dev/test, and third‑party workloads appear to share the same namespace (often default or a single custom namespace).
  1. See what runs in each namespace
kubectl get pods -A -o wide

Focus on columns NAMESPACE and NAME:

  • Many unrelated applications or teams sharing one namespace, especially default, indicates weak administrative boundaries.
  • System and platform components (ingress, monitoring, CI runners, internal apps) all mixed in one or two namespaces is a red flag.
  1. Check which namespaces are actually used for application workloads
kubectl get deploy,sts,ds,job,cronjob -A -o wide

Look for:

  • Application controllers (Deployments, StatefulSets, etc.) living in default alongside core platform or test workloads.
  • Lack of clear grouping (e.g., no separation like prod-*, dev-*, team-*, system-*); this makes RBAC scoping and blast-radius control hard.
  1. Inspect namespace labels/annotations (used for policy/RBAC scoping)
kubectl get ns --show-labels
kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations}{"\n"}{end}'

Potential issues:

  • Critical namespaces lack labels that would distinguish environment, owner, or sensitivity (e.g., no env=prod, owner=team-a, tier=platform), making it hard to target RBAC and policies.
  • No clear way to identify which namespace belongs to which team or environment.
  1. Check if the default namespace is overloaded
kubectl get all -n default

Indicates a problem when:

  • Many independent apps, batch jobs, and third‑party tools are all in default rather than structured namespaces.
  • Production workloads reside in default alongside experimental or transient workloads.
  1. Review role bindings per namespace (to understand intended boundaries)
kubectl get rolebinding,clusterrolebinding -A

Use this for context:

  • If a few broad ClusterRoleBindings grant access cluster‑wide, and there are no namespace‑scoped RoleBindings tailored to specific namespaces, then namespaces are not being used effectively as administrative boundaries.
  • If multiple teams share the same namespace and are all granted access via the same bindings, you likely need more granular namespace separation.

These commands only expose how namespaces are currently used; a human must decide if namespaces should be split, renamed, or reorganized to create appropriate administrative boundaries.

Automation
#!/usr/bin/env bash
# Report namespace usage and potential isolation issues
# Run on: any machine with kubectl access
# Usage: ./namespace-boundaries-report.sh

set -euo pipefail

echo "=== 1) Namespaces and labels ==="
kubectl get ns --show-labels

echo
echo "=== 2) Workloads per namespace (Deployments, StatefulSets, DaemonSets, Jobs, CronJobs) ==="
kubectl get deploy,sts,ds,job,cronjob -A -o wide || true

echo
echo "=== 3) Pods per namespace (including owning controller) ==="
kubectl get pods -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,PHASE:.status.phase,OWNER:.metadata.ownerReferences[0].kind,OWNER_NAME:.metadata.ownerReferences[0].name --sort-by=.metadata.namespace

echo
echo "=== 4) ClusterRoles and ClusterRoleBindings (cross-namespace permissions) ==="
echo "--- ClusterRoles ---"
kubectl get clusterrole -o wide
echo
echo "--- ClusterRoleBindings ---"
kubectl get clusterrolebinding -o custom-columns=NAME:.metadata.name,SA_SUBJECT_NS:.subjects[?(@.kind==\"ServiceAccount\")].namespace,SA_SUBJECT_NAME:.subjects[?(@.kind==\"ServiceAccount\")].name,ROLE:.roleRef.name

echo
echo "=== 5) RoleBindings (namespaced RBAC, who can affect what) ==="
kubectl get rolebinding -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,SUBJECT_KIND:.subjects[0].kind,SUBJECT_NS:.subjects[0].namespace,SUBJECT_NAME:.subjects[0].name,ROLE_KIND:.roleRef.kind,ROLE_NAME:.roleRef.name

echo
echo "=== 6) ServiceAccounts per namespace ==="
kubectl get sa -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name --sort-by=.metadata.namespace

echo
echo "=== 7) NetworkPolicies per namespace (traffic isolation) ==="
kubectl get networkpolicy -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,POLICY_TYPES:.spec.policyTypes --sort-by=.metadata.namespace || echo "No NetworkPolicies found"

echo
echo "=== 8) Namespaces with no NetworkPolicies defined ==="
# Namespaces with zero NetworkPolicies – often indicate no traffic isolation
ns_all=$(kubectl get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')
ns_np=$(kubectl get networkpolicy -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"\n"}{end}' 2>/dev/null | sort -u || true)

echo "Namespaces with NO NetworkPolicies:"
comm -23 <(printf "%s\n" $ns_all | sort -u) <(printf "%s\n" $ns_np | sort -u)

echo
echo "=== 9) Namespaces with mixed application labels (potentially shared by multiple teams/apps) ==="
# Heuristic: list distinct 'app' labels per namespace
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.labels.app}{"\n"}{end}' \
| awk '$2!="" {print}' \
| sort -u \
| awk '{count[$1]++} END {for (ns in count) if (count[ns]>1) print ns, "has", count[ns], "distinct app labels"}' \
| sort

echo
echo "=== 10) System vs user namespaces (for manual review) ==="
echo "Common system namespaces (should generally be separate from user workloads):"
echo " - kube-system"
echo " - kube-public"
echo " - kube-node-lease"
echo " - default (often misused for apps)"
echo
kubectl get pods -n default -o wide || echo "No pods in 'default' namespace"

echo
echo "=== 11) Summary hints for manual review ==="
cat <<'EOF'
Review guidance (manual, not automated pass/fail):

1) Namespaces and labels:
- Potential issue if:
* Most or all workloads run in 'default'.
* No clear team/app labels on namespaces.

2) Workloads/Pods per namespace:
- Potential issue if:
* Multiple unrelated applications share a single namespace with no clear reason.
* System and user workloads are mixed in the same namespace.

3) RBAC (ClusterRole/ClusterRoleBinding/RoleBinding):
- Potential issue if:
* ClusterRoleBindings grant broad privileges (e.g. cluster-admin) to service accounts used across many namespaces.
* Service accounts in one team/namespace can administer resources in others without clear justification.

4) NetworkPolicies:
- Potential issue if:
* Business-critical namespaces have no NetworkPolicies (no traffic isolation).
* One namespace is clearly used as a "shared" zone for many unrelated apps with no isolation.

5) Default namespace:
- Potential issue if:
* User applications are routinely deployed to 'default' instead of dedicated namespaces.

Use this report to decide:
- Which teams/apps should be separated into their own namespaces.
- Where RBAC and NetworkPolicies need tightening to respect those boundaries.
EOF

Additional Reading: