github.com/imran-kn/cilium-fork@v1.6.9/pkg/envoy/server_test.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // +build !privileged_tests 16 17 package envoy 18 19 import ( 20 "github.com/cilium/cilium/pkg/checker" 21 "github.com/cilium/cilium/pkg/identity" 22 "github.com/cilium/cilium/pkg/identity/cache" 23 "github.com/cilium/cilium/pkg/labels" 24 "github.com/cilium/cilium/pkg/policy" 25 "github.com/cilium/cilium/pkg/policy/api" 26 27 "github.com/cilium/proxy/go/cilium/api" 28 envoy_api_v2_core "github.com/cilium/proxy/go/envoy/api/v2/core" 29 envoy_api_v2_route "github.com/cilium/proxy/go/envoy/api/v2/route" 30 . "gopkg.in/check.v1" 31 ) 32 33 type ServerSuite struct{} 34 35 type DummySelectorCacheUser struct{} 36 37 func (d *DummySelectorCacheUser) IdentitySelectionUpdated(selector policy.CachedSelector, selections, added, deleted []identity.NumericIdentity) { 38 } 39 40 var ( 41 _ = Suite(&ServerSuite{}) 42 IPv4Addr = "10.1.1.1" 43 Identity = identity.NumericIdentity(123) 44 ) 45 46 var PortRuleHTTP1 = &api.PortRuleHTTP{ 47 Path: "/foo", 48 Method: "GET", 49 Host: "foo.cilium.io", 50 Headers: []string{"header2 value", "header1"}, 51 } 52 53 var PortRuleHTTP2 = &api.PortRuleHTTP{ 54 Path: "/bar", 55 Method: "PUT", 56 } 57 58 var PortRuleHTTP3 = &api.PortRuleHTTP{ 59 Path: "/bar", 60 Method: "GET", 61 } 62 63 var ExpectedHeaders1 = []*envoy_api_v2_route.HeaderMatcher{ 64 { 65 Name: ":authority", 66 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "foo.cilium.io"}, 67 }, 68 { 69 Name: ":method", 70 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "GET"}, 71 }, 72 { 73 Name: ":path", 74 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "/foo"}, 75 }, 76 { 77 Name: "header1", 78 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_PresentMatch{PresentMatch: true}, 79 }, 80 { 81 Name: "header2", 82 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_ExactMatch{ExactMatch: "value"}, 83 }, 84 } 85 86 var ExpectedHeaders2 = []*envoy_api_v2_route.HeaderMatcher{ 87 { 88 Name: ":method", 89 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "PUT"}, 90 }, 91 { 92 Name: ":path", 93 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "/bar"}, 94 }, 95 } 96 97 var ExpectedHeaders3 = []*envoy_api_v2_route.HeaderMatcher{ 98 { 99 Name: ":method", 100 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "GET"}, 101 }, 102 { 103 Name: ":path", 104 HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_RegexMatch{RegexMatch: "/bar"}, 105 }, 106 } 107 108 var ( 109 dummySelectorCacheUser = &DummySelectorCacheUser{} 110 111 IdentityCache = cache.IdentityCache{ 112 1001: labels.LabelArray{ 113 labels.NewLabel("app", "etcd", labels.LabelSourceK8s), 114 labels.NewLabel("version", "v1", labels.LabelSourceK8s), 115 }, 116 1002: labels.LabelArray{ 117 labels.NewLabel("app", "etcd", labels.LabelSourceK8s), 118 labels.NewLabel("version", "v2", labels.LabelSourceK8s), 119 }, 120 1003: labels.LabelArray{ 121 labels.NewLabel("app", "cassandra", labels.LabelSourceK8s), 122 labels.NewLabel("version", "v1", labels.LabelSourceK8s), 123 }, 124 } 125 126 testSelectorCache = policy.NewSelectorCache(IdentityCache) 127 128 wildcardCachedSelector, _ = testSelectorCache.AddIdentitySelector(dummySelectorCacheUser, api.WildcardEndpointSelector) 129 130 EndpointSelector1 = api.NewESFromLabels( 131 labels.NewLabel("app", "etcd", labels.LabelSourceK8s), 132 ) 133 cachedSelector1, _ = testSelectorCache.AddIdentitySelector(dummySelectorCacheUser, EndpointSelector1) 134 135 // EndpointSelector1 with FromRequires("k8s:version=v2") folded in 136 RequiresV2Selector1 = api.NewESFromLabels( 137 labels.NewLabel("app", "etcd", labels.LabelSourceK8s), 138 labels.NewLabel("version", "v2", labels.LabelSourceK8s), 139 ) 140 cachedRequiresV2Selector1, _ = testSelectorCache.AddIdentitySelector(dummySelectorCacheUser, RequiresV2Selector1) 141 142 EndpointSelector2 = api.NewESFromLabels( 143 labels.NewLabel("version", "v1", labels.LabelSourceK8s), 144 ) 145 cachedSelector2, _ = testSelectorCache.AddIdentitySelector(dummySelectorCacheUser, EndpointSelector2) 146 147 // Wildcard endpoint selector with FromRequires("k8s:version=v2") folded in 148 RequiresV2Selector = api.NewESFromLabels( 149 labels.NewLabel("version", "v2", labels.LabelSourceK8s), 150 ) 151 cachedRequiresV2Selector, _ = testSelectorCache.AddIdentitySelector(dummySelectorCacheUser, RequiresV2Selector) 152 ) 153 154 var L7Rules1 = api.L7Rules{HTTP: []api.PortRuleHTTP{*PortRuleHTTP1, *PortRuleHTTP2}} 155 156 var L7Rules2 = api.L7Rules{HTTP: []api.PortRuleHTTP{*PortRuleHTTP1}} 157 158 var ExpectedPortNetworkPolicyRule1 = &cilium.PortNetworkPolicyRule{ 159 RemotePolicies: []uint64{1001, 1002}, 160 L7: &cilium.PortNetworkPolicyRule_HttpRules{ 161 HttpRules: &cilium.HttpNetworkPolicyRules{ 162 HttpRules: []*cilium.HttpNetworkPolicyRule{ 163 {Headers: ExpectedHeaders2}, 164 {Headers: ExpectedHeaders1}, 165 }, 166 }, 167 }, 168 } 169 170 var ExpectedPortNetworkPolicyRule2 = &cilium.PortNetworkPolicyRule{ 171 RemotePolicies: []uint64{1001, 1003}, 172 L7: &cilium.PortNetworkPolicyRule_HttpRules{ 173 HttpRules: &cilium.HttpNetworkPolicyRules{ 174 HttpRules: []*cilium.HttpNetworkPolicyRule{ 175 {Headers: ExpectedHeaders1}, 176 }, 177 }, 178 }, 179 } 180 181 var ExpectedPortNetworkPolicyRule3 = &cilium.PortNetworkPolicyRule{ 182 RemotePolicies: nil, // Wildcard. Select all. 183 L7: &cilium.PortNetworkPolicyRule_HttpRules{ 184 HttpRules: &cilium.HttpNetworkPolicyRules{ 185 HttpRules: []*cilium.HttpNetworkPolicyRule{ 186 {Headers: ExpectedHeaders2}, 187 {Headers: ExpectedHeaders1}, 188 }, 189 }, 190 }, 191 } 192 193 var ExpectedPortNetworkPolicyRule4RequiresV2 = &cilium.PortNetworkPolicyRule{ 194 RemotePolicies: []uint64{1002}, // Like ExpectedPortNetworkPolicyRule1 but "k8s:version=v2" is required. 195 L7: &cilium.PortNetworkPolicyRule_HttpRules{ 196 HttpRules: &cilium.HttpNetworkPolicyRules{ 197 HttpRules: []*cilium.HttpNetworkPolicyRule{ 198 {Headers: ExpectedHeaders2}, 199 {Headers: ExpectedHeaders1}, 200 }, 201 }, 202 }, 203 } 204 205 var ExpectedPortNetworkPolicyRule5RequiresV2 = &cilium.PortNetworkPolicyRule{ 206 RemotePolicies: []uint64{1002}, // Wildcard, but "k8s:version=v2" required 207 L7: &cilium.PortNetworkPolicyRule_HttpRules{ 208 HttpRules: &cilium.HttpNetworkPolicyRules{ 209 HttpRules: []*cilium.HttpNetworkPolicyRule{ 210 {Headers: ExpectedHeaders2}, 211 {Headers: ExpectedHeaders1}, 212 }, 213 }, 214 }, 215 } 216 217 var ExpectedPortNetworkPolicyRule6 = &cilium.PortNetworkPolicyRule{ 218 RemotePolicies: []uint64{1001, 1002}, 219 } 220 221 var L4PolicyMap1 = map[string]*policy.L4Filter{ 222 "80/TCP": { 223 Port: 80, 224 Protocol: api.ProtoTCP, 225 L7Parser: policy.ParserTypeHTTP, 226 L7RulesPerEp: policy.L7DataMap{ 227 cachedSelector1: L7Rules1, 228 }, 229 }, 230 } 231 232 var L4PolicyMap1RequiresV2 = map[string]*policy.L4Filter{ 233 "80/TCP": { 234 Port: 80, 235 Protocol: api.ProtoTCP, 236 L7Parser: policy.ParserTypeHTTP, 237 L7RulesPerEp: policy.L7DataMap{ 238 cachedRequiresV2Selector1: L7Rules1, 239 }, 240 }, 241 } 242 243 var L4PolicyMap2 = map[string]*policy.L4Filter{ 244 "8080/UDP": { 245 Port: 8080, 246 Protocol: api.ProtoUDP, 247 L7Parser: policy.ParserTypeHTTP, 248 L7RulesPerEp: policy.L7DataMap{ 249 cachedSelector2: L7Rules2, 250 }, 251 }, 252 } 253 254 var L4PolicyMap3 = map[string]*policy.L4Filter{ 255 "80/UDP": { 256 Port: 80, 257 Protocol: api.ProtoTCP, 258 L7Parser: policy.ParserTypeHTTP, 259 L7RulesPerEp: policy.L7DataMap{ 260 wildcardCachedSelector: L7Rules1, 261 }, 262 }, 263 } 264 265 var L4PolicyMap3RequiresV2 = map[string]*policy.L4Filter{ 266 "80/UDP": { 267 Port: 80, 268 Protocol: api.ProtoTCP, 269 L7Parser: policy.ParserTypeHTTP, 270 L7RulesPerEp: policy.L7DataMap{ 271 cachedRequiresV2Selector: L7Rules1, 272 }, 273 }, 274 } 275 276 // L4PolicyMap4 is an L4-only policy, with no L7 rules. 277 var L4PolicyMap4 = map[string]*policy.L4Filter{ 278 "80/TCP": { 279 Port: 80, 280 Protocol: api.ProtoTCP, 281 L7RulesPerEp: policy.L7DataMap{ 282 cachedSelector1: api.L7Rules{}, 283 }, 284 }, 285 } 286 287 // L4PolicyMap5 is an L4-only policy, with no L7 rules. 288 var L4PolicyMap5 = map[string]*policy.L4Filter{ 289 "80/TCP": { 290 Port: 80, 291 Protocol: api.ProtoTCP, 292 L7RulesPerEp: policy.L7DataMap{ 293 wildcardCachedSelector: api.L7Rules{}, 294 }, 295 }, 296 } 297 298 var ExpectedPerPortPolicies1 = []*cilium.PortNetworkPolicy{ 299 { 300 Port: 80, 301 Protocol: envoy_api_v2_core.SocketAddress_TCP, 302 Rules: []*cilium.PortNetworkPolicyRule{ 303 ExpectedPortNetworkPolicyRule1, 304 }, 305 }, 306 } 307 308 var ExpectedPerPortPolicies2 = []*cilium.PortNetworkPolicy{ 309 { 310 Port: 8080, 311 Protocol: envoy_api_v2_core.SocketAddress_UDP, 312 Rules: []*cilium.PortNetworkPolicyRule{ 313 ExpectedPortNetworkPolicyRule2, 314 }, 315 }, 316 } 317 318 var ExpectedPerPortPolicies3 = []*cilium.PortNetworkPolicy{ 319 { 320 Port: 80, 321 Protocol: envoy_api_v2_core.SocketAddress_TCP, 322 Rules: []*cilium.PortNetworkPolicyRule{ 323 ExpectedPortNetworkPolicyRule3, 324 }, 325 }, 326 } 327 328 var ExpectedPerPortPolicies4RequiresV2 = []*cilium.PortNetworkPolicy{ 329 { 330 Port: 80, 331 Protocol: envoy_api_v2_core.SocketAddress_TCP, 332 Rules: []*cilium.PortNetworkPolicyRule{ 333 ExpectedPortNetworkPolicyRule4RequiresV2, 334 }, 335 }, 336 } 337 338 var ExpectedPerPortPolicies5RequiresV2 = []*cilium.PortNetworkPolicy{ 339 { 340 Port: 80, 341 Protocol: envoy_api_v2_core.SocketAddress_TCP, 342 Rules: []*cilium.PortNetworkPolicyRule{ 343 ExpectedPortNetworkPolicyRule5RequiresV2, 344 }, 345 }, 346 } 347 348 var ExpectedPerPortPolicies6 = []*cilium.PortNetworkPolicy{ 349 { 350 Port: 80, 351 Protocol: envoy_api_v2_core.SocketAddress_TCP, 352 Rules: []*cilium.PortNetworkPolicyRule{ 353 ExpectedPortNetworkPolicyRule6, 354 }, 355 }, 356 } 357 358 var ExpectedPerPortPolicies7 = []*cilium.PortNetworkPolicy{ 359 { 360 Port: 80, 361 Protocol: envoy_api_v2_core.SocketAddress_TCP, 362 }, 363 } 364 365 var L4Policy1 = &policy.L4Policy{ 366 Ingress: L4PolicyMap1, 367 Egress: L4PolicyMap2, 368 } 369 370 var L4Policy1RequiresV2 = &policy.L4Policy{ 371 Ingress: L4PolicyMap1RequiresV2, 372 Egress: L4PolicyMap2, 373 } 374 375 var L4Policy2 = &policy.L4Policy{ 376 Ingress: L4PolicyMap3, 377 Egress: L4PolicyMap2, 378 } 379 380 var L4Policy2RequiresV2 = &policy.L4Policy{ 381 Ingress: L4PolicyMap3RequiresV2, 382 Egress: L4PolicyMap2, 383 } 384 385 func (s *ServerSuite) TestGetHTTPRule(c *C) { 386 obtained, _ := getHTTPRule(PortRuleHTTP1) 387 c.Assert(obtained, checker.Equals, ExpectedHeaders1) 388 } 389 390 func (s *ServerSuite) TestGetPortNetworkPolicyRule(c *C) { 391 obtained := getPortNetworkPolicyRule(cachedSelector1, policy.ParserTypeHTTP, L7Rules1) 392 c.Assert(obtained, checker.Equals, ExpectedPortNetworkPolicyRule1) 393 394 obtained = getPortNetworkPolicyRule(cachedSelector2, policy.ParserTypeHTTP, L7Rules2) 395 c.Assert(obtained, checker.Equals, ExpectedPortNetworkPolicyRule2) 396 } 397 398 func (s *ServerSuite) TestGetDirectionNetworkPolicy(c *C) { 399 // L4+L7 400 obtained := getDirectionNetworkPolicy(L4PolicyMap1, true) 401 c.Assert(obtained, checker.Equals, ExpectedPerPortPolicies1) 402 403 // L4+L7 404 obtained = getDirectionNetworkPolicy(L4PolicyMap2, true) 405 c.Assert(obtained, checker.Equals, ExpectedPerPortPolicies2) 406 407 // L4-only 408 obtained = getDirectionNetworkPolicy(L4PolicyMap4, true) 409 c.Assert(obtained, checker.Equals, ExpectedPerPortPolicies6) 410 411 // L4-only 412 obtained = getDirectionNetworkPolicy(L4PolicyMap5, true) 413 c.Assert(obtained, checker.Equals, ExpectedPerPortPolicies7) 414 } 415 416 func (s *ServerSuite) TestGetNetworkPolicy(c *C) { 417 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy1, true, true) 418 expected := &cilium.NetworkPolicy{ 419 Name: IPv4Addr, 420 Policy: uint64(Identity), 421 IngressPerPortPolicies: ExpectedPerPortPolicies1, 422 EgressPerPortPolicies: ExpectedPerPortPolicies2, 423 } 424 c.Assert(obtained, checker.Equals, expected) 425 } 426 427 func (s *ServerSuite) TestGetNetworkPolicyWildcard(c *C) { 428 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy2, true, true) 429 expected := &cilium.NetworkPolicy{ 430 Name: IPv4Addr, 431 Policy: uint64(Identity), 432 IngressPerPortPolicies: ExpectedPerPortPolicies3, 433 EgressPerPortPolicies: ExpectedPerPortPolicies2, 434 } 435 c.Assert(obtained, checker.Equals, expected) 436 } 437 438 func (s *ServerSuite) TestGetNetworkPolicyDeny(c *C) { 439 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy1RequiresV2, true, true) 440 expected := &cilium.NetworkPolicy{ 441 Name: IPv4Addr, 442 Policy: uint64(Identity), 443 IngressPerPortPolicies: ExpectedPerPortPolicies4RequiresV2, 444 EgressPerPortPolicies: ExpectedPerPortPolicies2, 445 } 446 c.Assert(obtained, checker.Equals, expected) 447 } 448 449 func (s *ServerSuite) TestGetNetworkPolicyWildcardDeny(c *C) { 450 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy2RequiresV2, true, true) 451 expected := &cilium.NetworkPolicy{ 452 Name: IPv4Addr, 453 Policy: uint64(Identity), 454 IngressPerPortPolicies: ExpectedPerPortPolicies5RequiresV2, 455 EgressPerPortPolicies: ExpectedPerPortPolicies2, 456 } 457 c.Assert(obtained, checker.Equals, expected) 458 } 459 460 func (s *ServerSuite) TestGetNetworkPolicyNil(c *C) { 461 obtained := getNetworkPolicy(IPv4Addr, Identity, "", nil, true, true) 462 expected := &cilium.NetworkPolicy{ 463 Name: IPv4Addr, 464 Policy: uint64(Identity), 465 IngressPerPortPolicies: nil, 466 EgressPerPortPolicies: nil, 467 } 468 c.Assert(obtained, checker.Equals, expected) 469 } 470 471 func (s *ServerSuite) TestGetNetworkPolicyIngressNotEnforced(c *C) { 472 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy2, false, true) 473 expected := &cilium.NetworkPolicy{ 474 Name: IPv4Addr, 475 Policy: uint64(Identity), 476 IngressPerPortPolicies: allowAllPortNetworkPolicy, 477 EgressPerPortPolicies: ExpectedPerPortPolicies2, 478 } 479 c.Assert(obtained, checker.Equals, expected) 480 } 481 482 func (s *ServerSuite) TestGetNetworkPolicyEgressNotEnforced(c *C) { 483 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4Policy2RequiresV2, true, false) 484 expected := &cilium.NetworkPolicy{ 485 Name: IPv4Addr, 486 Policy: uint64(Identity), 487 IngressPerPortPolicies: ExpectedPerPortPolicies5RequiresV2, 488 EgressPerPortPolicies: allowAllPortNetworkPolicy, 489 } 490 c.Assert(obtained, checker.Equals, expected) 491 } 492 493 var L4PolicyL7 = &policy.L4Policy{ 494 Ingress: map[string]*policy.L4Filter{ 495 "9090/TCP": { 496 Port: 9090, Protocol: api.ProtoTCP, 497 L7Parser: "tester", 498 L7RulesPerEp: policy.L7DataMap{ 499 cachedSelector1: api.L7Rules{ 500 L7Proto: "tester", 501 L7: []api.PortRuleL7{ 502 map[string]string{ 503 "method": "PUT", 504 "path": "/"}, 505 map[string]string{ 506 "method": "GET", 507 "path": "/"}, 508 }, 509 }, 510 }, 511 Ingress: true, 512 }, 513 }, 514 } 515 516 var ExpectedPerPortPoliciesL7 = []*cilium.PortNetworkPolicy{ 517 { 518 Port: 9090, 519 Protocol: envoy_api_v2_core.SocketAddress_TCP, 520 Rules: []*cilium.PortNetworkPolicyRule{{ 521 RemotePolicies: []uint64{1001, 1002}, 522 L7Proto: "tester", 523 L7: &cilium.PortNetworkPolicyRule_L7Rules{ 524 L7Rules: &cilium.L7NetworkPolicyRules{ 525 L7Rules: []*cilium.L7NetworkPolicyRule{ 526 {Rule: map[string]string{ 527 "method": "PUT", 528 "path": "/"}}, 529 {Rule: map[string]string{ 530 "method": "GET", 531 "path": "/"}}, 532 }, 533 }, 534 }}, 535 }, 536 }, 537 } 538 539 func (s *ServerSuite) TestGetNetworkPolicyL7(c *C) { 540 obtained := getNetworkPolicy(IPv4Addr, Identity, "", L4PolicyL7, true, true) 541 expected := &cilium.NetworkPolicy{ 542 Name: IPv4Addr, 543 Policy: uint64(Identity), 544 IngressPerPortPolicies: ExpectedPerPortPoliciesL7, 545 } 546 c.Assert(obtained, checker.Equals, expected) 547 }