CIS ArgoCD Benchmark
Security configuration recommendations for ArgoCD GitOps continuous delivery
v1.0.0 01-2025Overview
▶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.
| Section | Area | Focus |
|---|---|---|
| 1 | Access Control | RBAC policies and SSO/OIDC enforcement |
| 2 | Transport & Credentials | TLS enforcement and SSH-based repo credentials |
| 3 | Project & Sync Policies | AppProject restrictions and safe sync configuration |
| 4 | Resource Management | Resource exclusions and failure notifications |
| 5 | Audit & Secrets | JSON audit logging and external secrets management |
| 6 | Infrastructure Hardening | Version management and network policies |
| 7 | Operations & Recovery | ApplicationSet patterns and backup procedures |
Profile Definitions
▶| Profile | Description | Intended Use |
|---|---|---|
| L1 | Level 1 — Standard | Essential security for all ArgoCD deployments; minimal performance impact. |
| L2 | Level 2 — Hardened | Advanced hardening for PCI-DSS, HIPAA, or high-security environments. |
1 — Access Control
▶1.1 RBAC & Authentication
▶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.
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.
# 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}'# 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
EOFThis 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.
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.
# 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'
# 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"
EOF2 — Transport & Credentials
▶2.1 TLS & Repository Security
▶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.
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.
# 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'
# 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
EOFThis 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.
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.
# 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'
# 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_deploy3 — Project & Sync Policies
▶3.1 AppProject & Sync
▶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.
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.
# 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'
# 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
EOFThis 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.
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.
# 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'
# 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
EOF4 — Resource Management
▶4.1 Exclusions & Notifications
▶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.
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.
# Check resource exclusions: kubectl get configmap argocd-cm -n argocd -o yaml | grep -A10 'resource.exclusions\|resource.inclusions'
# 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
EOFThis 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.
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.
# 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'
# 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}}
EOF5 — Audit & Secrets
▶5.1 Logging & Secret Management
▶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.
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.
# 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'
# 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
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.
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.
# 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
# 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
EOF6 — Infrastructure Hardening
▶6.1 Upgrades & Network
▶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.
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.
# Check ArgoCD version:
argocd version --client
kubectl get deploy -n argocd -o jsonpath='{.items[*].spec.template.spec.containers[*].image}' | tr ' ' '\n'# 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>
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.
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.
# Check network policies: kubectl get networkpolicy -n argocd # Verify pod-to-pod restrictions: kubectl get networkpolicy -n argocd -o yaml
# 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
EOF7 — Operations & Recovery
▶7.1 Multi-Cluster & Backup
▶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.
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.
# Check ApplicationSet usage: kubectl get applicationset -n argocd # Verify generator configs: kubectl get applicationset -n argocd -o yaml | head -40
# 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
EOFThis 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.
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.
# 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
# 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