Aller au contenu
CI/CD & Automatisation medium
🔐 Alerte sécurité — Incident supply chain Trivy : lire mon analyse de l'attaque

ArgoCD — Sécuriser votre déploiement GitOps

14 min de lecture

ArgoCD installé avec sa configuration par défaut est fonctionnel, mais pas prêt pour la production. L’administrateur par défaut a accès à tout, il n’y a pas de protection contre les déploiements dans des namespaces non autorisés, et les secrets en clair dans Git sont un risque majeur. Ce guide couvre les quatre piliers de la sécurisation d’ArgoCD : RBAC, AppProjects, SSO et gestion des secrets.

  • Configurer le RBAC ArgoCD avec des rôles personnalisés (syntaxe Casbin)
  • Créer des comptes de service pour la CI avec des droits minimaux
  • Utiliser les AppProjects pour isoler les équipes (sourceRepos, destinations, ressources autorisées)
  • Intégrer un SSO avec Dex (GitHub OAuth, GitLab OIDC) pour supprimer la gestion locale des utilisateurs
  • Gérer les secrets sans les stocker en clair dans Git (External Secrets, Sealed Secrets)
  • Configurer les notifications ArgoCD pour alerter en cas de drift ou d’échec de déploiement

Tout comme Kubernetes, ArgoCD applique un modèle RBAC (Role-Based Access Control). Par défaut, seul admin a accès à l’interface. En production, vous voulez que :

  • Les développeurs voient leurs applications mais ne les modifient pas
  • Les ops puissent synchroniser mais pas supprimer
  • Les CI tokens n’aient accès qu’à des Applications spécifiques
  • Chaque équipe ne voie que ses propres Applications

Le RBAC ArgoCD se configure dans le ConfigMap argocd-rbac-cm. La syntaxe est basée sur Casbin (un moteur de règles de contrôle d’accès).

ArgoCD fournit deux rôles de base :

RôleDroits
role:adminAccès complet (toutes les ressources, toutes les actions)
role:readonlyLecture seule sur toutes les ressources
# Patch du ConfigMap argocd-rbac-cm
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:readonly # Par défaut, tout le monde ne voit que
policy.csv: |
# Rôle développeur : voir et sync ses apps, pas de delete
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, */*, allow
p, role:developer, applications, action/*, */*, allow
p, role:developer, logs, get, */*, allow
# Rôle ops : tout sauf delete des projets et clusters
p, role:ops, applications, *, */*, allow
p, role:ops, repositories, *, *, allow
p, role:ops, clusters, get, *, allow
# Rôle CI token : sync uniquement sur des Applications précises
p, role:ci-bot, applications, get, myproject/*, allow
p, role:ci-bot, applications, sync, myproject/*, allow
# Assignation des rôles aux utilisateurs/groupes SSO
g, equipe-dev, role:developer
g, equipe-ops, role:ops
g, ci-service-account, role:ci-bot
Fenêtre de terminal
kubectl apply -f argocd-rbac-cm.yaml -n argocd
Fenêtre de terminal
# Créer un compte de service pour la CI (pas un compte humain)
argocd account generate-token --account ci-service-account
# Ou depuis kubectl (secret Kubernetes)
argocd account list
# Vérifier que ci-service-account est dans la liste

Ajoutez ce compte dans argocd-cm :

apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
accounts.ci-service-account: apiKey # Autorise uniquement les tokens API

Un AppProject définit ce qu’une Application ArgoCD est autorisée à faire : quels dépôts Git elle peut utiliser comme source, quels clusters/namespaces elle peut cibler, et quelles ressources Kubernetes elle peut créer.

Sans AppProject, une Application permet par défaut de déployer n’importe quoi n’importe où. En production, chaque équipe doit avoir son propre AppProject.

project-equipe-a.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: equipe-a
namespace: argocd
spec:
description: "Projet de l'équipe A — microservices e-commerce"
# Dépôts Git autorisés comme source
sourceRepos:
- https://github.com/mon-org/config-repo-equipe-a
# Clusters et namespaces autorisés comme destination
destinations:
- namespace: equipe-a-dev
server: https://kubernetes.default.svc
- namespace: equipe-a-staging
server: https://kubernetes.default.svc
- namespace: equipe-a-prod
server: https://prod-cluster.example.com
# Types de ressources cluster-wide autorisés (vide = interdits)
clusterResourceWhitelist: []
# Types de ressources de namespace autorisés
namespaceResourceWhitelist:
- group: apps
kind: Deployment
- group: apps
kind: StatefulSet
- group: ""
kind: Service
- group: ""
kind: ConfigMap
- group: ""
kind: Secret # À retirer si vous utilisez External Secrets Operator
# Politiques de sync
syncWindows:
- kind: allow
schedule: "0 8 * * 1-5" # Sync automatique permis en semaine 8h-18h
duration: 10h
applications:
- "*"

Dex est le composant intégré à ArgoCD pour la fédération d’identité. Il permet de se connecter à ArgoCD avec un compte GitHub ou GitLab (OIDC/OAuth2), au lieu de gérer des utilisateurs locaux.

1. Créer une OAuth App dans GitHub

Depuis Settings > Developer settings > OAuth Apps :

  • Application name : ArgoCD
  • Homepage URL : https://argocd.example.com
  • Authorization callback URL : https://argocd.example.com/api/dex/callback

Récupérez le Client ID et le Client Secret.

2. Configurer argocd-cm

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: votre-client-id
clientSecret: $github-client-secret # Référence à un Secret K8s
orgs:
- name: mon-organisation

3. Créer le Secret Kubernetes pour le client secret

Fenêtre de terminal
kubectl create secret generic github-client-secret \
--from-literal=github-client-secret="ghp_xxx..." \
-n argocd

Assigner les groupes SSO aux rôles RBAC :

# Dans argocd-rbac-cm
data:
policy.csv: |
g, mon-organisation:equipe-dev, role:developer
g, mon-organisation:equipe-ops, role:ops

C’est la règle absolue du GitOps : si un secret apparaît en clair dans votre config-repo, il est compromis. Deux solutions sont largement adoptées :

External Secrets Operator synchronise les secrets depuis un coffre-fort externe (Vault, AWS Secrets Manager, GCP Secret Manager…) vers des Secrets Kubernetes. Votre ExternalSecret dans Git ne contient que la référence au secret, jamais la valeur.

# external-secret.yaml (committé dans Git — ne contient pas le secret)
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
namespace: demo
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: db-credentials # Nom du Secret Kubernetes créé
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: secret/demo/db
property: password

L’opérateur récupère secret/demo/db depuis Vault et crée le Secret Kubernetes db-credentials avec la valeur réelle.

Sealed Secrets chiffre les secrets avec une clé publique spécifique à votre cluster. Le SealedSecret chiffré peut être commité dans Git en toute sécurité.

Fenêtre de terminal
# Installer le CLI kubeseal
KUBESEAL_VERSION="0.27.3"
curl -sSLo kubeseal \
"https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-linux-amd64"
chmod +x kubeseal && sudo mv kubeseal /usr/local/bin/
# Chiffrer un secret existant
kubectl create secret generic db-credentials \
--from-literal=password="MonMotDePasse123" \
--dry-run=client -o json | \
kubeseal --format yaml > sealed-db-credentials.yaml
# Ce fichier peut être commité dans Git en toute sécurité
cat sealed-db-credentials.yaml

ArgoCD peut notifier votre équipe en cas d’événement (sync réussi, erreur de santé, drift détecté). L’outil ArgoCD Notifications est intégré depuis ArgoCD v2.3.

Fenêtre de terminal
# Créer le ConfigMap de configuration des notifications
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-notifications-cm
namespace: argocd
data:
service.slack: |
token: \$slack-token
template.app-deployed: |
message: |
Application {{.app.metadata.name}} déployée avec succès.
Révision : {{.app.status.sync.revision}}
template.app-health-degraded: |
message: |
⚠️ Application {{.app.metadata.name}} est Degraded !
trigger.on-deployed: |
- when: app.status.operationState.phase in ['Succeeded']
send: [app-deployed]
trigger.on-health-degraded: |
- when: app.status.health.status == 'Degraded'
send: [app-health-degraded]
EOF
Fenêtre de terminal
# Créer le secret Slack
kubectl create secret generic argocd-notifications-secret \
--from-literal=slack-token="xoxb-votre-token-slack" \
-n argocd
Fenêtre de terminal
# Activer les notifications sur une Application
kubectl annotate application nginx-demo \
notifications.argoproj.io/subscribe.on-deployed.slack="mon-canal-deploys" \
notifications.argoproj.io/subscribe.on-health-degraded.slack="mon-canal-alertes" \
-n argocd
  • RBAC : configurez policy.csv dans argocd-rbac-cm. Le rôle par défaut devrait être role:readonly, jamais role:admin.
  • AppProjects : créez un projet par équipe avec des restrictions sur les sources Git, les namespaces cibles et les types de ressources autorisés.
  • SSO avec Dex : connectez ArgoCD à GitHub ou GitLab pour éviter la gestion de comptes locaux. Assignez les groupes SSO aux rôles RBAC.
  • Ne jamais mettre un secret en clair dans Git. Utilisez External Secrets Operator (si vous avez un vault) ou Sealed Secrets (plus simple).
  • Notifications : configurez des alertes Slack ou email sur les événements de déploiement et de dégradation de santé.
  • Les tokens CI doivent être des comptes de service dédiés avec des droits minimaux (get + sync sur un projet seulement).

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn