> ## Documentation Index
> Fetch the complete documentation index at: https://cloudanix.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenant Namespaces Should Have A ResourceQuota

### More Info:

Advisory: create a ResourceQuota per tenant namespace to bound aggregate CPU, memory and object counts, preventing one tenant from starving others.

### Risk Level

Low

### Address

Security

### Compliance Standards

* Cloudanix Best Practice

### Triage and Remediation

<Tabs>
  <Tab title="Remediation">
    ### Remediation

    <AccordionGroup>
      <Accordion title="Manual Steps" defaultOpen="true">
        1. Identify tenant namespaces (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get namespaces \
             --no-headers \
             | awk '!/kube-system|kube-public|kube-node-lease/ {print $1}'
           ```

        2. For each tenant namespace that has no ResourceQuota, create a baseline ResourceQuota manifest file (run on any machine with kubectl access). Example for namespace `tenant-a`:
           ```bash theme={null}
           cat > tenant-a-resourcequota.yaml << 'EOF'
           apiVersion: v1
           kind: ResourceQuota
           metadata:
             name: tenant-a-quota
             namespace: tenant-a
           spec:
             hard:
               requests.cpu: "2"
               requests.memory: "4Gi"
               limits.cpu: "4"
               limits.memory: "8Gi"
               pods: "50"
               services: "10"
               configmaps: "50"
               persistentvolumeclaims: "10"
               secrets: "100"
               replicationcontrollers: "20"
               resourcequotas: "1"
               services.loadbalancers: "5"
               services.nodeports: "5"
           EOF
           ```
           Adjust the `hard` values to match your tenant’s agreed limits.

        3. Apply the ResourceQuota for that tenant namespace (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl apply -f tenant-a-resourcequota.yaml
           ```

        4. Repeat steps 2–3 for each remaining tenant namespace, changing the `name`, `namespace`, and quota values as appropriate.

        5. (Optional) Review existing quotas in tenant namespaces to ensure they match expectations (run on any machine with kubectl access):
           ```bash theme={null}
           kubectl get resourcequota --all-namespaces -o wide
           ```

        6. Verify compliance (run on any machine with kubectl access):
           ```bash theme={null}
           { kubectl get resourcequotas --all-namespaces -o json
             kubectl get namespaces -o json
           } | jq -rs '
             .[0] as $quotas | .[1] |
             [ .items[]
             | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
             | .metadata as $m
             | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
             | ([ $quotas.items[] | select(.metadata.namespace == $m.name) ] | length) as $count
             | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
               + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
               + (if $labels == "" then "" else " labels=\($labels)" end)
               + " resourceQuotas=\($count)"
               + " is_compliant=\(if $count > 0 then "true" else "false" end)"
             ] as $rows
             | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
           ```
           Confirm that all tenant namespaces now show `is_compliant=true`.
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Identify tenant namespaces (run on any machine with kubectl access)
        kubectl get ns \
          --no-headers \
          | awk '!/kube-system|kube-public|kube-node-lease/ {print $1}'
        ```

        Create a ResourceQuota manifest per tenant namespace. Example for a tenant namespace `tenant-a`:

        ```yaml theme={null}
        # tenant-a-resourcequota.yaml
        apiVersion: v1
        kind: ResourceQuota
        metadata:
          name: tenant-a-quota
          namespace: tenant-a
        spec:
          hard:
            requests.cpu: "4"
            limits.cpu: "8"
            requests.memory: "8Gi"
            limits.memory: "16Gi"
            pods: "50"
            services: "20"
            configmaps: "50"
            secrets: "50"
            persistentvolumeclaims: "20"
            services.loadbalancers: "5"
            services.nodeports: "5"
        ```

        Apply it:

        ```bash theme={null}
        # 2) Apply ResourceQuota for tenant-a (run on any machine with kubectl access)
        kubectl apply -f tenant-a-resourcequota.yaml
        ```

        Repeat with adjusted names/values for each tenant namespace.

        Verification (adapted from the audit):

        ```bash theme={null}
        # 3) Confirm every tenant namespace has at least one ResourceQuota
        { kubectl get resourcequotas --all-namespaces -o json
          kubectl get namespaces -o json
        } | jq -rs '
          .[0] as $quotas | .[1] |
          [ .items[]
          | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ $quotas.items[] | select(.metadata.namespace == $m.name) ] | length) as $count
          | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " resourceQuotas=\($count)"
            + " is_compliant=\(if $count > 0 then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        ```
      </Accordion>

      <Accordion title="Automation">
        ```bash theme={null}
        #!/usr/bin/env bash
        # Create a default ResourceQuota for every tenant namespace that lacks one.
        # Run on: any machine with kubectl access and current context pointing at the target GKE cluster.

        set -euo pipefail

        # -----------------------------
        # Configuration (edit as needed)
        # -----------------------------

        # Namespaces to skip (system / non-tenant)
        EXCLUDED_NAMESPACES=(
          "kube-system"
          "kube-public"
          "kube-node-lease"
        )

        # Default ResourceQuota template (cluster-wide defaults; adjust for your tenants)
        # This is applied as-is to any non-excluded namespace that currently has 0 ResourceQuota objects.
        read -r -d '' RQ_TEMPLATE_JSON << 'EOF'
        {
          "apiVersion": "v1",
          "kind": "ResourceQuota",
          "metadata": {
            "name": "tenant-default-quota"
          },
          "spec": {
            "hard": {
              "requests.cpu": "4",
              "requests.memory": "8Gi",
              "limits.cpu": "8",
              "limits.memory": "16Gi",
              "pods": "50",
              "services": "10",
              "configmaps": "20",
              "persistentvolumeclaims": "10",
              "secrets": "50"
            }
          }
        }
        EOF

        # -----------------------------
        # Helper functions
        # -----------------------------

        is_excluded_ns() {
          local ns="$1"
          for e in "${EXCLUDED_NAMESPACES[@]}"; do
            if [[ "$ns" == "$e" ]]; then
              return 0
            fi
          done
          return 1
        }

        # -----------------------------
        # Main logic
        # -----------------------------

        echo "Discovering namespaces..."
        NAMESPACES=$(kubectl get namespaces -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}')

        # Track whether we made any changes
        CHANGED=0

        while IFS= read -r NS; do
          [[ -z "$NS" ]] && continue

          if is_excluded_ns "$NS"; then
            echo "Skipping excluded namespace: $NS"
            continue
          fi

          # Count existing ResourceQuotas in this namespace
          COUNT=$(kubectl get resourcequota -n "$NS" --no-headers 2>/dev/null | wc -l | tr -d ' ')

          if [[ "$COUNT" -gt 0 ]]; then
            echo "Namespace '$NS' already has $COUNT ResourceQuota object(s); leaving as-is."
            continue
          fi

          echo "Creating default ResourceQuota in namespace '$NS'..."
          echo "$RQ_TEMPLATE_JSON" | kubectl apply -n "$NS" -f -
          CHANGED=1
        done <<< "$NAMESPACES"

        if [[ "$CHANGED" -eq 0 ]]; then
          echo "No changes made; all tenant namespaces already have at least one ResourceQuota."
        fi

        echo
        echo "Verification (post-fix audit):"
        echo "------------------------------------------------------------"
        # Re-run the benchmark-style audit to confirm is_compliant=true for all rows.
        { kubectl get resourcequotas --all-namespaces -o json
          kubectl get namespaces -o json
        } | jq -rs '
          .[0] as $quotas | .[1] |
          [ .items[]
          | select(.metadata.name as $n | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
          | .metadata as $m
          | (($m.labels // {}) | to_entries | map("\(.key):\(.value)") | join(",")) as $labels
          | ([ $quotas.items[] | select(.metadata.namespace == $m.name) ] | length) as $count
          | "kind=Namespace name=\($m.name) uid=\($m.uid) apiVersion=v1"
            + (if ($m.creationTimestamp // "") == "" then "" else " created=\($m.creationTimestamp)" end)
            + (if $labels == "" then "" else " labels=\($labels)" end)
            + " resourceQuotas=\($count)"
            + " is_compliant=\(if $count > 0 then "true" else "false" end)"
          ] as $rows
          | if ($rows | length) == 0 then "is_compliant=true" else $rows[] end'
        echo "------------------------------------------------------------"
        echo "Ensure all tenant namespaces show is_compliant=true above."
        ```
      </Accordion>
    </AccordionGroup>
  </Tab>
</Tabs>
