github.com/fafucoder/cilium@v1.6.11/cilium/cmd/helpers_test.go (about) 1 // Copyright 2018-2019 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 cmd 18 19 import ( 20 "bytes" 21 "path" 22 "sort" 23 "testing" 24 25 "github.com/cilium/cilium/pkg/checker" 26 "github.com/cilium/cilium/pkg/labels" 27 "github.com/cilium/cilium/pkg/policy/trafficdirection" 28 "github.com/cilium/cilium/pkg/u8proto" 29 30 . "gopkg.in/check.v1" 31 ) 32 33 func Test(t *testing.T) { TestingT(t) } 34 35 type CMDHelpersSuite struct{} 36 37 var _ = Suite(&CMDHelpersSuite{}) 38 39 func (s *CMDHelpersSuite) TestExpandNestedJSON(c *C) { 40 buf := bytes.NewBufferString("not json at all") 41 res, err := expandNestedJSON(*buf) 42 c.Assert(err, IsNil) 43 c.Assert(string(res.Bytes()), Equals, `not json at all`) 44 45 buf = bytes.NewBufferString(`{\n\"notEscapedJson\": \"foo\"}`) 46 res, err = expandNestedJSON(*buf) 47 c.Assert(err, IsNil) 48 c.Assert(string(res.Bytes()), Equals, `{\n\"notEscapedJson\": \"foo\"}`) 49 50 buf = bytes.NewBufferString(`nonjson={\n\"notEscapedJson\": \"foo\"}`) 51 res, err = expandNestedJSON(*buf) 52 c.Assert(err, IsNil) 53 c.Assert(string(res.Bytes()), Equals, `nonjson={\n\"notEscapedJson\": \"foo\"}`) 54 55 buf = bytes.NewBufferString(`nonjson:morenonjson={\n\"notEscapedJson\": \"foo\"}`) 56 res, err = expandNestedJSON(*buf) 57 c.Assert(err, IsNil) 58 c.Assert(string(res.Bytes()), Equals, `nonjson:morenonjson={\n\"notEscapedJson\": \"foo\"}`) 59 60 buf = bytes.NewBufferString(`{"foo": ["{\n \"port\": 8080,\n \"protocol\": \"TCP\"\n}"]}`) 61 res, err = expandNestedJSON(*buf) 62 c.Assert(err, IsNil) 63 c.Assert(string(res.Bytes()), Equals, `{"foo": [{ 64 "port": 8080, 65 "protocol": "TCP" 66 }]}`) 67 68 buf = bytes.NewBufferString(`"foo": [ 69 "bar:baz/alice={\"bob\":{\"charlie\":4}}\n" 70 ]`) 71 res, err = expandNestedJSON(*buf) 72 c.Assert(err, IsNil) 73 c.Assert(string(res.Bytes()), Equals, `"foo": [ 74 bar:baz/alice={ 75 "bob": { 76 "charlie": 4 77 } 78 } 79 80 ]`) 81 82 buf = bytes.NewBufferString(`"foo": [ 83 "bar:baz/alice={\n\"bob\":\n{\n\"charlie\":\n4\n}\n}\n" 84 ]`) 85 res, err = expandNestedJSON(*buf) 86 c.Assert(err, IsNil) 87 c.Assert(string(res.Bytes()), Equals, `"foo": [ 88 bar:baz/alice={ 89 "bob": { 90 "charlie": 4 91 } 92 } 93 94 ]`) 95 96 buf = bytes.NewBufferString(`[ 97 { 98 "id": 2669, 99 "spec": { 100 "label-configuration": {}, 101 "options": { 102 "Conntrack": "Enabled", 103 "ConntrackAccounting": "Enabled", 104 "ConntrackLocal": "Disabled", 105 "Debug": "Enabled", 106 "DebugLB": "Enabled", 107 "DropNotification": "Enabled", 108 "MonitorAggregationLevel": "None", 109 "NAT46": "Disabled", 110 "TraceNotification": "Enabled" 111 } 112 }, 113 "status": { 114 "controllers": [ 115 { 116 "configuration": { 117 "error-retry": true, 118 "interval": "5m0s" 119 }, 120 "name": "resolve-identity-2669", 121 "status": { 122 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 123 "last-success-timestamp": "2019-06-10T19:36:42.497Z", 124 "success-count": 4 125 }, 126 "uuid": "aba643d9-8bb5-11e9-9be2-080027486be3" 127 }, 128 { 129 "configuration": { 130 "error-retry": true, 131 "interval": "5m0s" 132 }, 133 "name": "sync-IPv4-identity-mapping (2669)", 134 "status": { 135 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 136 "last-success-timestamp": "2019-06-10T19:36:42.529Z", 137 "success-count": 4 138 }, 139 "uuid": "aba631c3-8bb5-11e9-9be2-080027486be3" 140 }, 141 { 142 "configuration": { 143 "error-retry": true, 144 "interval": "5m0s" 145 }, 146 "name": "sync-IPv6-identity-mapping (2669)", 147 "status": { 148 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 149 "last-success-timestamp": "2019-06-10T19:36:42.529Z", 150 "success-count": 4 151 }, 152 "uuid": "aba637e9-8bb5-11e9-9be2-080027486be3" 153 }, 154 { 155 "configuration": { 156 "error-retry": true, 157 "interval": "1m0s" 158 }, 159 "name": "sync-policymap-2669", 160 "status": { 161 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 162 "last-success-timestamp": "2019-06-10T19:39:43.974Z", 163 "success-count": 16 164 }, 165 "uuid": "ad0a1388-8bb5-11e9-9be2-080027486be3" 166 } 167 ], 168 "external-identifiers": { 169 "container-id": "1968a48396a0e42f3faad360a7ffa23d8629faddee7f828408bf177d3eeac47a", 170 "container-name": "client", 171 "docker-endpoint-id": "05a27bef9f339e5ae25a191108b91ee1e7fdc2696d2c46908645157a62438ccd", 172 "docker-network-id": "e3ea8f2e1df2250df6702fd802ea0d3706091c1b374db998d48e7327bf9bd0fe", 173 "pod-name": "/" 174 }, 175 "health": { 176 "bpf": "OK", 177 "connected": true, 178 "overallHealth": "OK", 179 "policy": "OK" 180 }, 181 "identity": { 182 "id": 62004, 183 "labels": [ 184 "container:id.client" 185 ], 186 "labelsSHA256": "c2e7b3482b5e9e1abca840b8cc5568ff876c7524d723b3068683f539008537dc" 187 }, 188 "labels": { 189 "realized": {}, 190 "security-relevant": [ 191 "container:id.client" 192 ] 193 }, 194 "log": [ 195 { 196 "code": "OK", 197 "message": "Successfully regenerated endpoint program (Reason: policy rules added)", 198 "state": "ready", 199 "timestamp": "2019-06-10T19:26:43Z" 200 } 201 ], 202 "networking": { 203 "addressing": [ 204 { 205 "ipv4": "10.11.212.174", 206 "ipv6": "f00d::a0b:0:0:8cdf" 207 } 208 ], 209 "host-mac": "1a:c9:b9:4f:98:65", 210 "interface-index": 250, 211 "interface-name": "lxca8e38e6f627e", 212 "mac": "7e:41:1b:fd:02:81" 213 }, 214 "policy": { 215 "proxy-policy-revision": 48, 216 "proxy-statistics": [ 217 { 218 "allocated-proxy-port": 15814, 219 "location": "egress", 220 "port": 80, 221 "protocol": "http", 222 "statistics": { 223 "requests": { 224 "denied": 2, 225 "forwarded": 2, 226 "received": 4 227 }, 228 "responses": { 229 "forwarded": 2, 230 "received": 2 231 } 232 } 233 } 234 ], 235 "realized": { 236 "allowed-egress-identities": [], 237 "allowed-ingress-identities": [ 238 0, 239 1 240 ], 241 "build": 48, 242 "cidr-policy": { 243 "egress": [], 244 "ingress": [] 245 }, 246 "id": 62004, 247 "l4": { 248 "egress": [ 249 { 250 "derived-from-rules": [ 251 [] 252 ], 253 "rule": "{\n \"port\": 80,\n \"protocol\": \"TCP\",\n \"l7-rules\": [\n {\n \"\\u0026LabelSelector{MatchLabels:map[string]string{},MatchExpressions:[],}\": {\n \"http\": [\n {\n \"path\": \"/public\",\n \"method\": \"GET\"\n }\n ]\n }\n }\n ]\n}" 254 } 255 ], 256 "ingress": [] 257 }, 258 "policy-enabled": "egress", 259 "policy-revision": 48 260 }, 261 "spec": { 262 "allowed-egress-identities": [], 263 "allowed-ingress-identities": [ 264 0, 265 1 266 ], 267 "build": 48, 268 "cidr-policy": { 269 "egress": [], 270 "ingress": [] 271 }, 272 "id": 62004, 273 "l4": { 274 "egress": [ 275 { 276 "derived-from-rules": [ 277 [] 278 ], 279 "rule": "{\n \"port\": 80,\n \"protocol\": \"TCP\",\n \"l7-rules\": [\n {\n \"\\u0026LabelSelector{MatchLabels:map[string]string{},MatchExpressions:[],}\": {\n \"http\": [\n {\n \"path\": \"/public\",\n \"method\": \"GET\"\n }\n ]\n }\n }\n ]\n}" 280 } 281 ], 282 "ingress": [] 283 }, 284 "policy-enabled": "egress", 285 "policy-revision": 48 286 } 287 }, 288 "realized": { 289 "label-configuration": {}, 290 "options": { 291 "Conntrack": "Enabled", 292 "ConntrackAccounting": "Enabled", 293 "ConntrackLocal": "Disabled", 294 "Debug": "Enabled", 295 "DebugLB": "Enabled", 296 "DropNotification": "Enabled", 297 "MonitorAggregationLevel": "None", 298 "NAT46": "Disabled", 299 "TraceNotification": "Enabled" 300 } 301 }, 302 "state": "ready" 303 } 304 } 305 ]`) 306 res, err = expandNestedJSON(*buf) 307 c.Assert(err, IsNil) 308 c.Assert(string(res.Bytes()), Equals, `[ 309 { 310 "id": 2669, 311 "spec": { 312 "label-configuration": {}, 313 "options": { 314 "Conntrack": "Enabled", 315 "ConntrackAccounting": "Enabled", 316 "ConntrackLocal": "Disabled", 317 "Debug": "Enabled", 318 "DebugLB": "Enabled", 319 "DropNotification": "Enabled", 320 "MonitorAggregationLevel": "None", 321 "NAT46": "Disabled", 322 "TraceNotification": "Enabled" 323 } 324 }, 325 "status": { 326 "controllers": [ 327 { 328 "configuration": { 329 "error-retry": true, 330 "interval": "5m0s" 331 }, 332 "name": "resolve-identity-2669", 333 "status": { 334 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 335 "last-success-timestamp": "2019-06-10T19:36:42.497Z", 336 "success-count": 4 337 }, 338 "uuid": "aba643d9-8bb5-11e9-9be2-080027486be3" 339 }, 340 { 341 "configuration": { 342 "error-retry": true, 343 "interval": "5m0s" 344 }, 345 "name": "sync-IPv4-identity-mapping (2669)", 346 "status": { 347 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 348 "last-success-timestamp": "2019-06-10T19:36:42.529Z", 349 "success-count": 4 350 }, 351 "uuid": "aba631c3-8bb5-11e9-9be2-080027486be3" 352 }, 353 { 354 "configuration": { 355 "error-retry": true, 356 "interval": "5m0s" 357 }, 358 "name": "sync-IPv6-identity-mapping (2669)", 359 "status": { 360 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 361 "last-success-timestamp": "2019-06-10T19:36:42.529Z", 362 "success-count": 4 363 }, 364 "uuid": "aba637e9-8bb5-11e9-9be2-080027486be3" 365 }, 366 { 367 "configuration": { 368 "error-retry": true, 369 "interval": "1m0s" 370 }, 371 "name": "sync-policymap-2669", 372 "status": { 373 "last-failure-timestamp": "0001-01-01T00:00:00.000Z", 374 "last-success-timestamp": "2019-06-10T19:39:43.974Z", 375 "success-count": 16 376 }, 377 "uuid": "ad0a1388-8bb5-11e9-9be2-080027486be3" 378 } 379 ], 380 "external-identifiers": { 381 "container-id": "1968a48396a0e42f3faad360a7ffa23d8629faddee7f828408bf177d3eeac47a", 382 "container-name": "client", 383 "docker-endpoint-id": "05a27bef9f339e5ae25a191108b91ee1e7fdc2696d2c46908645157a62438ccd", 384 "docker-network-id": "e3ea8f2e1df2250df6702fd802ea0d3706091c1b374db998d48e7327bf9bd0fe", 385 "pod-name": "/" 386 }, 387 "health": { 388 "bpf": "OK", 389 "connected": true, 390 "overallHealth": "OK", 391 "policy": "OK" 392 }, 393 "identity": { 394 "id": 62004, 395 "labels": [ 396 "container:id.client" 397 ], 398 "labelsSHA256": "c2e7b3482b5e9e1abca840b8cc5568ff876c7524d723b3068683f539008537dc" 399 }, 400 "labels": { 401 "realized": {}, 402 "security-relevant": [ 403 "container:id.client" 404 ] 405 }, 406 "log": [ 407 { 408 "code": "OK", 409 "message": "Successfully regenerated endpoint program (Reason: policy rules added)", 410 "state": "ready", 411 "timestamp": "2019-06-10T19:26:43Z" 412 } 413 ], 414 "networking": { 415 "addressing": [ 416 { 417 "ipv4": "10.11.212.174", 418 "ipv6": "f00d::a0b:0:0:8cdf" 419 } 420 ], 421 "host-mac": "1a:c9:b9:4f:98:65", 422 "interface-index": 250, 423 "interface-name": "lxca8e38e6f627e", 424 "mac": "7e:41:1b:fd:02:81" 425 }, 426 "policy": { 427 "proxy-policy-revision": 48, 428 "proxy-statistics": [ 429 { 430 "allocated-proxy-port": 15814, 431 "location": "egress", 432 "port": 80, 433 "protocol": "http", 434 "statistics": { 435 "requests": { 436 "denied": 2, 437 "forwarded": 2, 438 "received": 4 439 }, 440 "responses": { 441 "forwarded": 2, 442 "received": 2 443 } 444 } 445 } 446 ], 447 "realized": { 448 "allowed-egress-identities": [], 449 "allowed-ingress-identities": [ 450 0, 451 1 452 ], 453 "build": 48, 454 "cidr-policy": { 455 "egress": [], 456 "ingress": [] 457 }, 458 "id": 62004, 459 "l4": { 460 "egress": [ 461 { 462 "derived-from-rules": [ 463 [] 464 ], 465 "rule": { 466 "l7-rules": [ 467 { 468 "\u0026LabelSelector{MatchLabels:map[string]string{},MatchExpressions:[],}": { 469 "http": [ 470 { 471 "method": "GET", 472 "path": "/public" 473 } 474 ] 475 } 476 } 477 ], 478 "port": 80, 479 "protocol": "TCP" 480 } 481 } 482 ], 483 "ingress": [] 484 }, 485 "policy-enabled": "egress", 486 "policy-revision": 48 487 }, 488 "spec": { 489 "allowed-egress-identities": [], 490 "allowed-ingress-identities": [ 491 0, 492 1 493 ], 494 "build": 48, 495 "cidr-policy": { 496 "egress": [], 497 "ingress": [] 498 }, 499 "id": 62004, 500 "l4": { 501 "egress": [ 502 { 503 "derived-from-rules": [ 504 [] 505 ], 506 "rule": { 507 "l7-rules": [ 508 { 509 "\u0026LabelSelector{MatchLabels:map[string]string{},MatchExpressions:[],}": { 510 "http": [ 511 { 512 "method": "GET", 513 "path": "/public" 514 } 515 ] 516 } 517 } 518 ], 519 "port": 80, 520 "protocol": "TCP" 521 } 522 } 523 ], 524 "ingress": [] 525 }, 526 "policy-enabled": "egress", 527 "policy-revision": 48 528 } 529 }, 530 "realized": { 531 "label-configuration": {}, 532 "options": { 533 "Conntrack": "Enabled", 534 "ConntrackAccounting": "Enabled", 535 "ConntrackLocal": "Disabled", 536 "Debug": "Enabled", 537 "DebugLB": "Enabled", 538 "DropNotification": "Enabled", 539 "MonitorAggregationLevel": "None", 540 "NAT46": "Disabled", 541 "TraceNotification": "Enabled" 542 } 543 }, 544 "state": "ready" 545 } 546 } 547 ]`) 548 549 } 550 551 func (s *CMDHelpersSuite) TestParseTrafficString(c *C) { 552 553 validIngressCases := []string{"ingress", "Ingress", "InGrEss"} 554 validEgressCases := []string{"egress", "Egress", "EGrEss"} 555 556 invalidStr := "getItDoneMan" 557 558 for _, validCase := range validIngressCases { 559 ingressDir, err := parseTrafficString(validCase) 560 c.Assert(ingressDir, Equals, trafficdirection.Ingress) 561 c.Assert(err, IsNil) 562 } 563 564 for _, validCase := range validEgressCases { 565 egressDir, err := parseTrafficString(validCase) 566 c.Assert(egressDir, Equals, trafficdirection.Egress) 567 c.Assert(err, IsNil) 568 } 569 570 invalid, err := parseTrafficString(invalidStr) 571 c.Assert(invalid, Equals, trafficdirection.Invalid) 572 c.Assert(err, Not(IsNil)) 573 574 } 575 576 func (s *CMDHelpersSuite) TestParsePolicyUpdateArgsHelper(c *C) { 577 sortProtos := func(ints []uint8) { 578 sort.Slice(ints, func(i, j int) bool { 579 return ints[i] < ints[j] 580 }) 581 } 582 583 allProtos := []uint8{} 584 for _, proto := range u8proto.ProtoIDs { 585 allProtos = append(allProtos, uint8(proto)) 586 } 587 588 tests := []struct { 589 args []string 590 invalid bool 591 mapBaseName string 592 trafficDirection trafficdirection.TrafficDirection 593 peerLbl uint32 594 port uint16 595 protos []uint8 596 }{ 597 { 598 args: []string{labels.IDNameHost, "ingress", "12345"}, 599 invalid: false, 600 mapBaseName: "cilium_policy_reserved_1", 601 trafficDirection: trafficdirection.Ingress, 602 peerLbl: 12345, 603 port: 0, 604 protos: []uint8{0}, 605 }, 606 { 607 args: []string{"123", "egress", "12345", "1/tcp"}, 608 invalid: false, 609 mapBaseName: "cilium_policy_00123", 610 trafficDirection: trafficdirection.Egress, 611 peerLbl: 12345, 612 port: 1, 613 protos: []uint8{uint8(u8proto.TCP)}, 614 }, 615 { 616 args: []string{"123", "ingress", "12345", "1"}, 617 invalid: false, 618 mapBaseName: "cilium_policy_00123", 619 trafficDirection: trafficdirection.Ingress, 620 peerLbl: 12345, 621 port: 1, 622 protos: allProtos, 623 }, 624 { 625 // Invalid traffic direction. 626 args: []string{"123", "invalid", "12345"}, 627 invalid: true, 628 }, 629 { 630 // Invalid protocol. 631 args: []string{"123", "invalid", "1/udt"}, 632 invalid: true, 633 }, 634 } 635 636 for _, tt := range tests { 637 args, err := parsePolicyUpdateArgsHelper(tt.args) 638 639 if tt.invalid { 640 c.Assert(err, NotNil) 641 } else { 642 c.Assert(err, IsNil) 643 644 c.Assert(path.Base(args.path), Equals, tt.mapBaseName) 645 c.Assert(args.trafficDirection, Equals, tt.trafficDirection) 646 c.Assert(args.label, Equals, tt.peerLbl) 647 c.Assert(args.port, Equals, tt.port) 648 649 sortProtos(args.protocols) 650 sortProtos(tt.protos) 651 c.Assert(args.protocols, checker.DeepEquals, tt.protos) 652 } 653 } 654 }