{"record":{"id":"bf88f7432e703e55","repo":"rancher/rancher","slug":"error-rendering-files-cluster-s-s-was-not-autho","errorCode":null,"errorMessage":"error rendering files: cluster %s/%s was not authorized to access secret %s/%s","messagePattern":"error rendering files: cluster (.+?)/(.+?) was not authorized to access secret (.+?)/(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/capr/planner/config.go","lineNumber":820,"sourceCode":"\t\t\t\t\tfor _, v := range fs.Secret.Items {\n\t\t\t\t\t\tfile := plan.File{\n\t\t\t\t\t\t\tPath:    v.Path,\n\t\t\t\t\t\t\tContent: base64.StdEncoding.EncodeToString(secret.Data[v.Key]),\n\t\t\t\t\t\t\tDynamic: v.Dynamic,\n\t\t\t\t\t\t}\n\t\t\t\t\t\thash := sha256.Sum256(secret.Data[v.Key])\n\t\t\t\t\t\tif v.Hash != \"\" && v.Hash != base64.StdEncoding.EncodeToString(hash[:]) {\n\t\t\t\t\t\t\treturn files, fmt.Errorf(\"secret %s does not contain the expected content\", secret.Name)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif v.Permissions != \"\" {\n\t\t\t\t\t\t\tfile.Permissions = v.Permissions\n\t\t\t\t\t\t} else if fs.Secret.DefaultPermissions != \"\" {\n\t\t\t\t\t\t\tfile.Permissions = fs.Secret.DefaultPermissions\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfiles = append(files, file)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn files, fmt.Errorf(\"error rendering files: cluster %s/%s was not authorized to access secret %s/%s\", controlPlane.Namespace, controlPlane.Name, controlPlane.Namespace, fs.Secret.Name)\n\t\t\t\t}\n\t\t\t}\n\t\t\tif fs.ConfigMap.Name != \"\" {\n\t\t\t\tconfigmap, err := p.configMapCache.Get(controlPlane.Namespace, fs.ConfigMap.Name)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn files, fmt.Errorf(\"error retrieving configmap %s/%s while rendering files: %v\", controlPlane.Namespace, fs.ConfigMap.Name, err)\n\t\t\t\t}\n\t\t\t\t// retrieve configmap and use contents\n\t\t\t\tif authorized, found := clusterObjectAuthorized(configmap, capr.AuthorizedObjectAnnotation, controlPlane.Name); authorized && found {\n\t\t\t\t\tfor _, v := range fs.ConfigMap.Items {\n\t\t\t\t\t\tfile := plan.File{\n\t\t\t\t\t\t\tPath:    v.Path,\n\t\t\t\t\t\t\tContent: base64.StdEncoding.EncodeToString([]byte(configmap.Data[v.Key])),\n\t\t\t\t\t\t\tDynamic: v.Dynamic,\n\t\t\t\t\t\t}\n\t\t\t\t\t\thash := sha256.Sum256([]byte(configmap.Data[v.Key]))\n\t\t\t\t\t\tif v.Hash != \"\" && v.Hash != base64.StdEncoding.EncodeToString(hash[:]) {\n\t\t\t\t\t\t\treturn files, fmt.Errorf(\"configmap %s does not contain the expected content\", configmap.Name)","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/rancher/rancher/blob/932558d4e68565aff2d2f36e89ec4a391b06e7c5/pkg/capr/planner/config.go#L802-L838","documentation":"Secrets delivered through machineSelectorFiles are gated by the annotation rke.cattle.io/object-authorized-for-clusters, a comma-separated list of cluster names; clusterObjectAuthorized splits on ',' and requires the cluster's name to appear as an element. If the annotation is absent or lists only other clusters, plan rendering aborts with this error. Note this is a different annotation than the single-value v2prov-secret-authorized-for-cluster used for cloud-provider secrets.","triggerScenarios":"Referencing a secret in fileSources when the secret has no rke.cattle.io/object-authorized-for-clusters annotation, or the annotation value omits this cluster's name (including whitespace or trailing-comma mismatches after splitting).","commonSituations":"Manually created file secrets; sharing one secret across several clusters without listing all of them; GitOps pipelines that create secrets but not the authorization annotation.","solutions":["Annotate the secret with the cluster: kubectl annotate secret <name> -n <ns> rke.cattle.io/object-authorized-for-clusters=<cluster-name>","For shared secrets, list all consuming clusters comma-separated with no extra spaces","Let Rancher's file-secret flow manage the annotation when possible","Verify with kubectl get secret <name> -o jsonpath='{.metadata.annotations}'"],"exampleFix":"# before\nkubectl create secret generic my-files -n fleet-default --from-file=hosts=./hosts\n# cluster spec fileSources references it -> not authorized\n\n# after\nkubectl create secret generic my-files -n fleet-default --from-file=hosts=./hosts\nkubectl annotate secret my-files -n fleet-default rke.cattle.io/object-authorized-for-clusters=my-cluster","handlingStrategy":"validation","validationCode":"func authorizedForObject(o metav1.Object, cluster string) bool {\n\tfor _, c := range strings.Split(o.GetAnnotations()[\"rke.cattle.io/object-authorized-for-clusters\"], \",\") {\n\t\tif c == cluster {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\n// call before referencing the secret in fileSources","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Annotate file-source secrets with rke.cattle.io/object-authorized-for-clusters at creation time","When sharing, list every consuming cluster comma-separated without spaces","Include the annotation in the same GitOps manifest as the secret","Remember this is a different annotation than the cloud-provider v2prov one"],"tags":["secret","annotation","authorization","files","rancher"],"backgroundTag":null,"analyzedSha":"932558d4e68565aff2d2f36e89ec4a391b06e7c5","analyzedAt":"2026-08-16T04:37:02.125Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}