github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/integration/lifecycle/security_test.go (about) 1 package lifecycle_test 2 3 import ( 4 "fmt" 5 "os" 6 "strings" 7 "time" 8 9 "github.com/cloudfoundry-incubator/garden" 10 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 "github.com/onsi/gomega/gbytes" 14 ) 15 16 var _ = Describe("Security", func() { 17 Describe("Isolating PIDs", func() { 18 It("isolates processes so that only process from inside the container are visible", func() { 19 client = startGarden() 20 container, err := client.Create(garden.ContainerSpec{}) 21 Expect(err).ToNot(HaveOccurred()) 22 23 _, err = container.Run(garden.ProcessSpec{ 24 Path: "sleep", 25 Args: []string{"989898"}, 26 }, garden.ProcessIO{ 27 Stdout: GinkgoWriter, 28 Stderr: GinkgoWriter, 29 }) 30 Expect(err).ToNot(HaveOccurred()) 31 32 psout := gbytes.NewBuffer() 33 ps, err := container.Run(garden.ProcessSpec{ 34 Path: "sh", 35 Args: []string{"-c", "ps -a"}, 36 }, garden.ProcessIO{ 37 Stdout: psout, 38 Stderr: GinkgoWriter, 39 }) 40 Expect(err).ToNot(HaveOccurred()) 41 42 Expect(ps.Wait()).To(Equal(0)) 43 Expect(strings.Split(string(psout.Contents()), "\n")).To(HaveLen(6)) // header, wshd, sleep, sh, ps, \n 44 }) 45 }) 46 47 Context("with a empty rootfs", func() { 48 var emptyRootFSPath string 49 50 BeforeEach(func() { 51 emptyRootFSPath = os.Getenv("GARDEN_EMPTY_TEST_ROOTFS") 52 53 if emptyRootFSPath == "" { 54 Fail("GARDEN_EMPTY_TEST_ROOTFS undefined;") 55 } 56 57 client = startGarden() 58 }) 59 60 It("runs a statically compiled executable in the container", func() { 61 container, err := client.Create( 62 garden.ContainerSpec{ 63 RootFSPath: emptyRootFSPath, 64 }, 65 ) 66 Expect(err).ToNot(HaveOccurred()) 67 68 stdout := gbytes.NewBuffer() 69 stderr := gbytes.NewBuffer() 70 process, err := container.Run( 71 garden.ProcessSpec{ 72 Path: "/hello", 73 }, 74 garden.ProcessIO{ 75 Stdout: stdout, 76 Stderr: stderr, 77 }, 78 ) 79 Expect(err).ToNot(HaveOccurred()) 80 81 exitStatus, err := process.Wait() 82 Expect(err).ToNot(HaveOccurred()) 83 Expect(exitStatus).To(Equal(0)) 84 85 Expect(string(stdout.Contents())).To(Equal("hello from stdout")) 86 Expect(string(stderr.Contents())).To(Equal("hello from stderr")) 87 }) 88 }) 89 90 Describe("Denying access to network ranges", func() { 91 var ( 92 blockedListener garden.Container 93 blockedListenerIP string = fmt.Sprintf("11.0.%d.1", GinkgoParallelNode()) 94 95 unblockedListener garden.Container 96 unblockedListenerIP string = fmt.Sprintf("11.1.%d.1", GinkgoParallelNode()) 97 98 allowedListener garden.Container 99 allowedListenerIP string = fmt.Sprintf("11.2.%d.1", GinkgoParallelNode()) 100 101 sender garden.Container 102 ) 103 104 BeforeEach(func() { 105 client = startGarden( 106 "-denyNetworks", strings.Join([]string{ 107 blockedListenerIP + "/32", 108 allowedListenerIP + "/32", 109 }, ","), 110 "-allowNetworks", allowedListenerIP+"/32", 111 ) 112 113 var err error 114 115 // create a listener to which we deny network access 116 blockedListener, err = client.Create(garden.ContainerSpec{Network: blockedListenerIP + "/30"}) 117 Expect(err).ToNot(HaveOccurred()) 118 blockedListenerIP = containerIP(blockedListener) 119 120 // create a listener to which we do not deny access 121 unblockedListener, err = client.Create(garden.ContainerSpec{Network: unblockedListenerIP + "/30"}) 122 Expect(err).ToNot(HaveOccurred()) 123 unblockedListenerIP = containerIP(unblockedListener) 124 125 // create a listener to which we exclicitly allow access 126 allowedListener, err = client.Create(garden.ContainerSpec{Network: allowedListenerIP + "/30"}) 127 Expect(err).ToNot(HaveOccurred()) 128 allowedListenerIP = containerIP(allowedListener) 129 130 // create a container with the new deny network configuration 131 sender, err = client.Create(garden.ContainerSpec{}) 132 Expect(err).ToNot(HaveOccurred()) 133 134 }) 135 136 AfterEach(func() { 137 err := client.Destroy(sender.Handle()) 138 Expect(err).ToNot(HaveOccurred()) 139 140 err = client.Destroy(blockedListener.Handle()) 141 Expect(err).ToNot(HaveOccurred()) 142 143 err = client.Destroy(unblockedListener.Handle()) 144 Expect(err).ToNot(HaveOccurred()) 145 146 err = client.Destroy(allowedListener.Handle()) 147 Expect(err).ToNot(HaveOccurred()) 148 }) 149 150 runInContainer := func(container garden.Container, script string) garden.Process { 151 process, err := container.Run(garden.ProcessSpec{ 152 Path: "sh", 153 Args: []string{"-c", script}, 154 }, garden.ProcessIO{ 155 Stdout: GinkgoWriter, 156 Stderr: GinkgoWriter, 157 }) 158 Expect(err).ToNot(HaveOccurred()) 159 160 return process 161 } 162 163 It("makes that block of ip addresses inaccessible to the container", func() { 164 runInContainer(blockedListener, "nc -l 0.0.0.0:12345") 165 runInContainer(unblockedListener, "nc -l 0.0.0.0:12345") 166 runInContainer(allowedListener, "nc -l 0.0.0.0:12345") 167 168 // a bit of time for the listeners to start, since they block 169 time.Sleep(time.Second) 170 171 process := runInContainer( 172 sender, 173 fmt.Sprintf("echo hello | nc -w 1 %s 12345", blockedListenerIP), 174 ) 175 Expect(process.Wait()).To(Equal(1)) 176 177 process = runInContainer( 178 sender, 179 fmt.Sprintf("echo hello | nc -w 1 %s 12345", unblockedListenerIP), 180 ) 181 Expect(process.Wait()).To(Equal(0)) 182 183 process = runInContainer( 184 sender, 185 fmt.Sprintf("echo hello | nc -w 1 %s 12345", allowedListenerIP), 186 ) 187 Expect(process.Wait()).To(Equal(0)) 188 }) 189 }) 190 })