Skip to content

Commit 7c44697

Browse files
Adds CAPI Machine VAP
- Adds CAPI Machine VAP, similar to the MAPI one, but for when MAPI is autoritative. - Adds tests
1 parent e6b0e94 commit 7c44697

File tree

2 files changed

+325
-19
lines changed

2 files changed

+325
-19
lines changed

manifests/0000_30_cluster-api_09_admission-policies.yaml

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)