# Argo CD RBAC and Authentication Methods: A Complete Configuration Guide

> Configure Argo CD RBAC and authentication with our complete guide. Learn to manage access using Casbin policies and integrate local users or SSO providers like OIDC.

- Repository: [Argo Project/argo-cd](https://github.com/argoproj/argo-cd)
- Tags: how-to-guide
- Published: 2026-07-14

---

**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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/util/rbac/rbac.go)) configures this behavior.

When evaluating requests, the `enforce` function (lines 400-426) follows strict precedence:
1. Check the **default role** (`policy.default`)
2. Invoke any custom **claims enforcer** for JWT tokens via `ClaimsEnforcerFunc`
3. Execute the Casbin policy check where `deny` rules always override `allow`

### Resources and Actions

Constants defined in [`util/rbac/rbac.go`](https://github.com/argoproj/argo-cd/blob/main/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:

```yaml
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`](https://github.com/argoproj/argo-cd/blob/main/server/rbacpolicy/rbacpolicy.go) invokes the Enforcer for each API request, passing the parsed JWT claims.

Example SSO policy mapping:

```yaml
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.

```go
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>`

```yaml
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`](https://github.com/argoproj/argo-cd/blob/main/cmd/argocd/commands/admin_settings_rbac.go) provide validation without applying changes:

```bash

# 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:

```go
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-cm` ConfigMap using Casbin CSV format with glob or regex matching modes
- The `Enforcer` struct in [`util/rbac/rbac.go`](https://github.com/argoproj/argo-cd/blob/main/util/rbac/rbac.go) manages policy loading, claims enforcement, and evaluation via the `enforce` function
- Authentication supports local users (stored in `argocd-cm`) and SSO/OIDC providers, with the `federated_claims.user_id`claim becoming the subject
- Policy evaluation follows the precedence: default role → custom claims enforcer → Casbin policy, where explicit `deny` rules always override `allow`
- Built-in roles `role:readonly` and `role:admin` are defined in `assets/builtin-policy.csv` and 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`](https://github.com/argoproj/argo-cd/blob/main/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`](https://github.com/argoproj/argo-cd/blob/main/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.