Policies

Updated at:
Copy as MD

The Agent Identity service's authorization policies are based on the Cedar policy language, providing fine-grained access control for outbound calls from AI Agents, such as requests to MCP Servers. By defining policies, you can precisely control "who (principal) can or cannot perform what action on what resource under what conditions."

Key concepts

Understanding the following concepts will help you better configure and manage your authorization policies:

  • policy: The basic unit of access control. Each policy defines a specific set of authorization rules.

  • policy set: A logical collection of policies. A policy set must be bound to an AIGateway to take effect. An AIGateway can only be bound to a single policy set, and all policies within that set jointly determine the final authorization result.

  • AIGateway: The policy enforcement point. All outbound calls from an AI Agent pass through the gateway for policy evaluation.

Policy evaluation logic

The policy evaluation engine for the Agent Identity service is based on the Cedar policy language and follows two core security principles:

  1. default deny: If the evaluation engine finds no applicable policy that explicitly permits a request, the request is denied by default. This ensures that all access must be explicitly authorized.

  2. Deny overrides: During the evaluation process, the deny (forbid) policy has the highest priority. The evaluation process is as follows:

    flowchart-policyevaluation

    • The engine first checks for any forbid policies that match the request. If such a policy exists, the request is immediately rejected, and the evaluation terminates.

    • If there is no matching forbid policy, the engine then looks for at least one matching permit policy. If one is found, the request is allowed.

    • If there is neither a matching forbid policy nor a matching permit policy, the request is denied based on the default deny principle.

Because a single AIGateway can only be bound to a single policy set, each request is evaluated only against the policies within that set. Cross-policy-set evaluation does not occur.

Policy structure

A complete policy consists of three parts: effect, scope, and condition.

// 1. Effect: permit (allow) or forbid (deny)
permit (
  // 2. Scope: Defines the principal, action, and resource the policy applies to
  principal is AgentIdentity::OAuthUser,
  action == AIGateway::Action::"mcp-servers.order-service.refund",
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:123...:gateway/gw-abc..."
)
// 3. Condition: Provides fine-grained filtering based on the request context
when {
  context.input.amount < 500
};

Effect

Specifies whether the policy permits or forbids access.

  • permit: Allows access.

  • forbid: Denies access. If any forbid policy matches, the request is immediately denied. Forbid policies take precedence over all permit policies.

Scope

Defines the boundaries of the policy using three elements: principal, action, and resource. The policy's condition and effect are evaluated only if a request's principal, action, and resource match those defined in the scope.

Principal

The principal is the identity making the request. You can specify one of the following three principal types, which correspond to the three methods for obtaining a Workload Access Token. A policy can only specify one principal type, or a single principal object within that type (when specifying a principal ID).

  • Workload identity

    • Use case: Programmatic, automated access without user involvement.

    • Example: principal == AgentIdentity::Workload::"acs:agentidentity:cn-beijing:{account_id}:workloadidentitydirectory/default/workloadidentity/test-workload-identity". This policy is matched when the requesting principal is a workload identity named test-workload-identity.

  • OAuth user

    • Use case: For access involving a user who authenticates through an OIDC/OAuth2-compatible Identity Provider (IdP). This is the most common use case.

    • Example: principal == AgentIdentity::OAuthUser::"iiCsOvhjNZX/hK0x1jl9****". Here, iiCsOvhjNZX/hK0x1jl9**** is the value of the sub field in the user's JWT token and can be used to uniquely identify the user.

  • Custom user

    • Use case: For access involving a user who authenticates without using the OIDC protocol.

    • Example: principal == AgentIdentity::SimpleUser::"test-user1", where test-user1 is the user ID declared in the request.

Note

If you omit the principal ID when specifying a principal type, the policy applies to all principals of that type. For example, the statement principal is AgentIdentity::OAuthUser applies the policy to all requests from principals of the OAuth user type.

Action

Defines the operation the principal is attempting to perform, such as accessing an MCP service or a tool within an MCP service.

  • Format: mcp-servers.{service_name}.{tool_name}

  • Example: action == AIGateway::Action::"mcp-servers.order-service.create-order". This means that a request for the create-order tool of the order-service service in MCP matches this policy.

  • For scenarios that involve multiple operations, you can use the in operator with a list of operations. For example: action in [AIGateway::Action::"mcp-servers.order-service.create-order", AIGateway::Action::"mcp-servers.order-service.get-order"]

  • Action hierarchy: Actions are hierarchical. Specifying a higher-level action (like a service) in a policy makes it apply to all nested actions (like all tools within that service). For example:

    • The statement action in AIGateway::Action::"mcp-servers" permits access to all MCP service tools under the specified gateway.

    • The statement action in AIGateway::Action::"mcp-servers.order-service" allows all tools in the MCP service order-service.

Resource

The object being accessed, which is the Alibaba Cloud Resource Name (ARN) of the target AIGateway.

Example: resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/gw-d6rs7qem1hks769c****", where gw-d6rs7qem1hks769c**** is the instance ID of the AI Gateway.

Note

You must specify a specific gateway resource. Applying a policy to all resources is not supported.

Condition

An optional element that provides dynamic, fine-grained control based on the request context. The condition clause follows the scope and supports two forms:

  • when: When the expression evaluates to true, the policy takes effect.

  • unless: If the expression evaluates to true, the policy does not take effect (negative condition). You must use the script editor to configure this.

Request context (context)

The request context object contains attributes about the request that you can use in a policy's condition clause. The following table lists the supported context attributes and their operators.

Context attribute

Description

Operator

Example

context.sourceIp

The source IP address of the request.

isInRange (is in CIDR block)
== (equals)
!= (does not equal)

ip(context.sourceIp).isInRange(ip("192.168.1.0/24"))

context.agent

The workload identity created in Agent Identity.

== (equals)
!= (does not equal)
like (pattern matching)

context.agent like "*workload-identity-name*"

context.input

Input parameters for the MCP tool call.

Depends on the data type of the input parameter.

context.input.amount < 1000

context.isHttps

Whether the request is made over HTTPS.

==, !=

context.isHttps == true

Note

String matching with conditional operators is case-sensitive.

Logical operators

You can use logical operators to combine multiple conditions:

  • && (AND): All conditions must be met.

  • || (OR): At least one condition must be met.

  • ! (NOT): Negates the condition.

Example: when { context.input.amount < 500 || ip(context.sourceIp).isInRange(ip("192.168.1.0/24")) }.

Note

When you use the visual policy editor to specify multiple conditions, the logical operator defaults to &&. To use other logical operators, use the script editor.

Create a policy

For instructions, see Add a Policy to a Policy Set.

Common policy examples

Example 1: Control access by MCP parameters

Allows calls to the refund API (refund), but the amount of a single refund must be less than 500.

permit (
  principal is AgentIdentity::OAuthUser,
  action == AIGateway::Action::"mcp-servers.payment-service.refund",
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/{gateway_instance_id}"
)
when { context.input.amount < 500 };

Example 2: Control access by IP whitelist

Permit access to a sensitive data query tool only for requests originating from a specific internal network segment (such as 10.0.0.0/8) or a corporate public egress IP range.

permit (
  principal is AgentIdentity::OAuthUser,
  action == AIGateway::Action::"mcp-servers.data-service.query",
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/{gateway_instance_id}"
)
when { ip(context.sourceIp).isInRange(ip("10.0.0.0/8")) };

Example 3: Grant a specific user MCP tool access

Allows OAuth users with a sub value of iiCsOvhjNZX/hK0x1jl9**** to call the create-order and get-order tools of the Order MCP service.

permit (
  principal == AgentIdentity::OAuthUser::"iiCsOvhjNZX/hK0x1jl9****",
  action in [AIGateway::Action::"mcp-servers.order-service.create-order", AIGateway::Action::"mcp-servers.order-service.get-order"],
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/{gateway_instance_id}"
);

Example 4: Deny a specific action (blacklist)

Forbid all users from calling the data deletion API. Because forbid policies have the highest precedence due to the deny overrides principle, this action is denied even if a permit policy also applies.

forbid (
  principal,
  action == AIGateway::Action::"mcp-servers.system-service.delete_data",
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/{gateway_instance_id}"
);

Example 5: Use reverse exclusion with 'unless'

Allow all users to call the query tool, but exclude requests from a specific IP address (192.168.1.100).

permit (
  principal,
  action == AIGateway::Action::"mcp-servers.data-service.query",
  resource == AIGateway::Gateway::"acs:apig:cn-beijing:{account_id}:gateway/{gateway_instance_id}"
)
unless {
  ip(context.sourceIp) == ip("192.168.1.100")
};