Skip to main content

Configure Cross-Namespace References

Cross-namespace references let platform teams operate shared Gateways, backends, and Secrets while application teams manage their own Routes and Consumers. Gateway API requires an explicit authorization at each namespace boundary so that creating a resource in one namespace does not grant access to resources owned by another team.

The required authorization depends on the relationship:

RelationshipAuthorization
Route to a Gateway in another namespaceThe Gateway listener selects the Route namespace with allowedRoutes.
Route to a backend in another namespaceA ReferenceGrant in the backend namespace permits the Route reference.
Gateway to a TLS Secret in another namespaceA ReferenceGrant in the Secret namespace permits the Gateway reference.
Consumer to a credential Secret in another namespaceA ReferenceGrant in the Secret namespace permits the Consumer reference.

Cross-namespace traffic references are supported through Gateway API resources. The Ingress resource and APISIX routing CRDs do not support cross-namespace traffic references. The Consumer credential reference is an implementation-specific use of ReferenceGrant.

These mechanisms authorize relationships between resources; they do not grant users permission to create or modify those resources. Use Kubernetes RBAC to delegate Gateway API access before configuring cross-namespace references.

Prerequisites

Complete the following prerequisites:

  • Set up the Ingress Controller and gateway with Gateway API resources.
  • Install the Gateway API CRDs supported by this version of the Ingress Controller.
  • Use an account with permission to create the namespaces and resources in each example.

The examples use a Gateway named apisix and a GatewayProxy named apisix-config in the aic namespace. These are the names created by the APISIX setup tutorial.

Allow a Route to Use a Backend in Another Namespace

The following example creates an HTTPRoute in tenant-a, attaches it to the Gateway in aic, and forwards requests to a Service in backend-ns:

The Gateway owner authorizes attachment from tenant-a, while the backend owner separately authorizes access to the httpbin Service.

Create the Namespaces

Create the Route and backend namespaces:

kubectl create namespace tenant-a
kubectl create namespace backend-ns

Kubernetes automatically adds the immutable kubernetes.io/metadata.name label to every namespace. The Gateway listener will use that label to select tenant-a; no custom namespace label is required.

Create the Backend Service

Create a deployment and Service in backend-ns:

httpbin-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin
namespace: backend-ns
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
spec:
containers:
- name: httpbin
image: kennethreitz/httpbin
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
namespace: backend-ns
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: httpbin

Apply the manifest:

kubectl apply -f httpbin-deployment.yaml

Authorize the Backend Reference

A ReferenceGrant must be created in the namespace containing the referenced object. Create the following grant in backend-ns to allow HTTPRoute resources in tenant-a to reference the httpbin Service:

backend-referencegrant.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-httpbin-from-tenant-a
namespace: backend-ns
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: tenant-a
to:
- group: ""
kind: Service
name: httpbin

The from entry trusts HTTPRoute resources in tenant-a. The to entry limits that trust to the httpbin Service in the ReferenceGrant's namespace. The to.name field is optional, but omitting it would permit references to every Service in backend-ns that is covered by a matching grant.

Apply the grant before creating the Route:

kubectl apply -f backend-referencegrant.yaml

Create the Route

Create an HTTPRoute in tenant-a that attaches to the Gateway in aic and references the Service in backend-ns:

httpbin-route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin-route
namespace: tenant-a
spec:
parentRefs:
- name: apisix
namespace: aic
rules:
- matches:
- path:
type: PathPrefix
value: /ip
backendRefs:
- kind: Service
name: httpbin
namespace: backend-ns
port: 80
weight: 1

Apply the Route:

kubectl apply -f httpbin-route.yaml

Authorize the Route Attachment

By default, a Gateway listener accepts Routes only from the Gateway's namespace. Configure allowedRoutes on the listener to select the tenant-a namespace. Preserve any other listeners or settings required by your existing Gateway:

gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: apisix
namespace: aic
spec:
gatewayClassName: apisix
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: tenant-a
infrastructure:
parametersRef:
group: apisix.apache.org
kind: GatewayProxy
name: apisix-config

Using the immutable namespace-name label prevents users who can modify ordinary namespace labels from changing which namespaces may attach Routes to the Gateway.

Apply the updated Gateway:

kubectl apply -f gateway.yaml

To accept Routes from every namespace, set from: All instead:

allowedRoutes:
namespaces:
from: All
caution

Using from: All in a multi-tenant or untrusted cluster lets any namespace attach HTTPRoute resources to this listener. A Route may claim a hostname before an authorized Route or expose backends through the shared Gateway. Prefer an explicit namespace selector.

Verify the Route

Forward the gateway Service port to your local machine. In the APISIX setup tutorial, both the Gateway and Service are in aic:

kubectl port-forward -n <gateway-service-namespace> \
svc/<gateway-service-name> 9080:80 &

Send a request to the Route:

curl -i "http://127.0.0.1:9080/ip"

You should receive an HTTP/1.1 200 OK response similar to the following:

{
"origin": "127.0.0.1"
}

If the request fails, inspect the Route's parent conditions. Accepted and ResolvedRefs should both be True:

kubectl describe httproute httpbin-route -n tenant-a

Allow a Gateway to Reference a TLS Secret

When a Gateway listener uses a certificate Secret in another namespace, the Secret owner must authorize the reference. For example, if the apisix Gateway is in aic and the Secret is named test-tls-secret in certificates, create this grant in certificates:

certificate-referencegrant.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-gateway-from-aic
namespace: certificates
spec:
from:
- group: gateway.networking.k8s.io
kind: Gateway
namespace: aic
to:
- group: ""
kind: Secret
name: test-tls-secret

Apply the grant before updating the Gateway:

kubectl apply -f certificate-referencegrant.yaml

Then include the Secret namespace in the listener's certificateRefs entry:

listeners:
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- group: ""
kind: Secret
name: test-tls-secret
namespace: certificates

After applying the Gateway, verify that the HTTPS listener reports ResolvedRefs=True:

kubectl describe gateway apisix -n aic

See Configure TLS Between Client and Gateway for the complete certificate and HTTPS Route configuration.

Allow a Consumer to Reference a Credential Secret

When a Consumer and its credential Secret are in different namespaces, the Secret owner must authorize the reference. Create the ReferenceGrant before applying or upgrading the Consumer. Without a matching grant, the admission webhook rejects the Consumer when the webhook is enabled. If the Consumer is admitted without a grant, the controller reports Available=False and does not program the credential.

Create the Consumer and Secret namespaces:

kubectl create namespace consumer-ns
kubectl create namespace secret-ns

Create a key-auth credential Secret in secret-ns:

consumer-credential.yaml
apiVersion: v1
kind: Secret
metadata:
name: consumer-credentials
namespace: secret-ns
type: Opaque
stringData:
key: example-api-key

Create a ReferenceGrant in secret-ns that allows Consumer resources in consumer-ns to reference this Secret:

consumer-referencegrant.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: ReferenceGrant
metadata:
name: allow-consumers-from-consumer-ns
namespace: secret-ns
spec:
from:
- group: apisix.apache.org
kind: Consumer
namespace: consumer-ns
to:
- group: ""
kind: Secret
name: consumer-credentials

Create the Consumer in consumer-ns. The gatewayRef identifies the Gateway for which the credential should be programmed:

consumer.yaml
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
name: example-consumer
namespace: consumer-ns
spec:
gatewayRef:
name: apisix
namespace: aic
credentials:
- type: key-auth
name: primary-key
secretRef:
name: consumer-credentials
namespace: secret-ns

Apply the Secret and grant before the Consumer:

kubectl apply -f consumer-credential.yaml
kubectl apply -f consumer-referencegrant.yaml
kubectl apply -f consumer.yaml

Wait for the Consumer to report that the credential was programmed successfully:

kubectl wait --for=condition=Available \
consumers.apisix.apache.org/example-consumer \
-n consumer-ns \
--timeout=60s

If the condition remains False, inspect its message and confirm that the grant's from.namespace, to.name, and metadata namespace match the Consumer and Secret:

kubectl describe consumer example-consumer -n consumer-ns