Skip to content

Commit

Permalink
Add support to azure provider for security group source CIDRs, and al…
Browse files Browse the repository at this point in the history
…so other related drive by fixes
  • Loading branch information
wallyworld committed Jan 23, 2017
1 parent d2e75e1 commit fc75ffb
Show file tree
Hide file tree
Showing 22 changed files with 363 additions and 207 deletions.
3 changes: 3 additions & 0 deletions environs/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,9 @@ type Firewaller interface {
// IngressRules returns the ingress rules applied to the whole environment.
// Must only be used if the environment was setup with the
// FwGlobal firewall mode.
// It is expected that there be only one ingress rule result for a given
// port range - the rule's SourceCIDRs will contain all applicable source
// address rules for that port range.
IngressRules() ([]network.IngressRule, error)
}

Expand Down
145 changes: 117 additions & 28 deletions environs/jujutest/livetests.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,92 +319,152 @@ func (t *LiveTests) TestPorts(c *gc.C) {

// Open some ports and check they're there.
err = inst1.OpenPorts(
"1", network.RulesFromPortRanges([]network.PortRange{{67, 67, "udp"}, {45, 45, "tcp"}, {80, 100, "tcp"}}...))
"1", []network.IngressRule{
network.MustNewIngressRule("udp", 67, 67),
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("tcp", 80, 100),
})

c.Assert(err, jc.ErrorIsNil)
rules, err = inst1.IngressRules("1")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 80, 100, "0.0.0.0/0"),
network.MustNewIngressRule("udp", 67, 67, "0.0.0.0/0"),
},
)
rules, err = inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
c.Assert(rules, gc.HasLen, 0)

err = inst2.OpenPorts(
"2", network.RulesFromPortRanges([]network.PortRange{{89, 89, "tcp"}, {45, 45, "tcp"}, {20, 30, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 89, 89),
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("tcp", 20, 30),
})
c.Assert(err, jc.ErrorIsNil)

// Check there's no crosstalk to another machine
rules, err = inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{20, 30, "tcp"}, {45, 45, "tcp"}, {89, 89, "tcp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 20, 30, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
},
)
rules, err = inst1.IngressRules("1")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 80, 100, "0.0.0.0/0"),
network.MustNewIngressRule("udp", 67, 67, "0.0.0.0/0"),
},
)

// Check that opening the same port again is ok.
oldRules, err := inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
err = inst2.OpenPorts(
"2", network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45),
})
c.Assert(err, jc.ErrorIsNil)
err = inst2.OpenPorts(
"2", network.RulesFromPortRanges([]network.PortRange{{20, 30, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 20, 30),
})
c.Assert(err, jc.ErrorIsNil)
rules, err = inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
c.Assert(rules, jc.DeepEquals, oldRules)

// Check that opening the same port again and another port is ok.
err = inst2.OpenPorts(
"2", network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {99, 99, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("tcp", 99, 99),
})
c.Assert(err, jc.ErrorIsNil)
rules, err = inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{20, 30, "tcp"}, {45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}}...))

[]network.IngressRule{
network.MustNewIngressRule("tcp", 20, 30, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 99, 99, "0.0.0.0/0"),
},
)
err = inst2.ClosePorts(
"2", network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {99, 99, "tcp"}, {20, 30, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("tcp", 99, 99),
network.MustNewIngressRule("tcp", 20, 30),
})
c.Assert(err, jc.ErrorIsNil)

// Check that we can close ports and that there's no crosstalk.
rules, err = inst2.IngressRules("2")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{89, 89, "tcp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
},
)
rules, err = inst1.IngressRules("1")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {80, 100, "tcp"}, {67, 67, "udp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 80, 100, "0.0.0.0/0"),
network.MustNewIngressRule("udp", 67, 67, "0.0.0.0/0"),
},
)

// Check that we can close multiple ports.
err = inst1.ClosePorts(
"1", network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {67, 67, "udp"}, {80, 100, "tcp"}}...))
"1", []network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("udp", 67, 67),
network.MustNewIngressRule("tcp", 80, 100),
})
c.Assert(err, jc.ErrorIsNil)
rules, err = inst1.IngressRules("1")
c.Assert(rules, gc.HasLen, 0)

// Check that we can close ports that aren't there.
err = inst2.ClosePorts(
"2", network.RulesFromPortRanges([]network.PortRange{{111, 111, "tcp"}, {222, 222, "udp"}, {600, 700, "tcp"}}...))
"2", []network.IngressRule{
network.MustNewIngressRule("tcp", 111, 111),
network.MustNewIngressRule("udp", 222, 222),
network.MustNewIngressRule("tcp", 600, 700),
})
c.Assert(err, jc.ErrorIsNil)
rules, err = inst2.IngressRules("2")
c.Assert(rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{89, 89, "tcp"}}...))
c.Assert(
rules, jc.DeepEquals,
[]network.IngressRule{
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
},
)

// Check errors when acting on environment.
err = t.Env.OpenPorts(network.RulesFromPortRanges([]network.PortRange{{80, 80, "tcp"}}...))
err = t.Env.OpenPorts([]network.IngressRule{network.MustNewIngressRule("tcp", 80, 80)})
c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for opening ports on model`)

err = t.Env.ClosePorts(network.RulesFromPortRanges([]network.PortRange{{80, 80, "tcp"}}...))
err = t.Env.ClosePorts([]network.IngressRule{network.MustNewIngressRule("tcp", 80, 80)})
c.Assert(err, gc.ErrorMatches, `invalid firewall mode "instance" for closing ports on model`)

_, err = t.Env.IngressRules()
Expand Down Expand Up @@ -441,43 +501,72 @@ func (t *LiveTests) TestGlobalPorts(c *gc.C) {
c.Assert(rules, gc.HasLen, 0)
defer t.Env.StopInstances(inst2.Id())

err = t.Env.OpenPorts(
network.RulesFromPortRanges([]network.PortRange{{67, 67, "udp"}, {45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}, {100, 110, "tcp"}}...))
err = t.Env.OpenPorts([]network.IngressRule{
network.MustNewIngressRule("udp", 67, 67),
network.MustNewIngressRule("tcp", 45, 45),
network.MustNewIngressRule("tcp", 89, 89),
network.MustNewIngressRule("tcp", 99, 99),
network.MustNewIngressRule("tcp", 100, 110),
})
c.Assert(err, jc.ErrorIsNil)

rules, err = t.Env.IngressRules()
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {99, 99, "tcp"}, {100, 110, "tcp"}, {67, 67, "udp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 99, 99, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 100, 110, "0.0.0.0/0"),
network.MustNewIngressRule("udp", 67, 67, "0.0.0.0/0"),
},
)

// Check closing some ports.
err = t.Env.ClosePorts(network.RulesFromPortRanges([]network.PortRange{{99, 99, "tcp"}, {67, 67, "udp"}}...))
err = t.Env.ClosePorts([]network.IngressRule{
network.MustNewIngressRule("tcp", 99, 99),
network.MustNewIngressRule("udp", 67, 67),
})
c.Assert(err, jc.ErrorIsNil)

rules, err = t.Env.IngressRules()
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {100, 110, "tcp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 100, 110, "0.0.0.0/0"),
},
)

// Check that we can close ports that aren't there.
err = t.Env.ClosePorts(network.RulesFromPortRanges([]network.PortRange{{111, 111, "tcp"}, {222, 222, "udp"}, {2000, 2500, "tcp"}}...))
err = t.Env.ClosePorts([]network.IngressRule{
network.MustNewIngressRule("tcp", 111, 111),
network.MustNewIngressRule("udp", 222, 222),
network.MustNewIngressRule("tcp", 2000, 2500),
})
c.Assert(err, jc.ErrorIsNil)

rules, err = t.Env.IngressRules()
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rules, jc.DeepEquals,
network.RulesFromPortRanges([]network.PortRange{{45, 45, "tcp"}, {89, 89, "tcp"}, {100, 110, "tcp"}}...))
[]network.IngressRule{
network.MustNewIngressRule("tcp", 45, 45, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 89, 89, "0.0.0.0/0"),
network.MustNewIngressRule("tcp", 100, 110, "0.0.0.0/0"),
},
)

// Check errors when acting on instances.
err = inst1.OpenPorts(
"1", network.RulesFromPortRanges([]network.PortRange{{80, 80, "tcp"}}...))
"1", []network.IngressRule{network.MustNewIngressRule("tcp", 80, 80)})
c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for opening ports on instance`)

err = inst1.ClosePorts(
"1", network.RulesFromPortRanges([]network.PortRange{{80, 80, "tcp"}}...))
"1", []network.IngressRule{network.MustNewIngressRule("tcp", 80, 80)})
c.Assert(err, gc.ErrorMatches, `invalid firewall mode "global" for closing ports on instance`)

_, err = inst1.IngressRules("1")
Expand Down
3 changes: 3 additions & 0 deletions instance/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type Instance interface {
// IngressRules returns the set of ingress rules for the instance,
// which should have been applied to the given machine id. The
// rules are returned as sorted by network.SortIngressRules().
// It is expected that there be only one ingress rule result for a given
// port range - the rule's SourceCIDRs will contain all applicable source
// address rules for that port range.
IngressRules(machineId string) ([]network.IngressRule, error)
}

Expand Down
5 changes: 3 additions & 2 deletions network/firewall.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ func NewOpenIngressRule(protocol string, from, to int) IngressRule {
// String is the string representation of IngressRule.
func (r IngressRule) String() string {
source := ""
if len(r.SourceCIDRs) > 0 {
source = " from " + strings.Join(r.SourceCIDRs, ",")
from := strings.Join(r.SourceCIDRs, ",")
if from != "" && from != "0.0.0.0/0" {
source = " from " + from
}
if r.FromPort == r.ToPort {
return fmt.Sprintf("%d/%s%s", r.FromPort, strings.ToLower(r.Protocol), source)
Expand Down
49 changes: 13 additions & 36 deletions network/firewall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,44 +18,21 @@ type FirewallSuite struct {
var _ = gc.Suite(&FirewallSuite{})

func (*FirewallSuite) TestStrings(c *gc.C) {
rule, err := network.NewIngressRule("tcp", 80, 80)
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rule.String(),
gc.Equals,
"80/tcp",
)
c.Assert(
rule.GoString(),
gc.Equals,
"80/tcp",
)
rule := network.MustNewIngressRule("tcp", 80, 80)
c.Assert(rule.String(), gc.Equals, "80/tcp")
c.Assert(rule.GoString(), gc.Equals, "80/tcp")

rule, err = network.NewIngressRule("tcp", 80, 100)
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rule.String(),
gc.Equals,
"80-100/tcp",
)
c.Assert(
rule.GoString(),
gc.Equals,
"80-100/tcp",
)
rule = network.MustNewIngressRule("tcp", 80, 80, "0.0.0.0/0")
c.Assert(rule.String(), gc.Equals, "80/tcp")
c.Assert(rule.GoString(), gc.Equals, "80/tcp")

rule, err = network.NewIngressRule("tcp", 80, 100, "0.0.0.0/0", "192.168.1.0/24")
c.Assert(err, jc.ErrorIsNil)
c.Assert(
rule.String(),
gc.Equals,
"80-100/tcp from 0.0.0.0/0,192.168.1.0/24",
)
c.Assert(
rule.GoString(),
gc.Equals,
"80-100/tcp from 0.0.0.0/0,192.168.1.0/24",
)
rule = network.MustNewIngressRule("tcp", 80, 100)
c.Assert(rule.String(), gc.Equals, "80-100/tcp")
c.Assert(rule.GoString(), gc.Equals, "80-100/tcp")

rule = network.MustNewIngressRule("tcp", 80, 100, "0.0.0.0/0", "192.168.1.0/24")
c.Assert(rule.String(), gc.Equals, "80-100/tcp from 0.0.0.0/0,192.168.1.0/24")
c.Assert(rule.GoString(), gc.Equals, "80-100/tcp from 0.0.0.0/0,192.168.1.0/24")
}

func (*FirewallSuite) TestSortIngressRules(c *gc.C) {
Expand Down
Loading

0 comments on commit fc75ffb

Please sign in to comment.