argoproj/argo-workflows · warning

no service account rule matches

Error message

no service account rule matches

What it means

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.

Source

Thrown at server/auth/gatekeeper.go:261

		serviceAccounts = append(serviceAccounts, serviceAccount)
	}
	sort.Slice(serviceAccounts, func(i, j int) bool { return precedence(serviceAccounts[i]) > precedence(serviceAccounts[j]) })
	for _, serviceAccount := range serviceAccounts {
		rule := serviceAccount.Annotations[common.AnnotationKeyRBACRule]
		v, err := jsonutil.Jsonify(claims)
		if err != nil {
			return nil, fmt.Errorf("failed to marshall claims: %w", err)
		}
		allow, err := argoexpr.EvalBool(rule, v)
		if err != nil {
			return nil, fmt.Errorf("failed to evaluate rule: %w", err)
		}
		if !allow {
			continue
		}
		return serviceAccount, nil
	}
	return nil, fmt.Errorf("no service account rule matches")
}

func (s *gatekeeper) canDelegateRBACToRequestNamespace(req any) bool {
	if s.namespaced || os.Getenv("SSO_DELEGATE_RBAC_TO_NAMESPACE") != "true" {
		return false
	}
	namespace := getNamespace(req)
	return len(namespace) != 0 && s.ssoNamespace != namespace
}

func (s *gatekeeper) getClientsForServiceAccount(ctx context.Context, claims *authTypes.Claims, serviceAccount *corev1.ServiceAccount) (*servertypes.Clients, error) {
	authorization, err := s.authorizationForServiceAccount(ctx, serviceAccount)
	if err != nil {
		return nil, err
	}
	_, clients, err := s.clientForAuthorization(authorization, s.restConfig)
	if err != nil {
		return nil, err

View on GitHub (pinned to 35bff19146)

Solutions

  1. 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.
  2. 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).
  3. 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.
  4. Check rule syntax so a valid rule isn't silently evaluating false (e.g. `"groups": ["*"]` semantics differ — use expr membership like `'admins' in groups`).

Example fix

// before: no matching SA
apiVersion: v1
kind: ServiceAccount
metadata:
  name: argo-admin
  annotations:
    workflows.argoproj.io/rbac-rule: 'groups == "argo-admins"'   # fails when groups is a list
// after
metadata:
  name: argo-admin
  annotations:
    workflows.argoproj.io/rbac-rule: '"argo-admins" in groups'
Defensive patterns

Strategy: validation

Validate before calling

// ensure at least one SA rule exists in the SSO namespace
kubectl -n argo get sa -o json | jq '[.items[] | select(.metadata.annotations["workflows.argoproj.io/rbac-rule"])] | length'

Try / catch

// argo CLI surfaces PermissionDenied
if err != nil {
    if st, ok := status.FromError(err); ok && st.Code() == codes.PermissionDenied {
        return fmt.Errorf("SSO user has no matching rbac-rule: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/6ab29d8b58549a3b. Report an issue: GitHub.