mirror of
https://github.com/alibaba/higress.git
synced 2026-05-25 13:17:28 +08:00
166 lines
4.9 KiB
Go
166 lines
4.9 KiB
Go
// Copyright Istio Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package istio
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"k8s.io/apimachinery/pkg/types"
|
|
gateway "sigs.k8s.io/gateway-api/apis/v1beta1"
|
|
|
|
creds "istio.io/istio/pilot/pkg/model/credentials"
|
|
"istio.io/istio/pkg/config"
|
|
"istio.io/istio/pkg/config/schema/collections"
|
|
"istio.io/istio/pkg/config/schema/gvk"
|
|
"istio.io/istio/pkg/kube/krt"
|
|
)
|
|
|
|
// Reference stores a reference to a namespaced GVK, as used by ReferenceGrant
|
|
type Reference struct {
|
|
Kind config.GroupVersionKind
|
|
Namespace gateway.Namespace
|
|
}
|
|
|
|
func (refs Reference) String() string {
|
|
return refs.Kind.String() + "/" + string(refs.Namespace)
|
|
}
|
|
|
|
type ReferencePair struct {
|
|
To, From Reference
|
|
}
|
|
|
|
func (r ReferencePair) String() string {
|
|
return fmt.Sprintf("%s->%s", r.From, r.To)
|
|
}
|
|
|
|
type ReferenceGrants struct {
|
|
collection krt.Collection[ReferenceGrant]
|
|
index krt.Index[ReferencePair, ReferenceGrant]
|
|
}
|
|
|
|
func ReferenceGrantsCollection(referenceGrants krt.Collection[*gateway.ReferenceGrant], opts krt.OptionsBuilder) krt.Collection[ReferenceGrant] {
|
|
return krt.NewManyCollection(referenceGrants, func(ctx krt.HandlerContext, obj *gateway.ReferenceGrant) []ReferenceGrant {
|
|
rp := obj.Spec
|
|
results := make([]ReferenceGrant, 0, len(rp.From)*len(rp.To))
|
|
for _, from := range rp.From {
|
|
fromKey := Reference{
|
|
Namespace: from.Namespace,
|
|
}
|
|
ref := normalizeReference(&from.Group, &from.Kind, config.GroupVersionKind{})
|
|
switch ref {
|
|
case gvk.KubernetesGateway, gvk.HTTPRoute, gvk.GRPCRoute, gvk.TLSRoute, gvk.TCPRoute, gvk.XListenerSet:
|
|
fromKey.Kind = ref
|
|
default:
|
|
// Not supported type. Not an error; may be for another controller
|
|
continue
|
|
}
|
|
for _, to := range rp.To {
|
|
toKey := Reference{
|
|
Namespace: gateway.Namespace(obj.Namespace),
|
|
}
|
|
|
|
ref := normalizeReference(&to.Group, &to.Kind, config.GroupVersionKind{})
|
|
switch ref {
|
|
case gvk.ConfigMap, gvk.Secret, gvk.Service, gvk.InferencePool:
|
|
toKey.Kind = ref
|
|
default:
|
|
continue
|
|
}
|
|
rg := ReferenceGrant{
|
|
Source: config.NamespacedName(obj),
|
|
From: fromKey,
|
|
To: toKey,
|
|
AllowAll: false,
|
|
AllowedName: "",
|
|
}
|
|
if to.Name != nil {
|
|
rg.AllowedName = string(*to.Name)
|
|
} else {
|
|
rg.AllowAll = true
|
|
}
|
|
results = append(results, rg)
|
|
}
|
|
}
|
|
return results
|
|
}, opts.WithName("ReferenceGrants")...)
|
|
}
|
|
|
|
func BuildReferenceGrants(collection krt.Collection[ReferenceGrant]) ReferenceGrants {
|
|
idx := krt.NewIndex(collection, "toFrom", func(o ReferenceGrant) []ReferencePair {
|
|
return []ReferencePair{{
|
|
To: o.To,
|
|
From: o.From,
|
|
}}
|
|
})
|
|
return ReferenceGrants{
|
|
collection: collection,
|
|
index: idx,
|
|
}
|
|
}
|
|
|
|
type ReferenceGrant struct {
|
|
Source types.NamespacedName
|
|
From Reference
|
|
To Reference
|
|
AllowAll bool
|
|
AllowedName string
|
|
}
|
|
|
|
func (g ReferenceGrant) ResourceName() string {
|
|
return g.Source.String() + "/" + g.From.String() + "/" + g.To.String()
|
|
}
|
|
|
|
func (refs ReferenceGrants) SecretAllowed(ctx krt.HandlerContext, kind config.GroupVersionKind, resourceName string, namespace string) bool {
|
|
p, err := creds.ParseResourceName(resourceName, "", "", "")
|
|
if err != nil {
|
|
log.Warnf("failed to parse resource name %q: %v", resourceName, err)
|
|
return false
|
|
}
|
|
resourceKind := config.GroupVersionKind{Kind: p.ResourceKind.String()}
|
|
resourceSchema, resourceSchemaFound := collections.All.FindByGroupKind(resourceKind)
|
|
if resourceSchemaFound {
|
|
resourceKind = resourceSchema.GroupVersionKind()
|
|
}
|
|
from := Reference{Kind: kind, Namespace: gateway.Namespace(namespace)}
|
|
to := Reference{Kind: resourceKind, Namespace: gateway.Namespace(p.Namespace)}
|
|
pair := ReferencePair{From: from, To: to}
|
|
grants := krt.FetchOrList(ctx, refs.collection, krt.FilterIndex(refs.index, pair))
|
|
for _, g := range grants {
|
|
if g.AllowAll || g.AllowedName == p.Name {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (refs ReferenceGrants) BackendAllowed(ctx krt.HandlerContext,
|
|
k config.GroupVersionKind,
|
|
toGVK config.GroupVersionKind,
|
|
backendName gateway.ObjectName,
|
|
backendNamespace gateway.Namespace,
|
|
routeNamespace string,
|
|
) bool {
|
|
from := Reference{Kind: k, Namespace: gateway.Namespace(routeNamespace)}
|
|
to := Reference{Kind: toGVK, Namespace: backendNamespace}
|
|
pair := ReferencePair{From: from, To: to}
|
|
grants := krt.Fetch(ctx, refs.collection, krt.FilterIndex(refs.index, pair))
|
|
for _, g := range grants {
|
|
if g.AllowAll || g.AllowedName == string(backendName) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|