github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/applicationproxy/serviceregistry/serviceregistry_test.go (about)

     1  // +build !windows
     2  
     3  package serviceregistry
     4  
     5  import (
     6  	"net"
     7  	"testing"
     8  	"time"
     9  
    10  	. "github.com/smartystreets/goconvey/convey"
    11  	triremecommon "go.aporeto.io/enforcerd/trireme-lib/common"
    12  	"go.aporeto.io/enforcerd/trireme-lib/controller/internal/enforcer/applicationproxy/common"
    13  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/pucontext"
    14  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/secrets"
    15  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/secrets/testhelper"
    16  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    17  	"go.aporeto.io/enforcerd/trireme-lib/utils/portspec"
    18  )
    19  
    20  func newBaseApplicationServices(exposedPortValue, publicPortValue, privatePortValue, dependentPortValue uint16) (*policy.ApplicationService, *policy.ApplicationService) {
    21  
    22  	exposed1 := "10.1.1.0/24"
    23  	exposed2 := "20.1.1.0/24"
    24  	public1 := "30.1.1.0/24"
    25  	public2 := "40.1.1.0/24"
    26  	dependent1 := "50.1.1.0/24"
    27  	dependent2 := "60.1.1.0/24"
    28  
    29  	exposedPort, err := portspec.NewPortSpec(exposedPortValue, exposedPortValue, nil)
    30  	So(err, ShouldBeNil)
    31  	publicPort, err := portspec.NewPortSpec(publicPortValue, publicPortValue, nil)
    32  	So(err, ShouldBeNil)
    33  	privatePort, err := portspec.NewPortSpec(privatePortValue, privatePortValue, nil)
    34  	So(err, ShouldBeNil)
    35  	dependentPort, err := portspec.NewPortSpec(dependentPortValue, dependentPortValue, nil)
    36  	So(err, ShouldBeNil)
    37  
    38  	return &policy.ApplicationService{
    39  			ID: "policyExposed",
    40  			NetworkInfo: &triremecommon.Service{
    41  				Ports:     exposedPort,
    42  				Protocol:  6,
    43  				Addresses: map[string]struct{}{exposed1: struct{}{}, exposed2: struct{}{}},
    44  			},
    45  			PublicNetworkInfo: &triremecommon.Service{
    46  				Ports:     publicPort,
    47  				Protocol:  6,
    48  				Addresses: map[string]struct{}{public1: struct{}{}},
    49  			},
    50  			PrivateNetworkInfo: &triremecommon.Service{
    51  				Ports:     privatePort,
    52  				Protocol:  6,
    53  				Addresses: map[string]struct{}{},
    54  			},
    55  			Type:                 policy.ServiceHTTP,
    56  			PublicServiceTLSType: policy.ServiceTLSTypeAporeto,
    57  		},
    58  		&policy.ApplicationService{
    59  			ID: "policyDepend",
    60  			NetworkInfo: &triremecommon.Service{
    61  				Ports:    dependentPort,
    62  				Protocol: 6,
    63  				FQDNs:    []string{"www.google.com"},
    64  				Addresses: map[string]struct{}{
    65  					dependent1: struct{}{},
    66  					dependent2: struct{}{},
    67  				},
    68  			},
    69  			PublicNetworkInfo: &triremecommon.Service{
    70  				Ports:     publicPort,
    71  				Protocol:  6,
    72  				Addresses: map[string]struct{}{public2: struct{}{}},
    73  			},
    74  			PrivateNetworkInfo: &triremecommon.Service{
    75  				Ports:     privatePort,
    76  				Protocol:  6,
    77  				Addresses: map[string]struct{}{},
    78  			},
    79  			Type:                 policy.ServiceHTTP,
    80  			PublicServiceTLSType: policy.ServiceTLSTypeAporeto,
    81  		}
    82  }
    83  
    84  func newPU(name string, exposedPort, publicPort, privatePort, dependentPort uint16, doubleExposed, doubleDependent bool) (*policy.PUInfo, *pucontext.PUContext, secrets.Secrets) {
    85  	exposed, dependent := newBaseApplicationServices(exposedPort, publicPort, privatePort, dependentPort)
    86  
    87  	exposedServices := policy.ApplicationServicesList{exposed}
    88  	if doubleExposed {
    89  		exposedServices = append(exposedServices, exposed)
    90  	}
    91  
    92  	dependentServices := policy.ApplicationServicesList{dependent}
    93  	if doubleDependent {
    94  		dependentServices = append(dependentServices, dependent)
    95  	}
    96  	plc := policy.NewPUPolicy(
    97  		name+"-policyid1",
    98  		"/ns1",
    99  		policy.Police,
   100  		policy.IPRuleList{},
   101  		policy.IPRuleList{},
   102  		policy.DNSRuleList{},
   103  		policy.TagSelectorList{},
   104  		policy.TagSelectorList{},
   105  		policy.NewTagStore(),
   106  		policy.NewTagStoreFromSlice([]string{"app=web", "type=aporeto"}),
   107  		nil,
   108  		nil,
   109  		0,
   110  		0,
   111  		exposedServices,
   112  		dependentServices,
   113  		[]string{},
   114  		policy.EnforcerMapping,
   115  		policy.Reject|policy.Log,
   116  		policy.Reject|policy.Log,
   117  	)
   118  
   119  	puInfo := policy.NewPUInfo(name, "/ns1", triremecommon.ContainerPU)
   120  	puInfo.Policy = plc
   121  	pctx, err := pucontext.NewPU(name, puInfo, nil, time.Second*1000)
   122  	So(err, ShouldBeNil)
   123  	_, s, _ := testhelper.NewTestCompactPKISecrets()
   124  	return puInfo, pctx, s
   125  }
   126  
   127  func TestRegister(t *testing.T) {
   128  	Convey("Given a new registry", t, func() {
   129  		r := Instance()
   130  		Convey("When I register a new PU with no services", func() {
   131  			puInfo, pctx, s := newPU("pu1", 8080, 443, 80, 8080, false, false)
   132  			sctx, err := r.Register("pu1", puInfo, pctx, s)
   133  			Convey("The data structures should be correct and I should be able to retrieve the service", func() {
   134  				So(err, ShouldBeNil)
   135  				So(sctx, ShouldNotBeNil)
   136  				So(sctx.PU, ShouldResemble, puInfo)
   137  				So(sctx.PUContext, ShouldResemble, pctx)
   138  				So(sctx.dependentServiceCache, ShouldNotBeNil)
   139  			})
   140  			Convey("And I should be able to retrieve the services using the three provided methods", func() {
   141  				serviceContext, rerr := r.RetrieveServiceByID("pu1")
   142  				So(rerr, ShouldBeNil)
   143  				So(serviceContext, ShouldNotBeNil)
   144  				So(serviceContext, ShouldResemble, sctx)
   145  
   146  				portContext, perr := r.RetrieveExposedServiceContext(net.ParseIP("10.1.1.1").To4(), 80, "")
   147  				So(perr, ShouldBeNil)
   148  				So(portContext, ShouldNotBeNil)
   149  				So(portContext.ID, ShouldResemble, "pu1")
   150  				So(portContext.TargetPort, ShouldEqual, 80)
   151  				So(portContext.Service, ShouldResemble, puInfo.Policy.ExposedServices()[0])
   152  				So(portContext.Type, ShouldEqual, common.HTTPSNetwork)
   153  
   154  			})
   155  			Convey("Update the dependent services by fqdn, and it should be able to find", func() {
   156  				for _, dependentService := range pctx.DependentServices("www.google.com") {
   157  					dependentService.NetworkInfo.Addresses["4.4.4.4/32"] = struct{}{}
   158  				}
   159  
   160  				err := r.UpdateDependentServicesByID("pu1")
   161  				So(err, ShouldBeNil)
   162  
   163  				_, _, err = r.RetrieveDependentServiceDataByIDAndNetwork("pu1", net.ParseIP("4.4.4.4").To4(), 8080, "")
   164  				So(err, ShouldBeNil)
   165  			})
   166  			Convey("But I should get errors for non existing ports or services", func() {
   167  				serviceContext, rerr := r.RetrieveServiceByID("badpu")
   168  				So(rerr, ShouldNotBeNil)
   169  				So(serviceContext, ShouldBeNil)
   170  
   171  				portContext, perr := r.RetrieveExposedServiceContext(net.ParseIP("100.1.1.1").To4(), 100, "")
   172  				So(perr, ShouldNotBeNil)
   173  				So(portContext, ShouldBeNil)
   174  			})
   175  
   176  			Convey("When I register a second service with no overlaps", func() {
   177  				puInfo, pctx, s := newPU("pu2", 8000, 4443, 8080, 10000, false, false)
   178  				sctx, err := r.Register("pu2", puInfo, pctx, s)
   179  				So(err, ShouldBeNil)
   180  				So(sctx, ShouldNotBeNil)
   181  
   182  				Convey("And I should be able to retrieve the updated services using the three provided methods", func() {
   183  					serviceContext, rerr := r.RetrieveServiceByID("pu2")
   184  					So(rerr, ShouldBeNil)
   185  					So(serviceContext, ShouldNotBeNil)
   186  					So(serviceContext, ShouldResemble, sctx)
   187  
   188  					portContext, perr := r.RetrieveExposedServiceContext(net.ParseIP("10.1.1.1").To4(), 8080, "")
   189  					So(perr, ShouldBeNil)
   190  					So(portContext, ShouldNotBeNil)
   191  					So(portContext.ID, ShouldResemble, "pu2")
   192  					So(portContext.TargetPort, ShouldEqual, 8080)
   193  					So(portContext.Service, ShouldResemble, puInfo.Policy.ExposedServices()[0])
   194  					So(portContext.Type, ShouldEqual, common.HTTPSNetwork)
   195  				})
   196  			})
   197  
   198  			Convey("When I register a second service with port overlaps, I should get errors", func() {
   199  				// exposedService overlap
   200  				puInfo, pctx, s := newPU("pu2", 8080, 4443, 8080, 10000, true, false)
   201  				sctx, err := r.Register("pu2", puInfo, pctx, s)
   202  				So(err, ShouldNotBeNil)
   203  				So(sctx, ShouldBeNil)
   204  
   205  				// dependentService overlap
   206  				puInfo, pctx, s = newPU("pu2", 8080, 4443, 8080, 10000, false, true)
   207  				sctx, err = r.Register("pu2", puInfo, pctx, s)
   208  				So(err, ShouldNotBeNil)
   209  				So(sctx, ShouldBeNil)
   210  
   211  				// both overlaps
   212  				puInfo, pctx, s = newPU("pu2", 8080, 4443, 8080, 10000, true, true)
   213  				sctx, err = r.Register("pu2", puInfo, pctx, s)
   214  				So(err, ShouldNotBeNil)
   215  				So(sctx, ShouldBeNil)
   216  
   217  			})
   218  
   219  			Convey("When I re-register the service with updates on the ports", func() {
   220  				puInfo, pctx, s := newPU("pu1", 8000, 4443, 8080, 10000, false, false)
   221  				sctx, err := r.Register("pu1", puInfo, pctx, s)
   222  				So(err, ShouldBeNil)
   223  				So(sctx, ShouldNotBeNil)
   224  
   225  				Convey("And I should be able to retrieve the updated services using the three provided methods", func() {
   226  					serviceContext, rerr := r.RetrieveServiceByID("pu1")
   227  					So(rerr, ShouldBeNil)
   228  					So(serviceContext, ShouldNotBeNil)
   229  					So(serviceContext, ShouldResemble, sctx)
   230  
   231  					portContext, perr := r.RetrieveExposedServiceContext(net.ParseIP("10.1.1.1").To4(), 8080, "")
   232  					So(perr, ShouldBeNil)
   233  					So(portContext, ShouldNotBeNil)
   234  					So(portContext.ID, ShouldResemble, "pu1")
   235  					So(portContext.TargetPort, ShouldEqual, 8080)
   236  					So(portContext.Service, ShouldResemble, puInfo.Policy.ExposedServices()[0])
   237  					So(portContext.Type, ShouldEqual, common.HTTPSNetwork)
   238  				})
   239  			})
   240  
   241  			Convey("When I unregister the service, it should be deleted", func() {
   242  				uerr := r.Unregister("pu1")
   243  				So(uerr, ShouldBeNil)
   244  				retrievedContext, rerr := r.RetrieveServiceByID("pu1")
   245  				So(rerr, ShouldNotBeNil)
   246  				So(retrievedContext, ShouldBeNil)
   247  				portContext, perr := r.RetrieveExposedServiceContext(net.ParseIP("10.1.1.1").To4(), 80, "")
   248  				So(perr, ShouldNotBeNil)
   249  				So(portContext, ShouldBeNil)
   250  			})
   251  		})
   252  	})
   253  }
   254  
   255  func TestServiceTypeToNetworkListenerType(t *testing.T) {
   256  	Convey("When I convert a network HTTP service it should be HTTPNetwork", t, func() {
   257  		t := serviceTypeToNetworkListenerType(policy.ServiceHTTP, true)
   258  		So(t, ShouldEqual, common.HTTPNetwork)
   259  	})
   260  	Convey("When I convert a network HTTPS service it should be HTTPSNetwork", t, func() {
   261  		t := serviceTypeToNetworkListenerType(policy.ServiceHTTP, false)
   262  		So(t, ShouldEqual, common.HTTPSNetwork)
   263  	})
   264  	Convey("When I convert a TCP service it should be TCPNetwork", t, func() {
   265  		t := serviceTypeToNetworkListenerType(policy.ServiceTCP, false)
   266  		So(t, ShouldEqual, common.TCPNetwork)
   267  	})
   268  }
   269  
   270  func TestServiceTypeToApplicationListenerType(t *testing.T) {
   271  	Convey("When I convert an application HTTP service it should be HTTPApplication", t, func() {
   272  		t := serviceTypeToApplicationListenerType(policy.ServiceHTTP)
   273  		So(t, ShouldEqual, common.HTTPApplication)
   274  	})
   275  	Convey("When I convert an application TCP service it should be TCPApplication", t, func() {
   276  		t := serviceTypeToApplicationListenerType(policy.ServiceTCP)
   277  		So(t, ShouldEqual, common.TCPApplication)
   278  	})
   279  }