github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/acls/aclcache_test.go (about) 1 // +build !windows 2 3 package acls 4 5 import ( 6 "net" 7 "testing" 8 9 . "github.com/smartystreets/goconvey/convey" 10 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/packet" 12 "go.aporeto.io/enforcerd/trireme-lib/policy" 13 ) 14 15 var catchAllPolicy = &policy.FlowPolicy{Action: policy.Reject | policy.Log, PolicyID: "default", ServiceID: "default"} 16 17 func TestEmptyACLCacheLookup(t *testing.T) { 18 19 Convey("Given an empty ACL Cache", t, func() { 20 c := NewACLCache() 21 Convey("When I lookup for a matching address but failed port, I should get reject", func() { 22 ip := net.ParseIP("192.168.100.1") 23 port := uint16(600) 24 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 25 So(err, ShouldNotBeNil) 26 So(a.Action&policy.Reject, ShouldEqual, policy.Reject) 27 So(a.PolicyID, ShouldEqual, "default") 28 So(p.Action&policy.Reject, ShouldEqual, policy.Reject) 29 So(p.ServiceID, ShouldEqual, "default") 30 }) 31 32 Convey("When I lookup for a matching address but failed port, I should get accept", func() { 33 ip := net.ParseIP("192.168.100.1") 34 port := uint16(600) 35 defaultFlowPolcy := &policy.FlowPolicy{Action: policy.Accept | policy.Log, PolicyID: "default", ServiceID: "default"} 36 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, defaultFlowPolcy) 37 So(err, ShouldBeNil) 38 So(a.Action&policy.Accept, ShouldEqual, policy.Accept) 39 So(a.PolicyID, ShouldEqual, "default") 40 So(p.Action&policy.Accept, ShouldEqual, policy.Accept) 41 So(p.ServiceID, ShouldEqual, "default") 42 }) 43 }) 44 } 45 46 func TestRejectPrioritizedOverAcceptCacheLookup(t *testing.T) { 47 48 rules = policy.IPRuleList{ 49 policy.IPRule{ 50 Addresses: []string{"172.0.0.0/8"}, 51 Ports: []string{"1"}, 52 Protocols: []string{constants.TCPProtoNum}, 53 Policy: &policy.FlowPolicy{ 54 Action: policy.Accept, 55 PolicyID: "tcp172/8"}, 56 }, 57 policy.IPRule{ 58 Addresses: []string{"0.0.0.0/0"}, 59 Ports: []string{"1"}, 60 Protocols: []string{constants.TCPProtoNum}, 61 Policy: &policy.FlowPolicy{ 62 Action: policy.Reject, 63 PolicyID: "catchAllDrop"}, 64 }, 65 } 66 67 Convey("Given an ACL Cache with accept and reject rules", t, func() { 68 c := NewACLCache() 69 So(c, ShouldNotBeNil) 70 err := c.AddRuleList(rules) 71 So(err, ShouldBeNil) 72 73 Convey("When I lookup for a matching address to both accept and reject rule, I should get reject", func() { 74 ip := net.ParseIP("172.1.1.1") 75 port := uint16(1) 76 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 77 So(err, ShouldBeNil) 78 So(a.Action, ShouldEqual, policy.Reject) 79 So(a.PolicyID, ShouldEqual, "catchAllDrop") 80 So(p.Action, ShouldEqual, policy.Reject) 81 So(p.PolicyID, ShouldEqual, "catchAllDrop") 82 }) 83 }) 84 } 85 86 func TestEmptyACLWithObserveContinueCacheLookup(t *testing.T) { 87 88 rules = policy.IPRuleList{ 89 policy.IPRule{ 90 Addresses: []string{"0.0.0.0/0"}, 91 Ports: []string{"1"}, 92 Protocols: []string{constants.TCPProtoNum}, 93 Policy: &policy.FlowPolicy{ 94 Action: policy.Accept, 95 ObserveAction: policy.ObserveContinue, 96 PolicyID: "ObserveAcceptContinue"}, 97 }, 98 } 99 100 Convey("Given an empty ACL Cache", t, func() { 101 c := NewACLCache() 102 So(c, ShouldNotBeNil) 103 err := c.AddRuleList(rules) 104 So(err, ShouldBeNil) 105 106 Convey("When I lookup for a matching address, I should get accept", func() { 107 ip := net.ParseIP("192.168.100.1") 108 port := uint16(1) 109 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 110 So(err, ShouldNotBeNil) 111 So(a.Action, ShouldEqual, policy.Accept) 112 So(a.PolicyID, ShouldEqual, "ObserveAcceptContinue") 113 So(p.Action&policy.Reject, ShouldEqual, policy.Reject) 114 So(p.PolicyID, ShouldEqual, "default") 115 }) 116 }) 117 } 118 119 func TestEmptyACLWithObserveApplyCacheLookup(t *testing.T) { 120 121 rules = policy.IPRuleList{ 122 policy.IPRule{ 123 Addresses: []string{"0.0.0.0/0"}, 124 Ports: []string{"1"}, 125 Protocols: []string{constants.TCPProtoNum}, 126 Policy: &policy.FlowPolicy{ 127 Action: policy.Accept, 128 ObserveAction: policy.ObserveApply, 129 PolicyID: "observeAcceptApply"}, 130 }, 131 } 132 133 Convey("Given an empty ACL Cache", t, func() { 134 c := NewACLCache() 135 So(c, ShouldNotBeNil) 136 err := c.AddRuleList(rules) 137 So(err, ShouldBeNil) 138 139 Convey("When I lookup for a matching address, I should get accept", func() { 140 ip := net.ParseIP("192.168.100.1") 141 port := uint16(1) 142 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 143 So(err, ShouldBeNil) 144 So(a.Action, ShouldEqual, policy.Accept) 145 So(a.PolicyID, ShouldEqual, "observeAcceptApply") 146 So(p.Action, ShouldEqual, policy.Accept) 147 So(p.PolicyID, ShouldEqual, "observeAcceptApply") 148 }) 149 }) 150 } 151 152 func TestObserveContinueApplyCacheLookup(t *testing.T) { 153 154 rules = policy.IPRuleList{ 155 policy.IPRule{ 156 Addresses: []string{"172.1.0.0/16"}, 157 Ports: []string{"1"}, 158 Protocols: []string{constants.TCPProtoNum}, 159 Policy: &policy.FlowPolicy{ 160 Action: policy.Reject, 161 ObserveAction: policy.ObserveContinue, 162 PolicyID: "observeRejectContinue-172.1/16"}, 163 }, 164 policy.IPRule{ 165 Addresses: []string{"172.0.0.0/8"}, 166 Ports: []string{"1"}, 167 Protocols: []string{constants.TCPProtoNum}, 168 Policy: &policy.FlowPolicy{ 169 Action: policy.Accept, 170 PolicyID: "tcp172/8"}, 171 }, 172 policy.IPRule{ 173 Addresses: []string{"172.0.0.0/8"}, 174 Ports: []string{"1"}, 175 Protocols: []string{constants.TCPProtoNum}, 176 Policy: &policy.FlowPolicy{ 177 Action: policy.Accept, 178 ObserveAction: policy.ObserveApply, 179 PolicyID: "observeRejectApply"}, 180 }, 181 policy.IPRule{ 182 Addresses: []string{"172.0.0.0/8"}, 183 Ports: []string{"1"}, 184 Protocols: []string{constants.TCPProtoNum}, 185 Policy: &policy.FlowPolicy{ 186 Action: policy.Reject, 187 ObserveAction: policy.ObserveContinue, 188 PolicyID: "observeRejectContinue"}, 189 }, 190 } 191 192 Convey("Given an ACL Cache with accept observe-apply and observe-continue rules for same prefix", t, func() { 193 c := NewACLCache() 194 So(c, ShouldNotBeNil) 195 err := c.AddRuleList(rules) 196 So(err, ShouldBeNil) 197 198 Convey("When I lookup for a matching address to /16, I should get report reject and packet accept and ignore observe-apply rule", func() { 199 ip := net.ParseIP("172.1.1.1") 200 port := uint16(1) 201 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 202 So(err, ShouldBeNil) 203 So(a.Action, ShouldEqual, policy.Reject) 204 So(a.PolicyID, ShouldEqual, "observeRejectContinue-172.1/16") 205 // So(p.Action, ShouldEqual, policy.Accept) 206 So(p.PolicyID, ShouldEqual, "tcp172/8") 207 }) 208 209 Convey("When I lookup for a matching address to /8, I should get report reject and packet accept and ignore observe-apply rule", func() { 210 ip := net.ParseIP("172.2.1.1") 211 port := uint16(1) 212 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 213 So(err, ShouldBeNil) 214 So(a.Action, ShouldEqual, policy.Reject) 215 So(a.PolicyID, ShouldEqual, "observeRejectContinue") 216 So(p.Action, ShouldEqual, policy.Accept) 217 So(p.PolicyID, ShouldEqual, "tcp172/8") 218 }) 219 }) 220 } 221 222 func TestAcceptWithNomatchCacheLookup(t *testing.T) { 223 224 rules = policy.IPRuleList{ 225 policy.IPRule{ 226 Addresses: []string{"0.0.0.0/1", "!10.10.10.0/24", "128.0.0.0/1", "!10.0.0.0/8", "10.10.0.0/16"}, 227 Ports: []string{"0:65535"}, 228 Protocols: []string{constants.TCPProtoNum}, 229 Policy: &policy.FlowPolicy{ 230 Action: policy.Accept, 231 }, 232 }, 233 } 234 235 Convey("Given an ACL Cache with accept policy with some nomatch addresses", t, func() { 236 c := NewACLCache() 237 So(c, ShouldNotBeNil) 238 err := c.AddRuleList(rules) 239 So(err, ShouldBeNil) 240 241 Convey("When I lookup address within nomatch outer but also within match inner, I should get accept", func() { 242 ip := net.ParseIP("10.10.2.100") 243 port := uint16(443) 244 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 245 So(err, ShouldBeNil) 246 So(a.Action, ShouldEqual, policy.Accept) 247 So(p.Action, ShouldEqual, policy.Accept) 248 }) 249 250 Convey("When I lookup address within nomatch, I should get no match", func() { 251 ip := net.ParseIP("10.10.10.100") 252 port := uint16(443) 253 _, _, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 254 So(err, ShouldNotBeNil) 255 }) 256 257 Convey("When I lookup address within nomatch outer and not also within match inner, I should get no match", func() { 258 ip := net.ParseIP("10.4.10.100") 259 port := uint16(443) 260 _, _, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 261 So(err, ShouldNotBeNil) 262 }) 263 264 Convey("When I lookup address within match outer and not also within match inner, I should get accept", func() { 265 ip := net.ParseIP("192.168.10.100") 266 port := uint16(443) 267 a, p, err := c.GetMatchingAction(ip.To4(), port, packet.IPProtocolTCP, catchAllPolicy) 268 So(err, ShouldBeNil) 269 So(a.Action, ShouldEqual, policy.Accept) 270 So(p.Action, ShouldEqual, policy.Accept) 271 }) 272 }) 273 } 274 275 func TestRemoveRules(t *testing.T) { 276 277 Convey("Given an ACL Cache with some rules", t, func() { 278 ip := net.ParseIP("172.1.0.0") 279 So(ip, ShouldNotBeNil) 280 c := NewACLCache() 281 So(c, ShouldNotBeNil) 282 err := c.AddRuleList(policy.IPRuleList{ 283 policy.IPRule{ 284 Addresses: []string{"172.1.0.0/16"}, 285 Ports: []string{"1"}, 286 Protocols: []string{constants.TCPProtoNum}, 287 Policy: &policy.FlowPolicy{ 288 Action: policy.Reject, 289 PolicyID: "reject", 290 }, 291 }, 292 policy.IPRule{ 293 Addresses: []string{"172.1.0.0/16"}, 294 Ports: []string{"1"}, 295 Protocols: []string{constants.TCPProtoNum}, 296 Policy: &policy.FlowPolicy{ 297 ObserveAction: policy.ObserveApply, 298 PolicyID: "observeApply", 299 }, 300 }, 301 policy.IPRule{ 302 Addresses: []string{"172.1.0.0/16"}, 303 Ports: []string{"1"}, 304 Protocols: []string{constants.TCPProtoNum}, 305 Policy: &policy.FlowPolicy{ 306 Action: policy.Accept, 307 PolicyID: "accept", 308 }, 309 }, 310 }) 311 So(err, ShouldBeNil) 312 val, ok := c.reject.tcpCache.Get(ip, 16) 313 So(ok, ShouldBeTrue) 314 So(val.(portActionList), ShouldNotBeEmpty) 315 val, ok = c.observe.tcpCache.Get(ip, 16) 316 So(ok, ShouldBeTrue) 317 So(val.(portActionList), ShouldNotBeEmpty) 318 val, ok = c.accept.tcpCache.Get(ip, 16) 319 So(ok, ShouldBeTrue) 320 So(val.(portActionList), ShouldNotBeEmpty) 321 322 Convey("Then I should error if I pass unparseable rules", func() { 323 err := c.RemoveRulesForAddress( 324 &Address{IP: ip, Mask: 16, NoMatch: false}, 325 constants.TCPProtoNum, 326 []string{"invalid"}, 327 &policy.FlowPolicy{ 328 Action: policy.Reject, 329 PolicyID: "reject", 330 }, 331 ) 332 So(err, ShouldNotBeNil) 333 }) 334 335 Convey("Then I should be able to remove the rules", func() { 336 err := c.RemoveRulesForAddress( 337 &Address{IP: ip, Mask: 16, NoMatch: false}, 338 constants.TCPProtoNum, 339 []string{"1"}, 340 &policy.FlowPolicy{ 341 Action: policy.Reject, 342 PolicyID: "reject", 343 }, 344 ) 345 So(err, ShouldBeNil) 346 err = c.RemoveRulesForAddress( 347 &Address{IP: ip, Mask: 16, NoMatch: false}, 348 constants.TCPProtoNum, 349 []string{"1"}, 350 &policy.FlowPolicy{ 351 ObserveAction: policy.ObserveApply, 352 PolicyID: "observeApply", 353 }, 354 ) 355 So(err, ShouldBeNil) 356 err = c.RemoveRulesForAddress( 357 &Address{IP: ip, Mask: 16, NoMatch: false}, 358 constants.TCPProtoNum, 359 []string{"1"}, 360 &policy.FlowPolicy{ 361 Action: policy.Accept, 362 PolicyID: "accept", 363 }, 364 ) 365 So(err, ShouldBeNil) 366 val, ok := c.reject.tcpCache.Get(ip, 16) 367 So(ok, ShouldBeTrue) 368 So(val.(portActionList), ShouldBeEmpty) 369 val, ok = c.observe.tcpCache.Get(ip, 16) 370 So(ok, ShouldBeTrue) 371 So(val.(portActionList), ShouldBeEmpty) 372 val, ok = c.accept.tcpCache.Get(ip, 16) 373 So(ok, ShouldBeTrue) 374 So(val.(portActionList), ShouldBeEmpty) 375 }) 376 377 }) 378 }