Skip to content

Commit e41a995

Browse files
committed
fix: kube-apiserver authorizers order
Fixes handling of `kube-apiserver` authorization config authorizers. order. Fixes: #10110 Signed-off-by: Noel Georgi <git@frezbo.dev>
1 parent db4ca56 commit e41a995

3 files changed

Lines changed: 137 additions & 8 deletions

File tree

hack/release.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ preface = """
2424
2525
Talos is built with Go 1.23.4.
2626
"""
27+
2728
[notes.driver-rebind]
2829
title = "Driver Rebind"
2930
description = """\
@@ -44,6 +45,35 @@ The kernel argument `talos.unified_cgroup_hierarchy` is now ignored.
4445
Kernel parameter `talos.auditd.disabled=1` can be used to disable Talos built-in `auditd` service.
4546
"""
4647

48+
[notes.kube-apiserver-authorization-config]
49+
title = "kube-apiserver Authorization Config"
50+
description = """\
51+
When using `.cluster.apiServer.authorizationConfig` the user provided order for the authorizers is honoured and `Node` and `RBAC` authorizers are always added to the end if not explicitly specified.
52+
53+
Eg: If user provides only `Webhook` authorizer, the final order will be `Webhook`, `Node`, `RBAC`.
54+
55+
To provide a specific order for `Node` or `RBAC` explicitly, user can provide the authorizer in the order they want.
56+
57+
Eg:
58+
59+
```yaml
60+
cluster:
61+
apiServer:
62+
authorizationConfig:
63+
- type: Node
64+
name: Node
65+
- type: Webhook
66+
name: Webhook
67+
webhook:
68+
connectionInfo:
69+
type: InClusterConfig
70+
...
71+
- type: RBAC
72+
name: rbac
73+
```
74+
75+
Usage of `authorization-mode` CLI argument will not support this form of customization.
76+
4777
[make_deps]
4878
4979
[make_deps.tools]

internal/app/machined/pkg/controllers/k8s/control_plane.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,6 @@ func NewControlPlaneAuthorizationController() *ControlPlaneAuthorizationControll
131131
var authorizers []k8s.AuthorizationAuthorizersSpec
132132

133133
for _, authorizer := range cfgProvider.Cluster().APIServer().AuthorizationConfig() {
134-
// skip Node and RBAC authorizers as we add them by default later on.
135-
if authorizer.Type() == "Node" || authorizer.Type() == "RBAC" {
136-
continue
137-
}
138-
139134
authorizers = slices.Concat(authorizers, []k8s.AuthorizationAuthorizersSpec{
140135
{
141136
Type: authorizer.Type(),
@@ -145,7 +140,25 @@ func NewControlPlaneAuthorizationController() *ControlPlaneAuthorizationControll
145140
})
146141
}
147142

148-
res.TypedSpec().Config = slices.Concat(v1alpha1.APIServerDefaultAuthorizationConfigAuthorizers, authorizers)
143+
if !slices.ContainsFunc(authorizers, func(a k8s.AuthorizationAuthorizersSpec) bool {
144+
return a.Type == "Node"
145+
}) {
146+
authorizers = slices.Insert(authorizers, 0, k8s.AuthorizationAuthorizersSpec{
147+
Type: "Node",
148+
Name: "node",
149+
})
150+
}
151+
152+
if !slices.ContainsFunc(authorizers, func(a k8s.AuthorizationAuthorizersSpec) bool {
153+
return a.Type == "RBAC"
154+
}) {
155+
authorizers = slices.Insert(authorizers, 1, k8s.AuthorizationAuthorizersSpec{
156+
Type: "RBAC",
157+
Name: "rbac",
158+
})
159+
}
160+
161+
res.TypedSpec().Config = authorizers
149162

150163
return nil
151164
},

internal/app/machined/pkg/controllers/k8s/control_plane_test.go

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,88 @@ func (suite *K8sControlPlaneSuite) TestReconcileAdditionalAuthorizationConfigAut
270270
},
271271
},
272272
},
273+
{
274+
AuthorizerType: "Node",
275+
AuthorizerName: "bar",
276+
},
277+
},
278+
},
279+
},
280+
},
281+
),
282+
)
283+
284+
suite.setupMachine(cfg)
285+
286+
expectedAuthorizers := []k8s.AuthorizationAuthorizersSpec{
287+
{
288+
Type: "RBAC",
289+
Name: "foo",
290+
},
291+
{
292+
Type: "Webhook",
293+
Name: "webhook",
294+
Webhook: map[string]any{
295+
"timeout": "3s",
296+
"subjectAccessReviewVersion": "v1",
297+
"matchConditionSubjectAccessReviewVersion": "v1",
298+
"failurePolicy": "NoOpinion",
299+
"connectionInfo": map[string]any{
300+
"type": "InClusterConfig",
301+
},
302+
},
303+
},
304+
{
305+
Type: "Node",
306+
Name: "bar",
307+
},
308+
}
309+
310+
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{k8s.AuthorizationConfigID},
311+
func(authorizationConfig *k8s.AuthorizationConfig, assert *assert.Assertions) {
312+
assert.Equal(expectedAuthorizers, authorizationConfig.TypedSpec().Config)
313+
},
314+
)
315+
}
316+
317+
func (suite *K8sControlPlaneSuite) TestReconcileAdditionalAuthorizationConfigAuthorizersWithOnlyNodeSet() {
318+
u, err := url.Parse("https://foo:6443")
319+
suite.Require().NoError(err)
320+
321+
cfg := config.NewMachineConfig(
322+
container.NewV1Alpha1(
323+
&v1alpha1.Config{
324+
ConfigVersion: "v1alpha1",
325+
MachineConfig: &v1alpha1.MachineConfig{
326+
MachineType: "controlplane",
327+
},
328+
ClusterConfig: &v1alpha1.ClusterConfig{
329+
ControlPlane: &v1alpha1.ControlPlaneConfig{
330+
Endpoint: &v1alpha1.Endpoint{
331+
URL: u,
332+
},
333+
},
334+
APIServerConfig: &v1alpha1.APIServerConfig{
335+
AuthorizationConfigConfig: []*v1alpha1.AuthorizationConfigAuthorizerConfig{
273336
{
274337
AuthorizerType: "Node",
275338
AuthorizerName: "foo",
276339
},
340+
{
341+
AuthorizerType: "Webhook",
342+
AuthorizerName: "webhook",
343+
AuthorizerWebhook: v1alpha1.Unstructured{
344+
Object: map[string]any{
345+
"timeout": "3s",
346+
"subjectAccessReviewVersion": "v1",
347+
"matchConditionSubjectAccessReviewVersion": "v1",
348+
"failurePolicy": "NoOpinion",
349+
"connectionInfo": map[string]any{
350+
"type": "InClusterConfig",
351+
},
352+
},
353+
},
354+
},
277355
},
278356
},
279357
},
@@ -283,7 +361,15 @@ func (suite *K8sControlPlaneSuite) TestReconcileAdditionalAuthorizationConfigAut
283361

284362
suite.setupMachine(cfg)
285363

286-
expectedAuthorizers := slices.Concat(v1alpha1.APIServerDefaultAuthorizationConfigAuthorizers, []k8s.AuthorizationAuthorizersSpec{
364+
expectedAuthorizers := []k8s.AuthorizationAuthorizersSpec{
365+
{
366+
Type: "Node",
367+
Name: "foo",
368+
},
369+
{
370+
Type: "RBAC",
371+
Name: "rbac",
372+
},
287373
{
288374
Type: "Webhook",
289375
Name: "webhook",
@@ -297,7 +383,7 @@ func (suite *K8sControlPlaneSuite) TestReconcileAdditionalAuthorizationConfigAut
297383
},
298384
},
299385
},
300-
})
386+
}
301387

302388
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{k8s.AuthorizationConfigID},
303389
func(authorizationConfig *k8s.AuthorizationConfig, assert *assert.Assertions) {

0 commit comments

Comments
 (0)