Baike.dev
All toolsAI codingTrendingOpen sourceNewsSubmit
Log in
Back to tool/Back to issues
#18755·kops

OIDC groupsClaims and requiredClaims are silently corrupted by the v1alpha2 conversion

Author: rifelpetCreated Aug 27, 2026Updated Sep 13, 2026
Labelskind/bug

/kind bug

1. What kops version are you running? The command kops version, will display this information.

Present on master (1.37 development). The conversion has had this shape since v1alpha3 was introduced.

2. What Kubernetes version are you running? kubectl version will print the version if a cluster is running or provide the Kubernetes version specified as a kops flag.

Not version specific — the corruption happens in the kOps API conversion layer, before anything reaches the cluster.

3. What cloud provider are you using?

All providers.

4. What commands did you run? What is the simplest way to reproduce this issue?

Configure an OIDC group claim containing a comma, or a required claim whose key contains an equals sign, then run any command that writes the cluster back to the state store (kops edit cluster, kops replace -f, kops update cluster).

yaml
spec:
  authentication:
    oidc:
      clientID: kubernetes
      issuerURL: https://example.com
      groupsClaims:
        - "a,b"
      requiredClaims:
        "a=b": "c"

5. What happened after the commands executed?

Both values are silently rewritten:

field stored read back
groupsClaims ["a,b"] ["a", "b"]
requiredClaims {"a=b": "c"} {"a": "b=c"}

No warning and no error — the cluster is reconciled against the corrupted values.

6. What did you expect to happen?

Either the claims round trip unchanged, or kOps rejects the configuration with a clear validation error instead of silently rewriting it.

7. Please provide your cluster manifest.

See the snippet in (4); nothing else is required to reproduce.

8. Please run the commands with most verbose logging by adding the -v 10 flag.

Not applicable — there is no log output, which is the point of the report.

9. Anything else do we need to know?

Cause. spec.authentication.oidc has no representation in v1alpha2. The hand written conversion flattens it into the legacy kube-apiserver OIDC flags, which are string encoded:

  • pkg/apis/kops/v1alpha2/conversion.go:402 joins GroupsClaims with , into the single oidcGroupsClaim flag; conversion.go:122 splits it back on ,.
  • pkg/apis/kops/v1alpha2/conversion.go:407 encodes each RequiredClaims entry as key=value into oidcRequiredClaim; conversion.go:129 splits each entry on the first =.

A separator inside a claim name is therefore indistinguishable from the separator itself. Comma and equals sign are unusual in JWT claim names but are perfectly legal, so this is silent data corruption rather than a rejected input.

This is live rather than theoretical, because the state store is still written as v1alpha2 (pkg/client/simple/vfsclientset/commonvfs.go: var StoreVersion = v1alpha2.SchemeGroupVersion). Every write/read cycle re-applies the corruption. v1alpha3 is unaffected — it carries authentication.oidc structurally.

Possible fixes.

  1. Validate and reject. Add validation that a groupsClaims entry contains no , and a requiredClaims key contains no =. Cheap, and converts silent corruption into a clear error. Downside: a cluster already storing such a value starts failing validation, though its configuration is already being corrupted today.
  2. Give v1alpha2 a structural home for OIDC. Change AuthenticationSpec.OIDC in pkg/apis/kops/v1alpha2/cluster.go from json:"-" to json:"oidc,omitempty" so the settings persist without the string encoding, leaving the kubeAPIServer.oidc* flags as a read-only migration path. The conversion already writes both forms, so an older kOps reading the newer state store still finds the legacy flags; the read path would need authentication.oidc to win when both are present. This mirrors what #18740 does for spec.cloudProvider.{aws,gce}.binariesLocation, which is the same class of problem: a structured internal field with no structured v1alpha2 home.

Related. A neighbouring crash in the same block — an oidcRequiredClaim entry with no = at all panicked with index out of range [1] with length 1 — was found at the same time and is being fixed separately.

Found while adding round trip test coverage for Cluster and InstanceGroup, which had been excluded from TestRoundTripTypes in pkg/apis/kops/install/roundtrip_test.go.

Source: kubernetes/kops

View original on GitHubView discussion on GitHub