From 869e18b264748357fa5b788d0a8e887412c5a704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Renan=20Gon=C3=A7alves?= Date: Mon, 23 May 2022 14:50:03 +0200 Subject: [PATCH] Avoid race conditions by copying the list before sorting (#8573) When creating several ingresses at the same time a race condition can happen by modifying a variable deep in another object. When this race condition is triggered the generated nginx configuration is broken: ``` nginx: [emerg] invalid parameter "8.8.8.8/32,8" in /tmp/nginx-cfg4027854160:671 nginx: configuration file /tmp/nginx-cfg4027854160 test failed ``` Once it happens, the controller won't ever be able to generate the configuration again. Thus the only option is to restart the process. There is not really a good way to reproduce this issue. It happens quite sporadically every 2 or 3 days. However, after this fix has been applied, we haven't seen it happen after about 4 weeks. Co-authored-by: Ruud van der Weijde --- internal/ingress/annotations/ipwhitelist/main.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/ingress/annotations/ipwhitelist/main.go b/internal/ingress/annotations/ipwhitelist/main.go index 77c2b6cc0..38610ade6 100644 --- a/internal/ingress/annotations/ipwhitelist/main.go +++ b/internal/ingress/annotations/ipwhitelist/main.go @@ -62,18 +62,21 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation { // e.g. `18.0.0.0/8,56.0.0.0/8` func (a ipwhitelist) Parse(ing *networking.Ingress) (interface{}, error) { defBackend := a.r.GetDefaultBackend() - sort.Strings(defBackend.WhitelistSourceRange) + + defaultWhitelistSourceRange := make([]string, len(defBackend.WhitelistSourceRange)) + copy(defaultWhitelistSourceRange, defBackend.WhitelistSourceRange) + sort.Strings(defaultWhitelistSourceRange) val, err := parser.GetStringAnnotation("whitelist-source-range", ing) // A missing annotation is not a problem, just use the default if err == ing_errors.ErrMissingAnnotations { - return &SourceRange{CIDR: defBackend.WhitelistSourceRange}, nil + return &SourceRange{CIDR: defaultWhitelistSourceRange}, nil } values := strings.Split(val, ",") ipnets, ips, err := net.ParseIPNets(values...) if err != nil && len(ips) == 0 { - return &SourceRange{CIDR: defBackend.WhitelistSourceRange}, ing_errors.LocationDenied{ + return &SourceRange{CIDR: defaultWhitelistSourceRange}, ing_errors.LocationDenied{ Reason: fmt.Errorf("the annotation does not contain a valid IP address or network: %w", err), } }