Skip to content

Security

Authentication, authorization, encryption, network security, and hardening for ArgoCD deployments.

Authentication

ArgoCD supports four authentication mechanisms, configured primarily through the argocd-cm ConfigMap.

Built-in Accounts

  • Admin account: Created by default with a bcrypt-hashed password stored in the argocd-secret Secret. Disable after SSO is configured by setting admin.enabled: false in argocd-cm.
  • Local users: Defined in argocd-cm under accounts.<username>. Suitable for service accounts and automation.
  • API tokens: Generated per user via argocd account generate-token or per project via argocd proj role create-token. Tokens are JWTs signed by ArgoCD.

SSO via OIDC

ArgoCD integrates with external identity providers through native OIDC or via the bundled Dex server.

Native OIDC (recommended for cloud-native IdPs like Okta, Azure AD, Keycloak):

# argocd-cm
data:
  url: https://argocd.YOUR_DOMAIN
  oidc.config: |
    name: Okta
    issuer: https://dev-12345.okta.com/oauth2/default
    clientID: aaaabbbbccccddd
    clientSecret: $oidc.okta.clientSecret
    requestedScopes: ["openid", "profile", "email", "groups"]
    requestedIDTokenClaims: {"groups": {"essential": true}}

Dex (required for SAML, LDAP, GitHub OAuth, and other non-OIDC connectors):

# argocd-cm
data:
  url: https://argocd.YOUR_DOMAIN
  dex.config: |
    connectors:
      - type: github
        id: github
        name: GitHub
        config:
          clientID: $dex.github.clientID
          clientSecret: $dex.github.clientSecret
          orgs:
            - name: my-org

Group Claim Mapping

Always configure requestedIDTokenClaims to pull the groups claim. This ensures OIDC groups are available for RBAC policy mapping via g, <oidc-group>, role:<argo-role> entries.

Authorization (RBAC)

ArgoCD uses a Casbin-based RBAC engine. Policies are defined in the argocd-rbac-cm ConfigMap.

Policy Format

p, <subject>, <resource>, <action>, <object>, <effect>
g, <subject>, <group>
  • subject: role:<name> or a user/group identifier
  • resource: applications, projects, repositories, clusters, logs, exec
  • action: get, create, update, delete, sync, action/<action-name>
  • object: <project>/<app-name> or */* for all

Built-in Roles

Role Scope
role:admin Full access to all resources
role:readonly Read access to all resources; no sync or modify
Custom roles Defined in policy.csv with arbitrary permissions

Project-Level RBAC

AppProjects provide namespace-like isolation within ArgoCD. Each project defines:

  • Source repos: Which Git repositories apps in this project can pull from
  • Destination clusters/namespaces: Where apps can be deployed
  • Roles: Fine-grained permissions scoped to the project
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-a
  namespace: argocd
spec:
  sourceRepos:
    - "https://github.com/org/team-a-*"
  destinations:
    - namespace: "team-a-*"
      server: "https://kubernetes.default.svc"
  roles:
    - name: admin
      groups:
        - org:team-a-admins
      policies:
        - p, proj:team-a:admin, applications, *, team-a/*, allow

Default Policy

Set policy.default in argocd-rbac-cm:

  • role:readonly -- safest default; unauthenticated users get read-only access
  • "" (empty) -- denies all access for unmapped users; recommended for enterprise

Anonymous Access

Setting users.anonymous.enabled: true in argocd-cm grants public read access to all applications. This should be false in production unless the ArgoCD instance is on an internal network.

Encryption and Secret Management

At Rest

Asset Encryption Method
Admin password bcrypt hash in argocd-secret
SSO client secrets Base64-encoded in argocd-secret; use Sealed Secrets or External Secrets Operator for GitOps management
Cluster credentials Base64-encoded in Secret with label argocd.argoproj.io/secret-type: cluster
Repository credentials Base64-encoded SSH keys, HTTPS tokens, or TLS certs in Secrets with label argocd.argoproj.io/secret-type: repository
Redis cache In-memory only; ephemeral; rebuilt on restart
Dex storage ConfigMap-backed or etcd; no persistent database

In Transit

  • All inter-component communication uses TLS: server-to-repo-server, server-to-controller, server-to-Redis
  • Configure argocd-server with a valid TLS certificate (via Ingress or direct)
  • The repo server communicates with Git repositories over HTTPS or SSH

Secret Management Integration

ArgoCD does not manage secrets natively. Use one of these patterns:

Approach Mechanism Trade-off
External Secrets Operator (ESO) ArgoCD deploys ExternalSecret CRDs; ESO syncs from Vault/AWS SM/GCP SM to K8s Secrets Best separation of concerns; secrets stay in Vault
ArgoCD Vault Plugin (AVP) Replaces <path:secret#key> placeholders during manifest rendering in repo-server True GitOps but requires plugin sidecar
SOPS + Kustomize Encrypt secrets in Git with SOPS; decrypt at render time via ksops plugin Everything in Git; key management is critical
Sealed Secrets Encrypt secrets client-side with kubeseal; SealedSecret controller decrypts in-cluster Simple; but secrets visible in Git (encrypted)

Recommended Pattern

Use External Secrets Operator for production. ArgoCD manages the ExternalSecret and SecretStore manifests, while the actual secret values live in an external vault (HashiCorp Vault, AWS Secrets Manager, etc.).

Network Security

Network Policies

Restrict inter-component and external traffic with Kubernetes NetworkPolicies:

# Restrict ArgoCD server ingress to internal networks
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: argocd-server-ingress
  namespace: argocd
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: argocd-server
  ingress:
    - from:
        - ipBlock:
            cidr: 10.0.0.0/8
      ports:
        - port: 8080
          protocol: TCP

Key network segmentation rules: - Restrict argocd-repo-server egress to only required Git hosts and registries - Restrict Redis ingress to only ArgoCD components - Deny argocd-repo-server access to the Kubernetes API server (prevents privilege escalation from compromised repos) - Use a separate argocd-repo-server deployment for untrusted repositories

Cluster Credential Security

  • Prefer short-lived ServiceAccount tokens over static bearer tokens
  • Use cloud-native auth (AWS IAM Roles, GCP Workload Identity, Azure Managed Identity) for managed clusters
  • Store cluster secrets as K8s Secrets with restricted RBAC (only argocd-application-controller needs read access)

Hardening Checklist

  • Disable admin account after SSO is configured (admin.enabled: false)
  • Set policy.default to empty string (deny-by-default)
  • Enable server.rbac.log.enforce.enable: true to enforce RBAC on log access
  • Use Sealed Secrets or ESO instead of plaintext Secrets in Git
  • Run ArgoCD components with SecurityContext (non-root, read-only root filesystem)
  • Apply Pod Security Standards (restricted profile) to the argocd namespace
  • Configure NetworkPolicies for all ArgoCD components
  • Use resource.customizations.ignoreDifferences to prevent reconciliation loops on dynamically-mutated resources (e.g., webhook configurations modified by operators)
  • Set repository.credentials in argocd-cm to use templated credential matching instead of per-repo secrets
  • Enable audit logging at the Kubernetes API server level for ArgoCD namespace

Known Pitfalls

Pitfall Impact Mitigation
Overly broad policy.default: role:readonly Any unauthenticated user can read all application manifests (which may contain sensitive config) Set policy.default: "" and require authentication
Static cluster bearer tokens that never expire Compromised tokens provide persistent cluster access Use short-lived ServiceAccount tokens or cloud IAM
Missing ignoreDifferences for operator-managed webhooks ArgoCD enters infinite sync loop against operators like cert-manager, gatekeeper Add resource.customizations.ignoreDifferences in argocd-cm
Unrestricted repo-server network access Compromised Git repo can exfiltrate data or reach internal services Apply strict egress NetworkPolicies to argocd-repo-server