mirror of
https://github.com/tinyauthapp/tinyauth.git
synced 2026-09-23 19:23:33 +08:00
chore: remove gateway extractors
This commit is contained in:
@@ -32,7 +32,6 @@ require (
|
|||||||
k8s.io/apimachinery v0.37.0
|
k8s.io/apimachinery v0.37.0
|
||||||
k8s.io/client-go v0.37.0
|
k8s.io/client-go v0.37.0
|
||||||
modernc.org/sqlite v1.58.0
|
modernc.org/sqlite v1.58.0
|
||||||
sigs.k8s.io/gateway-api v1.6.2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -71,7 +70,6 @@ require (
|
|||||||
github.com/docker/go-connections v0.6.0 // indirect
|
github.com/docker/go-connections v0.6.0 // indirect
|
||||||
github.com/docker/go-units v0.5.0 // indirect
|
github.com/docker/go-units v0.5.0 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
|
||||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||||
@@ -79,20 +77,6 @@ require (
|
|||||||
github.com/go-asn1-ber/asn1-ber v1.5.8 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.8 // indirect
|
||||||
github.com/go-logr/logr v1.4.4 // indirect
|
github.com/go-logr/logr v1.4.4 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v1.0.0 // indirect
|
|
||||||
github.com/go-openapi/jsonreference v1.0.0 // indirect
|
|
||||||
github.com/go-openapi/swag v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/cmdutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/conv v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/fileutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/jsonutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/loading v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/mangling v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/netutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/pools v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/stringutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/typeutils v0.27.1 // indirect
|
|
||||||
github.com/go-openapi/swag/yamlutils v0.27.1 // indirect
|
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||||
|
|||||||
@@ -138,8 +138,6 @@ github.com/go-openapi/swag/fileutils v0.27.1 h1:QQqBSoi5mW4XpU85nS0mLcA+zAE6vLzr
|
|||||||
github.com/go-openapi/swag/fileutils v0.27.1/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
github.com/go-openapi/swag/fileutils v0.27.1/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
||||||
github.com/go-openapi/swag/jsonutils v0.27.1 h1:SVgK3i4USzCU5mibOOS/l4ea2h9UQXy7J7RNLTjuXjU=
|
github.com/go-openapi/swag/jsonutils v0.27.1 h1:SVgK3i4USzCU5mibOOS/l4ea2h9UQXy7J7RNLTjuXjU=
|
||||||
github.com/go-openapi/swag/jsonutils v0.27.1/go.mod h1:tdlEpZqdcQ17uj6J4YdK9vd8It5qWMwjWXOs0tjpRlk=
|
github.com/go-openapi/swag/jsonutils v0.27.1/go.mod h1:tdlEpZqdcQ17uj6J4YdK9vd8It5qWMwjWXOs0tjpRlk=
|
||||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1 h1:mJu3COL9WEaZVp/Kf2PRMi7tPszPEJfSr/OO75ynCs8=
|
|
||||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.1/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
|
|
||||||
github.com/go-openapi/swag/loading v0.27.1 h1:/DxUgDXKbBX4bcn7r9uEXfJyzN5XpiJmZplzQTjrRCY=
|
github.com/go-openapi/swag/loading v0.27.1 h1:/DxUgDXKbBX4bcn7r9uEXfJyzN5XpiJmZplzQTjrRCY=
|
||||||
github.com/go-openapi/swag/loading v0.27.1/go.mod h1:jvGh3iA2+zyUUycB5fgJWzeHnhrpvGnJJM0RVE9ZShE=
|
github.com/go-openapi/swag/loading v0.27.1/go.mod h1:jvGh3iA2+zyUUycB5fgJWzeHnhrpvGnJJM0RVE9ZShE=
|
||||||
github.com/go-openapi/swag/mangling v0.27.1 h1:yC9D0HyUE8gbP+BfmGx9+AA89ikwZTMjESK3OnnoaqA=
|
github.com/go-openapi/swag/mangling v0.27.1 h1:yC9D0HyUE8gbP+BfmGx9+AA89ikwZTMjESK3OnnoaqA=
|
||||||
@@ -154,10 +152,6 @@ github.com/go-openapi/swag/typeutils v0.27.1 h1:KSTdFlfnse4r6dP9IrEnwMldjE+zs71U
|
|||||||
github.com/go-openapi/swag/typeutils v0.27.1/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
github.com/go-openapi/swag/typeutils v0.27.1/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||||
github.com/go-openapi/swag/yamlutils v0.27.1 h1:ftxv6xvXb1E3zohUc+okZ9nSqNb9StQX/FXnKZ98sQA=
|
github.com/go-openapi/swag/yamlutils v0.27.1 h1:ftxv6xvXb1E3zohUc+okZ9nSqNb9StQX/FXnKZ98sQA=
|
||||||
github.com/go-openapi/swag/yamlutils v0.27.1/go.mod h1:bnxFIB1qewGRiZHypXGZ3fNgf13/0HfRgnS/iZBDrOo=
|
github.com/go-openapi/swag/yamlutils v0.27.1/go.mod h1:bnxFIB1qewGRiZHypXGZ3fNgf13/0HfRgnS/iZBDrOo=
|
||||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
|
|
||||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
|
|
||||||
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
|
|
||||||
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
@@ -446,8 +440,6 @@ modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
|||||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||||
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
||||||
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
|
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
|
||||||
sigs.k8s.io/gateway-api v1.6.2 h1:vh5YzKlbdBivEaLX61+APKLGRq4tZ7Fj4XfGkv08xB4=
|
|
||||||
sigs.k8s.io/gateway-api v1.6.2/go.mod h1:FVfx3t389ybeXOqvDghLbdvJdSCfI/PReqCUI3lu3mY=
|
|
||||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||||
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
|
||||||
gateway "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KubernetesGRPCRouteExtractor struct {
|
|
||||||
log *logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubernetesGRPCRouteExtractorInput struct {
|
|
||||||
Log *logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewKubernetesGRPCRouteExtractor(i KubernetesGRPCRouteExtractorInput) *KubernetesGRPCRouteExtractor {
|
|
||||||
return &KubernetesGRPCRouteExtractor{
|
|
||||||
log: i.Log,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesGRPCRouteExtractor) getHosts(hostnames []gateway.Hostname) []string {
|
|
||||||
var hosts []string
|
|
||||||
|
|
||||||
for _, hostname := range hostnames {
|
|
||||||
if hostname != "" {
|
|
||||||
hosts = append(hosts, string(hostname))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hosts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesGRPCRouteExtractor) Extract(route *gateway.GRPCRoute) *ExtractionResult {
|
|
||||||
hosts := k.getHosts(route.Spec.Hostnames)
|
|
||||||
namespace := route.GetNamespace()
|
|
||||||
name := route.GetName()
|
|
||||||
annotations := route.GetAnnotations()
|
|
||||||
|
|
||||||
return &ExtractionResult{
|
|
||||||
typ: ResourceTypeGRPCRoute,
|
|
||||||
name: name,
|
|
||||||
namespace: namespace,
|
|
||||||
hosts: hosts,
|
|
||||||
annotations: annotations,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"slices"
|
|
||||||
|
|
||||||
"github.com/tinyauthapp/tinyauth/internal/utils/logger"
|
|
||||||
gateway "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KubernetesHTTPRouteExtractor struct {
|
|
||||||
log *logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubernetesHTTPRouteExtractorInput struct {
|
|
||||||
Log *logger.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewKubernetesHTTPRouteExtractor(i KubernetesHTTPRouteExtractorInput) *KubernetesHTTPRouteExtractor {
|
|
||||||
return &KubernetesHTTPRouteExtractor{
|
|
||||||
log: i.Log,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesHTTPRouteExtractor) getHosts(hostnames []gateway.Hostname) []string {
|
|
||||||
var hosts []string
|
|
||||||
|
|
||||||
for _, hostname := range hostnames {
|
|
||||||
if hostname != "" {
|
|
||||||
hosts = append(hosts, string(hostname))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hosts
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesHTTPRouteExtractor) getRuleMatchers(matchers []gateway.HTTPRouteMatch) []string {
|
|
||||||
var res []string
|
|
||||||
|
|
||||||
for _, m := range matchers {
|
|
||||||
if m.Path == nil {
|
|
||||||
res = append(res, "/")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pathType := gateway.PathMatchPathPrefix
|
|
||||||
if m.Path.Type != nil {
|
|
||||||
pathType = *m.Path.Type
|
|
||||||
}
|
|
||||||
if pathType != gateway.PathMatchPathPrefix {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pathValue := "/"
|
|
||||||
if m.Path.Value != nil {
|
|
||||||
pathValue = *m.Path.Value
|
|
||||||
}
|
|
||||||
res = append(res, pathValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesHTTPRouteExtractor) getPaths(rules []gateway.HTTPRouteRule) []string {
|
|
||||||
var paths []string
|
|
||||||
|
|
||||||
for _, rule := range rules {
|
|
||||||
if len(rule.Matches) == 0 {
|
|
||||||
paths = append(paths, "/")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
matchers := k.getRuleMatchers(rule.Matches)
|
|
||||||
paths = append(paths, matchers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesHTTPRouteExtractor) Extract(route *gateway.HTTPRoute) *ExtractionResult {
|
|
||||||
hosts := k.getHosts(route.Spec.Hostnames)
|
|
||||||
paths := k.getPaths(route.Spec.Rules)
|
|
||||||
|
|
||||||
namespace := route.GetNamespace()
|
|
||||||
name := route.GetName()
|
|
||||||
|
|
||||||
annotations := route.GetAnnotations()
|
|
||||||
|
|
||||||
if !slices.Contains(paths, "/") {
|
|
||||||
k.log.App.Warn().Str("namespace", namespace).Str("name", name).Strs("paths", paths).Msg("Route does not contain a catch-all path, another route may be able to bypass auth checks if it routes the same host with a different path. Consider adding a catch-all path to this route to ensure auth checks are applied to all paths for this host.")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ExtractionResult{
|
|
||||||
typ: ResourceTypeHTTPRoute,
|
|
||||||
name: name,
|
|
||||||
namespace: namespace,
|
|
||||||
hosts: hosts,
|
|
||||||
annotations: annotations,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
gateway "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type watchedResource struct {
|
type watchedResource struct {
|
||||||
@@ -36,9 +35,7 @@ func (w watchedResource) pretty() string {
|
|||||||
type ResourceType string
|
type ResourceType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ResourceTypeIngress ResourceType = "ingress"
|
ResourceTypeIngress ResourceType = "ingress"
|
||||||
ResourceTypeGRPCRoute ResourceType = "grpcroute"
|
|
||||||
ResourceTypeHTTPRoute ResourceType = "httproute"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var supportedResources = []watchedResource{
|
var supportedResources = []watchedResource{
|
||||||
@@ -50,22 +47,6 @@ var supportedResources = []watchedResource{
|
|||||||
},
|
},
|
||||||
typ: ResourceTypeIngress,
|
typ: ResourceTypeIngress,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
gvr: schema.GroupVersionResource{
|
|
||||||
Group: "gateway.networking.k8s.io",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "httproutes",
|
|
||||||
},
|
|
||||||
typ: ResourceTypeHTTPRoute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gvr: schema.GroupVersionResource{
|
|
||||||
Group: "gateway.networking.k8s.io",
|
|
||||||
Version: "v1",
|
|
||||||
Resource: "grpcroutes",
|
|
||||||
},
|
|
||||||
typ: ResourceTypeGRPCRoute,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hostMatchesHostname(host string, hostname string) bool {
|
func hostMatchesHostname(host string, hostname string) bool {
|
||||||
@@ -96,8 +77,6 @@ type ExtractionResult struct {
|
|||||||
type typedItem struct {
|
type typedItem struct {
|
||||||
typ ResourceType
|
typ ResourceType
|
||||||
ingress *networking.Ingress
|
ingress *networking.Ingress
|
||||||
route *gateway.HTTPRoute
|
|
||||||
grpc *gateway.GRPCRoute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertFromUnstructured[T any](obj *unstructured.Unstructured) (*T, error) {
|
func convertFromUnstructured[T any](obj *unstructured.Unstructured) (*T, error) {
|
||||||
@@ -121,24 +100,6 @@ func (ti *typedItem) fromUnstructured(typ ResourceType, obj *unstructured.Unstru
|
|||||||
typ: ResourceTypeIngress,
|
typ: ResourceTypeIngress,
|
||||||
ingress: typed,
|
ingress: typed,
|
||||||
}, nil
|
}, nil
|
||||||
case ResourceTypeHTTPRoute:
|
|
||||||
typed, err := convertFromUnstructured[gateway.HTTPRoute](obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &typedItem{
|
|
||||||
typ: ResourceTypeHTTPRoute,
|
|
||||||
route: typed,
|
|
||||||
}, nil
|
|
||||||
case ResourceTypeGRPCRoute:
|
|
||||||
typed, err := convertFromUnstructured[gateway.GRPCRoute](obj)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &typedItem{
|
|
||||||
typ: ResourceTypeGRPCRoute,
|
|
||||||
grpc: typed,
|
|
||||||
}, nil
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown resource type %s", typ)
|
return nil, fmt.Errorf("unknown resource type %s", typ)
|
||||||
}
|
}
|
||||||
@@ -169,9 +130,7 @@ type KubernetesService struct {
|
|||||||
connected bool
|
connected bool
|
||||||
|
|
||||||
extractors struct {
|
extractors struct {
|
||||||
ingress *KubernetesIngressExtractor
|
ingress *KubernetesIngressExtractor
|
||||||
httproute *KubernetesHTTPRouteExtractor
|
|
||||||
grpc *KubernetesGRPCRouteExtractor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,12 +162,6 @@ func NewKubernetesService(i KubernetesServiceInput) (*KubernetesService, error)
|
|||||||
service.extractors.ingress = NewKubernetesIngressExtractor(KubernetesIngressExtractorInput{
|
service.extractors.ingress = NewKubernetesIngressExtractor(KubernetesIngressExtractorInput{
|
||||||
Log: i.Log,
|
Log: i.Log,
|
||||||
})
|
})
|
||||||
service.extractors.httproute = NewKubernetesHTTPRouteExtractor(KubernetesHTTPRouteExtractorInput{
|
|
||||||
Log: i.Log,
|
|
||||||
})
|
|
||||||
service.extractors.grpc = NewKubernetesGRPCRouteExtractor(KubernetesGRPCRouteExtractorInput{
|
|
||||||
Log: i.Log,
|
|
||||||
})
|
|
||||||
|
|
||||||
watchedGVRs := make(map[string]bool)
|
watchedGVRs := make(map[string]bool)
|
||||||
|
|
||||||
@@ -297,18 +250,6 @@ func (k *KubernetesService) updateFromItem(res watchedResource, typedItem *typed
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
result = k.extractors.ingress.Extract(typedItem.ingress)
|
result = k.extractors.ingress.Extract(typedItem.ingress)
|
||||||
case ResourceTypeHTTPRoute:
|
|
||||||
if typedItem.route == nil {
|
|
||||||
k.log.App.Warn().Str("res", res.pretty()).Msg("HTTPRoute is nil, skipping")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result = k.extractors.httproute.Extract(typedItem.route)
|
|
||||||
case ResourceTypeGRPCRoute:
|
|
||||||
if typedItem.grpc == nil {
|
|
||||||
k.log.App.Warn().Str("res", res.pretty()).Msg("GRPCRoute is nil, skipping")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result = k.extractors.grpc.Extract(typedItem.grpc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
networking "k8s.io/api/networking/v1"
|
networking "k8s.io/api/networking/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
gateway "sigs.k8s.io/gateway-api/apis/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func watchedResourceForTest(t *testing.T, typ ResourceType) watchedResource {
|
func watchedResourceForTest(t *testing.T, typ ResourceType) watchedResource {
|
||||||
@@ -31,8 +30,6 @@ func newKubernetesServiceForTest(log *logger.Logger) *KubernetesService {
|
|||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
service.extractors.ingress = NewKubernetesIngressExtractor(KubernetesIngressExtractorInput{Log: log})
|
service.extractors.ingress = NewKubernetesIngressExtractor(KubernetesIngressExtractorInput{Log: log})
|
||||||
service.extractors.httproute = NewKubernetesHTTPRouteExtractor(KubernetesHTTPRouteExtractorInput{Log: log})
|
|
||||||
service.extractors.grpc = NewKubernetesGRPCRouteExtractor(KubernetesGRPCRouteExtractorInput{Log: log})
|
|
||||||
return service
|
return service
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,34 +47,6 @@ func testIngress(name string, annotations map[string]string, hosts ...string) *t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testHTTPRoute(name string, annotations map[string]string, hosts ...string) *typedItem {
|
|
||||||
hostnames := make([]gateway.Hostname, 0, len(hosts))
|
|
||||||
for _, host := range hosts {
|
|
||||||
hostnames = append(hostnames, gateway.Hostname(host))
|
|
||||||
}
|
|
||||||
return &typedItem{
|
|
||||||
typ: ResourceTypeHTTPRoute,
|
|
||||||
route: &gateway.HTTPRoute{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "default", Annotations: annotations},
|
|
||||||
Spec: gateway.HTTPRouteSpec{Hostnames: hostnames, Rules: []gateway.HTTPRouteRule{{}}},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testGRPCRoute(name string, annotations map[string]string, hosts ...string) *typedItem {
|
|
||||||
hostnames := make([]gateway.Hostname, 0, len(hosts))
|
|
||||||
for _, host := range hosts {
|
|
||||||
hostnames = append(hostnames, gateway.Hostname(host))
|
|
||||||
}
|
|
||||||
return &typedItem{
|
|
||||||
typ: ResourceTypeGRPCRoute,
|
|
||||||
grpc: &gateway.GRPCRoute{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "default", Annotations: annotations},
|
|
||||||
Spec: gateway.GRPCRouteSpec{Hostnames: hostnames},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupApp(service *KubernetesService, domain string) *model.App {
|
func lookupApp(service *KubernetesService, domain string) *model.App {
|
||||||
var app *model.App
|
var app *model.App
|
||||||
service.getEntry(domain, func(name string, candidate *model.App) bool {
|
service.getEntry(domain, func(name string, candidate *model.App) bool {
|
||||||
@@ -119,41 +88,6 @@ func TestKubernetesServiceUpdateFromItem(t *testing.T) {
|
|||||||
}, "Dashboard.example.com"),
|
}, "Dashboard.example.com"),
|
||||||
domain: "dashboard.example.com", allow: "alice",
|
domain: "dashboard.example.com", allow: "alice",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "HTTPRoute matches a configured domain",
|
|
||||||
resource: ResourceTypeHTTPRoute,
|
|
||||||
item: testHTTPRoute("http-route", map[string]string{
|
|
||||||
"tinyauth.apps.api.config.domain": "api.example.com",
|
|
||||||
"tinyauth.apps.api.users.allow": "bob",
|
|
||||||
}, "api.example.com"),
|
|
||||||
domain: "api.example.com", wantConfigDomain: "api.example.com", allow: "bob",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "HTTPRoute wildcard matches nested subdomains",
|
|
||||||
resource: ResourceTypeHTTPRoute,
|
|
||||||
item: testHTTPRoute("http-route", map[string]string{
|
|
||||||
"tinyauth.apps.api.config.domain": "deep.api.example.com",
|
|
||||||
"tinyauth.apps.api.users.allow": "bob",
|
|
||||||
}, "*.example.com"),
|
|
||||||
domain: "deep.api.example.com", wantConfigDomain: "deep.api.example.com", allow: "bob",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "GRPCRoute matches a configured domain",
|
|
||||||
resource: ResourceTypeGRPCRoute,
|
|
||||||
item: testGRPCRoute("grpc-route", map[string]string{
|
|
||||||
"tinyauth.apps.grpc.config.domain": "grpc.example.com",
|
|
||||||
"tinyauth.apps.grpc.users.allow": "carol",
|
|
||||||
}, "grpc.example.com"),
|
|
||||||
domain: "grpc.example.com", wantConfigDomain: "grpc.example.com", allow: "carol",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "GRPCRoute matches an app name through a wildcard",
|
|
||||||
resource: ResourceTypeGRPCRoute,
|
|
||||||
item: testGRPCRoute("grpc-route", map[string]string{
|
|
||||||
"tinyauth.apps.grpc.users.allow": "carol",
|
|
||||||
}, "*.example.com"),
|
|
||||||
domain: "grpc.example.com", allow: "carol",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -180,13 +114,7 @@ func TestKubernetesServiceUpdateFromItemRemovesStaleEntries(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{"Ingress without annotations", ResourceTypeIngress, testIngress("route", nil, "app.example.com")},
|
{"Ingress without annotations", ResourceTypeIngress, testIngress("route", nil, "app.example.com")},
|
||||||
{"Ingress without hosts", ResourceTypeIngress, testIngress("route", map[string]string{"tinyauth.apps.app.users.allow": "alice"})},
|
{"Ingress without hosts", ResourceTypeIngress, testIngress("route", map[string]string{"tinyauth.apps.app.users.allow": "alice"})},
|
||||||
{"HTTPRoute without annotations", ResourceTypeHTTPRoute, testHTTPRoute("route", nil, "app.example.com")},
|
|
||||||
{"HTTPRoute without hosts", ResourceTypeHTTPRoute, testHTTPRoute("route", map[string]string{"tinyauth.apps.app.users.allow": "alice"})},
|
|
||||||
{"GRPCRoute without annotations", ResourceTypeGRPCRoute, testGRPCRoute("route", nil, "app.example.com")},
|
|
||||||
{"GRPCRoute without hosts", ResourceTypeGRPCRoute, testGRPCRoute("route", map[string]string{"tinyauth.apps.app.users.allow": "alice"})},
|
|
||||||
{"Ingress with invalid annotations", ResourceTypeIngress, testIngress("route", map[string]string{"tinyauth.apps.app.users.break": "invalid"}, "app.example.com")},
|
{"Ingress with invalid annotations", ResourceTypeIngress, testIngress("route", map[string]string{"tinyauth.apps.app.users.break": "invalid"}, "app.example.com")},
|
||||||
{"HTTPRoute with invalid annotations", ResourceTypeHTTPRoute, testHTTPRoute("route", map[string]string{"tinyauth.apps.app.users.break": "invalid"}, "app.example.com")},
|
|
||||||
{"GRPCRoute with invalid annotations", ResourceTypeGRPCRoute, testGRPCRoute("route", map[string]string{"tinyauth.apps.app.users.break": "invalid"}, "app.example.com")},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -223,30 +151,6 @@ func TestTypedItemFromUnstructured(t *testing.T) {
|
|||||||
assert.Equal(t, "app.example.com", item.ingress.Spec.Rules[0].Host)
|
assert.Equal(t, "app.example.com", item.ingress.Spec.Rules[0].Host)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "HTTPRoute",
|
|
||||||
resource: ResourceTypeHTTPRoute,
|
|
||||||
item: unstructured.Unstructured{Object: map[string]any{
|
|
||||||
"metadata": map[string]any{"name": "http-route", "namespace": "default"},
|
|
||||||
"spec": map[string]any{"hostnames": []any{"app.example.com"}},
|
|
||||||
}},
|
|
||||||
assert: func(t *testing.T, item *typedItem) {
|
|
||||||
require.NotNil(t, item.route)
|
|
||||||
assert.Equal(t, gateway.Hostname("app.example.com"), item.route.Spec.Hostnames[0])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "GRPCRoute",
|
|
||||||
resource: ResourceTypeGRPCRoute,
|
|
||||||
item: unstructured.Unstructured{Object: map[string]any{
|
|
||||||
"metadata": map[string]any{"name": "grpc-route", "namespace": "default"},
|
|
||||||
"spec": map[string]any{"hostnames": []any{"app.example.com"}},
|
|
||||||
}},
|
|
||||||
assert: func(t *testing.T, item *typedItem) {
|
|
||||||
require.NotNil(t, item.grpc)
|
|
||||||
assert.Equal(t, gateway.Hostname("app.example.com"), item.grpc.Spec.Hostnames[0])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
@@ -305,8 +209,6 @@ func TestKubernetesServiceKeepsResourceTypesSeparate(t *testing.T) {
|
|||||||
domain string
|
domain string
|
||||||
}{
|
}{
|
||||||
{ResourceTypeIngress, testIngress("shared", map[string]string{"tinyauth.apps.ingress.config.domain": "ingress.example.com"}, "ingress.example.com"), "ingress.example.com"},
|
{ResourceTypeIngress, testIngress("shared", map[string]string{"tinyauth.apps.ingress.config.domain": "ingress.example.com"}, "ingress.example.com"), "ingress.example.com"},
|
||||||
{ResourceTypeHTTPRoute, testHTTPRoute("shared", map[string]string{"tinyauth.apps.http.config.domain": "http.example.com"}, "http.example.com"), "http.example.com"},
|
|
||||||
{ResourceTypeGRPCRoute, testGRPCRoute("shared", map[string]string{"tinyauth.apps.grpc.config.domain": "grpc.example.com"}, "grpc.example.com"), "grpc.example.com"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
@@ -317,34 +219,6 @@ func TestKubernetesServiceKeepsResourceTypesSeparate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKubernetesHTTPRouteExtractorPaths(t *testing.T) {
|
|
||||||
log := logger.NewLogger().WithTestConfig()
|
|
||||||
log.Init()
|
|
||||||
extractor := NewKubernetesHTTPRouteExtractor(KubernetesHTTPRouteExtractorInput{Log: log})
|
|
||||||
|
|
||||||
prefix := gateway.PathMatchPathPrefix
|
|
||||||
exact := gateway.PathMatchExact
|
|
||||||
api := "/api"
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
rules []gateway.HTTPRouteRule
|
|
||||||
want []string
|
|
||||||
}{
|
|
||||||
{"Rule without matches defaults to catch-all", []gateway.HTTPRouteRule{{}}, []string{"/"}},
|
|
||||||
{"Match without path defaults to catch-all", []gateway.HTTPRouteRule{{Matches: []gateway.HTTPRouteMatch{{}}}}, []string{"/"}},
|
|
||||||
{"Path defaults apply independently", []gateway.HTTPRouteRule{{Matches: []gateway.HTTPRouteMatch{{Path: &gateway.HTTPPathMatch{}}}}}, []string{"/"}},
|
|
||||||
{"Exact paths do not count as catch-all", []gateway.HTTPRouteRule{{Matches: []gateway.HTTPRouteMatch{{Path: &gateway.HTTPPathMatch{Type: &exact}}}}}, nil},
|
|
||||||
{"Prefix paths are retained", []gateway.HTTPRouteRule{{Matches: []gateway.HTTPRouteMatch{{Path: &gateway.HTTPPathMatch{Type: &prefix, Value: &api}}}}}, []string{"/api"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, test.want, extractor.getPaths(test.rules))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKubernetesHostMatching(t *testing.T) {
|
func TestKubernetesHostMatching(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user