99 "net/url"
1010 "os"
1111 "regexp"
12+ "slices"
1213 "strings"
1314 "time"
1415
@@ -47,7 +48,7 @@ type ComputeUtil struct {
4748
4849const (
4950 apiURL = "https://www.googleapis.com/compute/v1/projects/"
50- externalFirewallRuleSuffix = "external-rancher-node "
51+ externalFirewallRuleSuffix = "external-rancher-nodes "
5152 internalFirewallRuleSuffix = "internal-rancher-nodes"
5253 externalFirewallRuleLabelKey = "rancher-external-fw-rule"
5354 internalFirewallRuleLabelKey = "rancher-internal-fw-rule"
@@ -177,26 +178,63 @@ 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 )
198+ // if there is a mismatch between the currently opened
199+ // ports and existing ports, recreate the rule with only
200+ // the requested ports.
201+ recreate := false
202+
203+ for proto , ports := range opened {
204+ for _ , p := range ports {
205+ // a port needs to be closed
206+ if ! slices .Contains (requestedPorts [proto ], p ) {
207+ recreate = true
208+ break
209+ }
194210 }
195211 }
196- if len (missing ) > 0 {
197- log .Warnf ("found missing ports for firewall rule '%s': %v" , rule .Name , missing )
212+
213+ for proto , ports := range requestedPorts {
214+ for _ , p := range ports {
215+ // a port needs to be opened
216+ if ! slices .Contains (opened [proto ], p ) {
217+ recreate = true
218+ break
219+ }
220+ }
198221 }
199- return missing
222+
223+ if ! recreate {
224+ return false
225+ }
226+
227+ rule .Allowed = []* raw.FirewallAllowed {}
228+ for proto , ports := range requestedPorts {
229+ rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
230+ IPProtocol : proto ,
231+ // note that Ports can only include numbers, and not
232+ // number protocol pairs.
233+ Ports : ports ,
234+ })
235+ }
236+
237+ return true
200238}
201239
202240func (c * ComputeUtil ) portsUsed () ([]string , error ) {
@@ -233,8 +271,6 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
233271 "6443" ,
234272 "2379" ,
235273 "2380" ,
236- "4789" ,
237- "2376" ,
238274 "9345" ,
239275 "9796" ,
240276 "8472/udp" ,
@@ -256,17 +292,20 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
256292 }
257293 }
258294
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
295+ // ensure an existing firewall rule properly points to the specified network
296+ networkChanged := false
297+ desiredNet := c .globalURL + "/networks/" + d .Network
298+ if ! create {
299+ if desiredNet != rule .Network {
300+ networkChanged = true
301+ rule .Network = desiredNet
302+ }
263303 }
264304
265- for proto , ports := range missingPorts {
266- rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
267- IPProtocol : proto ,
268- Ports : ports ,
269- })
305+ // ensure the rule is specifying only the expected ports
306+ if ! updatePorts (rule , expectedPorts ) && ! networkChanged {
307+ log .Debugf ("Do not need to update internal firewall rule '%s' as all ports are configured" , rule .Name )
308+ return nil
270309 }
271310
272311 var err error
@@ -298,7 +337,6 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
298337 Description : "rancher-machine managed external firewall rule" ,
299338 Allowed : []* raw.FirewallAllowed {},
300339 SourceRanges : []string {"0.0.0.0/0" },
301- SourceTags : []string {c .externalFirewallRuleName ()},
302340 TargetTags : []string {c .externalFirewallRuleName ()},
303341 Network : c .globalURL + "/networks/" + d .Network ,
304342 }
@@ -309,16 +347,20 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
309347 return err
310348 }
311349
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
350+ // ensure an existing firewall rule properly points to the specified network
351+ networkChanged := false
352+ desiredNet := c .globalURL + "/networks/" + d .Network
353+ if ! create {
354+ if desiredNet != rule .Network {
355+ networkChanged = true
356+ rule .Network = desiredNet
357+ }
316358 }
317- for proto , ports := range missingPorts {
318- rule . Allowed = append ( rule . Allowed , & raw. FirewallAllowed {
319- IPProtocol : proto ,
320- Ports : ports ,
321- })
359+
360+ // ensure the rule is specifying only the requested ports
361+ if ! updatePorts ( rule , portsUsed ) && ! networkChanged {
362+ log . Debugf ( "Do not need to update internal firewall rule '%s' as all ports are configured" , rule . Name )
363+ return nil
322364 }
323365
324366 var op * raw.Operation
@@ -361,6 +403,9 @@ func (c *ComputeUtil) CleanUpFirewallRule(rule *raw.Firewall, labelKey string) e
361403 log .Infof ("Removing rancher-machine managed firewall rule '%s' from project as no instances are using it" , rule .Name )
362404 op , err := c .service .Firewalls .Delete (c .project , rule .Name ).Do ()
363405 if err != nil {
406+ if isNotFound (err ) {
407+ return nil
408+ }
364409 return fmt .Errorf ("failed to remove rancher-machine managed firewall rule '%s': %w" , rule .Name , err )
365410 }
366411
0 commit comments