neuvector之组的划分逻辑
原文链接,欢迎大家关注我的github账号
一、组的定义
NeuVector 会自动从正在运行的应用程序中创建组。这些组以前缀‘nv‘开头。您也可以使用 CRD 或 REST API 手动添加它们,并且可以在任何模式下创建、发现、监视或保护。网络和响应规则需要这些组定义。对于自动创建的组(以“nv”开头的“学习”组) ,NeuVector 将学习网络和处理规则,并在发现模式下添加它们。自定义组不会自动学习和填充规则。注意: nv组开始时默认为进程/文件保护启用零漂移。
二、组的类型
neuvector组的类型分为三种:
- 自定义组: 用户根据自定义的条件创建对应的组,自定义组不支持模式策略等;(支持相应规则、DLP\WAF检测、当NeuVector 无法识别内部网络,将其归类为“外部”网络时,可以为其指定内部服务的 DNS 名称、IP 地址或地址范围作为新的组,以避免被外部攻
击。 ) - crd生成的组:根据yaml文件内容生成对应的组;
- 系统生成的组:neuvector自己学习生成的组
其中系统生成的组的类型可分为以下四种:
- nodes:根据集群节点集合生成的组
- external:外部组,主要用于查看与外部通信的网络规则
- service组:其中还有k8s的service也会生成相关组,命名规则为nv+.+ip.+service的名称+.+domain,但是这种类型的组不具备策略
切换等操作,界面显示组时也会对传入并且属于内部(没有选择器的)的service类型组进行隐藏; - 容器与pod组:根据组名分组,容器的组名生成逻辑为groupName=nv+.+serviceName+.+domain; 其中domain为命名空间,无命名空间则为空(例如docker、containerd容器);serviceName通过global.ORCH.GetService(&info.ContainerMeta)方法获取对应的serviceName;
三、代码中执行流程
neuvector组的生成流程图如下:
四、关键函数解析
GetService方法执行流程如下图 :
GetService根据不同的平台调用不同的方法:
当为k8s平台时:
- 首先查找容器有没有为deploymentconfig的标签,有则直接以deploymentconfig标签的值作为serviceName进行返回;
- 无则继续查看容器有没有为io.kubernetes.pod.name的标签,有的情况下分以下五种情况:
2.1 如果k8s的flavor为rancher,并且这个容器的pod命名空间为"cattle-system",则判断这个pod的前缀和rancher相关的pod名称前缀
(“rancher-agent-”,“core-services-dns-”,“core-services-metadata-”,“core-services-healthcheck-”,“core-services-network-manager-”)
匹配,如果前缀匹配的话,将前缀作为serviceName进行返回;
2.2 当2.1不满足时,查看容器是否有"pod-template-hash"的标签, 有则去掉pod名称的hash值然后作为serviceName进行返回;( pod.
name比如采用如下格式: calico-node-m308t,其中-hash值是m308t,如果存在哈希标签,则删除它。serviceName为calico-node)
2.3主要路径: 当2.1、2.2不满足时,判断pod名称是否满足正则表达式"^.*-[a-f0-9]{6,10}-[a-z0-9]{5} " 或者 " . ∗ − [ 0 − 9 ] 1 , 5 − [ a − z 0 − 9 ] 5 "或者"^.*-[0-9]{1,5}-[a-z0-9]{5} "或者".∗−[0−9]1,5−[a−z0−9]5"的
pod名称,满足则以最后一个“-“作为分割线,将”-“之前的字符串作为serviceName进行返回;
2.4 以上都不满足时,判断pod名称是否存在”-“字符,则以最后一个“-“作为分割线,将”-“之前的字符串作为serviceName进行返回;
2.5 以上都不满足时,直接将pod名称作为serviceName进行返回; - 当上述1、2都不满足时,直接调用baseDriver.GetService(meta)方法;
3.1查看容器是否带有"com.docker.compose.project"、“com.docker.compose.service"标签也就是是否为docker compose方式部署 ,是则将(project + “.” + service)作为serviceName进行返回,其中service为"com.docker.compose.service"标签的值,project值为"Docker.Trusted.Registry"或者"Docker.UCP”
3.2 无则查看容器是否带有"com.docker.swarm.service.name"也就是docker swarm方式部署,是则直接以标签的值作为serviceName进行返回;
3.3 以上都不满足时,直接调用container.TrimContainerImageRepo(container.TrimContainerImageVersion(meta.Image)方法的返回值作为serviceName进行返回, 方法大概逻辑为去掉镜像的仓库前缀以及版本标签(以docker/controller:latest为例, serviceName为docker:controller);