update charts
diff --git a/charts/metallb/policy/controller.rego b/charts/metallb/policy/controller.rego
new file mode 100644
index 0000000..716eeb7
--- /dev/null
+++ b/charts/metallb/policy/controller.rego
@@ -0,0 +1,16 @@
+package main
+
+# validate serviceAccountName
+deny[msg] {
+ input.kind == "Deployment"
+ serviceAccountName := input.spec.template.spec.serviceAccountName
+ not serviceAccountName == "RELEASE-NAME-metallb-controller"
+ msg = sprintf("controller serviceAccountName '%s' does not match expected value", [serviceAccountName])
+}
+
+# validate node selector includes builtin when custom ones are provided
+deny[msg] {
+ input.kind == "Deployment"
+ not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux"
+ msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'"
+}
diff --git a/charts/metallb/policy/rbac.rego b/charts/metallb/policy/rbac.rego
new file mode 100644
index 0000000..047345e
--- /dev/null
+++ b/charts/metallb/policy/rbac.rego
@@ -0,0 +1,27 @@
+package main
+
+# Validate PSP exists in ClusterRole :controller
+deny[msg] {
+ input.kind == "ClusterRole"
+ input.metadata.name == "metallb:controller"
+ input.rules[3] == {
+ "apiGroups": ["policy"],
+ "resources": ["podsecuritypolicies"],
+ "resourceNames": ["metallb-controller"],
+ "verbs": ["use"]
+ }
+ msg = "ClusterRole metallb:controller does not include PSP rule"
+}
+
+# Validate PSP exists in ClusterRole :speaker
+deny[msg] {
+ input.kind == "ClusterRole"
+ input.metadata.name == "metallb:speaker"
+ input.rules[3] == {
+ "apiGroups": ["policy"],
+ "resources": ["podsecuritypolicies"],
+ "resourceNames": ["metallb-controller"],
+ "verbs": ["use"]
+ }
+ msg = "ClusterRole metallb:speaker does not include PSP rule"
+}
diff --git a/charts/metallb/policy/speaker.rego b/charts/metallb/policy/speaker.rego
new file mode 100644
index 0000000..d4d8137
--- /dev/null
+++ b/charts/metallb/policy/speaker.rego
@@ -0,0 +1,30 @@
+package main
+
+# validate serviceAccountName
+deny[msg] {
+ input.kind == "DaemonSet"
+ serviceAccountName := input.spec.template.spec.serviceAccountName
+ not serviceAccountName == "RELEASE-NAME-metallb-speaker"
+ msg = sprintf("speaker serviceAccountName '%s' does not match expected value", [serviceAccountName])
+}
+
+# validate METALLB_ML_SECRET_KEY (memberlist)
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.containers[0].env[5].name == "METALLB_ML_SECRET_KEY_PATH"
+ msg = "speaker env does not contain METALLB_ML_SECRET_KEY_PATH at env[5]"
+}
+
+# validate node selector includes builtin when custom ones are provided
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.nodeSelector["kubernetes.io/os"] == "linux"
+ msg = "controller nodeSelector does not include '\"kubernetes.io/os\": linux'"
+}
+
+# validate tolerations include the builtins when custom ones are provided
+deny[msg] {
+ input.kind == "DaemonSet"
+ not input.spec.template.spec.tolerations[0] == { "key": "node-role.kubernetes.io/master", "effect": "NoSchedule", "operator": "Exists" }
+ msg = "controller tolerations does not include node-role.kubernetes.io/master:NoSchedule"
+}