IngressRoute: add an option to disable cross-namespace routing
Co-authored-by: Jean-Baptiste Doumenjou <925513+jbdoumenjou@users.noreply.github.com>
This commit is contained in:
parent
c72769e2ea
commit
7ba907f261
21 changed files with 1123 additions and 36 deletions
|
@ -48,7 +48,8 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
|||
ingressName = ingressRoute.GenerateName
|
||||
}
|
||||
|
||||
cb := configBuilder{client}
|
||||
cb := configBuilder{client, p.AllowCrossNamespace}
|
||||
|
||||
for _, route := range ingressRoute.Spec.Routes {
|
||||
if route.Kind != "Rule" {
|
||||
logger.Errorf("Unsupported match kind: %s. Only \"Rule\" is supported for now.", route.Kind)
|
||||
|
@ -66,23 +67,10 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
|||
continue
|
||||
}
|
||||
|
||||
var mds []string
|
||||
for _, mi := range route.Middlewares {
|
||||
if strings.Contains(mi.Name, providerNamespaceSeparator) {
|
||||
if len(mi.Namespace) > 0 {
|
||||
logger.
|
||||
WithField(log.MiddlewareName, mi.Name).
|
||||
Warnf("namespace %q is ignored in cross-provider context", mi.Namespace)
|
||||
}
|
||||
mds = append(mds, mi.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
ns := mi.Namespace
|
||||
if len(ns) == 0 {
|
||||
ns = ingressRoute.Namespace
|
||||
}
|
||||
mds = append(mds, makeID(ns, mi.Name))
|
||||
mds, err := p.makeMiddlewareKeys(ctx, ingressRoute.Namespace, route.Middlewares)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to create middleware keys: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
normalized := provider.Normalize(makeID(ingressRoute.Namespace, serviceKey))
|
||||
|
@ -153,8 +141,38 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
|||
return conf
|
||||
}
|
||||
|
||||
func (p *Provider) makeMiddlewareKeys(ctx context.Context, ingRouteNamespace string, middlewares []v1alpha1.MiddlewareRef) ([]string, error) {
|
||||
var mds []string
|
||||
|
||||
for _, mi := range middlewares {
|
||||
if strings.Contains(mi.Name, providerNamespaceSeparator) {
|
||||
if len(mi.Namespace) > 0 {
|
||||
log.FromContext(ctx).
|
||||
WithField(log.MiddlewareName, mi.Name).
|
||||
Warnf("namespace %q is ignored in cross-provider context", mi.Namespace)
|
||||
}
|
||||
mds = append(mds, mi.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
ns := ingRouteNamespace
|
||||
if len(mi.Namespace) > 0 {
|
||||
if !isNamespaceAllowed(p.AllowCrossNamespace, ingRouteNamespace, mi.Namespace) {
|
||||
return nil, fmt.Errorf("middleware %s/%s is not in the IngressRoute namespace %s", mi.Namespace, mi.Name, ingRouteNamespace)
|
||||
}
|
||||
|
||||
ns = mi.Namespace
|
||||
}
|
||||
|
||||
mds = append(mds, makeID(ns, mi.Name))
|
||||
}
|
||||
|
||||
return mds, nil
|
||||
}
|
||||
|
||||
type configBuilder struct {
|
||||
client Client
|
||||
client Client
|
||||
allowCrossNamespace *bool
|
||||
}
|
||||
|
||||
// buildTraefikService creates the configuration for the traefik service defined in tService,
|
||||
|
@ -270,7 +288,7 @@ func (c configBuilder) buildServersLB(namespace string, svc v1alpha1.LoadBalance
|
|||
return &dynamic.Service{LoadBalancer: lb}, nil
|
||||
}
|
||||
|
||||
func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) {
|
||||
func (c configBuilder) loadServers(parentNamespace string, svc v1alpha1.LoadBalancerSpec) ([]dynamic.Server, error) {
|
||||
strategy := svc.Strategy
|
||||
if strategy == "" {
|
||||
strategy = roundRobinStrategy
|
||||
|
@ -279,7 +297,11 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
|
|||
return nil, fmt.Errorf("load balancing strategy %s is not supported", strategy)
|
||||
}
|
||||
|
||||
namespace := namespaceOrFallback(svc, fallbackNamespace)
|
||||
namespace := namespaceOrFallback(svc, parentNamespace)
|
||||
|
||||
if !isNamespaceAllowed(c.allowCrossNamespace, parentNamespace, namespace) {
|
||||
return nil, fmt.Errorf("load balancer service %s/%s is not in the parent resource namespace %s", svc.Namespace, svc.Name, parentNamespace)
|
||||
}
|
||||
|
||||
// If the service uses explicitly the provider suffix
|
||||
sanitizedName := strings.TrimSuffix(svc.Name, providerNamespaceSeparator+providerName)
|
||||
|
@ -355,10 +377,14 @@ func (c configBuilder) loadServers(fallbackNamespace string, svc v1alpha1.LoadBa
|
|||
// In addition, if the service is a Kubernetes one,
|
||||
// it generates and returns the configuration part for such a service,
|
||||
// so that the caller can add it to the global config map.
|
||||
func (c configBuilder) nameAndService(ctx context.Context, namespaceService string, service v1alpha1.LoadBalancerSpec) (string, *dynamic.Service, error) {
|
||||
func (c configBuilder) nameAndService(ctx context.Context, parentNamespace string, service v1alpha1.LoadBalancerSpec) (string, *dynamic.Service, error) {
|
||||
svcCtx := log.With(ctx, log.Str(log.ServiceName, service.Name))
|
||||
|
||||
namespace := namespaceOrFallback(service, namespaceService)
|
||||
namespace := namespaceOrFallback(service, parentNamespace)
|
||||
|
||||
if !isNamespaceAllowed(c.allowCrossNamespace, parentNamespace, namespace) {
|
||||
return "", nil, fmt.Errorf("service %s/%s not in the parent resource namespace %s", service.Namespace, service.Name, parentNamespace)
|
||||
}
|
||||
|
||||
switch {
|
||||
case service.Kind == "" || service.Kind == "Service":
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue