Published: 2026-06-01 โ€ข Updated: 2026-07-05

Configuring User Access and RBAC in ArgoCD

An enterprise-grade guide to securing your GitOps continuous delivery engine using Single Sign-On (SSO), granular Role-Based Access Control (RBAC), multi-tenant AppProjects, and zero-trust security principles.


Table of Contents


1. Introduction to ArgoCD Access Control

In an enterprise Kubernetes ecosystem, GitOps engines like ArgoCD act as the "keys to the kingdom." Because ArgoCD has high-privilege access to write, modify, and delete resources across multiple Kubernetes clusters, securing access to it is paramount. Leaving ArgoCD with default configurations, shared credentials, or overly permissive access levels exposes your entire infrastructure to catastrophic risks, including privilege escalation, data exfiltration, and malicious cluster takeovers.

Securing ArgoCD requires a comprehensive approach to identity and access management. This involves configuring Single Sign-On (SSO) to federate identity, defining granular Role-Based Access Control (RBAC) policies using the Casbin engine, and isolating workloads using ArgoCD AppProjects.

This guide provides an exhaustive, production-grade manual for configuring user access and RBAC in ArgoCD. It is designed for platform engineers, security architects, and site reliability engineers (SREs) who need to implement a zero-trust security model across multi-tenant enterprise clusters.

2. What You Will Learn

  • The architectural differences between Authentication (AuthN) and Authorization (AuthZ) in ArgoCD.
  • How to provision, rotate, and secure local users, including how to safely disable the default admin account.
  • How to design and implement Single Sign-On (SSO) using OpenID Connect (OIDC) and Dex with enterprise identity providers like Keycloak, Okta, and GitHub.
  • The Casbin policy engine syntax used by ArgoCD to define fine-grained permission matrices.
  • How to design multi-tenant environments using the AppProject Custom Resource Definition (CRD) to restrict target clusters, namespaces, repositories, and resource kinds.
  • A complete, end-to-end implementation of an enterprise permission matrix for Platform, Frontend, Backend, and Security teams.
  • How to debug, audit, and troubleshoot complex RBAC policies using the ArgoCD CLI and log analysis.

3. Prerequisites

To follow along with the technical configurations and implementation steps in this guide, you should have:

  • A running Kubernetes cluster (v1.24 or higher).
  • ArgoCD installed in the cluster (preferably v2.8+ or higher). If you need to set up ArgoCD, refer to the ArgoCD Architecture and Installation guide.
  • The kubectl command-line tool configured to communicate with your cluster.
  • The argocd CLI installed locally.
  • Administrative access to your identity provider (IdP) if you plan to implement the SSO configurations (e.g., Okta, Keycloak, or GitHub).

4. Authentication vs. Authorization in ArgoCD

Before configuring access controls, it is critical to distinguish between identity verification and permission enforcement. ArgoCD decouples these two concerns into distinct layers:

Concept Responsibility Configuration Mechanism Examples
Authentication (AuthN) Verifies who the user is. Identifies the user's username, email, and group memberships. argocd-cm ConfigMap, Dex configuration, or direct OIDC provider configuration. Logging in via Okta, Keycloak, GitHub OAuth, or local credentials.
Authorization (AuthZ) Determines what the authenticated user is allowed to do within ArgoCD. argocd-rbac-cm ConfigMap and AppProject manifests. Syncing an application, deleting a cluster, creating a repository connection, viewing logs.

If a user successfully authenticates via your enterprise identity provider, they still cannot perform any actions in ArgoCD unless an authorization policy explicitly grants them permission. By default, authenticated users who do not match any RBAC policies are assigned the default role, which should be configured as empty (no permissions) in production.


5. Architecture and Internal Workflow

To understand how ArgoCD evaluates access requests, we must look at the internal components involved in the lifecycle of an API or UI request. The primary components are:

  • argocd-server: The API server that hosts the gRPC/REST endpoints and serves the Web UI. It intercepts all user requests, validates session tokens, and enforces RBAC limits.
  • argocd-cm (ConfigMap): Contains global settings, including local user definitions, SSO provider parameters, and Dex configurations.
  • argocd-rbac-cm (ConfigMap): Contains the Casbin policy definitions, user-to-group mappings, and default role definitions.
  • AppProjects (CRDs): Custom resources that define logical boundaries for applications, including scoped RBAC roles and resource blacklists/whitelists.

The following ASCII diagram illustrates the sequence of authentication and authorization when a developer attempts to trigger a manual sync of an application:

+-------------+         +---------------+         +---------------+         +------------------+
|   User /    |         |    ArgoCD     |         |   Identity    |         |   Kubernetes     |
|   CLI / UI  |         |  API Server   |         | Provider (IdP)|         |   ConfigMaps     |
+-------------+         +---------------+         +---------------+         +------------------+
       |                        |                         |                           |
       |--- 1. Login Request -->|                         |                           |
       |                        |--- 2. Redirect to IdP ->|                           |
       |                        |<-- 3. Auth Token (JWT) -|                           |
       |<-- 4. Session Cookie --|                         |                           |
       |                        |                         |                           |
       |--- 5. Sync App -------->                         |                           |
       |    (Request)           |--- 6. Load RBAC Rules ---------------------------->| (argocd-rbac-cm)
       |                        |<-- 7. Return Policies ----------------------------|
       |                        |                         |                           |
       |                        |--- 8. Load Project Context ---------------------->| (AppProject CRD)
       |                        |<-- 9. Return Project Scope -----------------------|
       |                        |                         |                           |
       |                        |-- 10. Evaluate Casbin Policy --+                    |
       |                        |   | (User Group matches App    |                    |
       |                        |   |  Project and Resource?)    |                    |
       |                        |<--+                            |                    |
       |                        |                         |                           |
       |<-- 11. Action Allowed -|                         |                           |
       |    (or Permission Deny)|                         |                           |
    

6. Managing Local Users

While enterprise deployments should rely almost exclusively on SSO, local users are useful for initial bootstrapping, automation accounts (CI/CD pipelines), or emergency "break-glass" access when the identity provider is offline.

Local users are defined in the argocd-cm ConfigMap. Each user can be assigned one of two capabilities:

  • apiKey: Allows the user to generate long-lived JSON Web Tokens (JWT) for API and CLI access.
  • login: Allows the user to authenticate via the Web UI and CLI using a username and password.

Step 1: Defining Local Users in argocd-cm

To add local users, modify the argocd-cm ConfigMap. In this example, we define two local users: pipeline-runner (for CI/CD pipelines) and break-glass-admin (for emergency recovery).

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # Define local accounts
  accounts.pipeline-runner: apiKey
  accounts.break-glass-admin: login, apiKey

Step 2: Setting Passwords for Local Users

When a local user with the login capability is created, its account is initially disabled because it has no password. To set a password, you must hash the password using bcrypt and store it in the argocd-secret Secret, or use the ArgoCD CLI.

Using the ArgoCD CLI (must be logged in as an administrator):

# Log in as the admin bootstrap user
argocd login argocd.example.com --username admin --password <bootstrap-password>

# Set the password for break-glass-admin
argocd account update-password --account break-glass-admin --new-password "SuperSecretSecurePassword123!"

Step 3: Generating API Tokens for Automation

For the pipeline-runner account, which only has the apiKey capability, you can generate a JWT token for your CI/CD pipelines (e.g., GitHub Actions, GitLab CI) to trigger syncs:

# Generate a token that expires in 30 days (use 's' for seconds, 'm' for minutes, 'h' for hours, 'd' for days)
argocd account generate-token --account pipeline-runner --expires-in 30d

This will output a JWT string. Save this token immediately, as it cannot be retrieved again.

Step 4: Disabling the Default Admin Account

The default admin account is a major security risk because its password is static and it has unrestricted global permissions. As a production best practice, you should disable the local admin account once your SSO integration is fully validated.

To disable the admin account, set admin.enabled: "false" in the argocd-cm ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  admin.enabled: "false"
Warning: Ensure you have successfully configured SSO and mapped an administrative group to the ArgoCD admin role before disabling this account. Failing to do so can lock you out of your ArgoCD instance.

7. Single Sign-On (SSO) Integration Deep Dive

Enterprise identity federation ensures that user lifecycles are managed centrally. When an employee leaves the company or changes teams, revoking or modifying their corporate identity automatically updates their access to ArgoCD.

7.1 Dex vs. Direct OIDC

ArgoCD supports two primary patterns for integrating with external identity providers:

  • Dex (Bundled): Dex is an open-source OpenID Connect identity service that acts as an intermediary portal. ArgoCD installs Dex by default as an additional deployment (argocd-dex-server). Dex federates identity to upstream providers like LDAP, SAML, GitHub, GitLab, and Active Directory, and translates their responses into standard OIDC tokens for ArgoCD.
  • Direct OIDC: ArgoCD can bypass Dex entirely and connect directly to an OIDC-compliant identity provider (such as Okta, Keycloak, Azure AD/Entra ID, PingIdentity, or Google Workspace). This reduces architectural complexity and simplifies troubleshooting by removing the intermediate Dex hop.

7.2 Configuring Keycloak OIDC

Keycloak is a popular open-source identity and access management system. Here is how to configure a direct OIDC integration between ArgoCD and Keycloak.

Keycloak Server Setup:

  1. Create a new Client in your Realm:
    • Client ID: argocd
    • Client Protocol: openid-connect
    • Access Type: confidential
  2. Configure the Redirect URIs:
    • Valid Redirect URIs: https://argocd.example.com/auth/callback
  3. Create a Protocol Mapper to include group memberships in the token:
    • Mapper Type: Group Membership
    • Token Claim Name: groups
    • Full group path: false
  4. Retrieve the Client Secret from the Keycloak "Credentials" tab.

ArgoCD Kubernetes Configuration:

First, store the Keycloak Client Secret in the argocd-secret:

kubectl patch secret argocd-secret -n argocd -p '{"stringData": {"oidc.keycloak.clientSecret": "YOUR_KEYCLOAK_CLIENT_SECRET"}}'

Next, configure argocd-cm to enable direct OIDC:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.example.com
  oidc.config: |
    name: Keycloak
    issuer: https://keycloak.example.com/realms/my-realm
    clientID: argocd
    clientSecret: $oidc.keycloak.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]
    requestedIDTokenClaims:
      groups:
        essential: true

7.3 Configuring Okta OIDC

Okta is a widely used enterprise Identity-as-a-Service (IDaaS) provider.

Okta Application Setup:

  1. Create a new App Integration in Okta:
    • Sign-in method: OIDC - OpenID Connect
    • Application type: Web Application
  2. Configure Integration Settings:
    • Sign-in redirect URIs: https://argocd.example.com/auth/callback
    • Sign-out redirect URIs: https://argocd.example.com/login
  3. Configure Group Claims Filter:
    • In the application settings, navigate to the Sign On tab.
    • Under OpenID Connect ID Token / Group Claims Filter, set the filter to match your groups (e.g., Use Matches regex with value argocd-.* to only send groups starting with "argocd-").

ArgoCD Kubernetes Configuration:

Store the Okta Client Secret in the argocd-secret:

kubectl patch secret argocd-secret -n argocd -p '{"stringData": {"oidc.okta.clientSecret": "YOUR_OKTA_CLIENT_SECRET"}}'

Configure argocd-cm:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.example.com
  oidc.config: |
    name: Okta
    issuer: https://your-subdomain.okta.com
    clientID: 0oaXXXXXXXXXXXXXX
    clientSecret: $oidc.okta.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]

7.4 Configuring GitHub OAuth

If your organization manages access via GitHub Teams, you can use Dex to handle GitHub OAuth.

GitHub Developer Settings Setup:

  1. Navigate to your GitHub Organization -> Settings -> Developer Settings -> OAuth Apps.
  2. Click New OAuth App:
    • Application Name: ArgoCD Enterprise
    • Homepage URL: https://argocd.example.com
    • Authorization callback URL: https://argocd.example.com/api/dex/callback (Note the /api/dex prefix, as Dex is handling the callback).
  3. Generate a Client Secret and copy it.

ArgoCD Kubernetes Configuration:

Store the GitHub Client Secret in the argocd-secret:

kubectl patch secret argocd-secret -n argocd -p '{"stringData": {"dex.github.clientSecret": "YOUR_GITHUB_CLIENT_SECRET"}}'

Configure Dex in the argocd-cm ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  url: https://argocd.example.com
  dex.config: |
    connectors:
      - type: github
        id: github
        name: GitHub
        config:
          clientID: Iv1.XXXXXXXXXXXXXXXX
          clientSecret: $dex.github.clientSecret
          orgs:
            - name: My-Enterprise-Org
              teams:
                - platform-engineering
                - frontend-devs
                - backend-devs

When users log in using GitHub, Dex maps their team membership to the group claim format: My-Enterprise-Org:platform-engineering.


8. The ArgoCD RBAC Policy Engine (Casbin)

ArgoCD uses the Casbin authorization library under the hood. Casbin relies on an access control model defined in a CSV format. This system is highly flexible, supporting wildcard matchers, inheritance, and fine-grained resource definitions.

8.1 Policy Syntax Breakdown

The core syntax of an ArgoCD RBAC policy line is:

p, <subject>, <resource>, <action>, <object>, <effect>

Let's break down each element of this statement:

  • p: Identifies this line as a policy definition.
  • <subject>: The user or group to whom the policy applies. For local users, this is their username (e.g., accounts/pipeline-runner). For SSO users, this is the group name passed in the OIDC claim (e.g., argocd-platform-admins).
  • <resource>: The type of ArgoCD resource being evaluated (e.g., applications, projects, clusters, repositories).
  • <action>: The operation being performed (e.g., get, create, update, delete, sync, override).
  • <object>: The specific resource instance being targetted, usually formatted as <project-name>/<application-name> or <cluster-url>. Wildcards (*) are fully supported.
  • <effect>: The result of the policy. In ArgoCD, this is always allow. Deny rules are handled implicitly: if no policy explicitly allows an action, it is denied by default.

8.2 Resources, Actions, and Scopes

To build secure policies, you must understand the available resource types and the specific actions allowed on them.

Resource Supported Actions Object Format Description
applications get, create, update, delete, sync, override, action/<sub-action> <project>/<app-name> Controls access to view, create, sync, delete, or override parameters on applications.
projects get, create, update, delete <project-name> Controls access to manage the lifecycle of ArgoCD AppProjects.
clusters get, create, update, delete <cluster-server-url> Controls the ability to register and manage target Kubernetes clusters.
repositories get, create, update, delete <git-or-helm-repo-url> Controls access to add or remove Git/Helm source repositories.
certificates get, create, update, delete * (Global only) Controls management of SSH/TLS certificates for repositories.
accounts get, create, update, delete <account-name> Controls management of local user accounts.
gpgkeys get, create, delete <key-id> Controls the registration of GPG public keys for commit verification.
logs get <project>/<app-name> Controls access to view container stdout/stderr logs from the ArgoCD UI.
exec create <project>/<app-name> Controls access to open an interactive terminal inside application pods from the UI.

8.3 Policy Inheritance and Glob Matching

To prevent RBAC policies from becoming bloated, Casbin supports group inheritance and wildcards.

Group Inheritance (g rules):

An inheritance rule maps an identity (user or SSO group) to a specific role. The syntax is:

g, <subject>, <role_name>

For example, to assign all corporate users in the Okta group argocd-platform-admins to the built-in system administrator role (role:admin), you would write:

g, argocd-platform-admins, role:admin

Glob Matching:

ArgoCD supports glob/wildcard matching (using the Casbin keyMatch function). This makes it easy to assign permissions to a family of applications or projects without writing individual rules.

For example, to grant the frontend-developers group permission to view and sync any application within a project whose name starts with frontend-:

p, frontend-developers, applications, get, frontend-*/*, allow
p, frontend-developers, applications, sync, frontend-*/*, allow

9. Enterprise Multi-Tenancy with AppProjects

While global RBAC policies in argocd-rbac-cm are powerful, they can become difficult to maintain in large organizations with hundreds of teams and thousands of microservices. The AppProject Custom Resource Definition (CRD) acts as a secondary, decentralized authorization layer designed specifically for multi-tenant isolation.

An AppProject provides logical boundaries by restricting:

  • Source Repositories: Whitelist of Git/Helm repositories that applications in this project are allowed to pull manifests from.
  • Destination Clusters and Namespaces: Whitelist of target Kubernetes clusters and namespaces where applications in this project are allowed to deploy.
  • Resource Whitelists/Blacklists: Controls which Kubernetes API groups and resource kinds can be deployed (e.g., preventing developers from deploying ClusterRoleBindings, Ingress, or PersistentVolumeClaims).
  • Project-Scoped Roles: Defines local roles and JWT tokens specific to the project, which can be mapped directly to external SSO groups.

The following is a production-grade AppProject manifest designed for a backend development team:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: backend-team-project
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  description: "Secure, isolated namespace and repository scope for the backend development team."

  # 1. Restrict source repositories (Only official backend git repositories)
  sourceRepos:
    - "https://github.com/my-enterprise-org/backend-*"
    - "https://charts.helm.sh/stable"

  # 2. Restrict destinations (Only backend namespaces on development and staging clusters)
  destinations:
    - namespace: "backend-dev-*"
      server: "https://kubernetes.default.svc" # Local cluster
    - namespace: "backend-stage-*"
      server: "https://10.240.0.100:6443"    # Staging cluster

  # 3. Whitelist of allowed cluster-scoped and namespace-scoped resources
  # Here we block ClusterRoles and CustomResourceDefinitions by only listing allowed kinds.
  namespaceResourceWhitelist:
    - group: "apps"
      kind: "Deployment"
    - group: "apps"
      kind: "StatefulSet"
    - group: ""
      kind: "Service"
    - group: ""
      kind: "ConfigMap"
    - group: ""
      kind: "Secret"
    - group: "networking.k8s.io"
      kind: "Ingress"

  # 4. Project-Scoped Roles and RBAC Policies
  roles:
    - name: backend-developer
      description: "Read-write access to backend applications in dev and staging"
      policies:
        # Rules are formatted as: p, proj:<project-name>:<role-name>, <resource>, <action>, <object>, allow
        - p, proj:backend-team-project:backend-developer, applications, get, backend-team-project/*, allow
        - p, proj:backend-team-project:backend-developer, applications, sync, backend-team-project/*, allow
        - p, proj:backend-team-project:backend-developer, applications, update, backend-team-project/*, allow
        - p, proj:backend-team-project:backend-developer, logs, get, backend-team-project/*, allow
      groups:
        # Bind this project-scoped role to an external OIDC/SSO group
        - "okta-group-backend-engineers"

    - name: backend-lead
      description: "Full admin access to backend applications, including deletion"
      policies:
        - p, proj:backend-team-project:backend-lead, applications, *, backend-team-project/*, allow
      groups:
        - "okta-group-backend-leads"

10. Step-by-Step Enterprise Implementation Scenario

Let's walk through a real-world scenario where we configure a secure, multi-tenant ArgoCD instance for an enterprise with three distinct groups:

  1. Platform Engineers (SSO Group: oidc:platform-admins): Must have absolute admin rights across the entire ArgoCD system, including managing clusters, repos, and other projects.
  2. Frontend Developers (SSO Group: oidc:frontend-devs): Can manage applications in the frontend-project. They should be able to view, sync, and update applications, but cannot delete them or modify clusters/repositories. They are restricted to deploying only into namespaces starting with frontend-.
  3. Security Auditors (SSO Group: oidc:security-auditors): Must have strict read-only access to all applications, projects, settings, and logs across the entire system, but are completely blocked from modifying any state or triggering syncs.

Step 1: Define the AppProjects

We will create the frontend-project to restrict where the frontend team can deploy:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: frontend-project
  namespace: argocd
spec:
  description: "Frontend team sandbox"
  sourceRepos:
    - "https://github.com/my-enterprise-org/frontend-*"
  destinations:
    - namespace: "frontend-*"
      server: "*" # Allowed to deploy to any registered cluster, but restricted to frontend- namespaces
  namespaceResourceWhitelist:
    - group: "*"
      kind: "*"

Apply this manifest to your cluster:

kubectl apply -f frontend-project.yaml

Step 2: Configure Global RBAC Rules in argocd-rbac-cm

We will now edit the argocd-rbac-cm ConfigMap. This configuration defines the global roles, maps SSO groups to those roles, and sets up default permissions.

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  # 1. Set the default policy to empty (deny-all) for zero-trust security
  policy.default: ""

  # 2. Enable glob matching for flexible patterns
  policy.matchMode: "glob"

  # 3. Define the Casbin CSV policy matrix
  policy.csv: |
    # ==========================================
    # SECURITY AUDITOR ROLE
    # ==========================================
    p, role:security-auditor, applications, get, */*, allow
    p, role:security-auditor, projects, get, *, allow
    p, role:security-auditor, clusters, get, *, allow
    p, role:security-auditor, repositories, get, *, allow
    p, role:security-auditor, logs, get, */*, allow

    # ==========================================
    # FRONTEND DEVELOPER ROLE
    # ==========================================
    p, role:frontend-dev, applications, get, frontend-project/*, allow
    p, role:frontend-dev, applications, sync, frontend-project/*, allow
    p, role:frontend-dev, applications, update, frontend-project/*, allow
    p, role:frontend-dev, logs, get, frontend-project/*, allow

    # ==========================================
    # GROUP MAPPINGS (SSO to Roles)
    # ==========================================
    # Platform Admins get the built-in super-admin role
    g, oidc:platform-admins, role:admin

    # Frontend Devs get our custom frontend-dev role
    g, oidc:frontend-devs, role:frontend-dev

    # Security Auditors get our custom security-auditor role
    g, oidc:security-auditors, role:security-auditor

Apply this ConfigMap to your cluster:

kubectl apply -f argocd-rbac-cm.yaml

Step 3: Verify the Configurations

Once applied, users logging in via your OIDC provider will automatically be matched against these groups.

  • If a user belonging to oidc:platform-admins logs in, they will have full access.
  • If a user belonging to oidc:frontend-devs logs in, they will only see applications inside the frontend-project. The "Delete" buttons for applications will be disabled/hidden in the UI, and they will not be able to view system settings, repositories, or clusters.
  • If a user belonging to oidc:security-auditors logs in, they can view everything, but all action buttons (Sync, App Creation, Delete, Edit) will be completely disabled.

11. Advanced RBAC Features and Customizations

Web Terminal Access (exec Privilege)

ArgoCD includes a feature that allows users to open an interactive terminal inside container pods directly from the ArgoCD UI. While highly convenient for debugging, this is an extremely sensitive capability that bypasses traditional SSH/bastion controls.

To enable this feature, you must explicitly configure both the argocd-cm ConfigMap and grant the exec privilege in argocd-rbac-cm.

First, enable terminal access in argocd-cm:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  exec.enabled: "true"

Next, restrict access to this feature in argocd-rbac-cm. Only allow senior platform engineers to execute commands in pods:

# Only allow members of the platform-leads group to exec into pods in any project
p, oidc:platform-leads, exec, create, */*, allow

Resource Actions (action/<action-name>)

Sometimes, you want to allow users to trigger specific custom actions defined in Kubernetes Custom Resource Definitions (CRDs) without giving them full update permissions.

About the Author

Naresh Kumar

Naresh Kumar

Senior Java Backend Engineer experienced in Banking, Payments, ISO 20022, Spring Boot, Microservices, Kafka, Docker, Kubernetes, AWS and Cloud Native Systems.

Built enterprise payment solutions, transaction processing systems, API platforms and scalable microservices used in production.

LinkedIn Profile