88 "net/http"
99 "net/url"
1010 "os"
11+ "reflect"
1112 "regexp"
1213 "strings"
1314 "time"
@@ -177,26 +178,40 @@ func (c *ComputeUtil) internalFirewallRuleName() string {
177178 return name .SafeConcatName (c .internalFirewallRulePrefix , internalFirewallRuleSuffix )
178179}
179180
180- func missingOpenedPorts (rule * raw.Firewall , ports []string ) map [string ][]string {
181- missing := map [string ][]string {}
182- opened := map [string ]bool {}
181+ // updatePorts compares the provided firewall rule against the list of provided ports
182+ // and returns a boolean indicating if the provided rule has been updated to only include
183+ // the provided ports.
184+ func updatePorts (rule * raw.Firewall , ports []string ) bool {
185+ requestedPorts := map [string ][]string {}
186+ for _ , p := range ports {
187+ port , proto := driverutil .SplitPortProto (p )
188+ requestedPorts [proto ] = append (requestedPorts [proto ], port )
189+ }
183190
191+ opened := map [string ][]string {}
184192 for _ , allowed := range rule .Allowed {
185193 for _ , allowedPort := range allowed .Ports {
186- opened [allowedPort + "/" + allowed .IPProtocol ] = true
194+ opened [allowed .IPProtocol ] = append ( opened [ allowed . IPProtocol ], allowedPort )
187195 }
188196 }
189197
190- for _ , p := range ports {
191- port , proto := driverutil .SplitPortProto (p )
192- if ! opened [port + "/" + proto ] {
193- missing [proto ] = append (missing [proto ], port )
194- }
198+ // if all the ports match then there is no need
199+ // to update / recreate the rule.
200+ if reflect .DeepEqual (requestedPorts , opened ) {
201+ return false
195202 }
196- if len (missing ) > 0 {
197- log .Warnf ("found missing ports for firewall rule '%s': %v" , rule .Name , missing )
203+
204+ rule .Allowed = []* raw.FirewallAllowed {}
205+ for proto , ports := range requestedPorts {
206+ rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
207+ IPProtocol : proto ,
208+ // note that Ports can only include numbers, and not
209+ // number protocol pairs.
210+ Ports : ports ,
211+ })
198212 }
199- return missing
213+
214+ return true
200215}
201216
202217func (c * ComputeUtil ) portsUsed () ([]string , error ) {
@@ -233,8 +248,6 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
233248 "6443" ,
234249 "2379" ,
235250 "2380" ,
236- "4789" ,
237- "2376" ,
238251 "9345" ,
239252 "9796" ,
240253 "8472/udp" ,
@@ -256,17 +269,20 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
256269 }
257270 }
258271
259- missingPorts := missingOpenedPorts (rule , expectedPorts )
260- if len (missingPorts ) == 0 {
261- log .Debugf ("Do not need to update internal firewall rule '%s' as all ports are configured" , rule .Name )
262- return nil
272+ // ensure an existing firewall rule properly points to the specified network
273+ networkChanged := false
274+ desiredNet := c .globalURL + "/networks/" + d .Network
275+ if ! create {
276+ if desiredNet != rule .Network {
277+ networkChanged = true
278+ rule .Network = desiredNet
279+ }
263280 }
264281
265- for proto , ports := range missingPorts {
266- rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
267- IPProtocol : proto ,
268- Ports : ports ,
269- })
282+ // ensure the rule is specifying only the expected ports
283+ if ! updatePorts (rule , expectedPorts ) && ! networkChanged {
284+ log .Debugf ("Do not need to update internal firewall rule '%s' as all ports are configured" , rule .Name )
285+ return nil
270286 }
271287
272288 var err error
@@ -298,7 +314,6 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
298314 Description : "rancher-machine managed external firewall rule" ,
299315 Allowed : []* raw.FirewallAllowed {},
300316 SourceRanges : []string {"0.0.0.0/0" },
301- SourceTags : []string {c .externalFirewallRuleName ()},
302317 TargetTags : []string {c .externalFirewallRuleName ()},
303318 Network : c .globalURL + "/networks/" + d .Network ,
304319 }
@@ -309,16 +324,20 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
309324 return err
310325 }
311326
312- missingPorts := missingOpenedPorts (rule , portsUsed )
313- if len (missingPorts ) == 0 {
314- log .Infof ("Do not need to update external firewall rule '%s' as all ports are configured" , rule .Name )
315- return nil
327+ // ensure an existing firewall rule properly points to the specified network
328+ networkChanged := false
329+ desiredNet := c .globalURL + "/networks/" + d .Network
330+ if ! create {
331+ if desiredNet != rule .Network {
332+ networkChanged = true
333+ rule .Network = desiredNet
334+ }
316335 }
317- for proto , ports := range missingPorts {
318- rule . Allowed = append ( rule . Allowed , & raw. FirewallAllowed {
319- IPProtocol : proto ,
320- Ports : ports ,
321- })
336+
337+ // ensure the rule is specifying only the requested ports
338+ if ! updatePorts ( rule , portsUsed ) && ! networkChanged {
339+ log . Debugf ( "Do not need to update internal firewall rule '%s' as all ports are configured" , rule . Name )
340+ return nil
322341 }
323342
324343 var op * raw.Operation
@@ -361,6 +380,9 @@ func (c *ComputeUtil) CleanUpFirewallRule(rule *raw.Firewall, labelKey string) e
361380 log .Infof ("Removing rancher-machine managed firewall rule '%s' from project as no instances are using it" , rule .Name )
362381 op , err := c .service .Firewalls .Delete (c .project , rule .Name ).Do ()
363382 if err != nil {
383+ if isNotFound (err ) {
384+ return nil
385+ }
364386 return fmt .Errorf ("failed to remove rancher-machine managed firewall rule '%s': %w" , rule .Name , err )
365387 }
366388
0 commit comments