Add support for specifying `targetRef` namespace on authorization policies
Describe the feature request
When using the k8s gateway API (with Istio as a gateway controller), I'd like to be able to store authorization policies alongside applications, alongside HTTPRoutes and similar application-specific resources.
Today, it looks like the only way to target application-specific resources with AuthorizationPolicies when using the gateway API is to target the entire gateway, and then use a rule to filter the policy based on hosts/paths/etc. that match the application's HTTPRoute. While not ideal, this should in theory work.
However, because the AuthorizationPolicy does not support targeting gateways in other namespaces, the policy must live in either the default namespace (so it'll match gateways in all namespaces), or the gateway's namespace. This means moving application-specific resources away from the application, and away from all other related ingress configuration.
I'd like to be able to specify the namespace for the referenced gateway within the authorization policy so that I can place the policy in application namespaces, instead of gateway namespaces. It looks like work was already started on this here, but never completed.
Describe alternatives you've considered
Store the resource in the gateway namespace
Affected product area (please put an X in all that apply)
[ ] Configuration Infrastructure [ ] Docs [ ] Installation [x] Networking [ ] Performance and Scalability [x] Policies and Telemetry [x] Security [ ] Test and Release [ ] User Experience
Additional context
I don't want to be too dismissive but I don't think we would ever do this. To achieve the use case I would think an HTTPRoute attached policy would be more appropriate; we have actually discussed this but implementation is tricky
That'd be great and would be my preferred solution as well. I just figured given that the CRD and protobuf already has a namespace as a part of targetRef that this was something that was previously planned but forgotten/deprioritized.
Ran into another place where a lack of targetRef support gateway API route resources (e.g. HTTPRoute) support has a really nasty edge. Apparently only one provider can be referenced via all authorization policies attached to a "workload". When attaching multiple providers, the controller marks them as "accepted" via the resource status, but the istiod process fails with:
2025-09-29T02:42:10.607186Z error authorization Processed authorization policy: failed to process CUSTOM action, will generate deny configs for the specified rules: only 1 provider can be used per workload, found multiple providers: [my-idp-no-upstream-headers my-idp]
This is a problem because the provider config controls what headers are sent from the external authorizer to both the upstream and downstream. If an application requires different settings here (for example, it seems like apache tomcat gets upset with either too many headers or too large headers), then the application will need a different provider, and therefore also a different auth policy. Because the provider is technically different (they're backed by the same actual service but the headers are different), supporting today means that I need to deploy an entire additional gateway, use an additional LB service, public IP, DNS records, etc.
Let me know if this should be filed as a separate issue for tracking and I'll take care of it.
As I understand it this also goes against the intent gateway API model, because it requires application-specific gateways (a "cluster operator" resources) rather than just routes (an "application developer" resource).
@howardjohn RBAC, jwt authn, and ext authz all have per route configs. Is there something more fundamental blocking this?
@keithmattix per-route is extremely tricky and not what it seems on the surface.
Consider this setup and the 'obvious' implementation
.
The behavior I would expect, is that no matter what if Route2 is used for selecting a backend, pol3 is applied. This is not the case!
Envoy does not follow a linear request processing flow of applying each filter, then selecting routes, then applying each route filter. Instead, it ~guesses the route and starts applying the per-route rules. The filter can change the route selection, causing a different route to be selected, bypassing the policy.
But the per-route rules are only used once the filter is executed right? As long as the route-changing filter comes after the policy's filter, the policy would be applied. So in your scenario, if we put the rbac/ext-authz/jwt filter before any request mutation filters, it would get executed. If traffic is denied, then we stop processing. If something later in the filter chain changes the route, the filter-chain gets executed again but with different per route config. So, IIUC, we could apply both policies
That is not my understanding of how it works. If i have, for example, an ext-authz policy as those pol1/pol2/pol3, you can hit route2 without applying pol3 ext_authz
Ah you're right; I misread a config dump and had ChatGPT explain it to me. So yeah any changes to the route would be effectively broken regardless of ordering. That really sounds like an Envoy problem
Is this something that I should try to chase down upstream? I'm not very familiar with Envoy and most of this is over my head, so doing this myself may do more harm than good.
Ran into yet another issue related to this today. Would appreciate any advice on how to proceed.
I've got several applications that I'd like to use a CUSTOM auth provider for, so I've deployed a pretty simple policy for them:
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: my-idp-auth
spec:
targetRef:
kind: Gateway
group: gateway.networking.k8s.io
name: my-gateway
action: CUSTOM
provider:
name: my-idp
rules:
- to:
- operation:
hosts:
- app1.${SECRET_PUBLIC_DOMAIN_NAME}
- app2.${SECRET_PUBLIC_DOMAIN_NAME}
- appN.${SECRET_PUBLIC_DOMAIN_NAME}
This worked great until I added a C# app that uses SignalR, which sends CORS preflight requests. I then ran into this prematurely bot-closed issue, but for the external auth provider instead of an envoy filter. To work around this, it seems like I need to add the below policy to explicitly allow HTTP OPTIONS requests to bypass the auth requirement:
---
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: my-idp-auth-allow-options-requests
spec:
targetRef:
kind: Gateway
group: gateway.networking.k8s.io
name: my-gateway
action: ALLOW
rules:
- to:
- operation:
hosts:
- app1.${SECRET_PUBLIC_DOMAIN_NAME}
- app2.${SECRET_PUBLIC_DOMAIN_NAME}
- appN.${SECRET_PUBLIC_DOMAIN_NAME}
methods:
- OPTIONS
The problem is that I have several other applications attached to the same gateway that handle auth within the application. These should completely bypass the custom external auth provider, as they'll talk to the backing service (my IdP) directly. However, because the allow policy targets the gateway instead of individual HTTPRoute resources, this allow policy now blocks access to all of the other services!
I really, really don't want to create another network-namespaced auth policy that explicitly targets all of the other apps not using the custom provider. Is there any way around this?