> ## 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 ns \
          --no-headers \
          | awk '!/kube-system|kube-public|kube-node-lease/ {print $1}'
        ```

        2. For each tenant namespace without a ResourceQuota, create a baseline manifest file locally (edit the namespace and limits/requests as appropriate):

        ```bash theme={null}
        cat > tenant-resourcequota.yaml << 'EOF'
        apiVersion: v1
        kind: ResourceQuota
        metadata:
          name: tenant-quota
          namespace: TENANT_NAMESPACE_NAME
        spec:
          hard:
            requests.cpu: "2"
            requests.memory: "4Gi"
            limits.cpu: "4"
            limits.memory: "8Gi"
            pods: "50"
            services: "10"
            configmaps: "20"
            secrets: "50"
            persistentvolumeclaims: "10"
        EOF
        ```

        3. Apply the ResourceQuota for that tenant namespace (run once per namespace after editing the manifest):

        ```bash theme={null}
        kubectl apply -f tenant-resourcequota.yaml
        ```

        4. (Optional) Review the effective quotas in each tenant namespace to ensure they reflect your capacity and fairness goals:

        ```bash theme={null}
        kubectl describe resourcequota -n TENANT_NAMESPACE_NAME
        ```

        5. Repeat steps 2–4 for every tenant namespace that needs its own tailored resource bounds.

        6. Verification (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
          | ([ $quotas.items[] | select(.metadata.namespace == $m.name) ] | length) as $count
          | "kind=Namespace name=\($m.name) resourceQuotas=\($count) is_compliant=\(if $count > 0 then "true" else "false" end)"
          ][]'
        ```
      </Accordion>

      <Accordion title="Using kubectl">
        ```bash theme={null}
        # 1) Identify non-compliant “tenant” namespaces (any machine with kubectl access)
        kubectl get ns

        # Example: assume these are tenant namespaces that need quotas:
        #   team-a, team-b
        # Adjust the list and values for your environment.

        # 2) Create a ResourceQuota manifest for each tenant namespace (any machine with kubectl access)

        cat <<'EOF' > team-a-resourcequota.yaml
        apiVersion: v1
        kind: ResourceQuota
        metadata:
          name: tenant-quota
          namespace: team-a
        spec:
          hard:
            requests.cpu: "4"
            requests.memory: "8Gi"
            limits.cpu: "8"
            limits.memory: "16Gi"
            pods: "100"
            services: "20"
            configmaps: "100"
            secrets: "100"
            persistentvolumeclaims: "20"
        EOF

        kubectl apply -f team-a-resourcequota.yaml

        cat <<'EOF' > team-b-resourcequota.yaml
        apiVersion: v1
        kind: ResourceQuota
        metadata:
          name: tenant-quota
          namespace: team-b
        spec:
          hard:
            requests.cpu: "4"
            requests.memory: "8Gi"
            limits.cpu: "8"
            limits.memory: "16Gi"
            pods: "100"
            services: "20"
            configmaps: "100"
            secrets: "100"
            persistentvolumeclaims: "20"
        EOF

        kubectl apply -f team-b-resourcequota.yaml

        # 3) Verification (any machine with kubectl access)

        # Check ResourceQuota objects exist and review their limits
        kubectl get resourcequota --all-namespaces -o wide

        # Re-run the benchmark’s audit logic to confirm is_compliant=true
        { 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
        set -euo pipefail

        # This script ensures every tenant namespace in an AKS cluster
        # (all namespaces except kube-system, kube-public, kube-node-lease)
        # has at least one ResourceQuota object.
        #
        # Run on: any machine with kubectl access and jq installed.

        # Pre-flight checks
        command -v kubectl >/dev/null 2>&1 || {
          echo "kubectl not found in PATH" >&2
          exit 1
        }
        command -v jq >/dev/null 2>&1 || {
          echo "jq not found in PATH" >&2
          exit 1
        }

        # Quota template: adjust limits/requests to your multi-tenant policy.
        # This is intentionally conservative; change values before use if needed.
        create_quota() {
          local ns="$1"
          cat <<EOF | kubectl apply -f -
        apiVersion: v1
        kind: ResourceQuota
        metadata:
          name: tenant-default-quota
          namespace: ${ns}
        spec:
          hard:
            requests.cpu: "2"
            requests.memory: "4Gi"
            limits.cpu: "4"
            limits.memory: "8Gi"
            pods: "100"
            services: "50"
            configmaps: "50"
            secrets: "100"
            persistentvolumeclaims: "20"
        EOF
        }

        echo "Discovering tenant namespaces (excluding kube-system, kube-public, kube-node-lease)..."
        TENANT_NAMESPACES=$(kubectl get ns -o json \
          | jq -r '.items[]
            | select(.metadata.name as $n
              | ["kube-system","kube-public","kube-node-lease"] | index($n) | not)
            | .metadata.name')

        if [ -z "${TENANT_NAMESPACES}" ]; then
          echo "No tenant namespaces found; nothing to do."
        else
          echo "Tenant namespaces:"
          printf '  - %s\n' ${TENANT_NAMESPACES}
        fi

        for ns in ${TENANT_NAMESPACES:-}; do
          echo "Processing namespace: ${ns}"
          EXISTING_COUNT=$(kubectl get resourcequota -n "${ns}" -o json \
            | jq '.items | length')

          if [ "${EXISTING_COUNT}" -gt 0 ]; then
            echo "  Already has ${EXISTING_COUNT} ResourceQuota object(s); skipping creation."
            continue
          fi

          echo "  No ResourceQuota found; creating tenant-default-quota..."
          create_quota "${ns}"
        done

        echo
        echo "Verification (re-running benchmark-style audit)..."

        # Reuse the provided audit logic to confirm compliance
        {
          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>
    </AccordionGroup>
  </Tab>
</Tabs>
