func tcpRule(ip string, port uint16) garden.NetOutRule { return garden.NetOutRule{ Protocol: garden.ProtocolTCP, Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP(ip))}, Ports: []garden.PortRange{garden.PortRangeFromPort(port)}, Log: true, } }
func securityGroupRuleToNetOutRule(securityRule *models.SecurityGroupRule) (garden.NetOutRule, error) { var protocol garden.Protocol var portRanges []garden.PortRange var networks []garden.IPRange var icmp *garden.ICMPControl switch securityRule.Protocol { case models.TCPProtocol: protocol = garden.ProtocolTCP case models.UDPProtocol: protocol = garden.ProtocolUDP case models.ICMPProtocol: protocol = garden.ProtocolICMP icmp = &garden.ICMPControl{ Type: garden.ICMPType(securityRule.IcmpInfo.Type), Code: garden.ICMPControlCode(uint8(securityRule.IcmpInfo.Code)), } case models.AllProtocol: protocol = garden.ProtocolAll } if securityRule.PortRange != nil { portRanges = append(portRanges, garden.PortRange{Start: uint16(securityRule.PortRange.Start), End: uint16(securityRule.PortRange.End)}) } else if securityRule.Ports != nil { for _, port := range securityRule.Ports { portRanges = append(portRanges, garden.PortRangeFromPort(uint16(port))) } } for _, dest := range securityRule.Destinations { ipRange, err := toIPRange(dest) if err != nil { return garden.NetOutRule{}, err } networks = append(networks, ipRange) } netOutRule := garden.NetOutRule{ Protocol: protocol, Networks: networks, Ports: portRanges, ICMPs: icmp, Log: securityRule.Log, } return netOutRule, nil }
}) JustBeforeEach(func() { server.AppendHandlers( ghttp.CombineHandlers( ghttp.VerifyRequest("POST", fmt.Sprintf("/containers/%s/net/out", handle)), verifyRequestBody(&rule, &garden.NetOutRule{}), ghttp.RespondWith(200, "{}"))) }) Context("when a NetOutRule is passed", func() { BeforeEach(func() { rule = garden.NetOutRule{ Protocol: garden.ProtocolICMP, Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP("1.2.3.4"))}, Ports: []garden.PortRange{garden.PortRangeFromPort(2), garden.PortRangeFromPort(4)}, ICMPs: &garden.ICMPControl{Type: 3, Code: garden.ICMPControlCode(3)}, Log: true, } }) It("should send the rule over the wire", func() { Ω(connection.NetOut(handle, rule)).Should(Succeed()) }) }) }) Describe("Listing containers", func() { BeforeEach(func() { server.AppendHandlers( ghttp.CombineHandlers(
}) Describe("IPRangeFromIPNet", func() { It("Creates an IPRange with the Start and End set to the extent of the IPNet", func() { ip, cidr, err := net.ParseCIDR("1.2.3.0/24") Ω(err).Should(Succeed()) r := garden.IPRangeFromIPNet(cidr) Ω(r.Start.String()).Should(Equal(ip.String())) Ω(r.End.String()).Should(Equal("1.2.3.255")) }) }) Describe("PortRangeFromPort", func() { It("Creates an PortRange with the Start and End set to the passed port", func() { r := garden.PortRangeFromPort(2) Ω(r.Start).Should(Equal(uint16(2))) Ω(r.End).Should(Equal(r.Start)) }) }) Describe("ICMPControlCode", func() { It("returns an ICMPCode with the passed uint8", func() { var icmpVar *garden.ICMPCode code := garden.ICMPControlCode(uint8(2)) Ω(code).Should(BeAssignableToTypeOf(icmpVar)) Ω(*code).Should(BeNumerically("==", 2)) }) }) })
containerD := createContainer(gardenClient, garden.ContainerSpec{}) firstReusedPort, _, err := containerD.NetIn(0, 0) Ω(err).ShouldNot(HaveOccurred()) secondReusedPort, _, err := containerD.NetIn(0, 0) Ω(err).ShouldNot(HaveOccurred()) Ω(firstReusedPort).To(Equal(containerBPort)) Ω(secondReusedPort).To(Equal(containerAPort)) }) }) It("gives a better error message when NetOut is given port and no protocol (#87201436)", func() { container := createContainer(gardenClient, garden.ContainerSpec{}) err := container.NetOut(garden.NetOutRule{ Ports: []garden.PortRange{garden.PortRangeFromPort(80)}, }) Ω(err).Should(MatchError("Ports cannot be specified for Protocol ALL")) }) It("can open outbound ICMP connections (#85601268)", func() { container := createContainer(gardenClient, garden.ContainerSpec{}) Ω(container.NetOut(pingRule("8.8.8.8"))).Should(Succeed()) buffer := gbytes.NewBuffer() process, err := container.Run(garden.ProcessSpec{ User: "******", Path: "ping", Args: []string{"-c", "1", "-w", "3", "8.8.8.8"}, }, recordedProcessIO(buffer)) Ω(err).ShouldNot(HaveOccurred()) Ω(process.Wait()).Should(Equal(0))
Expect(fakeRunner).To(HaveExecutedSerially(fake_command_runner.CommandSpec{ Path: "/sbin/iptables", Args: []string{"-w", "-I", "foo-bar-baz", "1", "--protocol", "all", "-m", "iprange", "--dst-range", "1.2.3.4-2.3.4.5", "--jump", "RETURN"}, })) }) }) }) Describe("Ports", func() { Context("when a single port is specified", func() { It("opens only that port", func() { Expect(subject.PrependFilterRule(garden.NetOutRule{ Protocol: garden.ProtocolTCP, Ports: []garden.PortRange{ garden.PortRangeFromPort(22), }, })).To(Succeed()) Expect(fakeRunner).To(HaveExecutedSerially(fake_command_runner.CommandSpec{ Path: "/sbin/iptables", Args: []string{"-w", "-I", "foo-bar-baz", "1", "--protocol", "tcp", "--destination-port", "22", "--jump", "RETURN"}, })) }) }) Context("when a port range is specified", func() { It("opens that port range", func() { Expect(subject.PrependFilterRule(garden.NetOutRule{ Protocol: garden.ProtocolTCP, Ports: []garden.PortRange{
Ω(hostPort).Should(Equal(uint32(1))) Ω(containerPort).Should(Equal(uint32(2))) }) It("returns the ports", func() { Ω(gotHostPort).Should(Equal(hostPort)) Ω(gotContainerPort).Should(Equal(containerPort)) }) }) }) Describe("NetOut", func() { netOutRule := garden.NetOutRule{ Protocol: garden.ProtocolTCP, Ports: []garden.PortRange{ garden.PortRangeFromPort(13253), }, } itRetries(func() error { return conn.NetOut("la-contineur", netOutRule) }, func(err error) { innerConnection.NetOutReturns(err) }, func() int { return innerConnection.NetOutCallCount() }, func() { It("calls through to garden", func() { Ω(innerConnection.NetOutCallCount()).Should(Equal(1)) handle, calledNetOutRule := innerConnection.NetOutArgsForCall(0) Ω(handle).Should(Equal("la-contineur"))