Skip to content

Commit 5c69f7f

Browse files
committed
AgentCore policy fixes
1 parent 04cdcc8 commit 5c69f7f

3 files changed

Lines changed: 231 additions & 72 deletions

File tree

Lines changed: 150 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
2-
# Deploy Cedar policy to MCP Gateway
3-
# Requires AWS CLI 2.32+
2+
# Deploy Cedar policies to MCP Gateway
3+
# Creates: Policy Engine, Permit all, Forbid cancelTrip, IAM permissions, Gateway attachment
44
set -e
55

66
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -10,77 +10,182 @@ if [ -f "$SCRIPT_DIR/.env" ]; then
1010
source "$SCRIPT_DIR/.env"
1111
fi
1212

13+
# Set defaults if not in .env
14+
AWS_REGION=${AWS_REGION:-$(aws configure get region)}
15+
ACCOUNT_ID=${ACCOUNT_ID:-$(aws sts get-caller-identity --query Account --output text)}
16+
17+
# Get gateway ID if not set
18+
if [ -z "$MCP_GATEWAY_ID" ]; then
19+
MCP_GATEWAY_ID=$(aws bedrock-agentcore-control list-gateways --query 'items[0].gatewayId' --output text)
20+
fi
21+
1322
GATEWAY_ARN="arn:aws:bedrock-agentcore:${AWS_REGION}:${ACCOUNT_ID}:gateway/${MCP_GATEWAY_ID}"
14-
POLICY_FILE="${SCRIPT_DIR}/backoffice-policy.cedar"
1523

16-
echo "Deploying Cedar policy..."
24+
echo "Deploying Cedar policies..."
25+
echo " Region: ${AWS_REGION}"
1726
echo " Gateway: ${MCP_GATEWAY_ID}"
18-
echo " Policy Engine: ${MCP_POLICY_ENGINE_ID}"
1927
echo ""
2028

21-
# Read and substitute policy
22-
POLICY_STATEMENT=$(sed "s|\${GATEWAY_ARN}|${GATEWAY_ARN}|g" "$POLICY_FILE")
29+
# Step 1: Create or get Policy Engine
30+
echo "1. Setting up Policy Engine..."
31+
POLICY_ENGINE_ID=$(aws bedrock-agentcore-control list-policy-engines \
32+
--query 'policyEngines[?name==`BackofficePolicyEngine`].policyEngineId' --output text 2>/dev/null || true)
2333

24-
# Delete existing policies and wait for deletion
25-
echo "1. Cleaning up existing policies..."
34+
if [ -z "$POLICY_ENGINE_ID" ]; then
35+
echo " Creating new Policy Engine..."
36+
POLICY_ENGINE_ID=$(aws bedrock-agentcore-control create-policy-engine \
37+
--name "BackofficePolicyEngine" \
38+
--query "policyEngineId" --output text)
39+
40+
echo -n " Waiting for ACTIVE"
41+
while [ "$(aws bedrock-agentcore-control get-policy-engine --policy-engine-id "${POLICY_ENGINE_ID}" \
42+
--query 'status' --output text)" != "ACTIVE" ]; do
43+
echo -n "."; sleep 3
44+
done
45+
echo " Done"
46+
else
47+
echo " Using existing Policy Engine: ${POLICY_ENGINE_ID}"
48+
fi
49+
50+
POLICY_ENGINE_ARN="arn:aws:bedrock-agentcore:${AWS_REGION}:${ACCOUNT_ID}:policy-engine/${POLICY_ENGINE_ID}"
51+
52+
# Step 2: Delete existing policies
53+
echo ""
54+
echo "2. Cleaning up existing policies..."
2655
EXISTING=$(aws bedrock-agentcore-control list-policies \
27-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
56+
--policy-engine-id "${POLICY_ENGINE_ID}" \
2857
--query 'policies[].policyId' --output text 2>/dev/null || true)
2958

3059
for PID in $EXISTING; do
3160
echo " Deleting: $PID"
3261
aws bedrock-agentcore-control delete-policy \
33-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
62+
--policy-engine-id "${POLICY_ENGINE_ID}" \
3463
--policy-id "$PID" > /dev/null
3564

36-
# Wait for deletion to complete
3765
while true; do
3866
STATUS=$(aws bedrock-agentcore-control get-policy \
39-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
67+
--policy-engine-id "${POLICY_ENGINE_ID}" \
4068
--policy-id "$PID" \
4169
--query 'status' --output text 2>/dev/null || echo "DELETED")
70+
[ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ] && break
71+
sleep 2
72+
done
73+
done
74+
echo " Done"
75+
76+
# Step 3: Create permit policy (Cedar is deny-by-default)
77+
echo ""
78+
echo "3. Creating permit policy..."
79+
PERMIT_STATEMENT="permit (principal, action, resource == AgentCore::Gateway::\"${GATEWAY_ARN}\");"
80+
81+
PERMIT_ID=$(aws bedrock-agentcore-control create-policy \
82+
--policy-engine-id "${POLICY_ENGINE_ID}" \
83+
--name "PermitAllActions" \
84+
--validation-mode "IGNORE_ALL_FINDINGS" \
85+
--definition "{\"cedar\":{\"statement\":$(echo "$PERMIT_STATEMENT" | jq -Rs .)}}" \
86+
--query 'policyId' --output text)
87+
88+
echo " Policy ID: $PERMIT_ID"
89+
90+
# Step 4: Create forbid policy
91+
echo ""
92+
echo "4. Creating forbid policy..."
93+
FORBID_STATEMENT="forbid (principal, action == AgentCore::Action::\"backoffice___cancelTrip\", resource == AgentCore::Gateway::\"${GATEWAY_ARN}\");"
94+
95+
FORBID_ID=$(aws bedrock-agentcore-control create-policy \
96+
--policy-engine-id "${POLICY_ENGINE_ID}" \
97+
--name "ForbidCancelTrip" \
98+
--validation-mode "IGNORE_ALL_FINDINGS" \
99+
--definition "{\"cedar\":{\"statement\":$(echo "$FORBID_STATEMENT" | jq -Rs .)}}" \
100+
--query 'policyId' --output text)
101+
102+
echo " Policy ID: $FORBID_ID"
103+
104+
# Step 5: Wait for policies to become ACTIVE
105+
echo ""
106+
echo "5. Waiting for policies to become ACTIVE..."
107+
for PID in "$PERMIT_ID" "$FORBID_ID"; do
108+
for i in {1..30}; do
109+
STATUS=$(aws bedrock-agentcore-control get-policy \
110+
--policy-engine-id "${POLICY_ENGINE_ID}" \
111+
--policy-id "$PID" \
112+
--query 'status' --output text)
42113

43-
if [ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ]; then
114+
if [ "$STATUS" = "ACTIVE" ]; then
115+
echo " $PID: ACTIVE"
44116
break
117+
elif [[ "$STATUS" == *"FAILED"* ]]; then
118+
echo "❌ Policy $PID failed"
119+
exit 1
45120
fi
46121
sleep 2
47122
done
48123
done
49124

50-
# Create new policy
125+
# Step 6: Add IAM permissions for gateway role
51126
echo ""
52-
echo "2. Creating policy..."
53-
POLICY_ID=$(aws bedrock-agentcore-control create-policy \
54-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
55-
--name "ForbidDangerousOperations" \
56-
--validation-mode "IGNORE_ALL_FINDINGS" \
57-
--definition "{\"cedar\":{\"statement\":$(echo "$POLICY_STATEMENT" | jq -Rs .)}}" \
58-
--query 'policyId' --output text)
127+
echo "6. Adding IAM permissions..."
128+
cat > /tmp/policy-permissions.json << EOF
129+
{
130+
"Version": "2012-10-17",
131+
"Statement": [{
132+
"Effect": "Allow",
133+
"Action": "bedrock-agentcore:*",
134+
"Resource": [
135+
"${GATEWAY_ARN}",
136+
"${POLICY_ENGINE_ARN}",
137+
"${POLICY_ENGINE_ARN}/*"
138+
]
139+
}]
140+
}
141+
EOF
142+
143+
aws iam put-role-policy \
144+
--role-name mcp-gateway-role \
145+
--policy-name PolicyEngineAccess \
146+
--policy-document file:///tmp/policy-permissions.json
59147

60-
echo " Policy ID: $POLICY_ID"
148+
echo " Waiting for IAM propagation..."
149+
sleep 10
61150

62-
# Wait for ACTIVE
151+
# Step 7: Attach policy engine to gateway
63152
echo ""
64-
echo "3. Waiting for policy to become ACTIVE..."
65-
for i in {1..30}; do
66-
STATUS=$(aws bedrock-agentcore-control get-policy \
67-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
68-
--policy-id "$POLICY_ID" \
69-
--query 'status' --output text)
70-
71-
echo " Status: $STATUS"
72-
73-
if [ "$STATUS" = "ACTIVE" ]; then
74-
echo ""
75-
echo "✅ Policy deployed successfully!"
76-
exit 0
77-
elif [[ "$STATUS" == *"FAILED"* ]]; then
78-
echo ""
79-
echo "❌ Policy deployment failed"
80-
exit 1
81-
fi
82-
sleep 2
153+
echo "7. Attaching policy engine to gateway..."
154+
MCP_GATEWAY_ROLE_ARN=$(aws bedrock-agentcore-control get-gateway \
155+
--gateway-id "${MCP_GATEWAY_ID}" --query 'roleArn' --output text)
156+
157+
aws bedrock-agentcore-control update-gateway \
158+
--gateway-identifier "${MCP_GATEWAY_ID}" \
159+
--name "mcp-gateway" \
160+
--role-arn "${MCP_GATEWAY_ROLE_ARN}" \
161+
--protocol-type "MCP" \
162+
--authorizer-type "AWS_IAM" \
163+
--policy-engine-configuration "{\"arn\":\"${POLICY_ENGINE_ARN}\",\"mode\":\"ENFORCE\"}" \
164+
--no-cli-pager > /dev/null
165+
166+
echo -n " Waiting for gateway READY"
167+
while [ "$(aws bedrock-agentcore-control get-gateway --gateway-id "${MCP_GATEWAY_ID}" \
168+
--query 'status' --output text)" != "READY" ]; do
169+
echo -n "."; sleep 3
83170
done
171+
echo " Done"
172+
173+
# Save to .env for cleanup script
174+
if ! grep -q "MCP_POLICY_ENGINE_ID" "$SCRIPT_DIR/.env" 2>/dev/null; then
175+
echo "" >> "$SCRIPT_DIR/.env"
176+
echo "# Policy Engine" >> "$SCRIPT_DIR/.env"
177+
echo "MCP_POLICY_ENGINE_ID=${POLICY_ENGINE_ID}" >> "$SCRIPT_DIR/.env"
178+
fi
84179

85-
echo "❌ Timeout waiting for policy"
86-
exit 1
180+
echo ""
181+
echo "✅ Policies deployed successfully!"
182+
echo ""
183+
echo "Policies:"
184+
aws bedrock-agentcore-control list-policies \
185+
--policy-engine-id "${POLICY_ENGINE_ID}" \
186+
--query 'policies[].{Name:name,Status:status}' --output table
187+
188+
echo ""
189+
echo "Gateway:"
190+
aws bedrock-agentcore-control get-gateway --gateway-id "${MCP_GATEWAY_ID}" \
191+
--query '{PolicyEngine:policyEngineConfiguration.arn,Mode:policyEngineConfiguration.mode}' --output table
Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,92 @@
11
#!/bin/bash
2-
# Cleanup Cedar policies from MCP Gateway
2+
# Remove Cedar policies from MCP Gateway
33
set -e
44

55
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
66

7+
# Load environment
78
if [ -f "$SCRIPT_DIR/.env" ]; then
89
source "$SCRIPT_DIR/.env"
910
fi
1011

11-
echo "Cleaning up policies from engine: ${MCP_POLICY_ENGINE_ID}"
12-
echo ""
12+
# Set defaults if not in .env
13+
AWS_REGION=${AWS_REGION:-$(aws configure get region)}
14+
ACCOUNT_ID=${ACCOUNT_ID:-$(aws sts get-caller-identity --query Account --output text)}
1315

14-
POLICIES=$(aws bedrock-agentcore-control list-policies \
15-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
16-
--query 'policies[].policyId' --output text 2>/dev/null || true)
16+
# Get gateway ID if not set
17+
if [ -z "$MCP_GATEWAY_ID" ]; then
18+
MCP_GATEWAY_ID=$(aws bedrock-agentcore-control list-gateways --query 'items[0].gatewayId' --output text)
19+
fi
1720

18-
if [ -z "$POLICIES" ]; then
19-
echo "No policies found."
21+
# Get policy engine ID if not set
22+
if [ -z "$MCP_POLICY_ENGINE_ID" ]; then
23+
MCP_POLICY_ENGINE_ID=$(aws bedrock-agentcore-control list-policy-engines \
24+
--query 'policyEngines[?name==`BackofficePolicyEngine`].policyEngineId' --output text 2>/dev/null || true)
25+
fi
26+
27+
if [ -z "$MCP_POLICY_ENGINE_ID" ]; then
28+
echo "No policy engine found."
2029
exit 0
2130
fi
2231

23-
for PID in $POLICIES; do
24-
echo "Deleting: $PID"
25-
aws bedrock-agentcore-control delete-policy \
26-
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
27-
--policy-id "$PID" > /dev/null
32+
echo "Removing Cedar policies..."
33+
echo " Gateway: ${MCP_GATEWAY_ID}"
34+
echo " Policy Engine: ${MCP_POLICY_ENGINE_ID}"
35+
echo ""
36+
37+
# Step 1: Detach policy engine from gateway
38+
echo "1. Detaching policy engine from gateway..."
39+
CURRENT_POLICY=$(aws bedrock-agentcore-control get-gateway --gateway-id "${MCP_GATEWAY_ID}" \
40+
--query 'policyEngineConfiguration.arn' --output text 2>/dev/null || echo "None")
41+
42+
if [ "$CURRENT_POLICY" != "None" ] && [ -n "$CURRENT_POLICY" ]; then
43+
MCP_GATEWAY_ROLE_ARN=$(aws bedrock-agentcore-control get-gateway \
44+
--gateway-id "${MCP_GATEWAY_ID}" --query 'roleArn' --output text)
2845

29-
echo " Waiting for deletion..."
30-
while true; do
31-
STATUS=$(aws bedrock-agentcore-control get-policy \
46+
aws bedrock-agentcore-control update-gateway \
47+
--gateway-identifier "${MCP_GATEWAY_ID}" \
48+
--name "mcp-gateway" \
49+
--role-arn "${MCP_GATEWAY_ROLE_ARN}" \
50+
--protocol-type "MCP" \
51+
--authorizer-type "AWS_IAM" \
52+
--no-cli-pager > /dev/null
53+
54+
echo -n " Waiting for gateway READY"
55+
while [ "$(aws bedrock-agentcore-control get-gateway --gateway-id "${MCP_GATEWAY_ID}" \
56+
--query 'status' --output text)" != "READY" ]; do
57+
echo -n "."; sleep 3
58+
done
59+
echo " Done"
60+
else
61+
echo " No policy engine attached to gateway"
62+
fi
63+
64+
# Step 2: Delete all policies
65+
echo ""
66+
echo "2. Deleting policies..."
67+
EXISTING=$(aws bedrock-agentcore-control list-policies \
68+
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
69+
--query 'policies[].policyId' --output text 2>/dev/null || true)
70+
71+
if [ -z "$EXISTING" ]; then
72+
echo " No policies to delete."
73+
else
74+
for PID in $EXISTING; do
75+
echo " Deleting: $PID"
76+
aws bedrock-agentcore-control delete-policy \
3277
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
33-
--policy-id "$PID" \
34-
--query 'status' --output text 2>/dev/null || echo "DELETED")
78+
--policy-id "$PID" > /dev/null
3579

36-
if [ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ]; then
37-
echo " ✅ Deleted"
38-
break
39-
fi
40-
echo " Status: $STATUS"
41-
sleep 2
80+
while true; do
81+
STATUS=$(aws bedrock-agentcore-control get-policy \
82+
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
83+
--policy-id "$PID" \
84+
--query 'status' --output text 2>/dev/null || echo "DELETED")
85+
[ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ] && break
86+
sleep 2
87+
done
4288
done
43-
done
89+
fi
4490

4591
echo ""
46-
echo "All policies cleaned up!"
92+
echo "Policies removed. Gateway restored to full tool access."

apps/java-spring-ai-agents/scripts/backoffice-policy.cedar

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
// Backoffice MCP Gateway Policy
2-
// Forbid dangerous operations - everything else allowed by default
2+
// Cedar is deny-by-default, so we need permit-all first, then forbid specific actions
33

4+
// Permit all actions on the gateway (required - Cedar denies by default)
5+
permit(
6+
principal,
7+
action,
8+
resource == AgentCore::Gateway::"${GATEWAY_ARN}"
9+
);
10+
11+
// Forbid dangerous operations (takes precedence over permit)
412
forbid(
513
principal,
614
action in [

0 commit comments

Comments
 (0)