Argo CD RBAC and Authentication Methods: A Complete Configuration Guide
Argo CD implements role-based access control using Casbin policies stored in the argocd-rbac-cm ConfigMap, supporting both local users and SSO providers like OIDC/OAuth for authentication.
Argo CD (from the argoproj/argo-cd repository) delegates identity management to external providers while enforcing authorization through a lightweight, Kubernetes-native policy engine. Unlike platforms that maintain their own user databases, Argo CD relies on a stateless design where the argocd-rbac-cm ConfigMap holds the complete authorization policy, and authentication is handled either via local accounts defined in argocd-cm or federated SSO.
Architecture Overview
Policy Store and Casbin Enforcer
The authorization layer centers on the Enforcer struct defined in util/rbac/rbac.go (lines 27-40). This wrapper around the Casbin library loads three distinct policy sources: the built-in policy from assets/builtin-policy.csv (containing role:readonly and role:admin), the user-defined policy from the argocd-rbac-cm ConfigMap, and optional runtime policies for temporary overrides via EnforceRuntimePolicy.
Pattern Matching and Evaluation Logic
Policy evaluation supports two match modes controlled by policy.matchMode: glob (default, using github.com/gobwas/glob) or regex (using Go's regexp package). The SetMatchMode function (lines 103-111 in util/rbac/rbac.go) configures this behavior.
When evaluating requests, the enforce function (lines 400-426) follows strict precedence:
- Check the default role (
policy.default) - Invoke any custom claims enforcer for JWT tokens via
ClaimsEnforcerFunc - Execute the Casbin policy check where
denyrules always overrideallow
Resources and Actions
Constants defined in util/rbac/rbac.go declare the supported resources and their actions:
- applications:
get,create,update,delete,sync,action,override - applicationsets:
get,create,update,delete - clusters:
get,create,update,delete - projects:
get,create,update,delete - repositories:
get,create,update,delete - accounts:
get,update - extensions:
invoke
Fine-grained control over sub-resources (e.g., update/*/Pod/*/*) is supported since v3.0.0, with an optional backward-compatibility flag (server.rbac.disableApplicationFineGrainedRBACInheritance).
Authentication Methods
Local Users
Local accounts are defined in the argocd-cm ConfigMap under the data.accounts map. Passwords use bcrypt hashing. These users can be assigned policies directly or mapped to groups using the g, <user>, <role> syntax.
Example local user configuration:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
accounts.alice: "$2a$10$..." # bcrypt password
SSO and OIDC Integration
For enterprise authentication, Argo CD supports OIDC/OAuth providers. The token's federated_claims.user_id becomes the subject in policy checks, while group membership is extracted from configured scopes (default groups). The HTTP middleware in server/rbacpolicy/rbacpolicy.go invokes the Enforcer for each API request, passing the parsed JWT claims.
Example SSO policy mapping:
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
data:
policy.csv: |
p, my-org:team-beta, applications, sync, my-project/*, allow
g, my-org:team-beta, role:admin
scopes: '[groups, email]'
JWT Claims Enforcer
A pluggable ClaimsEnforcerFunc can be registered via Enforcer.SetClaimsEnforcerFunc to inspect JWT claims before Casbin evaluation. This allows arbitrary logic such as time-bound access or custom claim validation.
func myClaimsEnforcer(claims jwt.Claims, rvals ...any) bool {
m, _ := jwtutil.MapClaims(claims)
return m["role"] == "dev"
}
enf.SetClaimsEnforcerFunc(myClaimsEnforcer)
Configuration Examples
Defining RBAC Policies in ConfigMap
The policy.csv field uses Casbin's standard format:
- Group assignment:
g, <user|group>, <role> - Permission:
p, <subject>, <resource>, <action>, <object>, <effect>
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
# Grant every authenticated user read-only access by default
policy.default: role:readonly
# Custom policies
policy.csv: |
g, my-org:team-beta, role:admin
g, alice@example.com, role:readonly
p, role:admin, *, *, *, allow
p, role:readonly, applications, get, *, allow
Validating Policies via CLI
The argocd admin settings rbac commands in cmd/argocd/commands/admin_settings_rbac.go provide validation without applying changes:
# Validate CSV syntax
argocd admin settings rbac validate --policy-file my-rbac.yaml
# Test specific permissions
argocd admin settings rbac can --subject alice@example.com \
--resource applications --action sync --object myproj/*
Programmatic Policy Enforcement
Use the Enforcer API directly in Go applications:
import (
"github.com/argoproj/argo-cd/v3/util/rbac"
"k8s.io/client-go/kubernetes"
)
// Assuming kubernetes client `kc`
enf := rbac.NewEnforcer(kc, "argocd", "argocd-rbac-cm", nil)
// Load policies from ConfigMap
if err := enf.LoadPolicy(); err != nil {
panic(err)
}
// Check if user "bob" can sync apps in project "demo"
allowed := enf.Enforce("bob", rbac.ResourceApplications, rbac.ActionSync, "demo/*")
Summary
- Argo CD stores RBAC policies in the
argocd-rbac-cmConfigMap using Casbin CSV format with glob or regex matching modes - The
Enforcerstruct inutil/rbac/rbac.gomanages policy loading, claims enforcement, and evaluation via theenforcefunction - Authentication supports local users (stored in
argocd-cm) and SSO/OIDC providers, with thefederated_claims.user_idclaim becoming the subject - Policy evaluation follows the precedence: default role → custom claims enforcer → Casbin policy, where explicit
denyrules always overrideallow - Built-in roles
role:readonlyandrole:adminare defined inassets/builtin-policy.csvand can be extended via custom policies
Frequently Asked Questions
Where are Argo CD RBAC policies stored?
Policies reside in the argocd-rbac-cm ConfigMap within the Argo CD namespace. This includes the policy.csv definitions, the optional policy.default fallback role, and the policy.matchMode setting (glob or regex). The Enforcer struct in util/rbac/rbac.go watches this ConfigMap and reloads policies at runtime.
What is the difference between local users and SSO in Argo CD authentication?
Local users are defined directly in the argocd-cm ConfigMap with bcrypt-hashed passwords and exist only within the Argo CD instance. SSO users authenticate via external OIDC/OAuth providers; Argo CD receives a JWT where the federated_claims.user_id claim becomes the subject for RBAC checks, and groups are extracted from the configured scopes (default groups).
How does Argo CD handle deny versus allow policies?
According to the enforce function implementation in util/rbac/rbac.go (lines 400-426), explicit deny rules always take precedence over allow rules. If no deny rule matches, any matching allow rule grants access. The policy.default role applies only when no specific policy matches the subject.
Can I use regex instead of glob for policy matching?
Yes. Set policy.matchMode: regex in the argocd-rbac-cm ConfigMap. The default mode is glob, implemented using github.com/gobwas/glob, but regex mode uses Go's standard regexp package for more complex pattern matching. Configure this via the SetMatchMode function in the RBAC utility code.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →