{"record":{"id":"0501b9d4ef7cec7e","repo":"vitessio/vitess","slug":"rule-d-clusters-list-cannot-include-wildcard-and","errorCode":null,"errorMessage":"rule %d: clusters list cannot include wildcard and other clusters, have %v","messagePattern":"rule (.+?): clusters list cannot include wildcard and other clusters, have (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/rbac/config.go","lineNumber":107,"sourceCode":"\tfor i, rule := range c.Rules {\n\t\tresourceRules := byResource[rule.Resource]\n\n\t\tactions := sets.New[string](rule.Actions...)\n\t\tif actions.Has(\"*\") && actions.Len() > 1 {\n\t\t\t// error to have wildcard and something else\n\t\t\trec.RecordError(fmt.Errorf(\"rule %d: actions list cannot include wildcard and other actions, have %v\", i, sets.List(actions)))\n\t\t}\n\n\t\tsubjects := sets.New[string](rule.Subjects...)\n\t\tif subjects.Has(\"*\") && subjects.Len() > 1 {\n\t\t\t// error to have wildcard and something else\n\t\t\trec.RecordError(fmt.Errorf(\"rule %d: subjects list cannot include wildcard and other subjects, have %v\", i, sets.List(subjects)))\n\t\t}\n\n\t\tclusters := sets.New[string](rule.Clusters...)\n\t\tif clusters.Has(\"*\") && clusters.Len() > 1 {\n\t\t\t// error to have wildcard and something else\n\t\t\trec.RecordError(fmt.Errorf(\"rule %d: clusters list cannot include wildcard and other clusters, have %v\", i, sets.List(clusters)))\n\t\t}\n\n\t\tresourceRules = append(resourceRules, &Rule{\n\t\t\tactions:  actions,\n\t\t\tsubjects: subjects,\n\t\t\tclusters: clusters,\n\t\t})\n\t\tbyResource[rule.Resource] = resourceRules\n\t}\n\n\tif rec.HasErrors() {\n\t\treturn rec.Error()\n\t}\n\n\tlog.Info(fmt.Sprintf(\"[rbac]: loaded authorizer with %d rules\", len(c.Rules)))\n\n\tc.cfg = byResource\n\tc.authorizer = &Authorizer{","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/rbac/config.go#L89-L125","documentation":"As the third wildcard-consistency check in RBAC config reification, clusters per rule are validated: \"*\" (all clusters) cannot appear alongside specific cluster names. Mixing them makes rule matching ambiguous, so Reify records a validation error naming the rule index and offending cluster list. The config must be corrected before vtadmin will start.","triggerScenarios":"RBAC config rule with `clusters: [\"*\", \"local_cluster\"]`, loaded through config.Reify during vtadmin startup or RBAC tests.","commonSituations":"Multi-cluster setups where an operator appended a specific cluster to an existing catch-all rule; config templating that merges wildcard defaults with environment-specific clusters; migrating from single-cluster to multi-cluster configs.","solutions":["Keep \"*\" alone if the rule should apply to all clusters.","Otherwise remove \"*\" and list only the target cluster names.","Split into two rules if different resources need different cluster scopes."],"exampleFix":"// before\n{\"resource\": \"backups\", \"actions\": [\"*\"], \"clusters\": [\"*\", \"prod\"]}\n// after\n{\"resource\": \"backups\", \"actions\": [\"*\"], \"clusters\": [\"prod\"]}","handlingStrategy":"validation","validationCode":"for i, rule := range cfg.Rules {\n\tif slices.Contains(rule.Clusters, \"*\") && len(rule.Clusters) > 1 {\n\t\treturn fmt.Errorf(\"rule %d: clusters must be * alone or explicit list\", i)\n\t}\n}","typeGuard":"func clustersValid(clusters []string) bool {\n\treturn !(slices.Contains(clusters, \"*\") && len(clusters) > 1)\n}","tryCatchPattern":"rules, err := cfg.Reify()\nif err != nil {\n\tlog.Fatalf(\"fix RBAC clusters config: %v\", err)\n}","preventionTips":["Generate per-environment cluster lists rather than appending to a wildcard default.","Keep wildcard rules separate from cluster-specific rules.","Run config.Reify as a CI check on every RBAC config change."],"tags":["rbac","config-validation","vtadmin","authorization"],"backgroundTag":"wildcard-mixed-with-specific-clusters","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}