Skip to content

Commit 4a624e5

Browse files
committed
chore: address review comments
1 parent f5a0d71 commit 4a624e5

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

scrapers/kubernetes/rbac.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ func (r *rbacExtractor) processRoleBinding(obj *unstructured.Unstructured) {
313313
// Find all target resources based on the rules
314314
targetResources := r.findTargetResources(rules, bindingNamespace, kind == "ClusterRoleBinding")
315315

316+
// Compute the role alias once for the binding
317+
roleAlias := KubernetesAlias(r.clusterName, roleKind, roleNamespace, roleName)
318+
316319
// Get subjects
317320
subjects, found, _ := unstructured.NestedSlice(obj.Object, "subjects")
318321
if !found {
@@ -387,11 +390,21 @@ func (r *rbacExtractor) processRoleBinding(obj *unstructured.Unstructured) {
387390
// If we have rules and target resources, create ConfigAccess for each resource
388391
if hasRules && len(targetResources) > 0 {
389392
for _, target := range targetResources {
393+
subjectAlias := userAlias
394+
if subjectAlias == "" {
395+
subjectAlias = groupAlias
396+
}
397+
targetExternalID := KubernetesAlias(r.clusterName, target.kind, target.namespace, target.name)
398+
390399
access := v1.ExternalConfigAccess{
400+
ConfigAccess: models.ConfigAccess{
401+
ID: generateRBACID(subjectAlias, targetExternalID, roleAlias).String(),
402+
},
391403
ConfigExternalID: v1.ExternalID{
392-
ExternalID: KubernetesAlias(r.clusterName, target.kind, target.namespace, target.name),
404+
ExternalID: targetExternalID,
393405
ConfigType: GetConfigTypeForKind(target.kind),
394406
},
407+
ExternalRoleAliases: []string{roleAlias},
395408
}
396409

397410
if userAlias != "" {

scrapers/kubernetes/rbac_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,14 @@ func TestRBACExtractor_ProcessRoleBinding_ServiceAccount(t *testing.T) {
9696
access := extractor.getAccess()
9797
require.Len(t, access, 2, "expected 2 config access entries (one per pod in namespace)")
9898

99+
expectedRoleAlias := KubernetesAlias(clusterName, "Role", "default", "pod-reader")
100+
99101
// Check that access entries point to pods, not the role
100102
for _, a := range access {
101103
assert.Equal(t, ConfigTypePrefix+"Pod", a.ConfigExternalID.ConfigType)
102104
assert.Equal(t, []string{expectedUserAlias}, a.ExternalUserAliases)
105+
assert.Equal(t, []string{expectedRoleAlias}, a.ExternalRoleAliases)
106+
assert.NotEmpty(t, a.ID, "access ID should be set")
103107
}
104108
}
105109

@@ -136,6 +140,12 @@ func TestRBACExtractor_ProcessRoleBinding_User(t *testing.T) {
136140
// Should have ConfigAccess for the pod and service (cluster-wide)
137141
access := extractor.getAccess()
138142
assert.Len(t, access, 2, "expected 2 config access entries (pod + service)")
143+
144+
expectedRoleAlias := KubernetesAlias(clusterName, "ClusterRole", "", "cluster-admin")
145+
for _, a := range access {
146+
assert.Equal(t, []string{expectedRoleAlias}, a.ExternalRoleAliases)
147+
assert.NotEmpty(t, a.ID, "access ID should be set")
148+
}
139149
}
140150

141151
func TestRBACExtractor_ProcessRoleBinding_Group(t *testing.T) {
@@ -171,6 +181,10 @@ func TestRBACExtractor_ProcessRoleBinding_Group(t *testing.T) {
171181
require.Len(t, access, 1, "expected 1 config access entry")
172182
assert.Empty(t, access[0].ExternalUserAliases)
173183
assert.Equal(t, []string{expectedGroupAlias}, access[0].ExternalGroupAliases)
184+
185+
expectedRoleAlias := KubernetesAlias(clusterName, "ClusterRole", "", "view")
186+
assert.Equal(t, []string{expectedRoleAlias}, access[0].ExternalRoleAliases)
187+
assert.NotEmpty(t, access[0].ID, "access ID should be set")
174188
}
175189

176190
func TestRBACExtractor_ProcessRoleBinding_MixedSubjects(t *testing.T) {
@@ -203,6 +217,12 @@ func TestRBACExtractor_ProcessRoleBinding_MixedSubjects(t *testing.T) {
203217
// Each subject gets one ConfigAccess entry for the pod
204218
access := extractor.getAccess()
205219
assert.Len(t, access, 3, "expected 3 config access entries (one per subject, all pointing to same pod)")
220+
221+
expectedRoleAlias := KubernetesAlias(clusterName, "ClusterRole", "", "edit")
222+
for _, a := range access {
223+
assert.Equal(t, []string{expectedRoleAlias}, a.ExternalRoleAliases)
224+
assert.NotEmpty(t, a.ID, "access ID should be set")
225+
}
206226
}
207227

208228
func TestRBACExtractor_Deduplication(t *testing.T) {
@@ -286,6 +306,10 @@ func TestRBACExtractor_CRDResourceResolution(t *testing.T) {
286306
require.Len(t, access, 1, "expected 1 config access entry for the canary instance")
287307
assert.Equal(t, ConfigTypePrefix+"Canary", access[0].ConfigExternalID.ConfigType)
288308
assert.Equal(t, KubernetesAlias(clusterName, "Canary", "default", "my-canary"), access[0].ConfigExternalID.ExternalID)
309+
310+
expectedRoleAlias := KubernetesAlias(clusterName, "ClusterRole", "", "canary-admin")
311+
assert.Equal(t, []string{expectedRoleAlias}, access[0].ExternalRoleAliases)
312+
assert.NotEmpty(t, access[0].ID, "access ID should be set")
289313
}
290314

291315
// Helper types and functions

0 commit comments

Comments
 (0)