From 9cc102336b0dc638c29c7b30d1968ed6d126e2d5 Mon Sep 17 00:00:00 2001 From: Danny__Wei Date: Tue, 3 Dec 2024 16:15:55 +0800 Subject: [PATCH 1/3] feat: Add new networking built-in rules --- internal/profile/apparmor/apparmor.go | 17 ++++++++++- internal/profile/bpf/bpf.go | 43 +++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/internal/profile/apparmor/apparmor.go b/internal/profile/apparmor/apparmor.go index 50d3a68..82fae8a 100644 --- a/internal/profile/apparmor/apparmor.go +++ b/internal/profile/apparmor/apparmor.go @@ -284,7 +284,7 @@ func generateAttackProtectionRules(rule, qualifier string) (rules string) { rules += qualifier + "deny /proc/**/mountinfo r,\n" case "mitigate-host-ip-leak": rules += qualifier + "deny /proc/**/net/arp r,\n" - //// 5. Restrict the execution of sensitive commands inside the container + //// 5. Restrict the sensitive operations inside the container case "disable-write-etc": rules += qualifier + "deny /etc/** wl,\n" case "disable-busybox": @@ -302,6 +302,21 @@ func generateAttackProtectionRules(rule, qualifier string) (rules string) { case "disable-su-sudo": rules += qualifier + "deny /**/su rx,\n" rules += qualifier + "deny /**/sudo rx,\n" + //// 6. Others + case "disable-network": + rules += qualifier + "deny network,\n" + case "disable-ipv4", "disable-inet": + rules += qualifier + "deny network inet,\n" + case "disable-ipv6", "disable-inet6": + rules += qualifier + "deny network inet6,\n" + case "disable-unix-domain-socket": + rules += qualifier + "deny network unix,\n" + case "disable-icmp": + rules += qualifier + "deny network icmp,\n" + case "disable-tcp": + rules += qualifier + "deny network tcp,\n" + case "disable-udp": + rules += qualifier + "deny network udp,\n" } return rules } diff --git a/internal/profile/bpf/bpf.go b/internal/profile/bpf/bpf.go index b15c205..621dfec 100644 --- a/internal/profile/bpf/bpf.go +++ b/internal/profile/bpf/bpf.go @@ -535,6 +535,49 @@ func generateAttackProtectionRules(content *varmor.BpfContent, mode uint32, rule return err } content.Processes = append(content.Processes, *fileContent) + //// 6. Others + case "disable-network": + networkContent, err = newBpfNetworkCreateRule(mode, 1< Date: Tue, 3 Dec 2024 16:35:14 +0800 Subject: [PATCH 2/3] docs: Add descriptions for network built-in rules --- .../policies_and_rules/built_in_rules.md | 7 ++ .../built_in_rules.zh_CN.md | 7 ++ .../built_in_rules/attack_protection.md | 85 +++++++++++++ .../built_in_rules/attack_protection.md | 112 +++++++++++++----- .../built_in_rules/attack_protection.md | 112 +++++++++++++----- .../built_in_rules/attack_protection.md | 112 +++++++++++++----- 6 files changed, 351 insertions(+), 84 deletions(-) diff --git a/docs/guides/policies_and_rules/built_in_rules.md b/docs/guides/policies_and_rules/built_in_rules.md index 1fc6750..0d9a946 100644 --- a/docs/guides/policies_and_rules/built_in_rules.md +++ b/docs/guides/policies_and_rules/built_in_rules.md @@ -40,6 +40,13 @@ Note:
- The built-in rules supported by different enforcers are still under | | |Prohibit setting the execute/search bit of a file

`disable-chmod-x-bit`|ALL|When attackers gain control over a container through vulnerabilities, they typically attempt to download additional attack code or tools into the container for further attacks, such as privilege escalation, lateral movement, cryptocurrency mining, and more. In this attack chain, attackers might use the chmod syscalls to modify file permissions for execution.|Prohibit setting the execute/search bit of a file with `chmod/fchmod/fchmodat/fchmodat2` syscalls|Seccomp | | |Prohibit setting the SUID/SGID bit of a file

`disable-chmod-s-bit`|ALL|In some scenarios, attackers may attempt to invoke chmod syscalls to perform privilege elevation attacks by setting the file's s-bit (set-user-ID, set-group-ID).|Prohibit setting the set-user-ID/set-group-ID bit of a file with `chmod/fchmod/fchmodat/fchmodat2` syscalls|Seccomp | | |Prohibit the execution of su/sudo command

`disable-su-sudo`|ALL|When processes within a container run as non-root users, attackers often need to escalate privileges to the root user for further attacks. The sudo/su commands are common local privilege escalation avenues.|Prohibit the execution of su/sudo command.

Some base images may symlink su to /bin/busybox. In this scenario, it's also necessary to prohibit the execution of busybox command.|AppArmor
BPF +| |Others |Prohibit all network access

`disable-network`|ALL|When you want to prevent a container from accessing the network, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit accessing the network via inet4 addresses

`disable-inet`, `disable-ipv4`|ALL|When you want to prevent a container from accessing the network via IPv4 addresses, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit accessing the network via inet6 addresses

`disable-inet6`, `disable-ipv6`|ALL|When you want to prevent a container from accessing the network via IPv6 addresses, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit accessing the network via UDS addresses

`disable-unix-domain-socket`|ALL|When you want to prevent a container from accessing the network via Unix Domain Socket addresses, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit the use of the ICMP protocol

`disable-icmp`|ALL|When you want to prevent a container from using ICMP protocol, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit the use of the TCP protocol

`disable-tcp`|ALL|When you want to prevent a container from using TCP protocol, you can use this rule to disable it.|-|AppArmor
BPF +| | |Prohibit the use of the UDP protocol

`disable-udp`|ALL|When you want to prevent a container from using UDP protocol, you can use this rule to disable it.|-|AppArmor
BPF | |Restrict Specific Executable|-|ALL|This rule extends the use cases of 'Mitigating Information Leakage' and 'Disabling Sensitive Operations', it allows user to apply restrictions only to specific executable programs within containers.

Restricting specified executable programs serves two purposes:
1). Preventing sandbox policies from affecting the execution of application services within containers.
2).Restricting specified executable programs within containers increases the cost and difficulty for attackers

For example, this feature can be used to restrict programs like busybox, bash, sh, curl within containers, preventing attackers from using them to execute sensitive operations. Meanwhile, the application services is unaffected by sandbox policies and can continue to access ServiceAccount tokens and perform other tasks normally.

*Note: Due to the implementation principles of BPF LSM, this feature cannot be provided by the BPF enforcer.*|Enable sandbox restrictions for specified executable programs.|AppArmor |**Vulnerability Mitigation**|-|Mitigate cgroups & lxcfs escape

`cgroups-lxcfs-escape-mitigation`|ALL|If users mount the host's cgroupfs into a container or use lxcfs to provide a resource view for the container, there may be a risk of container escape in both scenarios. Attackers could manipulate cgroupfs from within the container to achieve container escape.

This rule can also be used to defend against [CVE-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/) vulnerability exploitation.|AppArmor Enforcer prevents writing to:
/\*\*/release_agent,
/\*\*/devices/device.allow,
/\*\*/devices/\*\*/device.allow,
/\*\*/devices/cgroup.procs,
/\*\*/devices/\*\*/cgroup.procs,
/\*\*/devices/task,
/\*\*/devices/\*\*/task,

BPF Enforcer prevents writing to:
/\*\*/release_agent
/\*\*/devices.allow
/\*\*/cgroup.procs
/\*\*/devices/tasks
|AppArmor
BPF | |-|Mitigate the ability to override runc to escape

`runc-override-mitigation`|ALL|The rule is designed to mitigate vulnerabilities such as [CVE-2019-5736](https://github.com/advisories/GHSA-gxmr-w5mj-v8hh) that exploit container escape by tampering with the host machine's runc.|Disallow writing to `/**/runc` files|AppArmor
BPF diff --git a/docs/guides/policies_and_rules/built_in_rules.zh_CN.md b/docs/guides/policies_and_rules/built_in_rules.zh_CN.md index cbeacee..392bf57 100644 --- a/docs/guides/policies_and_rules/built_in_rules.zh_CN.md +++ b/docs/guides/policies_and_rules/built_in_rules.zh_CN.md @@ -40,6 +40,13 @@ | | |禁止设置文件的可执行属性

`disable-chmod-x-bit`|ALL|此规则禁止容器进程通过 chmod 相关系统调用修改文件权限,创建可执行文件。

当攻击者通过漏洞获取容器内的控制权后,通常会尝试下载其他攻击代码、工具到容器内实施进一步的攻击(权限提升、横向渗透、挖矿等)。在这个攻击链路中,攻击者通常会调用 chmod 相关系统调用(chmod/fchmod/fchmodat/fchmodat2),设置文件的可执行权限。|禁止通过 chmod 相关系统调用,设置文件的 execute/search 权限。|Seccomp | | |禁止设置文件的 SUID/SGID 属性

`disable-chmod-s-bit`|ALL|此规则禁止容器进程通过 chmod 相关系统调用修改文件属性,设置文件的 s 标记位(set-user-ID, set-group-ID)。

在某些场景下,攻击者可能会尝试调用 chmod 系列的系统调用(chmod/fchmod/fchmodat/fchmodat2),通过设置文件的 s 标记位(set-user-ID, set-group-ID)来实施权限提升攻击。|禁止通过 chmod 相关系统调用,设置文件的 set-user-ID/set-group-ID 属性。|Seccomp | | |禁止执行 sudo、su 命令

`disable-su-sudo`|ALL|此规则禁止容器进程执行 sudo/su 命令进行权限提升。

当容器内的进程以非 root 用户运行时,攻击者需要先提权至 root 用户进行后续攻击。而 sudo/su 命令是本地提权的常见途径之一。|禁止 sudo、su 执行

有些基础镜像会动态链接 su 到 /bin/busybox,此情况下还需配合“禁止执行 busybox 命令”策略使用|AppArmor
BPF +| |其他 |禁止网络访问

`disable-network`|ALL|此规则禁止容器进程访问网络。|-|AppArmor
BPF +| | |禁止使用 inet4 地址的网络访问

`disable-inet`, `disable-ipv4`|ALL|此规则禁止容器进程通过 IPv4 地址访问网络。|-|AppArmor
BPF +| | |禁止使用 inet6 地址的网络访问

`disable-inet6`, `disable-ipv6`|ALL|此规则禁止容器进程通过 IPv6 地址访问网络。|-|AppArmor
BPF +| | |禁止使用 UDS 地址的网络访问

`disable-unix-domain-socket`|ALL|此规则禁止容器进程通过 UNIX domain socket 地址访问网络。|-|AppArmor
BPF +| | |禁止使用 ICMP 网络协议

`disable-icmp`|ALL|此规则禁止容器进程使用 ICMP 网络协议。|-|AppArmor
BPF +| | |禁止使用 TCP 网络协议

`disable-tcp`|ALL|此规则禁止容器进程使用 TCP 网络协议。|-|AppArmor
BPF +| | |禁止使用 UDP 网络协议

`disable-udp`|ALL|此规则禁止容器进程使用 UDP 网络协议。|-|AppArmor
BPF | |限制特定可执行文件|-|ALL|此规则对 “容器信息泄漏缓解” 和 “容器敏感命令限制” 两类策略的使用场景进行了扩充,使用户可以只对容器内的特定可执行文件及其子进程进行限制。

对指定的可执行文件进行限制,实现两个目的:
1). 避免沙箱策略影响容器内应用服务的正常执行
2). 对容器内指定可执行文件进行限制,增加攻击者成本和难度。

例如,可以利用此功能对容器中的 busybox、bash、sh、curl 进行限制,阻止攻击者利用它们来执行敏感操作。与此同时,应用服务的运行则不受沙箱策略的限制,可以正常执行读取 ServiceAccount token 等敏感操作。

注:受限于 BPF LSM 的实现原理,BPF enforcer 无法提供此功能|为特定可执行文件开启沙箱限制|AppArmor |**Vulnerability Mitigation**|-|缓解 cgroups & lxcfs 逃逸

`cgroups-lxcfs-escape-mitigation`|ALL|若用户将宿主机的 cgroupfs 挂载进容器,或使用 lxcfs 为容器提供资源视图。在这两种场景下可能存在容器逃逸风险,攻击者可以在容器内改写 cgroupfs 实施容器逃逸。

此规则也可用于防御 [CVE-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/) 漏洞利用。|AppArmor Enforcer 阻止在容器内修改:
/\*\*/release_agent,
/\*\*/devices/device.allow,
/\*\*/devices/\*\*/device.allow,
/\*\*/devices/cgroup.procs,
/\*\*/devices/\*\*/cgroup.procs,
/\*\*/devices/task,
/\*\*/devices/\*\*/task,

BPF Enforcer 阻止在容器内修改:
/\*\*/release_agent
/\*\*/devices.allow
/\*\*/cgroup.procs
/\*\*/devices/tasks
|AppArmor
BPF | |-|缓解通过改写 runc 实现的容器逃逸

`runc-override-mitigation`|ALL|本策略用于缓解通过改写宿主机 runc 从而实现容器逃逸的漏洞,例如 [CVE-2019-5736](https://github.com/advisories/GHSA-gxmr-w5mj-v8hh)。|禁止改写 /**/runc 文件|AppArmor
BPF diff --git a/website/docs/guides/policies_and_rules/built_in_rules/attack_protection.md b/website/docs/guides/policies_and_rules/built_in_rules/attack_protection.md index 54a3ad0..61fed15 100644 --- a/website/docs/guides/policies_and_rules/built_in_rules/attack_protection.md +++ b/website/docs/guides/policies_and_rules/built_in_rules/attack_protection.md @@ -267,6 +267,91 @@ Some base images may symlink su to `/bin/busybox`. In this scenario, it's also n * BPF ::: +## Others +### `disable-network` +Prohibit all network access. + +:::note[Description] +When you want to prevent a container from accessing the network, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet`, `disable-ipv4` +Prohibit accessing the network via inet4 addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via IPv4 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet6`, `disable-ipv6` +Prohibit accessing the network via inet6 addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via IPv6 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-unix-domain-socket` +Prohibit accessing the network via UDS addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via Unix Domain Socket addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-icmp` +Prohibit the use of the ICMP protocol. + +:::note[Description] +When you want to prevent a container from using ICMP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-tcp` +Prohibit the use of the TCP protocol. + +:::note[Description] +When you want to prevent a container from using TCP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-udp` +Prohibit the use of the UDP protocol. + +:::note[Description] +When you want to prevent a container from using UDP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + ## Restricting Specific Executable It extends the use cases of [Mitigating Information Leakage](#mitigating-information-leakage) and [Disabling Sensitive Operations](#disabling-sensitive-operations), it allows user to apply restrictions only to specific executable programs within containers. diff --git a/website/i18n/zh-cn/docusaurus-plugin-content-docs/current/guides/policies_and_rules/built_in_rules/attack_protection.md b/website/i18n/zh-cn/docusaurus-plugin-content-docs/current/guides/policies_and_rules/built_in_rules/attack_protection.md index 6c7d1da..61fed15 100644 --- a/website/i18n/zh-cn/docusaurus-plugin-content-docs/current/guides/policies_and_rules/built_in_rules/attack_protection.md +++ b/website/i18n/zh-cn/docusaurus-plugin-content-docs/current/guides/policies_and_rules/built_in_rules/attack_protection.md @@ -4,6 +4,7 @@ description: Rules against penetration tactics in the container environment. --- # Attack Protection +These rules are used to counter penetration tactics in the container environment, such as mitigating container information leakage and prohibiting execution of sensitive actions. ## Mitigating Information Leakage @@ -26,8 +27,6 @@ Disallow reading ServiceAccount-related files. * BPF ::: - - ### `mitigate-disk-device-number-leak` Mitigating host disk device number leakage. @@ -45,8 +44,6 @@ isallow reading `/proc/[PID]/mountinfo` and `/proc/partitions` files. * BPF ::: - - ### `mitigate-overlayfs-leak` Mitigating container overlayfs path leakage. @@ -66,8 +63,6 @@ This rule may impact some functionality of the mount command or syscall within c * BPF ::: - - ### `mitigate-host-ip-leak` Mitigating host IP leakage. @@ -85,8 +80,6 @@ Disallow reading ARP address resolution tables (such as `/proc/net/arp`, `/proc/ * BPF ::: - - ### `disallow-metadata-service` Disallow access to the metadata service. @@ -105,8 +98,6 @@ Prohibit connections to Instance Metadata Services' IP addresses. * BPF ::: - - ## Disabling Sensitive Operations ### `disable-write-etc` @@ -126,8 +117,6 @@ Disallow writing to the `/etc` directory. * BPF ::: - - ### `disable-busybox` Prohibit the execution of busybox command. @@ -147,8 +136,6 @@ If containerized services rely on busybox or related bash commands, enabling thi * BPF ::: - - ### `disable-shell` Prohibit the creation of Unix shells. @@ -170,8 +157,6 @@ Some base images may symlink sh to `/bin/busybox`. In this scenario, it's also n * BPF ::: - - ### `disable-wget` Prohibit the execution of wget command. @@ -193,8 +178,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-curl` Prohibit the execution of curl command. @@ -214,8 +197,6 @@ Prohibit the execution of curl command. * BPF ::: - - ### `disable-chmod` Prohibit the execution of chmod command. @@ -235,8 +216,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-chmod-x-bit` Prohibit setting the execute/search bit of a file. @@ -253,8 +232,6 @@ Prohibit setting the execute/search bit of a file with `chmod`, `fchmod`, `fchmo * Seccomp ::: - - ### `disable-chmod-s-bit` Prohibit setting the SUID/SGID bit of a file. @@ -271,8 +248,6 @@ Prohibit setting the set-user-ID/set-group-ID bit of a file with `chmod`, `fchmo * Seccomp ::: - - ### `disable-su-sudo` Prohibit the execution of su and sudo command. @@ -292,10 +267,92 @@ Some base images may symlink su to `/bin/busybox`. In this scenario, it's also n * BPF ::: +## Others +### `disable-network` +Prohibit all network access. +:::note[Description] +When you want to prevent a container from accessing the network, you can use this rule to disable it. +::: -## Restricting Specific Executable +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet`, `disable-ipv4` +Prohibit accessing the network via inet4 addresses. +:::note[Description] +When you want to prevent a container from accessing the network via IPv4 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet6`, `disable-ipv6` +Prohibit accessing the network via inet6 addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via IPv6 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-unix-domain-socket` +Prohibit accessing the network via UDS addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via Unix Domain Socket addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-icmp` +Prohibit the use of the ICMP protocol. + +:::note[Description] +When you want to prevent a container from using ICMP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-tcp` +Prohibit the use of the TCP protocol. + +:::note[Description] +When you want to prevent a container from using TCP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-udp` +Prohibit the use of the UDP protocol. + +:::note[Description] +When you want to prevent a container from using UDP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +## Restricting Specific Executable It extends the use cases of [Mitigating Information Leakage](#mitigating-information-leakage) and [Disabling Sensitive Operations](#disabling-sensitive-operations), it allows user to apply restrictions only to specific executable programs within containers. @@ -316,4 +373,3 @@ Enable sandbox restrictions for specified executable programs. :::tip[Supported Enforcer] * Apprmor ::: - diff --git a/website/i18n/zh-cn/docusaurus-plugin-content-docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md b/website/i18n/zh-cn/docusaurus-plugin-content-docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md index 6c7d1da..61fed15 100644 --- a/website/i18n/zh-cn/docusaurus-plugin-content-docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md +++ b/website/i18n/zh-cn/docusaurus-plugin-content-docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md @@ -4,6 +4,7 @@ description: Rules against penetration tactics in the container environment. --- # Attack Protection +These rules are used to counter penetration tactics in the container environment, such as mitigating container information leakage and prohibiting execution of sensitive actions. ## Mitigating Information Leakage @@ -26,8 +27,6 @@ Disallow reading ServiceAccount-related files. * BPF ::: - - ### `mitigate-disk-device-number-leak` Mitigating host disk device number leakage. @@ -45,8 +44,6 @@ isallow reading `/proc/[PID]/mountinfo` and `/proc/partitions` files. * BPF ::: - - ### `mitigate-overlayfs-leak` Mitigating container overlayfs path leakage. @@ -66,8 +63,6 @@ This rule may impact some functionality of the mount command or syscall within c * BPF ::: - - ### `mitigate-host-ip-leak` Mitigating host IP leakage. @@ -85,8 +80,6 @@ Disallow reading ARP address resolution tables (such as `/proc/net/arp`, `/proc/ * BPF ::: - - ### `disallow-metadata-service` Disallow access to the metadata service. @@ -105,8 +98,6 @@ Prohibit connections to Instance Metadata Services' IP addresses. * BPF ::: - - ## Disabling Sensitive Operations ### `disable-write-etc` @@ -126,8 +117,6 @@ Disallow writing to the `/etc` directory. * BPF ::: - - ### `disable-busybox` Prohibit the execution of busybox command. @@ -147,8 +136,6 @@ If containerized services rely on busybox or related bash commands, enabling thi * BPF ::: - - ### `disable-shell` Prohibit the creation of Unix shells. @@ -170,8 +157,6 @@ Some base images may symlink sh to `/bin/busybox`. In this scenario, it's also n * BPF ::: - - ### `disable-wget` Prohibit the execution of wget command. @@ -193,8 +178,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-curl` Prohibit the execution of curl command. @@ -214,8 +197,6 @@ Prohibit the execution of curl command. * BPF ::: - - ### `disable-chmod` Prohibit the execution of chmod command. @@ -235,8 +216,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-chmod-x-bit` Prohibit setting the execute/search bit of a file. @@ -253,8 +232,6 @@ Prohibit setting the execute/search bit of a file with `chmod`, `fchmod`, `fchmo * Seccomp ::: - - ### `disable-chmod-s-bit` Prohibit setting the SUID/SGID bit of a file. @@ -271,8 +248,6 @@ Prohibit setting the set-user-ID/set-group-ID bit of a file with `chmod`, `fchmo * Seccomp ::: - - ### `disable-su-sudo` Prohibit the execution of su and sudo command. @@ -292,10 +267,92 @@ Some base images may symlink su to `/bin/busybox`. In this scenario, it's also n * BPF ::: +## Others +### `disable-network` +Prohibit all network access. +:::note[Description] +When you want to prevent a container from accessing the network, you can use this rule to disable it. +::: -## Restricting Specific Executable +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet`, `disable-ipv4` +Prohibit accessing the network via inet4 addresses. +:::note[Description] +When you want to prevent a container from accessing the network via IPv4 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet6`, `disable-ipv6` +Prohibit accessing the network via inet6 addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via IPv6 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-unix-domain-socket` +Prohibit accessing the network via UDS addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via Unix Domain Socket addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-icmp` +Prohibit the use of the ICMP protocol. + +:::note[Description] +When you want to prevent a container from using ICMP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-tcp` +Prohibit the use of the TCP protocol. + +:::note[Description] +When you want to prevent a container from using TCP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-udp` +Prohibit the use of the UDP protocol. + +:::note[Description] +When you want to prevent a container from using UDP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +## Restricting Specific Executable It extends the use cases of [Mitigating Information Leakage](#mitigating-information-leakage) and [Disabling Sensitive Operations](#disabling-sensitive-operations), it allows user to apply restrictions only to specific executable programs within containers. @@ -316,4 +373,3 @@ Enable sandbox restrictions for specified executable programs. :::tip[Supported Enforcer] * Apprmor ::: - diff --git a/website/versioned_docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md b/website/versioned_docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md index 6c7d1da..61fed15 100644 --- a/website/versioned_docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md +++ b/website/versioned_docs/version-v0.6/guides/policies_and_rules/built_in_rules/attack_protection.md @@ -4,6 +4,7 @@ description: Rules against penetration tactics in the container environment. --- # Attack Protection +These rules are used to counter penetration tactics in the container environment, such as mitigating container information leakage and prohibiting execution of sensitive actions. ## Mitigating Information Leakage @@ -26,8 +27,6 @@ Disallow reading ServiceAccount-related files. * BPF ::: - - ### `mitigate-disk-device-number-leak` Mitigating host disk device number leakage. @@ -45,8 +44,6 @@ isallow reading `/proc/[PID]/mountinfo` and `/proc/partitions` files. * BPF ::: - - ### `mitigate-overlayfs-leak` Mitigating container overlayfs path leakage. @@ -66,8 +63,6 @@ This rule may impact some functionality of the mount command or syscall within c * BPF ::: - - ### `mitigate-host-ip-leak` Mitigating host IP leakage. @@ -85,8 +80,6 @@ Disallow reading ARP address resolution tables (such as `/proc/net/arp`, `/proc/ * BPF ::: - - ### `disallow-metadata-service` Disallow access to the metadata service. @@ -105,8 +98,6 @@ Prohibit connections to Instance Metadata Services' IP addresses. * BPF ::: - - ## Disabling Sensitive Operations ### `disable-write-etc` @@ -126,8 +117,6 @@ Disallow writing to the `/etc` directory. * BPF ::: - - ### `disable-busybox` Prohibit the execution of busybox command. @@ -147,8 +136,6 @@ If containerized services rely on busybox or related bash commands, enabling thi * BPF ::: - - ### `disable-shell` Prohibit the creation of Unix shells. @@ -170,8 +157,6 @@ Some base images may symlink sh to `/bin/busybox`. In this scenario, it's also n * BPF ::: - - ### `disable-wget` Prohibit the execution of wget command. @@ -193,8 +178,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-curl` Prohibit the execution of curl command. @@ -214,8 +197,6 @@ Prohibit the execution of curl command. * BPF ::: - - ### `disable-chmod` Prohibit the execution of chmod command. @@ -235,8 +216,6 @@ Some base images may symlink wget to `/bin/busybox`. In this scenario, it's also * BPF ::: - - ### `disable-chmod-x-bit` Prohibit setting the execute/search bit of a file. @@ -253,8 +232,6 @@ Prohibit setting the execute/search bit of a file with `chmod`, `fchmod`, `fchmo * Seccomp ::: - - ### `disable-chmod-s-bit` Prohibit setting the SUID/SGID bit of a file. @@ -271,8 +248,6 @@ Prohibit setting the set-user-ID/set-group-ID bit of a file with `chmod`, `fchmo * Seccomp ::: - - ### `disable-su-sudo` Prohibit the execution of su and sudo command. @@ -292,10 +267,92 @@ Some base images may symlink su to `/bin/busybox`. In this scenario, it's also n * BPF ::: +## Others +### `disable-network` +Prohibit all network access. +:::note[Description] +When you want to prevent a container from accessing the network, you can use this rule to disable it. +::: -## Restricting Specific Executable +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet`, `disable-ipv4` +Prohibit accessing the network via inet4 addresses. +:::note[Description] +When you want to prevent a container from accessing the network via IPv4 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-inet6`, `disable-ipv6` +Prohibit accessing the network via inet6 addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via IPv6 addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-unix-domain-socket` +Prohibit accessing the network via UDS addresses. + +:::note[Description] +When you want to prevent a container from accessing the network via Unix Domain Socket addresses, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-icmp` +Prohibit the use of the ICMP protocol. + +:::note[Description] +When you want to prevent a container from using ICMP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-tcp` +Prohibit the use of the TCP protocol. + +:::note[Description] +When you want to prevent a container from using TCP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +### `disable-udp` +Prohibit the use of the UDP protocol. + +:::note[Description] +When you want to prevent a container from using UDP protocol, you can use this rule to disable it. +::: + +:::tip[Supported Enforcer] +* AppArmor +* BPF +::: + +## Restricting Specific Executable It extends the use cases of [Mitigating Information Leakage](#mitigating-information-leakage) and [Disabling Sensitive Operations](#disabling-sensitive-operations), it allows user to apply restrictions only to specific executable programs within containers. @@ -316,4 +373,3 @@ Enable sandbox restrictions for specified executable programs. :::tip[Supported Enforcer] * Apprmor ::: - From 2eed3ef63be1875006383c4b887861d4842756d2 Mon Sep 17 00:00:00 2001 From: Danny__Wei Date: Tue, 3 Dec 2024 17:34:34 +0800 Subject: [PATCH 3/3] refactor: Integrate the logic of updating policy objects --- internal/policy/clusterpolicy_controller.go | 109 +++---------- internal/policy/policy_controller.go | 109 +++---------- internal/status/api/v1/manager.go | 120 +++----------- internal/status/api/v1/utils.go | 170 ++++++++++++++++++++ 4 files changed, 238 insertions(+), 270 deletions(-) diff --git a/internal/policy/clusterpolicy_controller.go b/internal/policy/clusterpolicy_controller.go index 591dceb..f00099f 100644 --- a/internal/policy/clusterpolicy_controller.go +++ b/internal/policy/clusterpolicy_controller.go @@ -29,7 +29,6 @@ import ( appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/retry" "k8s.io/client-go/util/workqueue" // informers "k8s.io/client-go/informers/core/v1" @@ -177,71 +176,11 @@ func (c *ClusterPolicyController) handleDeleteVarmorClusterPolicy(name string) e return nil } -func (c *ClusterPolicyController) updateVarmorClusterPolicyStatus( - vcp *varmor.VarmorClusterPolicy, - profileName string, - ready bool, - phase varmor.VarmorPolicyPhase, - condType varmor.VarmorPolicyConditionType, - status apicorev1.ConditionStatus, - reason, message string) error { - - condition := varmor.VarmorPolicyCondition{ - Type: condType, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - } - - regain := false - update := func() (err error) { - if regain { - vcp, err = c.varmorInterface.VarmorClusterPolicies().Get(context.Background(), vcp.Name, metav1.GetOptions{}) - if err != nil { - if k8errors.IsNotFound(err) { - return nil - } - return err - } - } - - exist := false - if condition.Type == varmortypes.VarmorPolicyUpdated { - for i, c := range vcp.Status.Conditions { - if c.Type == varmortypes.VarmorPolicyUpdated { - condition.DeepCopyInto(&vcp.Status.Conditions[i]) - exist = true - break - } - } - } - if !exist { - vcp.Status.Conditions = append(vcp.Status.Conditions, condition) - } - - if profileName != "" { - vcp.Status.ProfileName = profileName - } - vcp.Status.Ready = ready - if phase != varmortypes.VarmorPolicyUnchanged { - vcp.Status.Phase = phase - } - - _, err = c.varmorInterface.VarmorClusterPolicies().UpdateStatus(context.Background(), vcp, metav1.UpdateOptions{}) - if err != nil { - regain = true - } - return err - } - return retry.RetryOnConflict(retry.DefaultRetry, update) -} - func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, logger logr.Logger) (bool, error) { if vcp.Spec.Target.Kind != "Deployment" && vcp.Spec.Target.Kind != "StatefulSet" && vcp.Spec.Target.Kind != "DaemonSet" && vcp.Spec.Target.Kind != "Pod" { err := fmt.Errorf("Target.Kind is not supported") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "This kind of target is not supported.") return true, err @@ -250,7 +189,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log if vcp.Spec.Target.Name == "" && vcp.Spec.Target.Selector == nil { err := fmt.Errorf("target.Name and target.Selector are empty") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "You should specify the target workload by name or selector.") return true, err @@ -259,7 +198,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log if vcp.Spec.Target.Name != "" && vcp.Spec.Target.Selector != nil { err := fmt.Errorf("target.Name and target.Selector are exclusive") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "You shouldn't specify the target workload by both name and selector.") return true, err @@ -268,7 +207,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log if vcp.Spec.Policy.Mode == varmortypes.EnhanceProtectMode && vcp.Spec.Policy.EnhanceProtect == nil { err := fmt.Errorf("the EnhanceProtect field is not set when running with EnhanceProtect mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The EnhanceProtect field should be set when running with EnhanceProtect mode.") return true, err @@ -277,7 +216,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log if !c.enableBehaviorModeling && vcp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode { err := fmt.Errorf("the BehaviorModeling mode is not enabled") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The BehaviorModeling feature is not enabled.") return true, err @@ -286,7 +225,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log if c.enableBehaviorModeling && vcp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode && vcp.Spec.Policy.ModelingOptions == nil { err := fmt.Errorf("the ModelingOptions field is not set when running with BehaviorModeling mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The ModelingOptions field should be set when running with BehaviorModeling mode.") return true, err @@ -299,7 +238,7 @@ func (c *ClusterPolicyController) ignoreAdd(vcp *varmor.VarmorClusterPolicy, log err := fmt.Errorf("the length of ArmorProfile name is exceed 63. name: %s, length: %d", profileName, len(profileName)) logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") msg := fmt.Sprintf("The length of VarmorClusterPolicy object name is too long, please limit it to %d bytes", 63-len(varmorprofile.ClusterProfileNameTemplate)+4-len(varmorconfig.Namespace)) - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", msg) return true, err @@ -323,20 +262,20 @@ func (c *ClusterPolicyController) handleAddVarmorClusterPolicy(vcp *varmor.Varmo ap, err := varmorprofile.NewArmorProfile(vcp, c.varmorInterface, true) if err != nil { logger.Error(err, "NewArmorProfile()") - err = c.updateVarmorClusterPolicyStatus(vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Error", err.Error()) if err != nil { - logger.Error(err, "updateVarmorClusterPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } return nil } logger.Info("update VarmorClusterPolicy/status (created=true)") - err = c.updateVarmorClusterPolicyStatus(vcp, ap.Spec.Profile.Name, false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyCreated, apicorev1.ConditionTrue, "", "") + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, vcp, ap.Spec.Profile.Name, false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyCreated, apicorev1.ConditionTrue, "", "") if err != nil { - logger.Error(err, "updateVarmorClusterPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } @@ -378,7 +317,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy if !reflect.DeepEqual(newVp.Spec.Target, oldAp.Spec.Target) { err := fmt.Errorf("disallow modifying spec.target") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying the target of VarmorClusterPolicy is not allowed. You need to recreate the VarmorClusterPolicy object.") return true, err @@ -389,7 +328,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy oldAp.Spec.BehaviorModeling.Duration == 0 { err := fmt.Errorf("disallow switching spec.policy.mode from others to BehaviorModeling") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the mode from others to BehaviorModeling is not allowed. You need to recreate the VarmorClusterPolicy object.") return true, err @@ -400,7 +339,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy oldAp.Spec.BehaviorModeling.Duration != 0 { err := fmt.Errorf("disallow switching spec.policy.mode from BehaviorModeling to others") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the mode from BehaviorModeling to others is not allowed. You need to recreate the VarmorClusterPolicy object.") return true, err @@ -412,7 +351,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy if newEnforcers&oldEnforcers != oldEnforcers { err := fmt.Errorf("disallow shutting down the enforcer that has been activated") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying a policy to remove an already-set enforcer is not allowed. To remove enforcers, you must recreate the VarmorClusterPolicy object.") return true, err @@ -422,7 +361,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy if newEnforcers != oldEnforcers && newVp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode { err := fmt.Errorf("disallow switching the enforcer") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the enforcer during modeling is not allowed. You need to recreate the VarmorClusterPolicy object.") return true, err @@ -433,7 +372,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy newVp.Spec.Policy.EnhanceProtect == nil { err := fmt.Errorf("the EnhanceProtect field is not set when running with EnhanceProtect mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "The EnhanceProtect field should be set when running with EnhanceProtect mode.") return true, err @@ -446,12 +385,12 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy newVp.Spec.Policy.ModelingOptions.Duration != oldAp.Spec.BehaviorModeling.Duration { err := fmt.Errorf("disallow modifying the VarmorClusterPolicy that run as BehaviorModeling mode and already completed") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying the VarmorClusterPolicy that run as BehaviorModeling mode and already completed is not allowed. You need to recreate the VarmorClusterPolicy object.") return true, err } else { - err := c.updateVarmorClusterPolicyStatus(newVp, "", true, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") + err := statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", true, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") return true, err } } @@ -461,7 +400,7 @@ func (c *ClusterPolicyController) ignoreUpdate(newVp *varmor.VarmorClusterPolicy newVp.Spec.Policy.ModelingOptions == nil { err := fmt.Errorf("the ModelingOptions field is not set when running with BehaviorModeling mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "The ModelingOptions field should be set when running with BehaviorModeling mode.") return true, err @@ -484,9 +423,9 @@ func (c *ClusterPolicyController) handleUpdateVarmorClusterPolicy(newVp *varmor. // First, reset VarmorClusterPolicy/status logger.Info("1. reset VarmorClusterPolicy/status (updated=true)", "name", newVp.Name) - err := c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") + err := statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") if err != nil { - logger.Error(err, "updateVarmorClusterPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } @@ -495,11 +434,11 @@ func (c *ClusterPolicyController) handleUpdateVarmorClusterPolicy(newVp *varmor. newProfile, err := varmorprofile.GenerateProfile(newVp.Spec.Policy, oldAp.Name, varmorconfig.Namespace, c.varmorInterface, false) if err != nil { logger.Error(err, "GenerateProfile()") - err = c.updateVarmorClusterPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorClusterPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Error", err.Error()) if err != nil { - logger.Error(err, "updateVarmorClusterPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } return nil diff --git a/internal/policy/policy_controller.go b/internal/policy/policy_controller.go index c6c23d8..2ea6631 100644 --- a/internal/policy/policy_controller.go +++ b/internal/policy/policy_controller.go @@ -29,7 +29,6 @@ import ( appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/retry" "k8s.io/client-go/util/workqueue" // informers "k8s.io/client-go/informers/core/v1" @@ -182,71 +181,11 @@ func (c *PolicyController) handleDeleteVarmorPolicy(namespace, name string) erro return nil } -func (c *PolicyController) updateVarmorPolicyStatus( - vp *varmor.VarmorPolicy, - profileName string, - ready bool, - phase varmor.VarmorPolicyPhase, - condType varmor.VarmorPolicyConditionType, - status apicorev1.ConditionStatus, - reason, message string) error { - - condition := varmor.VarmorPolicyCondition{ - Type: condType, - Status: status, - LastTransitionTime: metav1.Now(), - Reason: reason, - Message: message, - } - - regain := false - update := func() (err error) { - if regain { - vp, err = c.varmorInterface.VarmorPolicies(vp.Namespace).Get(context.Background(), vp.Name, metav1.GetOptions{}) - if err != nil { - if k8errors.IsNotFound(err) { - return nil - } - return err - } - } - - exist := false - if condition.Type == varmortypes.VarmorPolicyUpdated { - for i, c := range vp.Status.Conditions { - if c.Type == varmortypes.VarmorPolicyUpdated { - condition.DeepCopyInto(&vp.Status.Conditions[i]) - exist = true - break - } - } - } - if !exist { - vp.Status.Conditions = append(vp.Status.Conditions, condition) - } - - if profileName != "" { - vp.Status.ProfileName = profileName - } - vp.Status.Ready = ready - if phase != varmortypes.VarmorPolicyUnchanged { - vp.Status.Phase = phase - } - - _, err = c.varmorInterface.VarmorPolicies(vp.Namespace).UpdateStatus(context.Background(), vp, metav1.UpdateOptions{}) - if err != nil { - regain = true - } - return err - } - return retry.RetryOnConflict(retry.DefaultRetry, update) -} - func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger) (bool, error) { if vp.Spec.Target.Kind != "Deployment" && vp.Spec.Target.Kind != "StatefulSet" && vp.Spec.Target.Kind != "DaemonSet" && vp.Spec.Target.Kind != "Pod" { err := fmt.Errorf("Target.Kind is not supported") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "This kind of target is not supported.") return true, err @@ -255,7 +194,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger if vp.Spec.Target.Name == "" && vp.Spec.Target.Selector == nil { err := fmt.Errorf("target.Name and target.Selector are empty") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "You should specify the target workload by name or selector.") return true, err @@ -264,7 +203,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger if vp.Spec.Target.Name != "" && vp.Spec.Target.Selector != nil { err := fmt.Errorf("target.Name and target.Selector are exclusive") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "You shouldn't specify the target workload by both both name and selector.") return true, err @@ -273,7 +212,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger if vp.Spec.Policy.Mode == varmortypes.EnhanceProtectMode && vp.Spec.Policy.EnhanceProtect == nil { err := fmt.Errorf("the EnhanceProtect field is not set when running with EnhanceProtect mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The EnhanceProtect field should be set when running with EnhanceProtect mode.") return true, err @@ -282,7 +221,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger if !c.enableBehaviorModeling && vp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode { err := fmt.Errorf("the BehaviorModeling feature is not enabled") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The BehaviorModeling feature is not enabled.") return true, err @@ -291,7 +230,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger if c.enableBehaviorModeling && vp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode && vp.Spec.Policy.ModelingOptions == nil { err := fmt.Errorf("the ModelingOptions field is not set when running with BehaviorModeling mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", "The ModelingOptions field should be set when running with BehaviorModeling mode.") return true, err @@ -304,7 +243,7 @@ func (c *PolicyController) ignoreAdd(vp *varmor.VarmorPolicy, logger logr.Logger err := fmt.Errorf("the length of ArmorProfile name is exceed 63. name: %s, length: %d", profileName, len(profileName)) logger.Error(err, "update VarmorPolicy/status with forbidden info") msg := fmt.Sprintf("The length of VarmorProfile object name is too long, please limit it to %d bytes", 63-len(varmorprofile.ProfileNameTemplate)+4-len(vp.Namespace)) - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Forbidden", msg) return true, err @@ -328,20 +267,20 @@ func (c *PolicyController) handleAddVarmorPolicy(vp *varmor.VarmorPolicy) error ap, err := varmorprofile.NewArmorProfile(vp, c.varmorInterface, false) if err != nil { logger.Error(err, "NewArmorProfile()") - err = c.updateVarmorPolicyStatus(vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyCreated, apicorev1.ConditionFalse, "Error", err.Error()) if err != nil { - logger.Error(err, "updateVarmorPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } return nil } logger.Info("update VarmorPolicy/status (created=true)") - err = c.updateVarmorPolicyStatus(vp, ap.Spec.Profile.Name, false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyCreated, apicorev1.ConditionTrue, "", "") + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, vp, ap.Spec.Profile.Name, false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyCreated, apicorev1.ConditionTrue, "", "") if err != nil { - logger.Error(err, "updateVarmorPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } @@ -383,7 +322,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo if !reflect.DeepEqual(newVp.Spec.Target, oldAp.Spec.Target) { err := fmt.Errorf("disallow modifying spec.target") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying the target of VarmorPolicy is not allowed. You need to recreate the VarmorPolicy object.") return true, err @@ -394,7 +333,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo oldAp.Spec.BehaviorModeling.Duration == 0 { err := fmt.Errorf("disallow switching spec.policy.mode from others to BehaviorModeling") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the mode from others to BehaviorModeling is not allowed. You need to recreate the VarmorPolicy object.") return true, err @@ -405,7 +344,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo oldAp.Spec.BehaviorModeling.Duration != 0 { err := fmt.Errorf("disallow switching spec.policy.mode from BehaviorModeling to others") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the mode from BehaviorModeling to others is not allowed. You need to recreate the VarmorPolicy object.") return true, err @@ -417,7 +356,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo if newEnforcers&oldEnforcers != oldEnforcers { err := fmt.Errorf("disallow shutting down the enforcer that has been activated") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying a policy to remove an already-set enforcer is not allowed. To remove enforcers, you must recreate the VarmorPolicy object.") return true, err @@ -427,7 +366,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo if newEnforcers != oldEnforcers && newVp.Spec.Policy.Mode == varmortypes.BehaviorModelingMode { err := fmt.Errorf("disallow switching the enforcer") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Switching the enforcer during modeling is not allowed. You need to recreate the VarmorPolicy object.") return true, err @@ -438,7 +377,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo newVp.Spec.Policy.EnhanceProtect == nil { err := fmt.Errorf("the EnhanceProtect field is not set when running with EnhanceProtect mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "The EnhanceProtect field should be set when running with EnhanceProtect mode.") return true, err @@ -451,12 +390,12 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo newVp.Spec.Policy.ModelingOptions.Duration != oldAp.Spec.BehaviorModeling.Duration { err := fmt.Errorf("disallow modifying the VarmorPolicy that run as BehaviorModeling mode and already completed") logger.Error(err, "update VarmorPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "Modifying the VarmorPolicy that run as BehaviorModeling mode and already completed is not allowed. You need to recreate the VarmorPolicy object.") return true, err } else { - err := c.updateVarmorPolicyStatus(newVp, "", true, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") + err := statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", true, varmortypes.VarmorPolicyUnchanged, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") return true, err } } @@ -466,7 +405,7 @@ func (c *PolicyController) ignoreUpdate(newVp *varmor.VarmorPolicy, oldAp *varmo newVp.Spec.Policy.ModelingOptions == nil { err := fmt.Errorf("the ModelingOptions field is not set when running with BehaviorModeling mode") logger.Error(err, "update VarmorClusterPolicy/status with forbidden info") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Forbidden", "The ModelingOptions field should be set when running with BehaviorModeling mode.") return true, err @@ -489,9 +428,9 @@ func (c *PolicyController) handleUpdateVarmorPolicy(newVp *varmor.VarmorPolicy, // First, reset VarmorPolicy/status logger.Info("1. reset VarmorPolicy/status (updated=true)", "namesapce", newVp.Namespace, "name", newVp.Name) - err := c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") + err := statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyPending, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionTrue, "", "") if err != nil { - logger.Error(err, "updateVarmorPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } @@ -500,11 +439,11 @@ func (c *PolicyController) handleUpdateVarmorPolicy(newVp *varmor.VarmorPolicy, newProfile, err := varmorprofile.GenerateProfile(newVp.Spec.Policy, oldAp.Name, oldAp.Namespace, c.varmorInterface, false) if err != nil { logger.Error(err, "GenerateProfile()") - err = c.updateVarmorPolicyStatus(newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, + err = statusmanager.UpdateVarmorPolicyStatus(c.varmorInterface, newVp, "", false, varmortypes.VarmorPolicyError, varmortypes.VarmorPolicyUpdated, apicorev1.ConditionFalse, "Error", err.Error()) if err != nil { - logger.Error(err, "updateVarmorPolicyStatus()") + logger.Error(err, "statusmanager.UpdateVarmorClusterPolicyStatus()") return err } return nil diff --git a/internal/status/api/v1/manager.go b/internal/status/api/v1/manager.go index cb58dd3..6174585 100644 --- a/internal/status/api/v1/manager.go +++ b/internal/status/api/v1/manager.go @@ -273,63 +273,23 @@ func (m *StatusManager) updateVarmorPolicyStatus( return nil } - // Prepare for condition - condition := varmor.VarmorPolicyCondition{ - Type: varmortypes.VarmorPolicyReady, - LastTransitionTime: metav1.Now(), - } + var status v1.ConditionStatus + var reason, message string + if ready { - condition.Status = v1.ConditionTrue - condition.Reason = "AllAgentsReady" + status = v1.ConditionTrue + reason = "AllAgentsReady" } else { - condition.Status = v1.ConditionFalse - condition.Reason = "Processing" + status = v1.ConditionFalse + reason = "Processing" if phase == varmortypes.VarmorPolicyError { - condition.Reason = "Error" - condition.Message = fmt.Sprintf("The agents failed processing the profile. Please refer to the status of ArmorProfile object (%s/%s) for more details.", + reason = "Error" + message = fmt.Sprintf("The agents failed processing the profile. Please refer to the status of ArmorProfile object (%s/%s) for more details.", vp.Namespace, vp.Status.ProfileName) } } - regain := false - update := func() (err error) { - if regain { - vp, err = m.varmorInterface.VarmorPolicies(vp.Namespace).Get(context.Background(), vp.Name, metav1.GetOptions{}) - if err != nil { - if k8errors.IsNotFound(err) { - return nil - } - return err - } - } - - // Update condition - exist := false - for i, c := range vp.Status.Conditions { - if c.Type == varmortypes.VarmorPolicyReady { - condition.DeepCopyInto(&vp.Status.Conditions[i]) - exist = true - break - } - } - if !exist { - vp.Status.Conditions = append(vp.Status.Conditions, condition) - } - - // Update status - vp.Status.Ready = ready - if phase != varmortypes.VarmorPolicyUnchanged { - vp.Status.Phase = phase - } - - // Update - _, err = m.varmorInterface.VarmorPolicies(vp.Namespace).UpdateStatus(context.Background(), vp, metav1.UpdateOptions{}) - if err != nil { - regain = true - } - return err - } - return retry.RetryOnConflict(retry.DefaultRetry, update) + return UpdateVarmorPolicyStatus(m.varmorInterface, vp, "", ready, phase, varmortypes.VarmorPolicyReady, status, reason, message) } func (m *StatusManager) updateVarmorClusterPolicyStatus( @@ -342,63 +302,23 @@ func (m *StatusManager) updateVarmorClusterPolicyStatus( return nil } - // Prepare for condition - condition := varmor.VarmorPolicyCondition{ - Type: varmortypes.VarmorPolicyReady, - LastTransitionTime: metav1.Now(), - } + var status v1.ConditionStatus + var reason, message string + if ready { - condition.Status = v1.ConditionTrue - condition.Reason = "AllAgentsReady" + status = v1.ConditionTrue + reason = "AllAgentsReady" } else { - condition.Status = v1.ConditionFalse - condition.Reason = "Processing" + status = v1.ConditionFalse + reason = "Processing" if phase == varmortypes.VarmorPolicyError { - condition.Reason = "Error" - condition.Message = fmt.Sprintf("The agents failed processing the profile. Please refer to the status of ArmorProfile object (%s/%s) for more details.", + reason = "Error" + message = fmt.Sprintf("The agents failed processing the profile. Please refer to the status of ArmorProfile object (%s/%s) for more details.", varmorconfig.Namespace, vcp.Status.ProfileName) } } - regain := false - update := func() (err error) { - if regain { - vcp, err = m.varmorInterface.VarmorClusterPolicies().Get(context.Background(), vcp.Name, metav1.GetOptions{}) - if err != nil { - if k8errors.IsNotFound(err) { - return nil - } - return err - } - } - - // Update condition - exist := false - for i, c := range vcp.Status.Conditions { - if c.Type == varmortypes.VarmorPolicyReady { - condition.DeepCopyInto(&vcp.Status.Conditions[i]) - exist = true - break - } - } - if !exist { - vcp.Status.Conditions = append(vcp.Status.Conditions, condition) - } - - // Update status - vcp.Status.Ready = ready - if phase != varmortypes.VarmorPolicyUnchanged { - vcp.Status.Phase = phase - } - - // Update - _, err = m.varmorInterface.VarmorClusterPolicies().UpdateStatus(context.Background(), vcp, metav1.UpdateOptions{}) - if err != nil { - regain = true - } - return err - } - return retry.RetryOnConflict(retry.DefaultRetry, update) + return UpdateVarmorClusterPolicyStatus(m.varmorInterface, vcp, "", ready, phase, varmortypes.VarmorPolicyReady, status, reason, message) } func (m *StatusManager) updateAllCRStatus(logger logr.Logger) { diff --git a/internal/status/api/v1/utils.go b/internal/status/api/v1/utils.go index 2a5f314..cb9af31 100644 --- a/internal/status/api/v1/utils.go +++ b/internal/status/api/v1/utils.go @@ -15,17 +15,21 @@ package statusmanagerv1 import ( + "context" "fmt" "io" "strings" "github.com/gin-gonic/gin" v1 "k8s.io/api/core/v1" + k8errors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/util/retry" varmor "github.com/bytedance/vArmor/apis/varmor/v1beta1" varmorprofile "github.com/bytedance/vArmor/internal/profile" varmortypes "github.com/bytedance/vArmor/internal/types" + varmorinterface "github.com/bytedance/vArmor/pkg/client/clientset/versioned/typed/varmor/v1beta1" ) func getHttpBody(c *gin.Context) ([]byte, error) { @@ -142,3 +146,169 @@ func newArmorProfileModelCondition( Message: message, } } + +func UpdateVarmorPolicyStatus( + i varmorinterface.CrdV1beta1Interface, + vp *varmor.VarmorPolicy, + profileName string, + ready bool, + phase varmor.VarmorPolicyPhase, + condType varmor.VarmorPolicyConditionType, + status v1.ConditionStatus, + reason, message string) error { + + // Prepare for condition + condition := varmor.VarmorPolicyCondition{ + Type: condType, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } + + regain := false + update := func() (err error) { + if regain { + vp, err = i.VarmorPolicies(vp.Namespace).Get(context.Background(), vp.Name, metav1.GetOptions{}) + if err != nil { + if k8errors.IsNotFound(err) { + return nil + } + return err + } + } + + // Update condition + exist := false + switch condition.Type { + case varmortypes.VarmorPolicyCreated: + for i, c := range vp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyCreated { + condition.DeepCopyInto(&vp.Status.Conditions[i]) + exist = true + break + } + } + case varmortypes.VarmorPolicyUpdated: + for i, c := range vp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyUpdated { + condition.DeepCopyInto(&vp.Status.Conditions[i]) + exist = true + break + } + } + case varmortypes.VarmorPolicyReady: + for i, c := range vp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyReady { + condition.DeepCopyInto(&vp.Status.Conditions[i]) + exist = true + break + } + } + } + if !exist { + vp.Status.Conditions = append(vp.Status.Conditions, condition) + } + + // Update profile name + if profileName != "" { + vp.Status.ProfileName = profileName + } + + // Update status + vp.Status.Ready = ready + if phase != varmortypes.VarmorPolicyUnchanged { + vp.Status.Phase = phase + } + + _, err = i.VarmorPolicies(vp.Namespace).UpdateStatus(context.Background(), vp, metav1.UpdateOptions{}) + if err != nil { + regain = true + } + return err + } + return retry.RetryOnConflict(retry.DefaultRetry, update) +} + +func UpdateVarmorClusterPolicyStatus( + i varmorinterface.CrdV1beta1Interface, + vcp *varmor.VarmorClusterPolicy, + profileName string, + ready bool, + phase varmor.VarmorPolicyPhase, + condType varmor.VarmorPolicyConditionType, + status v1.ConditionStatus, + reason, message string) error { + + // Prepare for condition + condition := varmor.VarmorPolicyCondition{ + Type: condType, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } + + regain := false + update := func() (err error) { + if regain { + vcp, err = i.VarmorClusterPolicies().Get(context.Background(), vcp.Name, metav1.GetOptions{}) + if err != nil { + if k8errors.IsNotFound(err) { + return nil + } + return err + } + } + + // Update condition + exist := false + switch condition.Type { + case varmortypes.VarmorPolicyCreated: + for i, c := range vcp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyCreated { + condition.DeepCopyInto(&vcp.Status.Conditions[i]) + exist = true + break + } + } + case varmortypes.VarmorPolicyUpdated: + for i, c := range vcp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyUpdated { + condition.DeepCopyInto(&vcp.Status.Conditions[i]) + exist = true + break + } + } + case varmortypes.VarmorPolicyReady: + for i, c := range vcp.Status.Conditions { + if c.Type == varmortypes.VarmorPolicyReady { + condition.DeepCopyInto(&vcp.Status.Conditions[i]) + exist = true + break + } + } + } + if !exist { + vcp.Status.Conditions = append(vcp.Status.Conditions, condition) + } + + // Update profile name + if profileName != "" { + vcp.Status.ProfileName = profileName + } + + // Update status + vcp.Status.Ready = ready + if phase != varmortypes.VarmorPolicyUnchanged { + vcp.Status.Phase = phase + } + + _, err = i.VarmorClusterPolicies().UpdateStatus(context.Background(), vcp, metav1.UpdateOptions{}) + if err != nil { + regain = true + } + return err + } + return retry.RetryOnConflict(retry.DefaultRetry, update) +}