def test_resolver_endpoint_ids_by_selectors(): resolver = EndpointResolver(test_endpoints) app1_ids = resolver.resolve_endpoint_ids(['id=app1'], [], [], 'default') assert 30391 in app1_ids assert 33243 in app1_ids assert len(app1_ids) == 2
def test_resolver_endpoint_ids_by_names(): resolver = EndpointResolver(test_endpoints) ids = resolver.resolve_endpoint_ids( [], ['default:app1-799c454b56-xcw8t', 'default:app3'], [], 'default') assert 30391 in ids assert 51796 in ids assert len(ids) == 2
def test_resolver_retrieve_ep_ids(): resolver = EndpointResolver(test_endpoints) ids = resolver.resolve_endpoint_ids([], [], ["10.0.0.1", "f00d::a0f:0:0:1687"], "default") assert 5766 in ids assert 30391 in ids
def run(self, monitor_args: MonitorArgs, nodes: List[str], cmd_override: str): api = core_v1_api.CoreV1Api() try: pods = api.list_namespaced_pod(self.namespace, label_selector='k8s-app=cilium') except ApiException as e: print('could not list Cilium pods: %s\n' % e) sys.exit(1) if nodes: names = [ (pod.metadata.name, pod.spec.node_name) for pod in pods.items if pod.metadata.name in nodes or pod.spec.node_name in nodes ] else: names = [(pod.metadata.name, pod.spec.node_name) for pod in pods.items] if not names: raise ValueError('No Cilium nodes in cluster match provided names' ', or Cilium is not deployed') endpoints = self.retrieve_endpoint_data() pod_resolver = EndpointResolver(endpoints) if cmd_override: cmd = cmd_override.split(" ") else: cmd = self.get_monitor_command(monitor_args, names, pod_resolver) mode = "" if monitor_args.raw: mode = "raw" if monitor_args.verbose or cmd_override: mode = "verbose" self.monitors = [ Monitor(name[0], name[1], self.namespace, self.data_queue, self.close_queue, api, cmd, mode, pod_resolver) for name in names ] for m in self.monitors: m.process.start()
def get_monitor_command(self, args: MonitorArgs, names: List[str], resolver: EndpointResolver) -> List[str]: related_ids = resolver.resolve_endpoint_ids(args.related_selectors, args.related_pods, args.related_ips, self.endpoint_namespace) if (args.related_selectors or args.related_pods) and not related_ids: raise NoEndpointException("No related endpoints found") related_ids.update(args.related_endpoints) to_ids = resolver.resolve_endpoint_ids(args.to_selectors, args.to_pods, args.to_ips, self.endpoint_namespace) if (args.to_selectors or args.to_pods) and not to_ids: raise NoEndpointException("No to endpoints found") to_ids.update(args.to_endpoints) from_ids = resolver.resolve_endpoint_ids(args.from_selectors, args.from_pods, args.from_ips, self.endpoint_namespace) if (args.from_selectors or args.from_pods) and not from_ids: raise NoEndpointException("No from endpoints found") from_ids.update(args.from_endpoints) exec_command = ['cilium', 'monitor'] if args.verbose: exec_command.append('-v') if args.hex: if '-v' not in exec_command: exec_command.append('-v') exec_command.append('--hex') if not args.hex and not args.verbose and not args.raw: exec_command.append('--json') if related_ids: for e in related_ids: exec_command.append('--related-to') exec_command.append(str(e)) if to_ids: for e in to_ids: exec_command.append('--to') exec_command.append(str(e)) if from_ids: for e in from_ids: exec_command.append('--from') exec_command.append(str(e)) if args.types: for t in args.types: exec_command.append('--type') exec_command.append(t) print(exec_command) return exec_command
def test_json_processor(): resolver = EndpointResolver(test_endpoints) p = MonitorOutputProcessorJSON(resolver) p.add_out('{"type":"logRecord","observationPoint":"Ingress","flowType":') p.add_out('"Request","l7Proto":"http","srcEpID":0,"srcEpLabels":["k8s:i') p.add_out('o.kubernetes.pod.namespace=default","k8s:id=app2"],"srcIdent') p.add_out('ity":3338,"dstEpID":13949,"dstEpLabels":["k8s:id=app1","k8s:') p.add_out('io.kubernetes.pod.namespace=default"],"DstIdentity":45459,"v') p.add_out('erdict":"Denied","http":{"Code":403,"Method":"GET","URL":{"S') p.add_out('cheme":"http","Opaque":"","User":null,"Host":"app1-service",') p.add_out('"Path":"/private","RawPath":"","ForceQuery":false,"RawQuery"') p.add_out(':"","Fragment":""},"Protocol":"HTTP/1.1","Headers":{"Accept"') p.add_out(':["*/*"],"User-Agent":["curl/7.54.0"],"X-Request-Id":["05199') p.add_out('9d8-6987-4d79-9fad-729c87cb49ae"]}}}') p.add_out('{"type":"logRecord","observationPoi') p.add_out('nt":"Ingress","flowType":"Request",') p.add_out('"l7Proto":"kafka","srcEpID":0,"srcE') p.add_out('pLabels":["k8s:app=empire-backup","') p.add_out('k8s:io.kubernetes.pod.namespace=def') p.add_out('ault"],"srcIdentity":8370,"dstEpID"') p.add_out(':29381,"dstEpLabels":["k8s:io.kuber') p.add_out('netes.pod.namespace=default","k8s:a') p.add_out('pp=kafka"],"DstIdentity":12427,"ver') p.add_out('dict":"Forwarded","kafka":{"ErrorCo') p.add_out('de":0,"APIVersion":5,"APIKey":"fetc') p.add_out('h","CorrelationID":10,"Topic":{"Top') p.add_out('ic":"deathstar-plans"}}}') p.add_out(""" { "cpu": "CPU 01:", "type": "trace", "mark": "0xd3f88100", "ifindex": "lxca3b25", "state": "reply", "observationPoint": "to-endpoint", "traceSummary": "-> endpoint 5766", "source": 5766, "bytes": 66, "srcLabel": 49055, "dstLabel": 20496, "dstID": 5766, "summary": { "l2":{"src":"22:46:9b:ed:13:e9", "dst":"06:ea:01:96:66:ef"}, "l3":{"src":"10.0.0.1", "dst":"10.0.0.2"}, "l4":{"src":"80", "dst":"37934"} } } """) p.add_out(""" { "cpu": "CPU 00:", "type": "drop", "mark": "0xa9263786", "ifindex": "lxc05f8b", "reason": "Policy denied (L3)", "source": 5766, "bytes": 66, "srcLabel": 49055, "dstLabel": 20496, "dstID": 5766, "summary": { "l2":{"src":"22:46:9b:ed:13:e9", "dst":"06:ea:01:96:66:ef"}, "l3":{"src":"10.0.0.1", "dst":"10.0.0.2"}, "l4":{"src":"80", "dst":"37934"} } } """) p.add_out('{"type":"debug","message":"debug message","cpu":"CPU 01"}') p.add_out(""" { "cpu": "CPU 01:", "type": "capture", "mark": "0x8b0fe309", "message": "Delivery to ifindex 51", "source": 29898, "bytes": 66, "summary": "capture summary", "prefix": "-> cilium_health" } """) p.add_out(""" { "type": "agent", "subtype": "Policy updated", "message": { "labels": [ "unspec:io.cilium.k8s.policy.name=rule1", "unspec:io.cilium.k8s.policy.namespace=default" ], "revision": 10, "rule_count": 1 } } """) events = [x for x in p] assert len(events) == 7 assert events[0] == ( "(k8s:id=app2) => (k8s:id=app1) http GET /private Denied") assert events[1] == ("(k8s:app=empire-backup) => (k8s:app=kafka)" " kafka fetch deathstar-plans Forwarded") assert events[2] == ( "trace (default:app2 10.0.0.1:80) => (default:app1-799c454b56-xcw8t 10.0.0.2:37934)" # noqa: E501 ) assert events[3] == ( "drop: Policy denied (L3) (default:app2 10.0.0.1:80) => (default:app1-799c454b56-xcw8t 10.0.0.2:37934)" # noqa: E501 ) assert events[4] == ("debug: debug message on CPU 01") assert events[5] == ("-> cilium_health: capture summary") assert events[6] == ( "Policy updated: {'labels': ['unspec:io.cilium.k8s.policy.name=rule1', 'unspec:io.cilium.k8s.policy.namespace=default'], 'revision': 10, 'rule_count': 1}" # noqa: E501 )