The solution.sh for the kubernetes-security-hardening-zero-disruption task was failing the RBAC check with score 0.75 even though the solution correctly:
- Created a dedicated ServiceAccount (
bleater-app) - Patched all Deployments/StatefulSets to use the new SA
- Performed a rolling restart
The grader's check_rbac() function queries ALL pods in the namespace:
pods = json.loads(out).get("items", [])
for pod in pods:
sa = pod.get("spec", {}).get("serviceAccountName", "default")
sas_in_use.add(sa)
if "default" in sas_in_use:
return False, "bleater workloads still use default ServiceAccount"This includes pods in Terminating state. After a rolling restart:
- New pods are created with the new ServiceAccount
- Old pods are marked for deletion but take time to fully terminate
kubectl rollout statusreturns success when new pods are ready, not when old pods are gone
The grader runs immediately after the solution completes, sees the Terminating pods still using default SA, and fails.
Add a wait loop after kubectl rollout status that polls until ALL pods using the default ServiceAccount have fully terminated:
timeout 120 bash -c '
while true; do
pods_with_default=$(kubectl get pods -n bleater -o json | \
python3 -c "import sys,json; pods=json.load(sys.stdin)[\"items\"]; print(len([p for p in pods if p[\"spec\"].get(\"serviceAccountName\",\"default\")==\"default\"]))")
if [ "$pods_with_default" = "0" ]; then
break
fi
sleep 5
done
'This ensures the grader only runs after old pods are completely gone, not just marked for deletion.
- Before fix: Score 0.75 (RBAC check fails)
- After fix: Score 1.0 (all checks pass)