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
44set -e
55
66SCRIPT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd) "
@@ -10,77 +10,182 @@ if [ -f "$SCRIPT_DIR/.env" ]; then
1010 source " $SCRIPT_DIR /.env"
1111fi
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+
1322GATEWAY_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} "
1726echo " Gateway: ${MCP_GATEWAY_ID} "
18- echo " Policy Engine: ${MCP_POLICY_ENGINE_ID} "
1927echo " "
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..."
2655EXISTING=$( 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
3059for 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
48123done
49124
50- # Create new policy
125+ # Step 6: Add IAM permissions for gateway role
51126echo " "
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
63152echo " "
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
83170done
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
0 commit comments