Skip to content

Latest commit

 

History

History
135 lines (124 loc) · 5.64 KB

File metadata and controls

135 lines (124 loc) · 5.64 KB

Configuring {mcpg} authorization with an AuthPolicy

The following example demonstrates using a Kuadrant AuthPolicy custom resource (CR) with Common Expression Language (CEL) to implement role-based access control. You can use this procedure as a general pattern for applying the authorization specific to your use case. The {mcpg} supports Istio or Gateway API compatible authorization mechanisms.

Prerequisites
  • You installed {mcpg}.

  • You installed {prodname}.

  • You configured a Gateway object with an mcp listener and an mcps listener. The mcps listener is required for internal tools/call routing and authorization.

  • You completed authentication procedures, including creating an AuthPolicy CR on the mcp listener.

  • You configured your identity provider to include group and role claims in JSON Web Tokens (JWT).

  • The identity provider client IDs match the namespaced MCPServerRegistration name in the format <namespace>/<mcpserverregistration_name>.

Procedure
  1. Ensure that your identity provider includes the required group and role claims in the issued JWTs. In the following example, {keycloak} is used:

    Example issued OAuth token claims:
    {
      "resource_access": {
        "mcp-ns/arithmetic-mcp-server": {
          "roles": ["add", "sum", "multiply", "divide"]
        },
        "mcp-ns/geometry-mcp-server": {
          "roles": ["area", "distance", "volume"]
        }
      }
    }
    • The "mcp-ns/arithmetic-mcp-server" specification must match the namespaced name of the MCPServerRegistration CR in the format {namespace}/{name}. For example, if your MCPServerRegistration CR is named arithmetic-mcp-server and is applied in the mcp-ns namespace, the {keycloak} client ID must be mcp-ns/arithmetic-mcp-server.

    • The "roles": ["add", "sum", "multiply", "divide"] parameter and values specify the roles representing the allowed tools.

  2. Configure tool-level authorization by creating an AuthPolicy CR that enforces tool-level access control on the mcps listener, as shown in the following example:

    Important

    The authorization AuthPolicy CR must target the mcps listener, not the mcp listener. The mcp listener only handles public traffic and has an authentication-only AuthPolicy CR.

    Example tool-level access control AuthPolicy
    apiVersion: kuadrant.io/v1
    kind: AuthPolicy
    metadata:
      name: <mcp_tool_auth_policy>
      namespace: <gateway_system>
    spec:
      targetRef:
        group: gateway.networking.k8s.io
        kind: Gateway
        name: <mcp_gateway>
        sectionName: <mcps>
      rules:
        authentication:
          'sso-server':
            jwt:
              issuerUrl: https://<keycloak.example.com>/realms/mcp
        authorization:
          'tool-access-check':
            patternMatching:
              patterns:
                - predicate: |
                    request.headers['x-mcp-toolname'] in (has(auth.identity.resource_access) && auth.identity.resource_access.exists(p, p == request.headers['x-mcp-servername']) ? auth.identity.resource_access[request.headers['x-mcp-servername']].roles : [])
        response:
          unauthenticated:
            headers:
              'WWW-Authenticate':
                value: Bearer resource_metadata=http://<mcp.example.com:8001>/.well-known/oauth-protected-resource
            body:
              value: |
                {
                  "error": "Unauthorized",
                  "message": "MCP Tool Access denied: Authentication required."
                }
          unauthorized:
            body:
              value: |
                {
                  "error": "Forbidden",
                  "message": "MCP Tool Access denied: Insufficient permissions for this tool."
                }
    • Replace metadata.name: with the name of the AuthPolicy.

    • Replace metadata.namespace: with the namespace where the AuthPolicy CR is applied.

    • Replace spec.targetRef.name: with the name of the Gateway CR.

    • The spec.targetRef.sectionName: value must be mcps, which is the internal listener for tool/call authorization. This listener must exist on your Gateway object.

    • Authentication: Validates the JWT token using the configured issuer URL. Replace <keycloak.example.com> with your identity provider hostname.

    • Authorization Logic: CEL expression checks if user’s roles allow access to the requested tool

    • CEL Breakdown:

      • request.headers['x-mcp-toolname']: The name of the requested MCP tool, stripped from prefix.

      • request.headers['x-mcp-servername']: The namespaced name of the MCP server matching the MCPServerRegistration CR.

      • auth.identity.resource_access: The JWT claim containing all roles representing each allowed tool the user can access, grouped by MCP server.

    • Response handling: Custom 401 and 403 responses for unauthenticated and unauthorized access attempts.

  3. Apply the AuthPolicy CR by running the following command:

    $ oc apply -f <mcp_tool_auth_policy.yaml>
    • Replace <mcp_tool_auth_policy.yaml> with the name of the AuthPolicy YAML filename.

Verification
  1. Monitor authorization decisions by checking the AuthPolicy CR status with the following command:

    $ oc get authpolicy <mcp_tool_auth_policy> -n <gateway_system> -o jsonpath='{.status.conditions[?(@.type=="Enforced")].status}'
    Example output
    True
  2. Check the authorization logs by running the following command:

    $ oc logs -n mcp-system -l app.kubernetes.io/name=mcp-gateway