github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/lookup/lookup_test.go (about) 1 // +build !windows 2 3 package lookup 4 5 import ( 6 "testing" 7 8 . "github.com/smartystreets/goconvey/convey" 9 "go.aporeto.io/enforcerd/trireme-lib/policy" 10 ) 11 12 var ( 13 appEqWeb = policy.KeyValueOperator{ 14 Key: "app", 15 Value: []string{"web"}, 16 Operator: policy.Equal, 17 ID: "1", 18 } 19 envEqDemo = policy.KeyValueOperator{ 20 Key: "env", 21 Value: []string{"demo"}, 22 Operator: policy.Equal, 23 ID: "2", 24 } 25 26 envEqDemoOrQa = policy.KeyValueOperator{ 27 Key: "env", 28 Value: []string{"demo", "qa"}, 29 Operator: policy.Equal, 30 ID: "3", 31 } 32 33 dcKeyExists = policy.KeyValueOperator{ 34 Key: "dc", 35 Operator: policy.KeyExists, 36 } 37 38 langNotJava = policy.KeyValueOperator{ 39 Key: "lang", 40 Value: []string{"java"}, 41 Operator: policy.NotEqual, 42 } 43 44 envNotDemoOrQA = policy.KeyValueOperator{ 45 Key: "env", 46 Value: []string{"demo", "qa"}, 47 Operator: policy.NotEqual, 48 } 49 50 envKeyNotExists = policy.KeyValueOperator{ 51 Key: "env", 52 Operator: policy.KeyNotExists, 53 } 54 55 vulnerKey = policy.KeyValueOperator{ 56 Key: "vulnerability", 57 Value: []string{"high"}, 58 Operator: policy.Equal, 59 } 60 61 vulnerLowKey = policy.KeyValueOperator{ 62 Key: "vulnerability", 63 Value: []string{"low"}, 64 Operator: policy.Equal, 65 } 66 67 namespaceKey = policy.KeyValueOperator{ 68 Key: "namespace", 69 Value: []string{"/a/b/*"}, 70 Operator: policy.Equal, 71 } 72 73 appEqWebAndenvEqDemo = policy.TagSelector{ 74 Clause: []policy.KeyValueOperator{appEqWeb, envEqDemo}, 75 Policy: &policy.FlowPolicy{Action: policy.Accept}, 76 } 77 78 appEqWebAndEnvEqDemoOrQa = policy.TagSelector{ 79 Clause: []policy.KeyValueOperator{appEqWeb, envEqDemoOrQa}, 80 Policy: &policy.FlowPolicy{Action: policy.Accept}, 81 } 82 83 dcTagExists = policy.TagSelector{ 84 Clause: []policy.KeyValueOperator{dcKeyExists}, 85 Policy: &policy.FlowPolicy{Action: policy.Accept}, 86 } 87 88 policylangNotJava = policy.TagSelector{ 89 Clause: []policy.KeyValueOperator{langNotJava}, 90 Policy: &policy.FlowPolicy{Action: policy.Accept}, 91 } 92 93 appEqWebAndenvNotDemoOrQA = policy.TagSelector{ 94 Clause: []policy.KeyValueOperator{appEqWeb, envNotDemoOrQA}, 95 Policy: &policy.FlowPolicy{Action: policy.Accept}, 96 } 97 98 envKeyNotExistsAndAppEqWeb = policy.TagSelector{ 99 Clause: []policy.KeyValueOperator{envKeyNotExists, appEqWeb}, 100 Policy: &policy.FlowPolicy{Action: policy.Accept}, 101 } 102 103 vulnTagPolicy = policy.TagSelector{ 104 Clause: []policy.KeyValueOperator{vulnerKey}, 105 Policy: &policy.FlowPolicy{Action: policy.Accept}, 106 } 107 108 policyNamespace = policy.TagSelector{ 109 Clause: []policy.KeyValueOperator{namespaceKey, vulnerLowKey}, 110 Policy: &policy.FlowPolicy{Action: policy.Accept}, 111 } 112 113 domainParent = policy.KeyValueOperator{ 114 Key: "domain", 115 Value: []string{"com.example.*", "com.*", "com.longexample.*", "com.ex.*"}, 116 Operator: policy.Equal, 117 } 118 119 domainFull = policy.KeyValueOperator{ 120 Key: "domain", 121 Value: []string{"com.example.web"}, 122 Operator: policy.Equal, 123 } 124 125 policyDomainParent = policy.TagSelector{ 126 Clause: []policy.KeyValueOperator{domainParent}, 127 Policy: &policy.FlowPolicy{Action: policy.Accept}, 128 } 129 130 policyDomainFull = policy.TagSelector{ 131 Clause: []policy.KeyValueOperator{domainFull}, 132 Policy: &policy.FlowPolicy{Action: policy.Accept}, 133 } 134 135 policyEnvDoesNotExist = policy.TagSelector{ 136 Clause: []policy.KeyValueOperator{envKeyNotExists}, 137 Policy: &policy.FlowPolicy{Action: policy.Accept}, 138 } 139 ) 140 141 // TestConstructorNewPolicyDB tests the NewPolicyDB constructor 142 func TestConstructorNewPolicyDB(t *testing.T) { 143 Convey("Given that I instantiate a new policy DB, I should not get nil", t, func() { 144 145 p := &PolicyDB{} 146 147 policyDB := NewPolicyDB() 148 149 So(policyDB, ShouldHaveSameTypeAs, p) 150 }) 151 } 152 153 // TestFuncAddPolicy tests the add policy function 154 func TestFuncAddPolicy(t *testing.T) { 155 156 Convey("Given an empty policy DB", t, func() { 157 policyDB := NewPolicyDB() 158 159 Convey("When I add a single policy it should be associated with all the tags", func() { 160 index := policyDB.AddPolicy(appEqWebAndenvEqDemo) 161 162 So(policyDB.numberOfPolicies, ShouldEqual, 1) 163 So(index, ShouldEqual, 1) 164 for _, c := range appEqWebAndenvEqDemo.Clause { 165 So(policyDB.equalMapTable[c.Key][c.Value[0]], ShouldNotBeNil) 166 So(policyDB.equalMapTable[c.Key][c.Value[0]][0].index, ShouldEqual, index) 167 So(policyDB.equalPrefixes[c.Key], ShouldNotContain, c.Key) 168 } 169 }) 170 171 Convey("When I add a policy with the not equal operator, it should be added to the notEqual db", func() { 172 index := policyDB.AddPolicy(policylangNotJava) 173 174 So(policyDB.numberOfPolicies, ShouldEqual, 1) 175 So(index, ShouldEqual, 1) 176 for _, c := range policylangNotJava.Clause { 177 So(policyDB.notEqualMapTable[c.Key][c.Value[0]], ShouldNotBeNil) 178 So(policyDB.notEqualMapTable[c.Key][c.Value[0]][0].index, ShouldEqual, index) 179 So(policyDB.equalPrefixes, ShouldNotContainKey, c.Key) 180 } 181 }) 182 183 Convey("When I add a policy with the KeyExists operator, it should be added as a prefix of 0", func() { 184 index := policyDB.AddPolicy(dcTagExists) 185 186 key := dcTagExists.Clause[0].Key 187 So(policyDB.numberOfPolicies, ShouldEqual, 1) 188 So(index, ShouldEqual, 1) 189 So(policyDB.equalPrefixes, ShouldContainKey, key) 190 So(policyDB.equalPrefixes[key], ShouldContain, 0) 191 So(policyDB.equalMapTable[key], ShouldHaveLength, 1) 192 So(policyDB.equalMapTable[key], ShouldContainKey, "") 193 So(policyDB.equalPrefixes[key], ShouldHaveLength, 1) 194 }) 195 196 Convey("When I add a policy with prefixes, it should be associated with the right prefixes", func() { 197 index := policyDB.AddPolicy(policyDomainParent) 198 199 key := policyDomainParent.Clause[0].Key 200 value0 := policyDomainParent.Clause[0].Value[0] 201 value1 := policyDomainParent.Clause[0].Value[1] 202 value2 := policyDomainParent.Clause[0].Value[2] 203 value3 := policyDomainParent.Clause[0].Value[3] 204 So(policyDB.numberOfPolicies, ShouldEqual, 1) 205 So(index, ShouldEqual, 1) 206 So(policyDB.equalMapTable[key], ShouldHaveLength, 4) 207 So(policyDB.equalMapTable[key], ShouldContainKey, value0[:len(value0)-1]) 208 So(policyDB.equalMapTable[key], ShouldContainKey, value1[:len(value1)-1]) 209 So(policyDB.equalMapTable[key], ShouldContainKey, value2[:len(value2)-1]) 210 So(policyDB.equalMapTable[key], ShouldContainKey, value3[:len(value3)-1]) 211 So(policyDB.equalPrefixes[key], ShouldHaveLength, 4) 212 So(policyDB.equalPrefixes[key], ShouldContain, len(value0)-1) 213 So(policyDB.equalPrefixes[key], ShouldContain, len(value1)-1) 214 So(policyDB.equalPrefixes[key], ShouldContain, len(value2)-1) 215 So(policyDB.equalPrefixes[key], ShouldContain, len(value3)-1) 216 }) 217 218 }) 219 } 220 221 // TestFuncSearch tests the search function of the lookup 222 func TestFuncSearch(t *testing.T) { 223 // policy1 : app=web and env=demo 224 // policy2 : lang != java 225 // policy3 : dc=* 226 // policy4: app=web and env IN (demo, qa) 227 // policy5: app=web and env NotIN (demo, qa) 228 // policy6: app=web not env=* 229 // policy7: domain IN ("com.*", "com.example.*") 230 // policy8: domain=com.example.web 231 // policy9: env doesn't exist 232 // policy10: vulnerability=high 233 // policy11: namespace=/a/b/* and vulnerability=low 234 235 Convey("Given an empty policyDB", t, func() { 236 policyDB := NewPolicyDB() 237 Convey("Given that I add two policy rules", func() { 238 index1 := policyDB.AddPolicy(appEqWebAndenvEqDemo) 239 index2 := policyDB.AddPolicy(policylangNotJava) 240 index3 := policyDB.AddPolicy(dcTagExists) 241 index4 := policyDB.AddPolicy(appEqWebAndEnvEqDemoOrQa) 242 index5 := policyDB.AddPolicy(appEqWebAndenvNotDemoOrQA) 243 index6 := policyDB.AddPolicy(envKeyNotExistsAndAppEqWeb) 244 index7 := policyDB.AddPolicy(policyDomainParent) 245 index8 := policyDB.AddPolicy(policyDomainFull) 246 index9 := policyDB.AddPolicy(policyEnvDoesNotExist) 247 index10 := policyDB.AddPolicy(vulnTagPolicy) 248 index11 := policyDB.AddPolicy(policyNamespace) 249 250 So(index1, ShouldEqual, 1) 251 So(index2, ShouldEqual, 2) 252 So(index3, ShouldEqual, 3) 253 So(index4, ShouldEqual, 4) 254 So(index5, ShouldEqual, 5) 255 So(index6, ShouldEqual, 6) 256 So(index9, ShouldEqual, 9) 257 258 Convey("The vulnerability tag policy should match", func() { 259 tags := policy.NewTagStore() 260 tags.AppendKeyValue("vulnerability", "high") 261 262 index, action := policyDB.Search(tags) 263 So(index, ShouldEqual, index10) 264 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 265 }) 266 267 Convey("A policy that matches ID should match", func() { 268 tags := policy.NewTagStoreFromSlice([]string{"1"}) 269 index, action := policyDB.Search(tags) 270 So(action, ShouldNotBeNil) 271 So(index, ShouldEqual, index6) 272 }) 273 274 Convey("A policy that matches only the namespace, shoud not match", func() { 275 tags := policy.NewTagStore() 276 tags.AppendKeyValue("namespace", "/a/b/c/d") 277 tags.AppendKeyValue("env", "privatedemo") 278 279 index, action := policyDB.Search(tags) 280 So(action, ShouldBeNil) 281 So(index, ShouldEqual, -1) 282 }) 283 284 Convey("A policy that matches namespace and vulnerability low, shoud match", func() { 285 tags := policy.NewTagStore() 286 tags.AppendKeyValue("namespace", "/a/b/c/d") 287 tags.AppendKeyValue("vulnerability", "low") 288 tags.AppendKeyValue("env", "privatedemo") 289 290 index, action := policyDB.Search(tags) 291 So(action, ShouldNotBeNil) 292 So(index, ShouldEqual, index11) 293 }) 294 295 Convey("Given that I search for a single matching that matches the equal rules, it should return the correct index,", func() { 296 tags := policy.NewTagStore() 297 tags.AppendKeyValue("app", "web") 298 tags.AppendKeyValue("env", "demo") 299 300 index, action := policyDB.Search(tags) 301 So(index, ShouldEqual, index1) 302 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 303 }) 304 305 Convey("Given that I search for a single matching that matches the not equal rules, it should return the right index,", func() { 306 tags := policy.NewTagStore() 307 tags.AppendKeyValue("lang", "go") 308 tags.AppendKeyValue("env", "demo") 309 310 index, action := policyDB.Search(tags) 311 So(index, ShouldEqual, index2) 312 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 313 }) 314 315 Convey("Given that I search for rules that match the KeyExists Policy, it should return the right index ", func() { 316 tags := policy.NewTagStore() 317 tags.AppendKeyValue("dc", "EAST") 318 tags.AppendKeyValue("env", "demo") 319 320 index, action := policyDB.Search(tags) 321 So(index, ShouldEqual, index3) 322 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 323 }) 324 325 Convey("Given that I search for a single matching that matches the Or rules, it should return the right index,", func() { 326 327 tags := policy.NewTagStore() 328 tags.AppendKeyValue("app", "web") 329 tags.AppendKeyValue("env", "qa") 330 331 index, action := policyDB.Search(tags) 332 So(index, ShouldEqual, index4) 333 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 334 }) 335 336 Convey("Given that I search for a single matching that matches the NOT Or rlues, it should return the right index,", func() { 337 tags := policy.NewTagStore() 338 tags.AppendKeyValue("app", "web") 339 tags.AppendKeyValue("env", "prod") 340 341 index, action := policyDB.Search(tags) 342 So(index, ShouldEqual, index5) 343 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 344 }) 345 346 Convey("Given that I search for a single clause that fails in the Not OR operator, it should fail ,", func() { 347 tags := policy.NewTagStore() 348 tags.AppendKeyValue("lang", "java") 349 tags.AppendKeyValue("env", "demo") 350 tags.AppendKeyValue("app", "db") 351 352 index, action := policyDB.Search(tags) 353 So(index, ShouldEqual, -1) 354 So(action, ShouldBeNil) 355 }) 356 357 Convey("Given that I search for rules that do not match, it should return an error ", func() { 358 tags := policy.NewTagStore() 359 tags.AppendKeyValue("tag", "node") 360 tags.AppendKeyValue("env", "node") 361 362 index, action := policyDB.Search(tags) 363 So(index, ShouldEqual, -1) 364 So(action, ShouldBeNil) 365 }) 366 367 Convey("Given that I search for a single that succeeds in the Not Key operator, it should succeed ,", func() { 368 tags := policy.NewTagStore() 369 tags.AppendKeyValue("app", "web") 370 371 index, action := policyDB.Search(tags) 372 So(index, ShouldEqual, index6) 373 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 374 }) 375 376 Convey("Given that I search for a value that matches a prefix", func() { 377 tags := policy.NewTagStore() 378 tags.AppendKeyValue("domain", "com.example.db") 379 index, action := policyDB.Search(tags) 380 So(index, ShouldEqual, index7) 381 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 382 }) 383 384 Convey("Given that I search for a value that matches a complete value ", func() { 385 tags := policy.NewTagStore() 386 tags.AppendKeyValue("domain", "com.example.web") 387 388 index, action := policyDB.Search(tags) 389 So(index, ShouldEqual, index8) 390 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 391 }) 392 393 Convey("Given that I search for a value that matches some of the prefix, it should return err ", func() { 394 tags := policy.NewTagStore() 395 tags.AppendKeyValue("domain", "co") 396 tags.AppendKeyValue("env", "node") 397 398 index, action := policyDB.Search(tags) 399 So(index, ShouldEqual, -1) 400 So(action, ShouldBeNil) 401 }) 402 403 Convey("Given that I search for a value matches only the env not exists policy ", func() { 404 tags := policy.NewTagStore() 405 tags.AppendKeyValue("sometag", "nomatch") 406 407 index, action := policyDB.Search(tags) 408 So(index, ShouldEqual, index9) 409 So(action.(*policy.FlowPolicy).Action, ShouldEqual, policy.Accept) 410 }) 411 412 }) 413 414 }) 415 } 416 417 // TestFuncDumbDB is a mock test for the print function 418 func TestFuncDumpDB(t *testing.T) { 419 Convey("Given an empty policy DB", t, func() { 420 policyDB := NewPolicyDB() 421 422 Convey("Given that I add two policy rules, I should be able to print the db ", func() { 423 index1 := policyDB.AddPolicy(appEqWebAndenvEqDemo) 424 index2 := policyDB.AddPolicy(policylangNotJava) 425 So(index1, ShouldEqual, 1) 426 So(index2, ShouldEqual, 2) 427 428 policyDB.PrintPolicyDB() 429 430 }) 431 }) 432 }