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:
Romain 2020-12-10 14:58:04 +01:00 committed by GitHub
parent c72769e2ea
commit 7ba907f261
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 1123 additions and 36 deletions

View file

@ -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":