Respond (RS) · Authorization
Authorization at the server side layer
external · Outside the agent entirely
How do I stop the bleeding now?
What this cell does
Apply emergency Kyverno deny-all, replace agent Role with empty rules, attach IAM deny-all, Git pre-receive reject.
Artifacts (3)
agent-deny-all-serverview on GitHub#!/usr/bin/env bash
# ABOUTME: Server-side authorization-shrink runbook. Applies Kyverno deny-all, empty Role, IAM deny-all.
# ABOUTME: Pre-stage kyverno-deny-all-agents.yaml, empty-role.yaml, and iam-deny-all.json under /etc/agents/emergency/ first.
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "Usage: agent-deny-all-server <AGENT_NAME>" >&2
exit 64
fi
AGENT_NAME="$1"
NAMESPACE="agent-${AGENT_NAME}"
INCIDENT_ID="$(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')"
EMERGENCY_DIR="${EMERGENCY_DIR:-/etc/agents/emergency}"
for src in \
"$EMERGENCY_DIR/kyverno-deny-all-agents.yaml" \
"$EMERGENCY_DIR/empty-role.yaml" \
"$EMERGENCY_DIR/iam-deny-all.json"; do
if [[ ! -r "$src" ]]; then
echo "REFUSING: pre-staged artifact missing: $src" >&2
exit 1
fi
done
# 1. Apply emergency Kyverno deny-all ClusterPolicy.
kubectl apply -f "$EMERGENCY_DIR/kyverno-deny-all-agents.yaml"
# 2. Overwrite the agent's Role with empty rules. The Role's name must match
# the original (claude-code in agent-* namespaces by convention).
kubectl apply -n "$NAMESPACE" -f "$EMERGENCY_DIR/empty-role.yaml"
# 3. Attach IAM deny-all policy. Idempotent with identity-revocation runbook.
aws iam put-role-policy \
--role-name "$AGENT_NAME" \
--policy-name "EmergencyDenyAll-${INCIDENT_ID}" \
--policy-document "file://$EMERGENCY_DIR/iam-deny-all.json" 2>/dev/null || \
echo "WARN: aws iam put-role-policy failed (already attached or role missing)" >&2
# 4. Cluster event for forensic timeline.
kubectl create event --namespace "$NAMESPACE" \
--type=Warning \
--reason=AuthorizationLocked \
--message="Emergency authorization shrink for $AGENT_NAME, incident $INCIDENT_ID" 2>/dev/null || true
logger -t agent-incident -p user.warning \
"$(jq -n \
--arg event "authorization_locked_server" \
--arg agent "$AGENT_NAME" \
--arg incident "$INCIDENT_ID" \
--arg actor "$(whoami)" \
--arg ts "$(date -Iseconds)" \
'{event:$event, agent:$agent, incident:$incident, actor:$actor, ts:$ts}')"
echo "Server-side authorization locked down for $AGENT_NAME (incident $INCIDENT_ID)"
empty-role.yamlview on GitHub# ABOUTME: Pre-staged empty Role used to overwrite an agent's namespace-scoped Role during response.
# ABOUTME: The Role name must match the original (claude-code by convention). Empty rules removes every permission.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: claude-code
annotations:
incident: "true"
rules: []
kyverno-deny-all-agents.yamlview on GitHub# ABOUTME: Emergency Kyverno ClusterPolicy denying all operations from agent ServiceAccounts. Excludes break-glass.
# ABOUTME: Pre-stage at /etc/agents/emergency/. Kyverno must run in Enforce mode (audit-only does not block).
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: emergency-deny-all-agents
annotations:
incident: "true"
policies.kyverno.io/title: Emergency lockdown of all agent ServiceAccounts
policies.kyverno.io/severity: critical
spec:
validationFailureAction: Enforce
background: false
rules:
- name: deny-everything-from-agent-sa
match:
any:
- resources:
kinds: ["*"]
exclude:
any:
# Break-glass identities. Add or remove based on your environment's
# incident-response identities. The operator who needs to remediate
# MUST be excluded or the lockdown locks them out too.
- subjects:
- kind: User
name: "system:admin"
- kind: User
name: "break-glass-operator"
- kind: ServiceAccount
name: "kyverno-admission-controller"
namespace: "kyverno"
preconditions:
any:
- key: "{{ request.userInfo.username }}"
operator: AnyIn
value:
- "system:serviceaccount:agent-*"
validate:
message: "Emergency lockdown: agent operations denied. See incident channel."
deny: {}
Cell notes
Interventions, Authorization / Server-side
Trigger. RBAC denial spike, Kyverno PolicyReport failures from agent SAs, IAM Access Analyzer findings, Git pre-receive rejection spike.
Authority. On-call, no second approval.
Speed target. Under 10 seconds.
Tooling
- -
kubectlwith permission to apply ClusterPolicies and Roles in agent namespaces. - - AWS CLI with permission to attach IAM policies.
- - Kyverno 1.18+ in
Enforcemode (audit-only does not block).
Files in this directory
- -
agent-deny-all-server, runbook script. Applies the emergency Kyverno ClusterPolicy, overwrites the agent's Role with empty rules, attaches IAMDeny *policy. - -
kyverno-deny-all-agents.yaml, pre-staged ClusterPolicy denying every operation from anysystem:serviceaccount:agent-*. Excludes the break-glass operator. Pre-stage at/etc/agents/emergency/kyverno-deny-all-agents.yaml. - -
empty-role.yaml, pre-staged Role withrules: []and the same name as the original agent Role. Overwriting it removes every permission. Pre-stage at/etc/agents/emergency/empty-role.yaml.
The IAM Deny * policy is at ../../identity/server-side/iam-deny-all.json (shared with identity revocation).
Verification
# 1. Kyverno deny-all in effect
kubectl get clusterpolicy emergency-deny-all-agents
kubectl --as=system:serviceaccount:agent-claude-code-prod:claude-code get pods
# expected: failure with "Emergency lockdown: agent operations denied"
# 2. Role is empty
kubectl get role -n agent-claude-code-prod claude-code -o jsonpath='{.rules}'
# expected: [] or null
# 3. IAM deny-all attached
aws iam get-role-policy --role-name claude-code-prod --policy-name EmergencyDenyAll
Common mistakes
- - Kyverno deny-all rule that does not exclude break-glass identities, locks out the operator who needs to remediate.
- - Kyverno installed in audit-only mode org-wide, emergency
Enforcepolicy still does not block. - - Empty Role applied with
kubectl applybut a stale RoleBinding still references a different (non-empty) Role. - - IAM deny-all that interacts badly with explicit allow policies in the same role's permission boundary.
Citation
NIST CSF 2.0 RS.MI-01, RS.MI-02; PR.AA-05 (response dimension). NIST SP 800-207 (Zero Trust). OWASP ASI02, ASI03, ASI05. NIST AI RMF MANAGE 4.1.
Primary failure modes
Documented, not hypothetical. A control whose bypass is undocumented is worse than no control, because somebody trusted it.
- Kyverno in audit-only mode does not block
- emergency policy locks out break-glass identity
Crosswalk
| NIST CSF 2 0 | RS.MI-01, RS.MI-02, PR.AA-05 |
|---|---|
| NIST AI RMF | MANAGE 4.1 |
| OWASP AGENTIC | ASI02, ASI03, ASI05 |
| OTHER | NIST SP 800-207 |
Cite this cell:
https://agenticcovenants.com/respond/authorization/server-side/