Kuadrant / Kuadrant/accesspolicy-controller

XAccessPolicy → AuthPolicy translation

Open
#1 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
1
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Here's a possible mapping from XAccessPolicy to AuthPolicy, to perhaps shape the translation logic in the controller.

It uses the priority field of the AuthPolicy in conjunction with when conditions to implement XAccessPolicy's allow-override behaviour – in contrast to the AuthPolicy's deny-override default approach.

The example also demonstrates how XAccessPolicy's source could be modelled in the AuthPolicy, for both types of source – ServiceAccount and SPIFFE.

For multiple XAccessPolicy CRs targeting a common gateway, merge all rules from all policies into a single AuthPolicy, respecting the order of the resources (by creation timestamp) and rules within the resources.

I haven't tested this yet, but I think it's sound.

Source:

apiVersion: agentic.networking.x-k8s.io/v1alpha1
kind: XAccessPolicy
metadata:
  name: demo-access-policy
  namespace: quickstart-ns
spec:
  targetRefs:
    - group: gateway.networking.k8s.io
      kind: Gateway
      name: demo-gateway
  action: Allow
  rules:
    - name: allow-get-sum
      source:
        type: ServiceAccount
        serviceAccount:
          name: default
      authorization:
        type: Inline
        mcp:
          methods:
            - name: tools/call
              params: ["get-sum"]
    - name: allow-get-tiny-image
      source:
        type: ServiceAccount
        serviceAccount:
          name: default
      authorization:
        type: Inline
        mcp:
          methods:
            - name: tools/call
              params: ["get-tiny-image"]
    - name: allow-non-tools
      source:
        type: ServiceAccount
        serviceAccount:
          name: default
      authorization:
        type: Inline
        mcpBaseProtocolMethodsOption: MATCH_BASE_PROTOCOL_METHODS

Target:

apiVersion: kuadrant.io/v1
kind: AuthPolicy
metadata:
  name: demo-gateway-auth
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: Gateway
    name: demo-gateway
  rules:
    authentication:
      # ServiceAccount authentication - Kuadrant will validate the bearer token in the `Authorization` header against the Kubernetes API server.
      # `auth.identity.principal` will be set to the Kubernetes username of the service account (e.g. `system:serviceaccount:<namespace>:<serviceaccount>`).
      "service-account":
        when:
        - predicate: |
            'authorization' in request.headers && request.headers['authorization'].startsWith('Bearer ')
        kubernetesTokenReview:
          audiences:
          - https://kubernetes.default.svc.cluster.local
        overrides:
          "principal":
            expression: auth.identity.user.username

      # SPIFFE authentication - requires the proxy to validate the workload identity (typically by X.509 client certificate)
      # and set the SPIFFE ID into the `source.principal` field of the authorization request.
      # `auth.identity.principal` will be set to the SPIFFE ID of the workload (e.g. `spiffe://<trust-domain>/<namespace>/<serviceaccount>`).
      "spiffe":
        when:
        - predicate: source.principal.startsWith('spiffe://')
        plain:
          expression: source.principal
        overrides:
          "principal":
            expression: source.principal

    authorization:
      "allow-get-sum":
        priority: 0
        when:
        - predicate: size(auth.authorization) == 0
        - predicate: auth.identity.principal == 'system:serviceaccount:quickstart-ns:default'
        - predicate: request.headers['x-mcp-method'] == 'tools/call' && request.headers['x-mcp-toolname'] == 'get-sum'
        opa:
          rego: allow = true
      "allow-get-tiny-image":
        priority: 1
        when:
        - predicate: size(auth.authorization) == 0
        - predicate: auth.identity.principal == 'system:serviceaccount:quickstart-ns:default'
        - predicate: request.headers['x-mcp-method'] == 'tools/call' && request.headers['x-mcp-toolname'] == 'get-tiny-image'
        opa:
          rego: allow = true
      "allow-non-tools":
        priority: 2
        when:
        - predicate: size(auth.authorization) == 0
        - predicate: auth.identity.principal == 'system:serviceaccount:quickstart-ns:default'
        - predicate: request.headers['x-mcp-method'] in ['initialize', 'tools/list', 'completion', 'logging', 'notifications', 'ping'] || request.method in ['GET', 'DELETE']
        opa:
          rego: allow = true

      # Fail-close rule: if no other rules match, deny the request
      "fail-close":
        priority: 3
        when:
        - predicate: size(auth.authorization) == 0
        opa:
          rego: allow = false

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the controller translation logic for XAccessPolicy and AuthPolicy resources; this issue names no files, tests, or entry points. Compare the proposed YAML mapping and determine how multiple policies, rule ordering, authentication sources, and the fail-close rule should be represented, then verify the behavior with the project's controller tests if available.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.