88 "net/http"
99 "net/url"
1010 "os"
11+ "reflect"
1112 "regexp"
1213 "strings"
1314 "time"
@@ -177,26 +178,59 @@ 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+ if ! reflect .DeepEqual (requestedPorts [proto ], ports ) {
205+ recreate = true
206+ break
207+ }
208+ }
209+
210+ if ! recreate {
211+ for proto , ports := range requestedPorts {
212+ if ! reflect .DeepEqual (requestedPorts [proto ], ports ) {
213+ recreate = true
214+ break
215+ }
194216 }
195217 }
196- if len (missing ) > 0 {
197- log .Warnf ("found missing ports for firewall rule '%s': %v" , rule .Name , missing )
218+
219+ if ! recreate {
220+ return false
221+ }
222+
223+ rule .Allowed = []* raw.FirewallAllowed {}
224+ for proto , ports := range requestedPorts {
225+ rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
226+ IPProtocol : proto ,
227+ // note that Ports can only include numbers, and not
228+ // number protocol pairs.
229+ Ports : ports ,
230+ })
198231 }
199- return missing
232+
233+ return true
200234}
201235
202236func (c * ComputeUtil ) portsUsed () ([]string , error ) {
@@ -233,8 +267,6 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
233267 "6443" ,
234268 "2379" ,
235269 "2380" ,
236- "4789" ,
237- "2376" ,
238270 "9345" ,
239271 "9796" ,
240272 "8472/udp" ,
@@ -256,17 +288,20 @@ func (c *ComputeUtil) openInternalFirewallPorts(d *Driver) error {
256288 }
257289 }
258290
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
291+ // ensure an existing firewall rule properly points to the specified network
292+ networkChanged := false
293+ desiredNet := c .globalURL + "/networks/" + d .Network
294+ if ! create {
295+ if desiredNet != rule .Network {
296+ networkChanged = true
297+ rule .Network = desiredNet
298+ }
263299 }
264300
265- for proto , ports := range missingPorts {
266- rule .Allowed = append (rule .Allowed , & raw.FirewallAllowed {
267- IPProtocol : proto ,
268- Ports : ports ,
269- })
301+ // ensure the rule is specifying only the expected ports
302+ if ! updatePorts (rule , expectedPorts ) && ! networkChanged {
303+ log .Debugf ("Do not need to update internal firewall rule '%s' as all ports are configured" , rule .Name )
304+ return nil
270305 }
271306
272307 var err error
@@ -298,7 +333,6 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
298333 Description : "rancher-machine managed external firewall rule" ,
299334 Allowed : []* raw.FirewallAllowed {},
300335 SourceRanges : []string {"0.0.0.0/0" },
301- SourceTags : []string {c .externalFirewallRuleName ()},
302336 TargetTags : []string {c .externalFirewallRuleName ()},
303337 Network : c .globalURL + "/networks/" + d .Network ,
304338 }
@@ -309,16 +343,20 @@ func (c *ComputeUtil) openPublicFirewallPorts(d *Driver) error {
309343 return err
310344 }
311345
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
346+ // ensure an existing firewall rule properly points to the specified network
347+ networkChanged := false
348+ desiredNet := c .globalURL + "/networks/" + d .Network
349+ if ! create {
350+ if desiredNet != rule .Network {
351+ networkChanged = true
352+ rule .Network = desiredNet
353+ }
316354 }
317- for proto , ports := range missingPorts {
318- rule . Allowed = append ( rule . Allowed , & raw. FirewallAllowed {
319- IPProtocol : proto ,
320- Ports : ports ,
321- })
355+
356+ // ensure the rule is specifying only the requested ports
357+ if ! updatePorts ( rule , portsUsed ) && ! networkChanged {
358+ log . Debugf ( "Do not need to update internal firewall rule '%s' as all ports are configured" , rule . Name )
359+ return nil
322360 }
323361
324362 var op * raw.Operation
0 commit comments