🤖 Generated by the Agentic Engineer
Evidence
EKSOwnershipState deliberately records the complete AWS environment-variable-name mapping used when a cluster was bound:
// AWSOptions stores the complete environment-variable-name mapping used to resolve AWS
// credentials. Credential values are never persisted. Records without this mapping predate the
// schema extension and require explicit rebind before state-only lifecycle commands may use them.
AWSOptions v1alpha1.OptionsAWS `json:"awsOptions,omitzero"`
ListEKSOwnershipStates enforces that: a record without a complete mapping is rejected as unusable. So the mapping is treated as a precondition for acting on a record at all.
But the binding path then discards it. bindFromOwnershipRecord keeps only the region:
return &clusterprovisioner.EKSConfig{
Name: name,
Region: region,
ConfigPath: configPath,
}, nil
clusterprovisioner.EKSConfig has no field for it — its fields are Name, NameFromConfig, Region, ConfigPath, KubeconfigPath — so the mapping cannot be carried through even in principle without a type change.
Problem / audience
Operators who resolve AWS credentials through non-default environment-variable names (a per-account or per-profile naming scheme). The lifecycle spec built from an ownership record carries no Spec.Provider.AWS options, so credential resolution falls back to the canonical AWS_* variables instead of the names captured at bind time.
Two outcomes, and the second is the dangerous one:
- the action fails despite valid credentials being present under the operator's own variable names; or
- the canonical variables select a different AWS account that happens to contain a cluster of the same name, and the action targets that one.
This is the same class of defect as the region redirect that motivated the ownership record in the first place — an action resolving its target from ambient environment rather than from what was recorded — one axis over. It affects delete, which makes it destructive.
Note the guard that still stands: confirmEKSOwnership runs regardless, so this is not an unauthenticated path. The risk is that it authenticates against the wrong account's cluster.
Why it is not fixed in the PR that found it
Found by review on #6385. Fixing it means adding the mapping to clusterprovisioner.EKSConfig and threading it through DefaultFactory into credential resolution — a cross-package change to a shared provisioner type, on a destructive path. #6385 already carries two behaviour changes through several review rounds, and folding a third in would make it materially harder to review.
Smallest useful change
- Carry the recorded
AWSOptions on the config the binding produces.
- Resolve credentials from that frozen mapping for state-bound lifecycle actions, rather than from the ambient defaults.
- Prove it with a test where the recorded variable names differ from the canonical ones, asserting which names are read — not merely that the action succeeds, since it succeeds either way when both point at the same account.
Acceptance criteria
Rough size: S–M.
Evidence
EKSOwnershipStatedeliberately records the complete AWS environment-variable-name mapping used when a cluster was bound:ListEKSOwnershipStatesenforces that: a record without a complete mapping is rejected as unusable. So the mapping is treated as a precondition for acting on a record at all.But the binding path then discards it.
bindFromOwnershipRecordkeeps only the region:clusterprovisioner.EKSConfighas no field for it — its fields areName,NameFromConfig,Region,ConfigPath,KubeconfigPath— so the mapping cannot be carried through even in principle without a type change.Problem / audience
Operators who resolve AWS credentials through non-default environment-variable names (a per-account or per-profile naming scheme). The lifecycle spec built from an ownership record carries no
Spec.Provider.AWSoptions, so credential resolution falls back to the canonicalAWS_*variables instead of the names captured at bind time.Two outcomes, and the second is the dangerous one:
This is the same class of defect as the region redirect that motivated the ownership record in the first place — an action resolving its target from ambient environment rather than from what was recorded — one axis over. It affects delete, which makes it destructive.
Note the guard that still stands:
confirmEKSOwnershipruns regardless, so this is not an unauthenticated path. The risk is that it authenticates against the wrong account's cluster.Why it is not fixed in the PR that found it
Found by review on #6385. Fixing it means adding the mapping to
clusterprovisioner.EKSConfigand threading it throughDefaultFactoryinto credential resolution — a cross-package change to a shared provisioner type, on a destructive path. #6385 already carries two behaviour changes through several review rounds, and folding a third in would make it materially harder to review.Smallest useful change
AWSOptionson the config the binding produces.Acceptance criteria
AWS_*names when the record names others.Rough size: S–M.