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  })