diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index f2ab15fd..02181a63 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -121,6 +121,18 @@ rules: - get - patch - update +- apiGroups: + - gateway.networking.k8s.io + resources: + - referencegrants + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - gateway.networking.k8s.io resources: diff --git a/config/samples/tcproute/gateway.yaml b/config/samples/tcproute/gateway.yaml index 7274b892..89402c62 100644 --- a/config/samples/tcproute/gateway.yaml +++ b/config/samples/tcproute/gateway.yaml @@ -3,6 +3,7 @@ kind: GatewayClass apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: blixt-tcproute-sample + namespace: gwapi-ref-ns spec: controllerName: konghq.com/blixt --- @@ -10,6 +11,7 @@ kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: blixt-tcproute-sample + namespace: gwapi-ref-ns spec: gatewayClassName: blixt-tcproute-sample listeners: diff --git a/config/samples/tcproute/server.yaml b/config/samples/tcproute/server.yaml index cc0942f2..ba6b2350 100644 --- a/config/samples/tcproute/server.yaml +++ b/config/samples/tcproute/server.yaml @@ -40,3 +40,8 @@ spec: selector: app: blixt-tcproute-sample type: ClusterIP +--- +apiVersion: v1 +kind: Namespace +metadata: + name: gwapi-ref-ns diff --git a/config/samples/tcproute/tcproute.yaml b/config/samples/tcproute/tcproute.yaml index 1b51b660..5c8b415e 100644 --- a/config/samples/tcproute/tcproute.yaml +++ b/config/samples/tcproute/tcproute.yaml @@ -2,6 +2,7 @@ apiVersion: gateway.networking.k8s.io/v1alpha2 kind: TCPRoute metadata: name: blixt-tcproute-sample + namespace: gwapi-ref-ns spec: parentRefs: - name: blixt-tcproute-sample @@ -10,3 +11,18 @@ spec: - backendRefs: - name: blixt-tcproute-sample port: 8080 + namespace: default +--- +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: tcproute-sample-ref + namespace: default +spec: + from: + - group: gateway.networking.k8s.io + kind: TCPRoute + namespace: gwapi-ref-ns + to: + - group: "" + kind: Service diff --git a/controllers/gateway_controller.go b/controllers/gateway_controller.go index 019f0218..1aae6e50 100644 --- a/controllers/gateway_controller.go +++ b/controllers/gateway_controller.go @@ -21,6 +21,7 @@ import ( ) //+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=referencegrants,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/status,verbs=get;update;patch //+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/finalizers,verbs=update diff --git a/internal/dataplane/client/utils.go b/internal/dataplane/client/utils.go index 4b5d4c96..0ef582de 100644 --- a/internal/dataplane/client/utils.go +++ b/internal/dataplane/client/utils.go @@ -3,6 +3,7 @@ package client import ( context "context" "encoding/binary" + "errors" "fmt" "net" @@ -40,7 +41,12 @@ func CompileUDPRouteToDataPlaneBackend(ctx context.Context, c client.Client, udp // TODO only using one endpoint for now until https://github.com/Kong/blixt/issues/10 var target *Target if udproute.DeletionTimestamp == nil { - endpoints, err := endpointsFromBackendRef(ctx, c, udproute.Namespace, backendRef) + from := objectKindNamespacedName{ + kind: udproute.Kind, + namespace: udproute.Namespace, + name: udproute.Name, + } + endpoints, err := endpointsFromBackendRef(ctx, from, c, udproute.Namespace, backendRef) if err != nil { return nil, err } @@ -112,7 +118,12 @@ func CompileTCPRouteToDataPlaneBackend(ctx context.Context, c client.Client, tcp // TODO only using one endpoint for now until https://github.com/Kong/blixt/issues/10 var target *Target if tcproute.DeletionTimestamp == nil { - endpoints, err := endpointsFromBackendRef(ctx, c, tcproute.Namespace, backendRef) + from := objectKindNamespacedName{ + kind: tcproute.Kind, + namespace: tcproute.Namespace, + name: tcproute.Name, + } + endpoints, err := endpointsFromBackendRef(ctx, from, c, tcproute.Namespace, backendRef) if err != nil { return nil, err } @@ -156,9 +167,46 @@ func CompileTCPRouteToDataPlaneBackend(ctx context.Context, c client.Client, tcp return targets, nil } -func endpointsFromBackendRef(ctx context.Context, c client.Client, namespace string, backendRef gatewayv1alpha2.BackendRef) (*corev1.Endpoints, error) { - if backendRef.Namespace != nil { - namespace = string(*backendRef.Namespace) +type objectKindNamespacedName struct { + kind string + namespace string + name string +} + +func endpointsFromBackendRef(ctx context.Context, from objectKindNamespacedName, c client.Client, namespace string, backendRef gatewayv1alpha2.BackendRef) (*corev1.Endpoints, error) { + refGrantFoundOrNotNeeded := false + if backendRef.Namespace != nil && from.namespace != string(*backendRef.Namespace) { + refGrantList := &gatewayv1beta1.ReferenceGrantList{} + err := c.List(ctx, refGrantList, &client.ListOptions{Namespace: string(*backendRef.Namespace)}) + for _, refGrant := range refGrantList.Items { + useRefGrant := false + for _, dest := range refGrant.Spec.To { + if dest.Group == "" && dest.Kind == "Service" { + useRefGrant = true + break + } + } + if !useRefGrant { + continue + } + for _, src := range refGrant.Spec.From { + if src.Kind == gatewayv1alpha2.Kind(from.kind) && string(src.Namespace) == from.namespace { + refGrantFoundOrNotNeeded = true + namespace = string(*backendRef.Namespace) + break + } + } + } + if err != nil { + return nil, errors.New("not able to list reference grant") + } + + } else if backendRef.Namespace == nil { + refGrantFoundOrNotNeeded = true + } + + if !refGrantFoundOrNotNeeded { + return nil, errors.New("route does not have reference grant for endpoints") } endpoints := new(corev1.Endpoints)