Example policies - Amazon Bedrock AgentCore

Example policies

This section provides comprehensive examples of Cedar authorization policies for an insurance management system. These examples demonstrate various Cedar language features and authorization patterns that you can adapt for your own applications.

Available tools

The Insurance API provides five tools for managing insurance policies and claims:

InsuranceAPI__get_policy

Retrieve insurance policy details.

Parameters:

  • policyId (string, required) - The policy identifier

InsuranceAPI__file_claim

File an insurance claim.

Parameters:

  • policyId (string, required) - The policy identifier

  • claimType (string, required) - Type of claim (e.g., "health", "property", "auto")

  • amount (number, required) - Claim amount

  • description (string, optional) - Claim description

InsuranceAPI__update_coverage

Update policy coverage.

Parameters:

  • policyId (string, required) - The policy identifier

  • coverageType (string, required) - Type of coverage (e.g., "liability", "collision")

  • newLimit (number, required) - New coverage limit

InsuranceAPI__get_claim_status

Check claim status.

Parameters:

  • claimId (string, required) - The claim identifier

InsuranceAPI__calculate_premium

Calculate insurance premium.

Parameters:

  • coverageType (string, required) - Type of coverage

  • coverageAmount (number, required) - Coverage amount

  • riskFactors (object, optional) - Risk assessment factors

Authorization policies

The following policies demonstrate various Cedar language features and authorization patterns. Each policy includes natural language description, Cedar code, and detailed explanation.

Policy 1: Multi-action permit

This policy demonstrates how to grant access to multiple related actions using a single policy statement.

Natural language: Allow all principals to get policy and get claim status.

Cedar policy:

permit( principal is AgentCore::OAuthUser, action in [ AgentCore::Action::"InsuranceAPI__get_policy", AgentCore::Action::"InsuranceAPI__get_claim_status" ], resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" );

Explanation: This policy demonstrates multi-action permits using the in operator. Instead of writing separate policies for each read operation, a single policy grants access to multiple related actions. This is useful for grouping similar operations that share the same authorization requirements.

Policy 2: Scope-based authorization

This policy shows how to use OAuth scopes to control access to specific operations.

Natural language: Allow principals with scope containing "insurance:claim" to file claims.

Cedar policy:

permit( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) when { principal.hasTag("scope") && principal.getTag("scope") like "*insurance:claim*" };

Explanation: This policy demonstrates OAuth scope validation using tags. The hasTag method checks if the tag exists, and getTag retrieves its value. The like operator with wildcards (*) performs pattern matching, allowing flexible scope formats like "insurance:claim", "insurance:claim:write", or "admin insurance:claim".

Policy 3: Role-based authorization with unless

This policy demonstrates using the unless clause to create exceptions to restrictions.

Natural language: Block principals from updating coverage unless the principal has role "senior-adjuster" or "manager".

Cedar policy:

forbid( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__update_coverage", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) unless { principal.hasTag("role") && (principal.getTag("role") == "senior-adjuster" || principal.getTag("role") == "manager") };

Explanation: This policy demonstrates the unless clause, which inverts the condition logic. The forbid applies unless the user has one of the specified roles. This is useful for creating exceptions to restrictions. The policy also shows OR logic for checking multiple acceptable values.

Policy 4: String equality with OR logic

This policy shows how to validate input parameters and use OR logic for multiple acceptable values.

Natural language: Allow principals to file claims when the claim type is health, property, or auto.

Cedar policy:

permit( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) when { context.input has claimType && (context.input.claimType == "health" || context.input.claimType == "property" || context.input.claimType == "auto") };

Explanation: This policy demonstrates accessing tool input parameters via context.input and string equality checks with OR logic. The has operator first verifies the field exists before accessing it, preventing errors when optional fields are missing.

Policy 5: Field existence check

This policy demonstrates how to enforce business rules by requiring optional fields.

Natural language: Block principals from filing claims unless a description is provided.

Cedar policy:

forbid( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) unless { context.input has description };

Explanation: This policy demonstrates enforcing required fields for optional parameters. The description field is optional in the tool schema, but this policy makes it mandatory by forbidding requests that don't include it. This shows how policies can add business rules beyond schema validation.

Policy 6: Username-based authorization

This policy shows how to grant access based on specific user identities.

Natural language: Allow principals with username "Clare" to update coverage.

Cedar policy:

permit( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__update_coverage", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) when { principal.hasTag("username") && principal.getTag("username") == "Clare" };

Explanation: This policy demonstrates username-based authorization using exact string matching. Combined with Policy 3, this creates a two-part authorization: users must have the username "insurance-agent" AND have the role "senior-adjuster" or "manager" to update coverage.

Policy 7: Pattern matching with like

This policy demonstrates flexible pattern matching using wildcards for category-based access control.

Natural language: Allow principals to calculate premium when the coverage type contains "auto".

Cedar policy:

permit( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__calculate_premium", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) when { context.input has coverageType && context.input.coverageType like "*auto*" };

Explanation: This policy demonstrates flexible pattern matching with the like operator. The wildcard * matches any characters, so "auto", "auto-liability", "comprehensive-auto", or "auto-collision" would all match. This is useful when you want to match a category of values rather than exact strings.

Policy 8: Combined conditions with AND

This policy shows how to combine multiple conditions to create complex authorization rules.

Natural language: Allow principals to update coverage when the coverage type is liability or collision and a new limit is provided.

Cedar policy:

permit( principal is AgentCore::OAuthUser, action == AgentCore::Action::"InsuranceAPI__update_coverage", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance" ) when { context.input has coverageType && context.input has newLimit && (context.input.coverageType == "liability" || context.input.coverageType == "collision") };

Explanation: This policy demonstrates combining multiple conditions with AND logic. All three conditions must be true: coverageType must exist, newLimit must exist, and coverageType must be either "liability" or "collision". This works with Policy 6 to create layered authorization: who can update (Policy 6) and what they can update (Policy 8).

Understanding authorization semantics

These policies demonstrate key Cedar authorization semantics:

Default deny

If no policy explicitly permits an action, it's denied. For example, a user without the "insurance:claim" scope cannot file claims even though no policy explicitly forbids it.

Forbid wins

If any forbid policy matches, the request is denied even if permit policies also match. Policy 5 (forbid without description) overrides Policy 2 (permit with scope) when description is missing.

Policy layering

Multiple policies can apply to the same request:

  • Policy 6 permits insurance-agent to update coverage

  • Policy 3 forbids updates unless user has senior-adjuster or manager role

  • Policy 8 permits updates only for liability or collision types

For a request to succeed, it must satisfy all three: be insurance-agent (Policy 6), have senior-adjuster or manager role (Policy 3), and update liability or collision (Policy 8).

Test scenarios

The following scenarios demonstrate how the policies work together in practice:

Scenario 1: Regular user viewing policy

User: username="john", scope="insurance:view"

Action: get_policy

Expected: ALLOW (Policy 1)

Scenario 2: User filing health claim with description

User: username="jane", scope="insurance:claim"

Action: file_claim with claimType="health", description="Medical expenses"

Expected: ALLOW (Policy 2, Policy 4, Policy 5 does not forbid)

Scenario 3: User filing claim without description

User: username="jane", scope="insurance:claim"

Action: file_claim with claimType="health", no description

Expected: DENY (Policy 5 forbid wins)

Scenario 4: Insurance agent updating coverage

User: username="insurance-agent", role="senior-adjuster"

Action: update_coverage with coverageType="liability"

Expected: ALLOW (Policy 6, Policy 3 does not forbid, Policy 8)

Scenario 5: Insurance agent without senior role

User: username="insurance-agent", role="agent"

Action: update_coverage with coverageType="liability"

Expected: DENY (Policy 3 forbid wins)

Scenario 6: Premium calculation for auto coverage

User: username="anyone", scope="any"

Action: calculate_premium with coverageType="auto-liability"

Expected: ALLOW (Policy 7, pattern matches "auto")