Skip to content

Commit f26cf38

Browse files
authored
Merge pull request kubernetes#126553 from aramase/aramase/c/kep_3331_disallow_k8s_io_prefix
Disallow `k8s.io` and `kubernetes.io` namespaced extra key in structured authn config
2 parents 66dca45 + 89c619f commit f26cf38

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ func validateClaimMappings(compiler authenticationcel.Compiler, state *validatio
355355
if mapping.Key != strings.ToLower(mapping.Key) {
356356
allErrs = append(allErrs, field.Invalid(fldPath.Child("key"), mapping.Key, "key must be lowercase"))
357357
}
358+
359+
if isKubernetesDomainPrefix(mapping.Key) {
360+
allErrs = append(allErrs, field.Invalid(fldPath.Child("key"), mapping.Key, "k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use"))
361+
}
362+
358363
if seenExtraKeys.Has(mapping.Key) {
359364
allErrs = append(allErrs, field.Duplicate(fldPath.Child("key"), mapping.Key))
360365
continue
@@ -394,6 +399,24 @@ func validateClaimMappings(compiler authenticationcel.Compiler, state *validatio
394399
return allErrs
395400
}
396401

402+
func isKubernetesDomainPrefix(key string) bool {
403+
domainPrefix := getDomainPrefix(key)
404+
if domainPrefix == "kubernetes.io" || strings.HasSuffix(domainPrefix, ".kubernetes.io") {
405+
return true
406+
}
407+
if domainPrefix == "k8s.io" || strings.HasSuffix(domainPrefix, ".k8s.io") {
408+
return true
409+
}
410+
return false
411+
}
412+
413+
func getDomainPrefix(key string) string {
414+
if parts := strings.SplitN(key, "/", 2); len(parts) == 2 {
415+
return parts[0]
416+
}
417+
return ""
418+
}
419+
397420
func usesEmailClaim(ast *celgo.Ast) bool {
398421
return hasSelectExp(ast.Expr(), "claims", "email")
399422
}

staging/src/k8s.io/apiserver/pkg/apis/apiserver/validation/validation_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,69 @@ func TestValidateClaimMappings(t *testing.T) {
13631363
structuredAuthnFeatureEnabled: true,
13641364
want: `issuer.claimMappings.extra[0].key: Invalid value: "example.org/Foo": key must be lowercase`,
13651365
},
1366+
{
1367+
name: "extra mapping key prefix is k8.io",
1368+
in: api.ClaimMappings{
1369+
Username: api.PrefixedClaimOrExpression{Expression: "claims.username"},
1370+
Groups: api.PrefixedClaimOrExpression{Expression: "claims.groups"},
1371+
Extra: []api.ExtraMapping{
1372+
{Key: "k8s.io/foo", ValueExpression: "claims.extra"},
1373+
},
1374+
},
1375+
structuredAuthnFeatureEnabled: true,
1376+
want: `issuer.claimMappings.extra[0].key: Invalid value: "k8s.io/foo": k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use`,
1377+
},
1378+
{
1379+
name: "extra mapping key prefix contains k8.io",
1380+
in: api.ClaimMappings{
1381+
Username: api.PrefixedClaimOrExpression{Expression: "claims.username"},
1382+
Groups: api.PrefixedClaimOrExpression{Expression: "claims.groups"},
1383+
Extra: []api.ExtraMapping{
1384+
{Key: "example.k8s.io/foo", ValueExpression: "claims.extra"},
1385+
},
1386+
},
1387+
structuredAuthnFeatureEnabled: true,
1388+
want: `issuer.claimMappings.extra[0].key: Invalid value: "example.k8s.io/foo": k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use`,
1389+
},
1390+
{
1391+
name: "extra mapping key prefix is kubernetes.io",
1392+
in: api.ClaimMappings{
1393+
Username: api.PrefixedClaimOrExpression{Expression: "claims.username"},
1394+
Groups: api.PrefixedClaimOrExpression{Expression: "claims.groups"},
1395+
Extra: []api.ExtraMapping{
1396+
{Key: "kubernetes.io/foo", ValueExpression: "claims.extra"},
1397+
},
1398+
},
1399+
structuredAuthnFeatureEnabled: true,
1400+
want: `issuer.claimMappings.extra[0].key: Invalid value: "kubernetes.io/foo": k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use`,
1401+
},
1402+
{
1403+
name: "extra mapping key prefix contains kubernetes.io",
1404+
in: api.ClaimMappings{
1405+
Username: api.PrefixedClaimOrExpression{Expression: "claims.username"},
1406+
Groups: api.PrefixedClaimOrExpression{Expression: "claims.groups"},
1407+
Extra: []api.ExtraMapping{
1408+
{Key: "example.kubernetes.io/foo", ValueExpression: "claims.extra"},
1409+
},
1410+
},
1411+
structuredAuthnFeatureEnabled: true,
1412+
want: `issuer.claimMappings.extra[0].key: Invalid value: "example.kubernetes.io/foo": k8s.io, kubernetes.io and their subdomains are reserved for Kubernetes use`,
1413+
},
1414+
{
1415+
name: "extra mapping key prefix with ak8s.io, *.ak8s.io, bkubernetes.io, *.bkubernetes.io are still valid",
1416+
in: api.ClaimMappings{
1417+
Username: api.PrefixedClaimOrExpression{Expression: "claims.username"},
1418+
Groups: api.PrefixedClaimOrExpression{Expression: "claims.groups"},
1419+
Extra: []api.ExtraMapping{
1420+
{Key: "ak8s.io/foo", ValueExpression: "claims.extra"},
1421+
{Key: "example.ak8s.io/foo", ValueExpression: "claims.extra"},
1422+
{Key: "bkubernetes.io/foo", ValueExpression: "claims.extra"},
1423+
{Key: "example.bkubernetes.io/foo", ValueExpression: "claims.extra"},
1424+
},
1425+
},
1426+
structuredAuthnFeatureEnabled: true,
1427+
want: "",
1428+
},
13661429
{
13671430
name: "valid claim mappings but uses email without verification",
13681431
in: api.ClaimMappings{

0 commit comments

Comments
 (0)