CIS ArgoCD Benchmark

Security configuration recommendations for ArgoCD GitOps continuous delivery

v1.0.0 01-2025

Overview

▶

This benchmark provides prescriptive guidance for establishing a secure configuration posture for ArgoCD GitOps deployments. It covers RBAC policies, SSO/OIDC integration, TLS enforcement, repository credential management, AppProject restrictions, sync policies, resource exclusions, notifications, audit logging, secrets management, network policies, and disaster recovery procedures.

14Recommendations
7Sections
2Profile Levels
SectionAreaFocus
1Access ControlRBAC policies and SSO/OIDC enforcement
2Transport & CredentialsTLS enforcement and SSH-based repo credentials
3Project & Sync PoliciesAppProject restrictions and safe sync configuration
4Resource ManagementResource exclusions and failure notifications
5Audit & SecretsJSON audit logging and external secrets management
6Infrastructure HardeningVersion management and network policies
7Operations & RecoveryApplicationSet patterns and backup procedures

Profile Definitions

▶
ProfileDescriptionIntended Use
L1Level 1 — StandardEssential security for all ArgoCD deployments; minimal performance impact.
L2Level 2 — HardenedAdvanced hardening for PCI-DSS, HIPAA, or high-security environments.

1 — Access Control

▶

1.1 RBAC & Authentication

▶
1.1.1 Ensure RBAC policies follow least-privilege with readonly default (Automated)
L1 Auto
Description

This recommendation verifies that RBAC policies follow least-privilege with readonly default on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check RBAC configuration:
kubectl get configmap argocd-rbac-cm -n argocd -o yaml

# Verify default policy:
kubectl get configmap argocd-rbac-cm -n argocd -o jsonpath='{.data.policy\.default}'
Remediation
# Configure restrictive RBAC:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly
  policy.csv: |
    p, role:dev, applications, get, */*, allow
    p, role:dev, applications, sync, dev/*, allow
    p, role:admin, applications, *, */*, allow
    p, role:admin, clusters, *, *, allow
    g, dev-team, role:dev
    g, platform-team, role:admin
EOF
1.1.2 Ensure SSO/OIDC is configured with local admin account disabled (Automated)
L1 Auto
Description

This recommendation verifies that SSO/OIDC is configured with local admin account disabled on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check SSO/OIDC configuration:
kubectl get configmap argocd-cm -n argocd -o yaml | grep -A20 'oidc.config\|dex.config'

# Verify local accounts disabled:
kubectl get configmap argocd-cm -n argocd -o yaml | grep 'accounts'
Remediation
# Configure OIDC integration:
kubectl apply -f - << 'EOF'
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/argocd
    clientID: argocd
    clientSecret: $oidc.keycloak.clientSecret
    requestedScopes:
      - openid
      - profile
      - email
      - groups
  admin.enabled: "false"
EOF

2 — Transport & Credentials

▶

2.1 TLS & Repository Security

▶
2.1.1 Ensure ArgoCD server uses TLS with valid certificates (Automated)
L1 Auto
Description

This recommendation verifies that ArgoCD server uses TLS with valid certificates on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check TLS configuration:
kubectl get ingress -n argocd -o yaml | grep -A5 'tls'

# Verify argocd-server TLS:
kubectl get configmap argocd-cmd-params-cm -n argocd -o yaml | grep 'server.insecure'
Remediation
# Ensure TLS on ArgoCD server:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  server.insecure: "false"
EOF

# Configure TLS Ingress:
kubectl apply -f - << 'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-tls
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443
EOF
2.1.2 Ensure repository credentials use SSH keys stored as Kubernetes secrets (Automated)
L1 Auto
Description

This recommendation verifies that repository credentials use SSH keys stored as Kubernetes secrets on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check repository credentials:
kubectl get secrets -n argocd -l argocd.argoproj.io/secret-type=repository

# Verify SSH key usage:
kubectl get secret -n argocd repo-creds -o yaml 2>/dev/null | grep 'sshPrivateKey'
Remediation
# Configure repository with SSH keys:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: private-repo
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
stringData:
  type: git
  url: git@github.com:org/repo.git
  sshPrivateKey: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    <KEY_CONTENT>
    -----END OPENSSH PRIVATE KEY-----
EOF

# Or use credential templates for org-wide:
argocd repo add git@github.com:org/ --ssh-private-key-path ~/.ssh/argocd_deploy

3 — Project & Sync Policies

▶

3.1 AppProject & Sync

▶
3.1.1 Ensure AppProjects restrict source repos and destination namespaces (Automated)
L1 Auto
Description

This recommendation verifies that AppProjects restrict source repos and destination namespaces on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check AppProject configurations:
kubectl get appproject -n argocd -o yaml

# Verify source/destination restrictions:
kubectl get appproject -n argocd -o yaml | grep -A10 'sourceRepos\|destinations'
Remediation
# Create restricted AppProject:
kubectl apply -f - << 'EOF'
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: Production applications
  sourceRepos:
  - 'git@github.com:org/app-manifests.git'
  destinations:
  - namespace: 'production'
    server: 'https://kubernetes.default.svc'
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceBlacklist:
  - group: ''
    kind: ResourceQuota
  - group: ''
    kind: LimitRange
  roles:
  - name: deployer
    policies:
    - p, proj:production:deployer, applications, sync, production/*, allow
EOF
3.1.2 Ensure sync policies use validation with pruning disabled for production (Automated)
L1 Auto
Description

This recommendation verifies that sync policies use validation with pruning disabled for production on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check sync policies:
kubectl get applications -n argocd -o yaml | grep -A15 'syncPolicy'

# Verify auto-sync settings:
kubectl get applications -n argocd -o yaml | grep -B2 -A5 'automated'
Remediation
# Configure safe sync policy:
kubectl apply -f - << 'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-app
  namespace: argocd
spec:
  project: production
  source:
    repoURL: git@github.com:org/manifests.git
    targetRevision: main
    path: production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: false
      selfHeal: true
    syncOptions:
    - CreateNamespace=false
    - PrunePropagationPolicy=foreground
    - Validate=true
    retry:
      limit: 3
      backoff:
        duration: 5s
        maxDuration: 3m
EOF

4 — Resource Management

▶

4.1 Exclusions & Notifications

▶
4.1.1 Ensure sensitive resource types are excluded from ArgoCD tracking (Automated)
L1 Auto
Description

This recommendation verifies that sensitive resource types are excluded from ArgoCD tracking on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check resource exclusions:
kubectl get configmap argocd-cm -n argocd -o yaml | grep -A10 'resource.exclusions\|resource.inclusions'
Remediation
# Configure resource exclusions:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.exclusions: |
    - apiGroups:
      - "*"
      kinds:
      - "Secret"
      clusters:
      - "*"
  resource.compareoptions: |
    ignoreAggregatedRoles: true
EOF
4.1.2 Ensure notifications are configured for sync failures and health degradation (Automated)
L1 Auto
Description

This recommendation verifies that notifications are configured for sync failures and health degradation on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check ArgoCD notifications:
kubectl get configmap argocd-notifications-cm -n argocd -o yaml 2>/dev/null

# Verify notification triggers:
kubectl get configmap argocd-notifications-cm -n argocd -o yaml | grep 'trigger'
Remediation
# Configure sync notifications:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-sync-failed: |
    - when: app.status.sync.status == 'Unknown' || app.status.operationState.phase in ['Error', 'Failed']
      send: [app-sync-failed]
  trigger.on-health-degraded: |
    - when: app.status.health.status == 'Degraded'
      send: [app-health-degraded]
  template.app-sync-failed: |
    message: |
      Application {{.app.metadata.name}} sync failed.
      Revision: {{.app.status.sync.revision}}
EOF

5 — Audit & Secrets

▶

5.1 Logging & Secret Management

▶
5.1.1 Ensure audit logging is enabled with JSON format (Automated)
L1 Auto
Description

This recommendation verifies that audit logging is enabled with JSON format on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check audit logging:
kubectl logs -n argocd deployment/argocd-server --tail=20 | grep -i audit

# Verify log level:
kubectl get configmap argocd-cmd-params-cm -n argocd -o yaml | grep 'log'
Remediation
# Enable detailed audit logging:
kubectl apply -f - << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
data:
  server.log.level: info
  server.log.format: json
  controller.log.level: info
  controller.log.format: json
EOF

# Restart ArgoCD components:
kubectl rollout restart deployment -n argocd argocd-server argocd-repo-server argocd-application-controller
5.1.2 Ensure secrets are managed via External Secrets Operator or Sealed Secrets (Automated)
L1 Auto
Description

This recommendation verifies that secrets are managed via External Secrets Operator or Sealed Secrets on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check for sensitive data in Git:
argocd app list -o yaml | grep -i 'secret\|password\|token' | head -10

# Verify sealed-secrets or external-secrets usage:
kubectl get sealedsecrets --all-namespaces 2>/dev/null
kubectl get externalsecrets --all-namespaces 2>/dev/null
Remediation
# Use External Secrets Operator:
kubectl apply -f - << 'EOF'
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secrets
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: app-secrets
  data:
  - secretKey: db-password
    remoteRef:
      key: secret/data/production/db
      property: password
EOF

6 — Infrastructure Hardening

▶

6.1 Upgrades & Network

▶
6.1.1 Ensure ArgoCD is running a supported and current version (Manual)
L1 Manual
Description

This recommendation verifies that ArgoCD is running a supported and current version on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check ArgoCD version:
argocd version --client
kubectl get deploy -n argocd -o jsonpath='{.items[*].spec.template.spec.containers[*].image}' | tr ' ' '\n'
Remediation
# Upgrade ArgoCD:
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# Or with Helm:
helm upgrade argocd argo/argo-cd -n argocd --version <LATEST>
6.1.2 Ensure network policies restrict ArgoCD component communication (Automated)
L1 Auto
Description

This recommendation verifies that network policies restrict ArgoCD component communication on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check network policies:
kubectl get networkpolicy -n argocd

# Verify pod-to-pod restrictions:
kubectl get networkpolicy -n argocd -o yaml
Remediation
# Apply network policies:
kubectl apply -f - << 'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: argocd-server-policy
  namespace: argocd
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: argocd-server
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-system
    ports:
    - port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-repo-server
    ports:
    - port: 8081
  - to:
    - podSelector:
        matchLabels:
          app.kubernetes.io/name: argocd-redis
    ports:
    - port: 6379
EOF

7 — Operations & Recovery

▶

7.1 Multi-Cluster & Backup

▶
7.1.1 Ensure ApplicationSets are used for consistent multi-cluster deployments (Automated)
L2 Auto
Description

This recommendation verifies that ApplicationSets are used for consistent multi-cluster deployments on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check ApplicationSet usage:
kubectl get applicationset -n argocd

# Verify generator configs:
kubectl get applicationset -n argocd -o yaml | head -40
Remediation
# Use ApplicationSet for multi-cluster:
kubectl apply -f - << 'EOF'
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: multi-cluster-app
  namespace: argocd
spec:
  generators:
  - clusters:
      selector:
        matchLabels:
          env: production
  template:
    metadata:
      name: 'app-{{name}}'
    spec:
      project: production
      source:
        repoURL: git@github.com:org/manifests.git
        targetRevision: main
        path: 'clusters/{{name}}'
      destination:
        server: '{{server}}'
        namespace: production
      syncPolicy:
        automated:
          selfHeal: true
EOF
7.1.2 Ensure ArgoCD configuration and application state backups are automated (Automated)
L1 Auto
Description

This recommendation verifies that ArgoCD configuration and application state backups are automated on the ArgoCD GitOps platform. Implementing this control strengthens the overall security configuration and reduces exposure to potential threats.

Rationale

Failure to implement this control may leave the ArgoCD GitOps platform vulnerable to attack or non-compliant with organizational security policies. This control helps establish a consistent, hardened configuration baseline.

Audit
# Check ArgoCD backup:
kubectl get all -n argocd -o name

# Export ArgoCD resources:
argocd admin export -n argocd > /tmp/argocd-backup.yaml 2>/dev/null
wc -l /tmp/argocd-backup.yaml
Remediation
# Create backup script:
cat > /usr/local/bin/argocd-backup.sh << 'SCRIPT'
#!/bin/bash
BACKUP_DIR=/opt/argocd-backups
mkdir -p $BACKUP_DIR
DATE=$(date +%Y%m%d)

# Export all ArgoCD resources:
for resource in applications appprojects; do
  kubectl get $resource -n argocd -o yaml > $BACKUP_DIR/${resource}-${DATE}.yaml
done

# Export ConfigMaps and Secrets:
for cm in argocd-cm argocd-rbac-cm argocd-cmd-params-cm; do
  kubectl get configmap $cm -n argocd -o yaml > $BACKUP_DIR/${cm}-${DATE}.yaml
done

# Compress and cleanup:
tar czf $BACKUP_DIR/argocd-backup-${DATE}.tar.gz $BACKUP_DIR/*-${DATE}.yaml
rm $BACKUP_DIR/*-${DATE}.yaml
find $BACKUP_DIR -mtime +30 -delete
SCRIPT
chmod +x /usr/local/bin/argocd-backup.sh