@@ -49,24 +49,25 @@ const controllerAgentName = "flagger"
4949
5050// Controller is managing the canary objects and schedules canary deployments
5151type Controller struct {
52- kubeClient kubernetes.Interface
53- flaggerClient clientset.Interface
54- flaggerInformers Informers
55- flaggerSynced cache.InformerSynced
56- flaggerWindow time.Duration
57- workqueue workqueue.RateLimitingInterface
58- eventRecorder record.EventRecorder
59- logger * zap.SugaredLogger
60- canaries * sync.Map
61- jobs map [string ]CanaryJob
62- recorder metrics.Recorder
63- notifier notifier.Interface
64- canaryFactory * canary.Factory
65- routerFactory * router.Factory
66- observerFactory * observers.Factory
67- meshProvider string
68- eventWebhook string
69- clusterName string
52+ kubeClient kubernetes.Interface
53+ flaggerClient clientset.Interface
54+ flaggerInformers Informers
55+ flaggerSynced cache.InformerSynced
56+ flaggerWindow time.Duration
57+ workqueue workqueue.RateLimitingInterface
58+ eventRecorder record.EventRecorder
59+ logger * zap.SugaredLogger
60+ canaries * sync.Map
61+ jobs map [string ]CanaryJob
62+ recorder metrics.Recorder
63+ notifier notifier.Interface
64+ canaryFactory * canary.Factory
65+ routerFactory * router.Factory
66+ observerFactory * observers.Factory
67+ meshProvider string
68+ eventWebhook string
69+ clusterName string
70+ noCrossNamespaceRefs bool
7071}
7172
7273type Informers struct {
@@ -89,6 +90,7 @@ func NewController(
8990 version string ,
9091 eventWebhook string ,
9192 clusterName string ,
93+ noCrossNamespaceRefs bool ,
9294) * Controller {
9395 logger .Debug ("Creating event broadcaster" )
9496 flaggerscheme .AddToScheme (scheme .Scheme )
@@ -103,24 +105,25 @@ func NewController(
103105 recorder .SetInfo (version , meshProvider )
104106
105107 ctrl := & Controller {
106- kubeClient : kubeClient ,
107- flaggerClient : flaggerClient ,
108- flaggerInformers : flaggerInformers ,
109- flaggerSynced : flaggerInformers .CanaryInformer .Informer ().HasSynced ,
110- workqueue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), controllerAgentName ),
111- eventRecorder : eventRecorder ,
112- logger : logger ,
113- canaries : new (sync.Map ),
114- jobs : map [string ]CanaryJob {},
115- flaggerWindow : flaggerWindow ,
116- observerFactory : observerFactory ,
117- recorder : recorder ,
118- notifier : notifier ,
119- canaryFactory : canaryFactory ,
120- routerFactory : routerFactory ,
121- meshProvider : meshProvider ,
122- eventWebhook : eventWebhook ,
123- clusterName : clusterName ,
108+ kubeClient : kubeClient ,
109+ flaggerClient : flaggerClient ,
110+ flaggerInformers : flaggerInformers ,
111+ flaggerSynced : flaggerInformers .CanaryInformer .Informer ().HasSynced ,
112+ workqueue : workqueue .NewNamedRateLimitingQueue (workqueue .DefaultControllerRateLimiter (), controllerAgentName ),
113+ eventRecorder : eventRecorder ,
114+ logger : logger ,
115+ canaries : new (sync.Map ),
116+ jobs : map [string ]CanaryJob {},
117+ flaggerWindow : flaggerWindow ,
118+ observerFactory : observerFactory ,
119+ recorder : recorder ,
120+ notifier : notifier ,
121+ canaryFactory : canaryFactory ,
122+ routerFactory : routerFactory ,
123+ meshProvider : meshProvider ,
124+ eventWebhook : eventWebhook ,
125+ clusterName : clusterName ,
126+ noCrossNamespaceRefs : noCrossNamespaceRefs ,
124127 }
125128
126129 flaggerInformers .CanaryInformer .Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
@@ -250,6 +253,10 @@ func (c *Controller) syncHandler(key string) error {
250253 return nil
251254 }
252255
256+ if err := c .verifyCanary (cd ); err != nil {
257+ return fmt .Errorf ("invalid canary spec: %s" , err )
258+ }
259+
253260 // Finalize if canary has been marked for deletion and revert is desired
254261 if cd .Spec .RevertOnDeletion && cd .ObjectMeta .DeletionTimestamp != nil {
255262 // If finalizers have been previously removed proceed
@@ -312,6 +319,34 @@ func (c *Controller) enqueue(obj interface{}) {
312319 c .workqueue .AddRateLimited (key )
313320}
314321
322+ func (c * Controller ) verifyCanary (canary * flaggerv1.Canary ) error {
323+ if c .noCrossNamespaceRefs {
324+ if err := verifyNoCrossNamespaceRefs (canary ); err != nil {
325+ return err
326+ }
327+ }
328+ return nil
329+ }
330+
331+ func verifyNoCrossNamespaceRefs (canary * flaggerv1.Canary ) error {
332+ if canary .Spec .UpstreamRef != nil && canary .Spec .UpstreamRef .Namespace != canary .Namespace {
333+ return fmt .Errorf ("can't access gloo upstream %s.%s, cross-namespace references are blocked" , canary .Spec .UpstreamRef .Name , canary .Spec .UpstreamRef .Namespace )
334+ }
335+ if canary .Spec .Analysis != nil {
336+ for _ , metric := range canary .Spec .Analysis .Metrics {
337+ if metric .TemplateRef != nil && metric .TemplateRef .Namespace != canary .Namespace {
338+ return fmt .Errorf ("can't access metric template %s.%s, cross-namespace references are blocked" , metric .TemplateRef .Name , metric .TemplateRef .Namespace )
339+ }
340+ }
341+ for _ , alert := range canary .Spec .Analysis .Alerts {
342+ if alert .ProviderRef .Namespace != canary .Namespace {
343+ return fmt .Errorf ("can't access alert provider %s.%s, cross-namespace references are blocked" , alert .ProviderRef .Name , alert .ProviderRef .Namespace )
344+ }
345+ }
346+ }
347+ return nil
348+ }
349+
315350func checkCustomResourceType (obj interface {}, logger * zap.SugaredLogger ) (flaggerv1.Canary , bool ) {
316351 var roll * flaggerv1.Canary
317352 var ok bool
0 commit comments