{"record":{"id":"427977351f5f720d","repo":"k3s-io/k3s","slug":"more-than-3-providers-d-found-in-secrets-encryp-427977","errorCode":null,"errorMessage":"more than 3 providers (%d) found in secrets encryption","messagePattern":"more than 3 providers \\((.+?)\\) found in secrets encryption","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/server/handlers/secrets-encrypt.go","lineNumber":151,"sourceCode":"\t\t}\n\t}\n\n\treturn state, nil\n}\n\nfunc encryptionEnable(ctx context.Context, control *config.Control, enable bool) error {\n\tproviders, err := secretsencrypt.GetEncryptionProviders(control.Runtime)\n\t// Enable secrets encryption with an identity provider on a cluster that does not have any encryption config\n\tif err != nil && os.IsNotExist(err) && enable {\n\t\tif err := secretsencrypt.WriteIdentityConfig(control); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn cluster.Save(ctx, control, true)\n\t} else if err != nil {\n\t\treturn err\n\t}\n\tif len(providers) > 3 {\n\t\treturn fmt.Errorf(\"more than 3 providers (%d) found in secrets encryption\", len(providers))\n\t}\n\tcurKeys, err := secretsencrypt.GetEncryptionKeys(control.Runtime)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif providers[len(providers)-1].Identity != nil && (providers[0].AESCBC != nil || providers[0].Secretbox != nil) && !enable {\n\t\tlogrus.Infoln(\"Disabling secrets encryption\")\n\t\tif err := secretsencrypt.WriteEncryptionConfig(control.Runtime, curKeys, control.EncryptProvider, enable); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else if !enable {\n\t\tlogrus.Infoln(\"Secrets encryption already disabled\")\n\t\treturn nil\n\t} else if providers[0].Identity != nil && (providers[1].AESCBC != nil || providers[1].Secretbox != nil) && enable {\n\t\tfoundKey := false\n\t\t// Check the rest of the providers (generally 2nd and 3rd) for the key type we are trying to enable.\n\t\t// If we find one, we can proceed.","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/server/handlers/secrets-encrypt.go#L133-L169","documentation":"Before enabling/disabling secrets encryption, k3s parses /var/lib/rancher/k3s/server/cred/encryption-config.yaml into provider blocks. Its rotation state machine only understands configurations with at most three providers (active key, old key(s), identity fallback). More than three providers means the config was produced outside the documented k3s flow and k3s refuses to operate on it.","triggerScenarios":"Running 'k3s secrets-encrypt enable/disable' (or POSTing to the secrets-encrypt endpoint) after the encryption config file was hand-edited or externally generated with four or more provider entries, e.g. several manual aescbc/secretbox blocks plus identity.","commonSituations":"Admins hand-crafting the encryption config for multi-key policies; config management (Ansible/Helm) overwriting the file with a larger provider list; copying a config from a different k8s distribution that does not enforce the 3-provider bound; mixing k3s rotation stages with manual edits.","solutions":["Restore an encryption config generated by k3s itself: copy the file from another control-plane node that k3s still manages, or rebuild the config with exactly one active key provider plus identity.","Keep provider count within k3s's supported layout (first-key, second-key, identity) and perform all changes through 'k3s secrets-encrypt' stages instead of editing the file.","Verify with 'k3s secrets-encrypt status' that k3s can parse the repaired config before retrying enable/disable.","Ensure no external tool rewrites the file afterward (exclude it from config management)."],"exampleFix":"# before: 4 providers in /var/lib/rancher/k3s/server/cred/encryption-config.yaml\napiVersion: apiserver.config.k8s.io/v1\nkind: EncryptionConfiguration\nresources:\n- providers: [aescbc, aescbc, aescbc, identity]  # -> error\n\n# after: k3s-managed 3-provider layout\n- providers: [aescbc(active), identity]  # old key added only during rotate stages","handlingStrategy":"validation","validationCode":"// Before enabling, count providers in the config k3s will parse\nimport \"sigs.k8s.io/yaml\"\n\ntype encConf struct {\n    Resources []struct{ Providers []map[string]any `json:\"providers\"` } `json:\"resources\"`\n}\nvar c encConf\nyaml.Unmarshal(raw, &c)\nif n := len(c.Resources[0].Providers); n > 3 {\n    log.Fatalf(\"%d providers - reduce to k3s-managed layout\", n)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit encryption-config.yaml; use k3s secrets-encrypt stages","Exclude the cred directory from config management overwrite","Audit provider count after restores or migrations"],"tags":["secrets-encryption","configuration","security"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}