{"record":{"id":"6ab29d8b58549a3b","repo":"argoproj/argo-workflows","slug":"no-service-account-rule-matches","errorCode":null,"errorMessage":"no service account rule matches","messagePattern":"no service account rule matches","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/auth/gatekeeper.go","lineNumber":261,"sourceCode":"\t\tserviceAccounts = append(serviceAccounts, serviceAccount)\n\t}\n\tsort.Slice(serviceAccounts, func(i, j int) bool { return precedence(serviceAccounts[i]) > precedence(serviceAccounts[j]) })\n\tfor _, serviceAccount := range serviceAccounts {\n\t\trule := serviceAccount.Annotations[common.AnnotationKeyRBACRule]\n\t\tv, err := jsonutil.Jsonify(claims)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to marshall claims: %w\", err)\n\t\t}\n\t\tallow, err := argoexpr.EvalBool(rule, v)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to evaluate rule: %w\", err)\n\t\t}\n\t\tif !allow {\n\t\t\tcontinue\n\t\t}\n\t\treturn serviceAccount, nil\n\t}\n\treturn nil, fmt.Errorf(\"no service account rule matches\")\n}\n\nfunc (s *gatekeeper) canDelegateRBACToRequestNamespace(req any) bool {\n\tif s.namespaced || os.Getenv(\"SSO_DELEGATE_RBAC_TO_NAMESPACE\") != \"true\" {\n\t\treturn false\n\t}\n\tnamespace := getNamespace(req)\n\treturn len(namespace) != 0 && s.ssoNamespace != namespace\n}\n\nfunc (s *gatekeeper) getClientsForServiceAccount(ctx context.Context, claims *authTypes.Claims, serviceAccount *corev1.ServiceAccount) (*servertypes.Clients, error) {\n\tauthorization, err := s.authorizationForServiceAccount(ctx, serviceAccount)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\t_, clients, err := s.clientForAuthorization(authorization, s.restConfig)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/auth/gatekeeper.go#L243-L279","documentation":"When SSO RBAC is enabled, argo-server maps the authenticated user's OIDC claims to a ServiceAccount by finding one whose rbac-rule annotation evaluates true in the SSO namespace. This error means every candidate rule evaluated to false (or no ServiceAccounts carry rbac-rule annotations at all), so no service account could be selected for the user. rbacAuthorization treats this specially (continues to try namespace delegation) and finally surfaces 'PermissionDenied: not allowed' to the client.","triggerScenarios":"An SSO-authenticated request where all rbac-rule annotations in the SSO namespace evaluate false for the user's claims, and either delegation is disabled (namespaced mode or SSO_DELEGATE_RBAC_TO_NAMESPACE != \"true\") or no namespace rule matches either.","commonSituations":"New user with an email/domain not covered by any rule; IDP changed claim shape (e.g. groups format, email hidden); ServiceAccount rbac-rule annotations missing or not applied; rules written against `groups` but the IDP sends different claim names; user filtered out of group claims by the OIDC client scopes.","solutions":["Add or fix a ServiceAccount rbac-rule annotation in the SSO namespace that matches the user's actual claims, e.g. `workflows.argoproj.io/rbac-rule: 'email.endsWith(\"@example.com\")'`, with matching rbac-rule-precedence if needed.","Verify the claims your IDP sends (decode the ID token at jwt.io) and align rule field names — often `groups` or `email` differ or are absent due to scopes/claims mappings in the OIDC config (sso: scopes, custom group claim mapping in server config).","If you intend per-namespace rules, set env SSO_DELEGATE_RBAC_TO_NAMESPACE=true on argo-server and ensure the target namespace has a matching ServiceAccount rule.","Check rule syntax so a valid rule isn't silently evaluating false (e.g. `\"groups\": [\"*\"]` semantics differ — use expr membership like `'admins' in groups`)."],"exampleFix":"// before: no matching SA\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: argo-admin\n  annotations:\n    workflows.argoproj.io/rbac-rule: 'groups == \"argo-admins\"'   # fails when groups is a list\n// after\nmetadata:\n  name: argo-admin\n  annotations:\n    workflows.argoproj.io/rbac-rule: '\"argo-admins\" in groups'","handlingStrategy":"validation","validationCode":"// ensure at least one SA rule exists in the SSO namespace\nkubectl -n argo get sa -o json | jq '[.items[] | select(.metadata.annotations[\"workflows.argoproj.io/rbac-rule\"])] | length'","typeGuard":null,"tryCatchPattern":"// argo CLI surfaces PermissionDenied\nif err != nil {\n    if st, ok := status.FromError(err); ok && st.Code() == codes.PermissionDenied {\n        return fmt.Errorf(\"SSO user has no matching rbac-rule: %w\", err)\n    }\n    return err\n}","preventionTips":["Always define a low-precedence catch-all rule (rbac-rule: 'true') mapping to a default SA","Keep rules in sync with your IDP's claim names and group formats","Re-verify rules after OIDC provider config/scope changes","Remember requests to the SSO namespace itself never use namespace delegation"],"tags":["sso","rbac","authorization","misconfiguration"],"backgroundTag":"no-rbac-rule-matches","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}