@@ -2,7 +2,6 @@ package certificate
2
2
3
3
import (
4
4
"context"
5
- "fmt"
6
5
"strings"
7
6
8
7
certificatesv1 "k8s.io/api/certificates/v1"
@@ -12,11 +11,7 @@ import (
12
11
"k8s.io/apimachinery/pkg/api/meta"
13
12
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
13
"k8s.io/apimachinery/pkg/runtime"
15
- certificatesinformers "k8s.io/client-go/informers/certificates/v1"
16
- v1beta1certificatesinformers "k8s.io/client-go/informers/certificates/v1beta1"
17
14
"k8s.io/client-go/kubernetes"
18
- certificateslisters "k8s.io/client-go/listers/certificates/v1"
19
- v1beta1certificateslisters "k8s.io/client-go/listers/certificates/v1beta1"
20
15
"k8s.io/client-go/tools/cache"
21
16
"k8s.io/klog/v2"
22
17
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
@@ -50,42 +45,45 @@ var (
50
45
EnableV1Beta1CSRCompatibility = true
51
46
)
52
47
48
+ type CSR interface {
49
+ * certificatesv1.CertificateSigningRequest | * certificatesv1beta1.CertificateSigningRequest
50
+ GetLabels () map [string ]string
51
+ GetName () string
52
+ }
53
+
54
+ type CSRLister [T CSR ] interface {
55
+ Get (name string ) (T , error )
56
+ }
57
+
58
+ type CSRApprover [T CSR ] interface {
59
+ approve (ctx context.Context , csr T ) error
60
+ isInTerminalState (csr T ) bool
61
+ }
62
+
53
63
// csrApprovingController auto approve the renewal CertificateSigningRequests for an accepted spoke cluster on the hub.
54
- type csrApprovingController struct {
55
- kubeClient kubernetes.Interface
64
+ type csrApprovingController [T CSR ] struct {
56
65
agentAddons map [string ]agent.AgentAddon
57
66
managedClusterLister clusterlister.ManagedClusterLister
58
67
managedClusterAddonLister addonlisterv1alpha1.ManagedClusterAddOnLister
59
- csrLister certificateslisters. CertificateSigningRequestLister
60
- csrListerBeta v1beta1certificateslisters. CertificateSigningRequestLister
68
+ csrLister CSRLister [ T ]
69
+ approver CSRApprover [ T ]
61
70
}
62
71
63
72
// NewCSRApprovingController creates a new csr approving controller
64
- func NewCSRApprovingController (
65
- kubeClient kubernetes.Interface ,
73
+ func NewCSRApprovingController [T CSR ](
66
74
clusterInformers clusterinformers.ManagedClusterInformer ,
67
- csrV1Informer certificatesinformers.CertificateSigningRequestInformer ,
68
- csrBetaInformer v1beta1certificatesinformers.CertificateSigningRequestInformer ,
69
75
addonInformers addoninformerv1alpha1.ManagedClusterAddOnInformer ,
76
+ csrInformer cache.SharedIndexInformer ,
77
+ csrLister CSRLister [T ],
78
+ approver CSRApprover [T ],
70
79
agentAddons map [string ]agent.AgentAddon ,
71
80
) factory.Controller {
72
- if (csrV1Informer != nil ) == (csrBetaInformer != nil ) {
73
- klog .Fatalf ("V1 and V1beta1 CSR informer cannot be present or absent at the same time" )
74
- }
75
- c := & csrApprovingController {
76
- kubeClient : kubeClient ,
81
+ c := & csrApprovingController [T ]{
77
82
agentAddons : agentAddons ,
78
83
managedClusterLister : clusterInformers .Lister (),
79
84
managedClusterAddonLister : addonInformers .Lister (),
80
- }
81
- var csrInformer cache.SharedIndexInformer
82
- if csrV1Informer != nil {
83
- c .csrLister = csrV1Informer .Lister ()
84
- csrInformer = csrV1Informer .Informer ()
85
- }
86
- if EnableV1Beta1CSRCompatibility && csrBetaInformer != nil {
87
- c .csrListerBeta = csrBetaInformer .Lister ()
88
- csrInformer = csrBetaInformer .Informer ()
85
+ csrLister : csrLister ,
86
+ approver : approver ,
89
87
}
90
88
91
89
return factory .New ().
@@ -113,18 +111,18 @@ func NewCSRApprovingController(
113
111
ToController ("CSRApprovingController" )
114
112
}
115
113
116
- func (c * csrApprovingController ) sync (ctx context.Context , syncCtx factory.SyncContext , csrName string ) error {
114
+ func (c * csrApprovingController [ T ] ) sync (ctx context.Context , syncCtx factory.SyncContext , csrName string ) error {
117
115
klog .V (4 ).Infof ("Reconciling CertificateSigningRequests %q" , csrName )
118
116
119
- csr , err := c .getCSR (csrName )
120
- if csr == nil {
117
+ csr , err := c .csrLister . Get (csrName )
118
+ if errors . IsNotFound ( err ) {
121
119
return nil
122
120
}
123
121
if err != nil {
124
122
return err
125
123
}
126
124
127
- if isCSRApproved ( csr ) || IsCSRInTerminalState (csr ) {
125
+ if c . approver . isInTerminalState (csr ) {
128
126
return nil
129
127
}
130
128
@@ -161,32 +159,14 @@ func (c *csrApprovingController) sync(ctx context.Context, syncCtx factory.SyncC
161
159
return err
162
160
}
163
161
164
- if registrationOption .CSRApproveCheck == nil {
165
- klog .V (4 ).Infof ("addon csr %q cannont be auto approved due to approve check not defined" , csr .GetName ())
166
- return nil
167
- }
168
-
169
162
if err := c .approve (ctx , registrationOption , managedCluster , managedClusterAddon , csr ); err != nil {
170
163
return err
171
164
}
172
165
173
166
return nil
174
167
}
175
168
176
- func (c * csrApprovingController ) getCSR (csrName string ) (metav1.Object , error ) {
177
- // TODO: remove the following block for deprecating V1beta1 CSR compatibility
178
- if EnableV1Beta1CSRCompatibility {
179
- if c .csrListerBeta != nil {
180
- csr , err := c .csrListerBeta .Get (csrName )
181
- if errors .IsNotFound (err ) {
182
- return nil , nil
183
- }
184
- if err != nil {
185
- return nil , err
186
- }
187
- return csr , nil
188
- }
189
- }
169
+ func (c * csrApprovingController [T ]) getCSR (csrName string ) (T , error ) {
190
170
csr , err := c .csrLister .Get (csrName )
191
171
if errors .IsNotFound (err ) {
192
172
return nil , nil
@@ -197,143 +177,125 @@ func (c *csrApprovingController) getCSR(csrName string) (metav1.Object, error) {
197
177
return csr , nil
198
178
}
199
179
200
- func (c * csrApprovingController ) approve (
201
- ctx context.Context ,
202
- registrationOption * agent.RegistrationOption ,
203
- managedCluster * clusterv1.ManagedCluster ,
204
- managedClusterAddon * addonv1alpha1.ManagedClusterAddOn ,
205
- csr metav1.Object ) error {
180
+ // CSRV1Approver implement CSRApprover interface
181
+ type CSRV1Approver struct {
182
+ kubeClient kubernetes.Interface
183
+ }
206
184
207
- switch t := csr .(type ) {
208
- case * certificatesv1.CertificateSigningRequest :
209
- approve := registrationOption .CSRApproveCheck (managedCluster , managedClusterAddon , t )
210
- if ! approve {
211
- klog .V (4 ).Infof ("addon csr %q cannont be auto approved due to approve check fails" , csr .GetName ())
212
- return nil
185
+ func NewCSRV1Approver (client kubernetes.Interface ) * CSRV1Approver {
186
+ return & CSRV1Approver {kubeClient : client }
187
+ }
188
+
189
+ func (c * CSRV1Approver ) isInTerminalState (csr * certificatesv1.CertificateSigningRequest ) bool {
190
+ for _ , c := range csr .Status .Conditions {
191
+ if c .Type == certificatesv1 .CertificateApproved {
192
+ return true
213
193
}
214
- return c .approveCSRV1 (ctx , t )
215
- // TODO: remove the following block for deprecating V1beta1 CSR compatibility
216
- case * certificatesv1beta1.CertificateSigningRequest :
217
- v1CSR := unsafeConvertV1beta1CSRToV1CSR (t )
218
- approve := registrationOption .CSRApproveCheck (managedCluster , managedClusterAddon , v1CSR )
219
- if ! approve {
220
- klog .V (4 ).Infof ("addon csr %q cannont be auto approved due to approve check fails" , csr .GetName ())
221
- return nil
194
+ if c .Type == certificatesv1 .CertificateDenied {
195
+ return true
222
196
}
223
- return c .approveCSRV1Beta1 (ctx , t )
224
- default :
225
- return fmt .Errorf ("unknown csr object type: %t" , csr )
226
197
}
198
+ return false
227
199
}
228
200
229
- func (c * csrApprovingController ) approveCSRV1 (ctx context.Context , v1CSR * certificatesv1.CertificateSigningRequest ) error {
230
- v1CSR .Status .Conditions = append (v1CSR .Status .Conditions , certificatesv1.CertificateSigningRequestCondition {
201
+ func (c * CSRV1Approver ) approve (ctx context.Context , csr * certificatesv1.CertificateSigningRequest ) error {
202
+ csrCopy := csr .DeepCopy ()
203
+ // Auto approve the spoke cluster csr
204
+ csrCopy .Status .Conditions = append (csr .Status .Conditions , certificatesv1.CertificateSigningRequestCondition {
231
205
Type : certificatesv1 .CertificateApproved ,
232
206
Status : corev1 .ConditionTrue ,
233
207
Reason : "AutoApprovedByHubCSRApprovingController" ,
234
- Message : "Auto approving addon agent certificate." ,
208
+ Message : "Auto approving Managed cluster agent certificate after SubjectAccessReview ." ,
235
209
})
236
- _ , err := c .kubeClient .CertificatesV1 ().CertificateSigningRequests ().UpdateApproval (ctx , v1CSR .GetName (), v1CSR , metav1.UpdateOptions {})
237
- if err != nil {
238
- return err
239
- }
240
- return nil
210
+ _ , err := c .kubeClient .CertificatesV1 ().CertificateSigningRequests ().UpdateApproval (ctx , csrCopy .Name , csrCopy , metav1.UpdateOptions {})
211
+ return err
241
212
}
242
213
243
- func (c * csrApprovingController ) approveCSRV1Beta1 (ctx context.Context , v1beta1CSR * certificatesv1beta1.CertificateSigningRequest ) error {
244
- v1beta1CSR .Status .Conditions = append (v1beta1CSR .Status .Conditions , certificatesv1beta1.CertificateSigningRequestCondition {
245
- Type : certificatesv1beta1 .CertificateApproved ,
246
- Status : corev1 .ConditionTrue ,
247
- Reason : "AutoApprovedByHubCSRApprovingController" ,
248
- Message : "Auto approving addon agent certificate." ,
249
- })
250
- _ , err := c .kubeClient .CertificatesV1beta1 ().CertificateSigningRequests ().UpdateApproval (ctx , v1beta1CSR , metav1.UpdateOptions {})
251
- if err != nil {
252
- return err
253
- }
254
- return nil
214
+ type CSRV1beta1Approver struct {
215
+ kubeClient kubernetes.Interface
255
216
}
256
217
257
- // Check whether a CSR is in terminal state
258
- func IsCSRInTerminalState (csr metav1.Object ) bool {
259
- if v1CSR , ok := csr .(* certificatesv1.CertificateSigningRequest ); ok {
260
- for _ , c := range v1CSR .Status .Conditions {
261
- if c .Type == certificatesv1 .CertificateApproved {
262
- return true
263
- }
264
- if c .Type == certificatesv1 .CertificateDenied {
265
- return true
266
- }
218
+ func NewCSRV1beta1Approver (client kubernetes.Interface ) * CSRV1beta1Approver {
219
+ return & CSRV1beta1Approver {kubeClient : client }
220
+ }
221
+
222
+ func (c * CSRV1beta1Approver ) isInTerminalState (csr * certificatesv1beta1.CertificateSigningRequest ) bool {
223
+ for _ , c := range csr .Status .Conditions {
224
+ if c .Type == certificatesv1beta1 .CertificateApproved {
225
+ return true
267
226
}
268
- }
269
- // TODO: remove the following block for deprecating V1beta1 CSR compatibility
270
- if EnableV1Beta1CSRCompatibility {
271
- if v1beta1CSR , ok := csr .(* certificatesv1beta1.CertificateSigningRequest ); ok {
272
- for _ , c := range v1beta1CSR .Status .Conditions {
273
- if c .Type == certificatesv1beta1 .CertificateApproved {
274
- return true
275
- }
276
- if c .Type == certificatesv1beta1 .CertificateDenied {
277
- return true
278
- }
279
- }
227
+ if c .Type == certificatesv1beta1 .CertificateDenied {
228
+ return true
280
229
}
281
230
}
282
231
return false
283
232
}
284
233
285
- func isCSRApproved (csr metav1.Object ) bool {
286
- approved := false
287
- if v1CSR , ok := csr .(* certificatesv1.CertificateSigningRequest ); ok {
288
- for _ , condition := range v1CSR .Status .Conditions {
289
- if condition .Type == certificatesv1 .CertificateDenied {
290
- return false
291
- } else if condition .Type == certificatesv1 .CertificateApproved {
292
- approved = true
293
- }
294
- }
234
+ func (c * CSRV1beta1Approver ) approve (ctx context.Context , csr * certificatesv1beta1.CertificateSigningRequest ) error {
235
+ csrCopy := csr .DeepCopy ()
236
+ // Auto approve the spoke cluster csr
237
+ csrCopy .Status .Conditions = append (csr .Status .Conditions , certificatesv1beta1.CertificateSigningRequestCondition {
238
+ Type : certificatesv1beta1 .CertificateApproved ,
239
+ Status : corev1 .ConditionTrue ,
240
+ Reason : "AutoApprovedByHubCSRApprovingController" ,
241
+ Message : "Auto approving Managed cluster agent certificate after SubjectAccessReview." ,
242
+ })
243
+ _ , err := c .kubeClient .CertificatesV1beta1 ().CertificateSigningRequests ().UpdateApproval (ctx , csrCopy , metav1.UpdateOptions {})
244
+ return err
245
+ }
246
+
247
+ func (c * csrApprovingController [T ]) approve (
248
+ ctx context.Context ,
249
+ registrationOption * agent.RegistrationOption ,
250
+ managedCluster * clusterv1.ManagedCluster ,
251
+ managedClusterAddon * addonv1alpha1.ManagedClusterAddOn ,
252
+ csr T ) error {
253
+
254
+ v1CSR := unsafeConvertV1beta1CSRToV1CSR [T ](csr )
255
+ if registrationOption .CSRApproveCheck == nil {
256
+ klog .V (4 ).Infof ("addon csr %q cannont be auto approved due to approve check not defined" , csr .GetName ())
257
+ return nil
295
258
}
296
- // TODO: remove the following block for deprecating V1beta1 CSR compatibility
297
- if EnableV1Beta1CSRCompatibility {
298
- if v1beta1CSR , ok := csr .(* certificatesv1beta1.CertificateSigningRequest ); ok {
299
- for _ , condition := range v1beta1CSR .Status .Conditions {
300
- if condition .Type == certificatesv1beta1 .CertificateDenied {
301
- return false
302
- } else if condition .Type == certificatesv1beta1 .CertificateApproved {
303
- approved = true
304
- }
305
- }
306
- }
259
+ approve := registrationOption .CSRApproveCheck (managedCluster , managedClusterAddon , v1CSR )
260
+ if ! approve {
261
+ klog .V (4 ).Infof ("addon csr %q cannont be auto approved due to approve check fails" , csr .GetName ())
262
+ return nil
307
263
}
308
- return approved
264
+
265
+ return c .approver .approve (ctx , csr )
309
266
}
310
267
311
268
// TODO: remove the following block for deprecating V1beta1 CSR compatibility
312
- func unsafeConvertV1beta1CSRToV1CSR (v1beta1CSR * certificatesv1beta1.CertificateSigningRequest ) * certificatesv1.CertificateSigningRequest {
313
- v1CSR := & certificatesv1.CertificateSigningRequest {
314
- TypeMeta : metav1.TypeMeta {
315
- APIVersion : certificatesv1 .SchemeGroupVersion .String (),
316
- Kind : "CertificateSigningRequest" ,
317
- },
318
- ObjectMeta : * v1beta1CSR .ObjectMeta .DeepCopy (),
319
- Spec : certificatesv1.CertificateSigningRequestSpec {
320
- Request : v1beta1CSR .Spec .Request ,
321
- ExpirationSeconds : v1beta1CSR .Spec .ExpirationSeconds ,
322
- Usages : unsafeCovertV1beta1KeyUsageToV1KeyUsage (v1beta1CSR .Spec .Usages ),
323
- Username : v1beta1CSR .Spec .Username ,
324
- UID : v1beta1CSR .Spec .UID ,
325
- Groups : v1beta1CSR .Spec .Groups ,
326
- Extra : unsafeCovertV1beta1ExtraValueToV1ExtraValue (v1beta1CSR .Spec .Extra ),
327
- },
328
- Status : certificatesv1.CertificateSigningRequestStatus {
329
- Certificate : v1beta1CSR .Status .Certificate ,
330
- Conditions : unsafeCovertV1beta1ConditionsToV1Conditions (v1beta1CSR .Status .Conditions ),
331
- },
332
- }
333
- if v1beta1CSR .Spec .SignerName != nil {
334
- v1CSR .Spec .SignerName = * v1beta1CSR .Spec .SignerName
269
+ func unsafeConvertV1beta1CSRToV1CSR [T CSR ](csr T ) * certificatesv1.CertificateSigningRequest {
270
+ switch obj := any (csr ).(type ) {
271
+ case * certificatesv1.CertificateSigningRequest :
272
+ return obj
273
+ case * certificatesv1beta1.CertificateSigningRequest :
274
+ v1CSR := & certificatesv1.CertificateSigningRequest {
275
+ TypeMeta : metav1.TypeMeta {
276
+ APIVersion : certificatesv1 .SchemeGroupVersion .String (),
277
+ Kind : "CertificateSigningRequest" ,
278
+ },
279
+ ObjectMeta : * obj .ObjectMeta .DeepCopy (),
280
+ Spec : certificatesv1.CertificateSigningRequestSpec {
281
+ Request : obj .Spec .Request ,
282
+ ExpirationSeconds : obj .Spec .ExpirationSeconds ,
283
+ Usages : unsafeCovertV1beta1KeyUsageToV1KeyUsage (obj .Spec .Usages ),
284
+ Username : obj .Spec .Username ,
285
+ UID : obj .Spec .UID ,
286
+ Groups : obj .Spec .Groups ,
287
+ Extra : unsafeCovertV1beta1ExtraValueToV1ExtraValue (obj .Spec .Extra ),
288
+ },
289
+ Status : certificatesv1.CertificateSigningRequestStatus {
290
+ Certificate : obj .Status .Certificate ,
291
+ Conditions : unsafeCovertV1beta1ConditionsToV1Conditions (obj .Status .Conditions ),
292
+ },
293
+ }
294
+ if obj .Spec .SignerName != nil {
295
+ v1CSR .Spec .SignerName = * obj .Spec .SignerName
296
+ }
335
297
}
336
- return v1CSR
298
+ return nil
337
299
}
338
300
339
301
// TODO: remove the following block for deprecating V1beta1 CSR compatibility
0 commit comments