Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,13 @@ public Expense getExpense(String expenseReference) {
.items().stream().findFirst()
.orElseThrow(() -> new ResourceNotFoundException("Expense", expenseReference));
}

public Expense deleteExpense(String expenseReference) {
Expense expense = getExpense(expenseReference);
if (expense.getStatus() != Expense.ExpenseStatus.DRAFT) {
throw new InvalidOperationException("Only draft expenses can be deleted");
}
dynamoDbTemplate.delete(expense);
return expense;
}
}
6 changes: 6 additions & 0 deletions apps/java-spring-ai-agents/backoffice/tools/ExpenseTools.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,10 @@ public Expense submitExpense(
@ToolParam(description = "Expense reference (EXP-XXXXXXXX)") String expenseReference) {
return service.submitExpense(expenseReference);
}

@Tool(description = "Delete a draft expense")
public Expense deleteExpense(
@ToolParam(description = "Expense reference (EXP-XXXXXXXX)") String expenseReference) {
return service.deleteExpense(expenseReference);
}
}
86 changes: 86 additions & 0 deletions apps/java-spring-ai-agents/scripts/13-mcp-policy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/bash
# Deploy Cedar policy to MCP Gateway
# Requires AWS CLI 2.32+
set -e

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

# Load environment
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
fi

GATEWAY_ARN="arn:aws:bedrock-agentcore:${AWS_REGION}:${ACCOUNT_ID}:gateway/${MCP_GATEWAY_ID}"
POLICY_FILE="${SCRIPT_DIR}/backoffice-policy.cedar"

echo "Deploying Cedar policy..."
echo " Gateway: ${MCP_GATEWAY_ID}"
echo " Policy Engine: ${MCP_POLICY_ENGINE_ID}"
echo ""

# Read and substitute policy
POLICY_STATEMENT=$(sed "s|\${GATEWAY_ARN}|${GATEWAY_ARN}|g" "$POLICY_FILE")

# Delete existing policies and wait for deletion
echo "1. Cleaning up existing policies..."
EXISTING=$(aws bedrock-agentcore-control list-policies \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--query 'policies[].policyId' --output text 2>/dev/null || true)

for PID in $EXISTING; do
echo " Deleting: $PID"
aws bedrock-agentcore-control delete-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--policy-id "$PID" > /dev/null

# Wait for deletion to complete
while true; do
STATUS=$(aws bedrock-agentcore-control get-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--policy-id "$PID" \
--query 'status' --output text 2>/dev/null || echo "DELETED")

if [ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ]; then
break
fi
sleep 2
done
done

# Create new policy
echo ""
echo "2. Creating policy..."
POLICY_ID=$(aws bedrock-agentcore-control create-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--name "ForbidDangerousOperations" \
--validation-mode "IGNORE_ALL_FINDINGS" \
--definition "{\"cedar\":{\"statement\":$(echo "$POLICY_STATEMENT" | jq -Rs .)}}" \
--query 'policyId' --output text)

echo " Policy ID: $POLICY_ID"

# Wait for ACTIVE
echo ""
echo "3. Waiting for policy to become ACTIVE..."
for i in {1..30}; do
STATUS=$(aws bedrock-agentcore-control get-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--policy-id "$POLICY_ID" \
--query 'status' --output text)

echo " Status: $STATUS"

if [ "$STATUS" = "ACTIVE" ]; then
echo ""
echo "✅ Policy deployed successfully!"
exit 0
elif [[ "$STATUS" == *"FAILED"* ]]; then
echo ""
echo "❌ Policy deployment failed"
exit 1
fi
sleep 2
done

echo "❌ Timeout waiting for policy"
exit 1
46 changes: 46 additions & 0 deletions apps/java-spring-ai-agents/scripts/14-mcp-policy-cleanup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/bin/bash
# Cleanup Cedar policies from MCP Gateway
set -e

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

if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
fi

echo "Cleaning up policies from engine: ${MCP_POLICY_ENGINE_ID}"
echo ""

POLICIES=$(aws bedrock-agentcore-control list-policies \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--query 'policies[].policyId' --output text 2>/dev/null || true)

if [ -z "$POLICIES" ]; then
echo "No policies found."
exit 0
fi

for PID in $POLICIES; do
echo "Deleting: $PID"
aws bedrock-agentcore-control delete-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--policy-id "$PID" > /dev/null

echo " Waiting for deletion..."
while true; do
STATUS=$(aws bedrock-agentcore-control get-policy \
--policy-engine-id "${MCP_POLICY_ENGINE_ID}" \
--policy-id "$PID" \
--query 'status' --output text 2>/dev/null || echo "DELETED")

if [ "$STATUS" = "DELETED" ] || [ -z "$STATUS" ]; then
echo " ✅ Deleted"
break
fi
echo " Status: $STATUS"
sleep 2
done
done

echo ""
echo "✅ All policies cleaned up!"
11 changes: 11 additions & 0 deletions apps/java-spring-ai-agents/scripts/backoffice-policy.cedar
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Backoffice MCP Gateway Policy
// Forbid dangerous operations - everything else allowed by default

forbid(
principal,
action in [
AgentCore::Action::"backoffice___cancelTrip",
AgentCore::Action::"backoffice___deleteExpense"
],
resource == AgentCore::Gateway::"${GATEWAY_ARN}"
);
Loading