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 AKS
  • CIS Critical Security Controls v8
  • 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 workloads

    • Run on: any machine with kubectl access
    • Command:
      kubectl get namespaces
      kubectl get all --all-namespaces
      kubectl get crd
    • Review whether most application workloads are concentrated in default or other shared namespaces without a clear purpose (e.g., mixing dev/test/prod in one namespace).
  2. Map applications, teams, and environments to desired namespaces

    • Run on: any machine with kubectl access
    • Command (gather current labels/ownership hints):
      kubectl get pods --all-namespaces -o jsonpath='{range .items[*]}{.metadata.namespace}{" "}{.metadata.name}{" "}{.metadata.labels}{"\n"}{end}'
    • Decide an intended namespace model, for example:
      • Environment-based: dev, test, stage, prod
      • Team-based: team-a, team-b
      • App-based: payments, search
    • Document which workloads should live in which namespaces.
  3. Define or update namespaces to match the model

    • Run on: any machine with kubectl access
    • Create any missing namespaces (example names; adapt to your model):
      kubectl create namespace dev
      kubectl create namespace prod
    • Or with manifests (recommended for GitOps):
      cat << 'EOF' | kubectl apply -f -
      apiVersion: v1
      kind: Namespace
      metadata:
      name: dev
      ---
      apiVersion: v1
      kind: Namespace
      metadata:
      name: prod
      EOF
  4. Plan and, if acceptable, migrate workloads into dedicated namespaces

    • Run on: any machine with kubectl access
    • For each deployment/statefulset/etc., decide the target namespace and update manifests accordingly. Example (moving an app from default to dev):
      # Export existing manifest
      kubectl get deployment my-app -n default -o yaml > my-app.yaml

      # Edit my-app.yaml: change
      # namespace: default
      # to
      # namespace: dev
      # (or add metadata.namespace: dev if absent)

      # Apply into the new namespace
      kubectl apply -f my-app.yaml

      # Optionally delete old objects once verified
      kubectl delete deployment my-app -n default
    • Check for namespace-specific dependencies (ConfigMaps, Secrets, Services, RBAC) and duplicate or adjust them in the target namespace as needed.
  5. Align RBAC and policies with the namespace boundaries

    • Run on: any machine with kubectl access
    • Gather RBAC scoped to or spanning multiple namespaces:
      kubectl get role,rolebinding --all-namespaces
      kubectl get clusterrole,clusterrolebinding
    • Adjust or create Role/RoleBinding objects so that:
      • Access for a team or app is granted only in its dedicated namespace(s).
      • Broad ClusterRoleBinding grants are replaced with namespace-scoped bindings where appropriate.
    • If you use NetworkPolicies, PodSecurity admission, or ResourceQuotas, ensure they are defined per namespace according to your boundaries.
  6. Verify that administrative boundaries exist and are enforced

    • Run on: any machine with kubectl access
    • Confirm workloads are distributed and not all in default or a single shared namespace:
      kubectl get pods --all-namespaces
    • Validate that a representative user/service account cannot access out-of-scope namespaces (example using a kubeconfig/context for that identity):
      # List pods in allowed namespace
      kubectl --context=<limited-context> get pods -n dev

      # Attempt to list pods in a disallowed namespace; this should be forbidden
      kubectl --context=<limited-context> get pods -n prod
    • If workloads and RBAC now reflect clear, intentional namespace-based separation, this control can be considered satisfied.
Using kubectl

Using kubectl

Run these commands from any machine with kubectl access.

1. List all namespaces and their basic metadata

kubectl get namespaces -o wide

Review the output for:

  • Almost everything running in default, kube-system, or other built‑in namespaces.
  • Only one or two namespaces total in a non-trivial cluster.

This suggests poor separation of environments/teams/apps.

2. See which namespaces your workloads actually use

kubectl get all --all-namespaces

Look for:

  • Multiple unrelated applications or teams using the same namespace.
  • All custom workloads in default instead of app/team/environment‑specific namespaces.

This indicates weak administrative boundaries.

3. Group workloads by label across namespaces

If you use labels for apps/environments:

kubectl get pods --all-namespaces -L app,environment,team

Red flags:

  • Same app or team label spread across many unrelated namespaces without a clear reason.
  • Mixed environment values (e.g., prod, dev, test) inside the same namespace.

This may indicate namespaces are not aligned with your intended boundaries.

4. Inspect RBAC bindings per namespace

kubectl get rolebindings,roles -A

Look for:

  • Very broad roles (e.g., * verbs or resources) reused in many namespaces.
  • Many subjects (users/groups/serviceaccounts) sharing the same namespace unintentionally.

This can show that namespaces are not providing the intended isolation.

5. Identify objects in the default namespace

kubectl get all -n default

If you see:

  • Critical or production workloads,
  • Multiple unrelated applications,
  • Shared infrastructure components mixed with app workloads,

then your default namespace is being overused instead of having dedicated namespaces.

6. Drill into a specific namespace

Replace my-namespace with a candidate namespace that looks overloaded:

kubectl get all -n my-namespace
kubectl describe namespace my-namespace

Indicators of a problem:

  • Many unrelated apps/teams/environments mixed in one namespace.
  • No annotations/labels explaining ownership or purpose.

These observations should drive a human decision on whether to introduce or adjust namespaces to create clearer administrative boundaries.

Automation
#!/usr/bin/env bash
# Report namespace usage and potential multi-tenant / boundary issues

set -euo pipefail

echo "=== 1) Namespace list with labels and resource counts ==="
kubectl get ns -o json \
| jq -r '
.items[]
| {
name: .metadata.name,
labels: .metadata.labels,
pods: ( .metadata.name as $ns
| ( input // empty | .items[] | select(.metadata.namespace==$ns) ) ),
roles: (""), rolebindings: (""), clusterrolebindings: ("")
}' \
--slurpfile pods <(kubectl get pods -A -o json) \
> /tmp/ns_raw.json

# Summarize: name, labels, pod count
jq -r '
( "NAMESPACE\tLABELS\tPOD_COUNT" ),
( .[] |
.name as $n |
.labels as $l |
$n,
($l // {} | to_entries | map("\(.key)=\(.value)") | join(",")),
0
)' /tmp/ns_raw.json | paste - - - \
| column -t -s $'\t'

echo
echo "=== 2) Namespaces containing workloads by logical app (from labels) ==="
echo "Heuristic: shows how many distinct app labels exist per namespace."
kubectl get pods -A -o json \
| jq -r '
.items[]
| {
ns: .metadata.namespace,
app: (
.metadata.labels.app
// .metadata.labels."app.kubernetes.io/name"
// "UNLABELED"
)
}' \
| jq -sr '
group_by(.ns)
| map({
namespace: .[0].ns,
apps: (map(.app) | unique)
})
| .[]
| "\(.namespace)\t\(.apps | length)\t\(.apps | join(","))"
' \
| awk 'BEGIN {print "NAMESPACE\tDISTINCT_APPS\tAPPS"}1' \
| column -t -s $'\t'

echo
echo "=== 3) Workloads running in kube-system and default namespaces ==="
echo "Review any non-core or tenant workloads here; they should usually be moved."
echo "--- Pods in kube-system ---"
kubectl get pods -n kube-system -o wide || true
echo
echo "--- Pods in default ---"
kubectl get pods -n default -o wide || true

echo
echo "=== 4) Namespaces without any ResourceQuota or LimitRange ==="
echo "These namespaces have no basic resource boundaries."
echo "--- Namespaces with NO ResourceQuota ---"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
if ! kubectl get resourcequota -n "$ns" >/dev/null 2>&1; then
echo "$ns"
fi
done

echo
echo "--- Namespaces with NO LimitRange ---"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
if ! kubectl get limitrange -n "$ns" >/dev/null 2>&1; then
echo "$ns"
fi
done

echo
echo "=== 5) RBAC scope: RoleBindings vs ClusterRoleBindings per namespace ==="
echo "Multiple tenants sharing a namespace + broad ClusterRoleBindings is a risk."
echo "--- ClusterRoleBindings (cluster-wide) ---"
kubectl get clusterrolebindings.rbac.authorization.k8s.io -o wide

echo
echo "--- RoleBindings per namespace (who can do what inside each namespace) ---"
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
echo
echo "Namespace: $ns"
kubectl get rolebindings.rbac.authorization.k8s.io -n "$ns" -o wide || true
done

echo
echo "=== 6) ServiceAccounts shared across namespaces (unusual) ==="
echo "ServiceAccounts should be namespace-scoped; same name across many namespaces may indicate shared operational boundary."
kubectl get sa -A -o json \
| jq -r '
.items[]
| {ns: .metadata.namespace, name: .metadata.name}
' \
| jq -sr '
group_by(.name)
| map(select(length > 1))
| .[]
| "\(.[0].name)\t\(.|map(.ns)|join(","))"
' \
| awk 'BEGIN {print "SERVICEACCOUNT\tNAMESPACES"}1' \
| column -t -s $'\t'

echo
echo "=== 7) Summary: possible issues to review ==="
echo "1) Namespaces with many distinct apps (from section 2) may mix unrelated workloads."
echo "2) Workloads in 'default' or 'kube-system' (section 3) often indicate missing namespaces."
echo "3) Namespaces listed in section 4 lack quotas/limits and may need stronger boundaries."
echo "4) Broad ClusterRoleBindings (section 5) + shared namespaces weaken administrative separation."
echo "5) ServiceAccounts reused across many namespaces (section 6) may indicate blurred boundaries."

echo
echo "Review the above and decide where new namespaces or stricter policies are needed; remediation remains a manual design decision."

How to interpret problematic output

  • Many unrelated apps in the same namespace (section 2: DISTINCT_APPS is high, or APPS is a long mixed list) → boundaries between teams/apps are not enforced.
  • Non-core or tenant workloads in default or kube-system (section 3) → those objects should usually be moved into dedicated namespaces.
  • Namespaces listed as having no ResourceQuota or no LimitRange (section 4) → no basic resource governance; may not meet your boundary requirements.
  • ClusterRoleBindings granting broad permissions to many subjects who all work in shared namespaces (section 5) → weak administrative isolation.
  • ServiceAccounts showing up in many namespaces (section 6) → may indicate shared operational boundaries instead of clear namespace-based separation.

Additional Reading: