fix: default namespace for cross-namespace ref validation

When cross-namespace references are disabled, ensure that UpstreamRef,
MetricTemplateRef, and AlertProviderRef default to the canary's namespace
if their namespace field is empty. This aligns the validation logic with
the rest of the controller and prevents false positives when the namespace
is omitted.

Fixes #1827

Signed-off-by: Barrera, Angel <angelbarrerasanchez@protonmail.com>
This commit is contained in:
Barrera, Angel
2025-09-29 19:13:42 +02:00
parent 0743ef72b3
commit eeeac3543a
2 changed files with 46 additions and 5 deletions

View File

@@ -345,17 +345,36 @@ func (c *Controller) verifyCanary(canary *flaggerv1.Canary) error {
}
func verifyNoCrossNamespaceRefs(canary *flaggerv1.Canary) error {
if canary.Spec.UpstreamRef != nil && canary.Spec.UpstreamRef.Namespace != canary.Namespace {
return fmt.Errorf("can't access gloo upstream %s.%s, cross-namespace references are blocked", canary.Spec.UpstreamRef.Name, canary.Spec.UpstreamRef.Namespace)
if canary.Spec.UpstreamRef != nil {
// Default to canary namespace if upstreamRef namespace is empty
namespace := canary.Spec.UpstreamRef.Namespace
if namespace == "" {
namespace = canary.Namespace
}
if namespace != canary.Namespace {
return fmt.Errorf("can't access gloo upstream %s.%s, cross-namespace references are blocked", canary.Spec.UpstreamRef.Name, canary.Spec.UpstreamRef.Namespace)
}
}
if canary.Spec.Analysis != nil {
for _, metric := range canary.Spec.Analysis.Metrics {
if metric.TemplateRef != nil && metric.TemplateRef.Namespace != canary.Namespace {
return fmt.Errorf("can't access metric template %s.%s, cross-namespace references are blocked", metric.TemplateRef.Name, metric.TemplateRef.Namespace)
if metric.TemplateRef != nil {
// Default to canary namespace if templateRef namespace is empty
namespace := metric.TemplateRef.Namespace
if namespace == "" {
namespace = canary.Namespace
}
if namespace != canary.Namespace {
return fmt.Errorf("can't access metric template %s.%s, cross-namespace references are blocked", metric.TemplateRef.Name, metric.TemplateRef.Namespace)
}
}
}
for _, alert := range canary.Spec.Analysis.Alerts {
if alert.ProviderRef.Namespace != canary.Namespace {
// Default to canary namespace if providerRef namespace is empty
namespace := alert.ProviderRef.Namespace
if namespace == "" {
namespace = canary.Namespace
}
if namespace != canary.Namespace {
return fmt.Errorf("can't access alert provider %s.%s, cross-namespace references are blocked", alert.ProviderRef.Name, alert.ProviderRef.Namespace)
}
}

View File

@@ -70,6 +70,28 @@ func TestController_verifyCanary(t *testing.T) {
},
wantErr: true,
},
{
name: "MetricTemplate in same namespace with no namespace specified should not return an error",
canary: flaggerv1.Canary{
ObjectMeta: metav1.ObjectMeta{
Name: "cd-1",
Namespace: "default",
},
Spec: flaggerv1.CanarySpec{
Analysis: &flaggerv1.CanaryAnalysis{
Metrics: []flaggerv1.CanaryMetric{
{
TemplateRef: &flaggerv1.CrossNamespaceObjectReference{
Name: "mt-1",
Namespace: "",
},
},
},
},
},
},
wantErr: false,
},
{
name: "AlertProvider in a different namespace should return an error",
canary: flaggerv1.Canary{