@@ -153,6 +153,113 @@ data:
153153 message: "Cannot modify a Cluster API controlled label except to match the Cluster API mirrored machine. This is because status.authoritativeAPI is set to Cluster API."
154154 ---
155155 apiVersion: admissionregistration.k8s.io/v1
156+ kind: ValidatingAdmissionPolicyBinding
157+ metadata:
158+ name: cluster-api-machine-vap
159+ spec:
160+ matchResources:
161+ namespaceSelector:
162+ matchLabels:
163+ kubernetes.io/metadata.name: openshift-cluster-api
164+ paramRef:
165+ namespace: openshift-machine-api
166+ # We 'Allow' here as we don't want to block CAPI Machine functionality
167+ # when no MAPI machine (param) exists. This might happen when a user
168+ # wants to not use MAPI, or is migrating.
169+ parameterNotFoundAction: Allow
170+ selector: {}
171+ policyName: cluster-api-machine-vap
172+ validationActions: [Deny]
173+ ---
174+ apiVersion: admissionregistration.k8s.io/v1
175+ kind: ValidatingAdmissionPolicy
176+ metadata:
177+ name: cluster-api-machine-vap
178+ spec:
179+ failurePolicy: Fail
180+
181+ paramKind:
182+ apiVersion: machine.openshift.io/v1beta1
183+ kind: Machine
184+
185+ matchConstraints:
186+ resourceRules:
187+ - apiGroups: ["cluster.x-k8s.io"]
188+ apiVersions: ["v1beta1"]
189+ operations: ["UPDATE"]
190+ resources: ["machines"]
191+
192+ # Requests must satisfy every matchCondition to reach the validations
193+ matchConditions:
194+ - name: check-only-non-service-account-requests
195+ expression: >-
196+ !(request.userInfo.username in [
197+ "system:serviceaccount:openshift-machine-api:machine-api-controllers",
198+ "system:serviceaccount:openshift-cluster-api:cluster-capi-operator"
199+ ])
200+ - name: check-param-match
201+ expression: 'object.metadata.name == params.metadata.name'
202+ - name: check-authoritativeAPI-machineapi
203+ expression: "params.?status.?authoritativeAPI.orValue(\"\") == \"MachineAPI\""
204+ variables:
205+ # label maps
206+ - name: newLabels
207+ expression: "object.metadata.?labels.orValue({})"
208+ - name: oldLabels
209+ expression: "oldObject.metadata.?labels.orValue({})"
210+ - name: paramLabels
211+ expression: "params.metadata.?labels.orValue({})"
212+
213+ # annotation maps
214+ - name: newAnn
215+ expression: "object.metadata.?annotations.orValue({})"
216+ - name: oldAnn
217+ expression: "oldObject.metadata.?annotations.orValue({})"
218+
219+ # All validations must evaluate to TRUE
220+ validations:
221+ # Only spec.authoritativeAPI may change
222+ - expression: "object.spec == oldObject.spec"
223+ message: "Changing .spec is not allowed. This is because status.authoritativeAPI is set to Machine API."
224+
225+ # Guard machine.openshift.io/* and kubernetes.io/* and cluster.x-k8s.io/* labels
226+ - expression: >
227+ !(
228+ variables.newLabels.exists(k,
229+ (k.startsWith('machine.openshift.io') || k.startsWith('kubernetes.io') || k.contains('cluster.x-k8s.io/')) &&
230+ (variables.oldLabels[?k].orValue(null) != variables.newLabels[k])
231+ ) ||
232+ variables.oldLabels.exists(k,
233+ (k.startsWith('machine.openshift.io') || k.startsWith('kubernetes.io') || k.contains('cluster.x-k8s.io/')) &&
234+ !(k in variables.newLabels)
235+ )
236+ )
237+ message: "Cannot add, modify or delete any machine.openshift.io/*, kubernetes.io/* or cluster.x-k8s.io/* label. This is because status.authoritativeAPI is set to Machine API."
238+
239+ # Guard machine.openshift.io/* and cluster.x-k8s.io/* and clusters.x-k8s.io/* annotations
240+ - expression: >
241+ !(
242+ variables.newAnn.exists(k,
243+ (k.startsWith('machine.openshift.io') || k.contains('cluster.x-k8s.io') || k.contains('clusters.x-k8s.io')) &&
244+ (variables.oldAnn[?k].orValue(null) != variables.newAnn[k])
245+ ) ||
246+ variables.oldAnn.exists(k,
247+ (k.startsWith('machine.openshift.io') || k.contains('cluster.x-k8s.io') || k.contains('clusters.x-k8s.io')) &&
248+ !(k in variables.newAnn)
249+ )
250+ )
251+ message: "Cannot add, modify or delete any machine.openshift.io/* or cluster.x-k8s.io or clusters.x-k8s.io annotation. This is because status.authoritativeAPI is set to Machine API."
252+
253+ # Param-controlled labels (labels on the MAPI machine) may change only to match the value on the MAPI Machine
254+ - expression: >
255+ variables.paramLabels.all(
256+ k,
257+ variables.newLabels[?k].orValue(null) == variables.oldLabels[?k].orValue(null) ||
258+ variables.newLabels[?k].orValue(null) == variables.paramLabels[k]
259+ )
260+ message: "Cannot modify a Machine API controlled label except to match the Machine API mirrored machine. This is because status.authoritativeAPI is set to Machine API."
261+ ---
262+ apiVersion: admissionregistration.k8s.io/v1
156263 kind: ValidatingAdmissionPolicy
157264 metadata:
158265 name: openshift-cluster-api-prevent-setting-of-capi-fields-unsupported-by-mapi
@@ -165,15 +272,15 @@ data:
165272 operations: ["CREATE", "UPDATE"]
166273 resources: ["machines", "machinesets"]
167274 variables:
168- - name: machineSpec
169- expression: "object.kind == 'Machine' ? object.spec : object.spec.template.spec"
170- - name: specPath
171- expression: "object.kind == 'Machine' ? 'spec' : 'spec.template.spec'"
275+ - name: machineSpec
276+ expression: "object.kind == 'Machine' ? object.spec : object.spec.template.spec"
277+ - name: specPath
278+ expression: "object.kind == 'Machine' ? 'spec' : 'spec.template.spec'"
172279 validations:
173- - expression: "!has(variables.machineSpec.version)"
174- messageExpression: "variables.specPath + '.version is a forbidden field'"
175- - expression: "!has(variables.machineSpec.readinessGates)"
176- messageExpression: "variables.specPath + '.readinessGates is a forbidden field'"
280+ - expression: "!has(variables.machineSpec.version)"
281+ messageExpression: "variables.specPath + '.version is a forbidden field'"
282+ - expression: "!has(variables.machineSpec.readinessGates)"
283+ messageExpression: "variables.specPath + '.readinessGates is a forbidden field'"
177284 ---
178285 apiVersion: admissionregistration.k8s.io/v1
179286 kind: ValidatingAdmissionPolicyBinding
0 commit comments