github.com/cloudfoundry-attic/garden-linux@v0.333.2-candidate/integration/networking/net_out_test.go (about)

     1  package networking_test
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strings"
     7  
     8  	"github.com/cloudfoundry-incubator/garden"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  
    12  	"github.com/onsi/gomega/gbytes"
    13  )
    14  
    15  var _ = Describe("Net Out", func() {
    16  	var (
    17  		container      garden.Container
    18  		otherContainer garden.Container
    19  		gardenArgs     []string
    20  
    21  		containerNetwork string
    22  		denyRange        string
    23  		allowRange       string
    24  	)
    25  
    26  	const containerHandle = "6e4ea858-6b31-4243-5dcc-093cfb83952d"
    27  
    28  	BeforeEach(func() {
    29  		denyRange = ""
    30  		allowRange = ""
    31  		gardenArgs = []string{}
    32  	})
    33  
    34  	JustBeforeEach(func() {
    35  		gardenArgs = []string{
    36  			"-denyNetworks", strings.Join([]string{
    37  				denyRange,
    38  				allowRange, // so that it can be overridden by allowNetworks below
    39  			}, ","),
    40  			"-allowNetworks", allowRange,
    41  			"-iptablesLogMethod", "nflog", // so that we can read logs when running in fly
    42  		}
    43  		client = startGarden(gardenArgs...)
    44  
    45  		var err error
    46  		container, err = client.Create(garden.ContainerSpec{Network: containerNetwork, Privileged: true, Handle: containerHandle})
    47  		Expect(err).ToNot(HaveOccurred())
    48  	})
    49  
    50  	AfterEach(func() {
    51  		err := client.Destroy(container.Handle())
    52  		Expect(err).ToNot(HaveOccurred())
    53  	})
    54  
    55  	runInContainer := func(container garden.Container, script string) (garden.Process, *gbytes.Buffer) {
    56  		out := gbytes.NewBuffer()
    57  		process, err := container.Run(garden.ProcessSpec{
    58  			User: "alice",
    59  			Path: "sh",
    60  			Args: []string{"-c", script},
    61  		}, garden.ProcessIO{
    62  			Stdout: io.MultiWriter(out, GinkgoWriter),
    63  			Stderr: GinkgoWriter,
    64  		})
    65  		Expect(err).ToNot(HaveOccurred())
    66  
    67  		return process, out
    68  	}
    69  
    70  	Context("external addresses", func() {
    71  		var (
    72  			ByAllowingTCP, ByRejectingTCP func()
    73  		)
    74  
    75  		BeforeEach(func() {
    76  			ByAllowingTCP = func() {
    77  				By("allowing outbound tcp traffic", func() {
    78  					Expect(checkInternet(container)).To(Succeed())
    79  				})
    80  			}
    81  
    82  			ByRejectingTCP = func() {
    83  				By("rejecting outbound tcp traffic", func() {
    84  					Expect(checkInternet(container)).To(HaveOccurred())
    85  				})
    86  			}
    87  		})
    88  
    89  		Context("when the target address is inside DENY_NETWORKS", func() {
    90  			//The target address is the ip addr of www.example.com in these tests
    91  			BeforeEach(func() {
    92  				denyRange = "0.0.0.0/0"
    93  				allowRange = "9.9.9.9/30"
    94  				containerNetwork = fmt.Sprintf("10.1%d.0.0/24", GinkgoParallelNode())
    95  			})
    96  
    97  			It("disallows TCP connections", func() {
    98  				ByRejectingTCP()
    99  			})
   100  
   101  			Context("when a rule that allows all traffic to the target is added", func() {
   102  				JustBeforeEach(func() {
   103  					err := container.NetOut(garden.NetOutRule{
   104  						Networks: []garden.IPRange{
   105  							garden.IPRangeFromIP(externalIP),
   106  						},
   107  					})
   108  					Expect(err).ToNot(HaveOccurred())
   109  				})
   110  
   111  				It("allows TCP traffic to the target", func() {
   112  					ByAllowingTCP()
   113  				})
   114  			})
   115  		})
   116  
   117  		Context("when the target address is inside ALLOW_NETWORKS", func() {
   118  			BeforeEach(func() {
   119  				denyRange = "0.0.0.0/0"
   120  				allowRange = "0.0.0.0/0"
   121  				containerNetwork = fmt.Sprintf("10.1%d.0.0/24", GinkgoParallelNode())
   122  			})
   123  
   124  			It("allows connections", func() {
   125  				ByAllowingTCP()
   126  			})
   127  		})
   128  
   129  		Context("when the target address is in neither ALLOW_NETWORKS nor DENY_NETWORKS", func() {
   130  			BeforeEach(func() {
   131  				denyRange = "4.4.4.4/30"
   132  				allowRange = "4.4.4.4/30"
   133  				containerNetwork = fmt.Sprintf("10.1%d.0.0/24", GinkgoParallelNode())
   134  			})
   135  
   136  			It("allows connections", func() {
   137  				ByAllowingTCP()
   138  			})
   139  		})
   140  
   141  		Context("when there are two containers in the same subnet", func() {
   142  			BeforeEach(func() {
   143  				denyRange = "0.0.0.0/0"
   144  				containerNetwork = fmt.Sprintf("10.1%d.0.0/24", GinkgoParallelNode())
   145  			})
   146  
   147  			It("does not allow rules from the second container to affect the first", func() {
   148  				var err error
   149  				secondContainer, err := client.Create(garden.ContainerSpec{Network: containerNetwork, Privileged: true})
   150  				Expect(err).ToNot(HaveOccurred())
   151  
   152  				ByRejectingTCP()
   153  
   154  				Expect(secondContainer.NetOut(garden.NetOutRule{
   155  					Networks: []garden.IPRange{
   156  						garden.IPRangeFromIP(externalIP),
   157  					},
   158  				})).To(Succeed())
   159  
   160  				By("continuing to reject")
   161  				ByRejectingTCP()
   162  			})
   163  		})
   164  	})
   165  
   166  	Describe("Other Containers", func() {
   167  
   168  		const tcpPort = 8080
   169  
   170  		targetIP := func(c garden.Container) string {
   171  			info, err := c.Info()
   172  			Expect(err).ToNot(HaveOccurred())
   173  			return info.ContainerIP
   174  		}
   175  
   176  		ByAllowingTCP := func() {
   177  			By("allowing tcp traffic to it", func() {
   178  				Eventually(func() error {
   179  					return checkConnection(container, targetIP(otherContainer), tcpPort)
   180  				}).Should(Succeed())
   181  			})
   182  		}
   183  
   184  		Context("containers in the same subnet", func() {
   185  			JustBeforeEach(func() {
   186  				var err error
   187  				otherContainer, err = client.Create(garden.ContainerSpec{Network: containerNetwork})
   188  				Expect(err).ToNot(HaveOccurred())
   189  
   190  				runInContainer(otherContainer, fmt.Sprintf("echo hello | nc -l -p %d", tcpPort)) //tcp
   191  			})
   192  
   193  			Context("even if the address is in deny networks", func() {
   194  				BeforeEach(func() {
   195  					denyRange = "0.0.0.0/8"
   196  					allowRange = ""
   197  					containerNetwork = fmt.Sprintf("10.1%d.0.0/24", GinkgoParallelNode())
   198  				})
   199  
   200  				It("can route to each other", func() {
   201  					ByAllowingTCP()
   202  				})
   203  			})
   204  		})
   205  
   206  		Context("containers in distinct subnets", func() {
   207  			var otherContainerNetwork string
   208  
   209  			JustBeforeEach(func() {
   210  				otherContainerNetwork = fmt.Sprintf("10.1%d.1.0/24", GinkgoParallelNode())
   211  				var err error
   212  				otherContainer, err = client.Create(garden.ContainerSpec{Network: otherContainerNetwork})
   213  				Expect(err).ToNot(HaveOccurred())
   214  
   215  				runInContainer(otherContainer, fmt.Sprintf("echo hello | nc -l -p %d", tcpPort)) //tcp
   216  			})
   217  
   218  			Context("when deny networks is empty", func() {
   219  				It("can route to each other", func() {
   220  					ByAllowingTCP()
   221  				})
   222  			})
   223  		})
   224  	})
   225  })