From 91fa53281829597f677719b0d856fee5b7f9098e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Jeanneret?= Date: Mon, 6 Jul 2026 14:41:23 +0200 Subject: [PATCH] security: restrict BareMetalHost creation to OpenStack namespaces Add ValidatingAdmissionPolicy to enforce namespace-scoped access controls for BareMetalHost resources while maintaining watchAllNamespaces: true in the Bare Metal Operator configuration. Changes: - Add ValidatingAdmissionPolicy restricting BareMetalHost CREATE operations to 'openstack' and 'openstack-operators' namespaces only - Add ValidatingAdmissionPolicyBinding to apply policy cluster-wide - Grant ArgoCD RBAC permissions for admissionregistration.k8s.io resources using explicit verbs (no wildcards) following least-privilege pattern - Configure ArgoCD sync-wave -35 to deploy policy before namespace creation - Create baremetalhost-validation component integrated with provisioning-config This prevents unauthorized bare metal host enrollment from arbitrary namespaces while preserving operational flexibility required by RHOSO. Co-Authored-By: Claude Sonnet 4.5 --- .../argocd/annotations/kustomization.yaml | 15 +++++++++++ .../kustomization.yaml | 6 +++++ .../policy-binding.yaml | 11 ++++++++ .../baremetalhost-validation/policy.yaml | 25 +++++++++++++++++++ .../provisioning-config/kustomization.yaml | 2 ++ .../enable/clusterrole.yaml | 13 ++++++++++ 6 files changed, 72 insertions(+) create mode 100644 components/dependencies/baremetalhost-validation/kustomization.yaml create mode 100644 components/dependencies/baremetalhost-validation/policy-binding.yaml create mode 100644 components/dependencies/baremetalhost-validation/policy.yaml diff --git a/components/argocd/annotations/kustomization.yaml b/components/argocd/annotations/kustomization.yaml index 495f550..b4facbd 100644 --- a/components/argocd/annotations/kustomization.yaml +++ b/components/argocd/annotations/kustomization.yaml @@ -33,6 +33,21 @@ patches: value: argocd.argoproj.io/managed-by: openshift-gitops argocd.argoproj.io/sync-wave: "-31" + # --- Wave -35: Create ValidatingAdmissionPolicy before namespaces (security control) --- + - target: + kind: ValidatingAdmissionPolicy + name: restrict-baremetalhost-to-openstack.metal3.io + patch: |- + - op: add + path: /metadata/annotations/argocd.argoproj.io~1sync-wave + value: "-35" + - target: + kind: ValidatingAdmissionPolicyBinding + name: restrict-baremetalhost-to-openstack-binding.metal3.io + patch: |- + - op: add + path: /metadata/annotations/argocd.argoproj.io~1sync-wave + value: "-35" # --- Wave -20: Set up OperatorGroup and CatalogSource for Operator deployments --- - target: kind: OperatorGroup diff --git a/components/dependencies/baremetalhost-validation/kustomization.yaml b/components/dependencies/baremetalhost-validation/kustomization.yaml new file mode 100644 index 0000000..0ebe608 --- /dev/null +++ b/components/dependencies/baremetalhost-validation/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component +resources: + - policy.yaml + - policy-binding.yaml diff --git a/components/dependencies/baremetalhost-validation/policy-binding.yaml b/components/dependencies/baremetalhost-validation/policy-binding.yaml new file mode 100644 index 0000000..1f0caf6 --- /dev/null +++ b/components/dependencies/baremetalhost-validation/policy-binding.yaml @@ -0,0 +1,11 @@ +--- +# ValidatingAdmissionPolicyBinding for BareMetalHost restriction policy +# Binds the restrict-baremetalhost-to-openstack policy cluster-wide + +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: restrict-baremetalhost-to-openstack-binding.metal3.io +spec: + policyName: restrict-baremetalhost-to-openstack.metal3.io + validationActions: [Deny] diff --git a/components/dependencies/baremetalhost-validation/policy.yaml b/components/dependencies/baremetalhost-validation/policy.yaml new file mode 100644 index 0000000..8b950e1 --- /dev/null +++ b/components/dependencies/baremetalhost-validation/policy.yaml @@ -0,0 +1,25 @@ +--- +# ValidatingAdmissionPolicy to restrict BareMetalHost creation to OpenStack namespaces +# This policy enforces that BareMetalHost resources can only be created in the +# 'openstack' or 'openstack-operators' namespaces, even though the Bare Metal +# Operator is configured to watch all namespaces (watchAllNamespaces: true). +# This implements namespace-scoped security controls for bare metal provisioning. + +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: restrict-baremetalhost-to-openstack.metal3.io +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["metal3.io"] + apiVersions: ["v1alpha1"] + operations: ["CREATE"] + resources: ["baremetalhosts"] + validations: + - expression: >- + namespaceObject.metadata.name == 'openstack' || + namespaceObject.metadata.name == 'openstack-operators' + message: "BareMetalHost resources can only be created in openstack or openstack-operators namespaces" + reason: Forbidden diff --git a/components/dependencies/provisioning-config/kustomization.yaml b/components/dependencies/provisioning-config/kustomization.yaml index f34bd00..b375994 100644 --- a/components/dependencies/provisioning-config/kustomization.yaml +++ b/components/dependencies/provisioning-config/kustomization.yaml @@ -1,5 +1,7 @@ --- apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component +components: + - ../baremetalhost-validation resources: - provisioning-config.yaml diff --git a/openshift-gitops.deploy/enable/clusterrole.yaml b/openshift-gitops.deploy/enable/clusterrole.yaml index eebc793..db9b44f 100644 --- a/openshift-gitops.deploy/enable/clusterrole.yaml +++ b/openshift-gitops.deploy/enable/clusterrole.yaml @@ -125,6 +125,19 @@ rules: - 'openstackdataplaneservices' verbs: - '*' + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingadmissionpolicies + - validatingadmissionpolicybindings + verbs: + - get + - list + - watch + - create + - update + - patch + - delete --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding