Split View: ArgoCD 보안 모델: 인증, 인가, 시크릿 관리
ArgoCD 보안 모델: 인증, 인가, 시크릿 관리
- 1. ArgoCD 보안 아키텍처 개요
- 2. 인증 (Authentication)
- 3. 인가 (Authorization) - RBAC
- 4. 저장소 자격 증명 관리
- 5. 클러스터 자격 증명 관리
- 6. 시크릿 관리 통합
- 7. 네트워크 보안
- 8. 감사 로깅 (Audit Logging)
- 9. 보안 모범 사례
- 10. 정리
1. ArgoCD 보안 아키텍처 개요
ArgoCD는 Kubernetes 환경에서 GitOps를 구현하는 도구이므로, 클러스터와 Git 저장소에 대한 광범위한 접근 권한을 보유합니다. 따라서 보안은 ArgoCD 운영의 핵심입니다.
보안 계층
Layer 1: 인증 (Authentication)
- 누가 접근하는가?
- Local Users, SSO (OIDC/SAML/LDAP via Dex)
Layer 2: 인가 (Authorization)
- 무엇을 할 수 있는가?
- RBAC Policies, AppProject Scoping
Layer 3: 자격 증명 관리 (Credential Management)
- Git 저장소, 클러스터 접근 자격 증명
- Kubernetes Secrets로 안전하게 저장
Layer 4: 시크릿 관리 (Secret Management)
- 애플리케이션 시크릿의 안전한 처리
- Sealed Secrets, External Secrets, Vault
Layer 5: 네트워크 보안 (Network Security)
- TLS, Network Policy, 접근 제한
2. 인증 (Authentication)
Local Users
ArgoCD는 내장 사용자 계정을 제공합니다:
# argocd-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
# 로컬 사용자 정의
accounts.alice: apiKey, login
accounts.bob: login
accounts.ci-bot: apiKey # CI/CD 전용 (API 키만)
계정 기능:
| 기능 | 설명 |
|---|---|
| login | Web UI 및 CLI 로그인 가능 |
| apiKey | API 토큰 생성 가능 (자동화용) |
비밀번호 관리:
# 사용자 비밀번호 변경
argocd account update-password --account alice
# API 토큰 생성 (CI/CD용)
argocd account generate-token --account ci-bot
SSO via Dex
Dex는 ArgoCD에 내장된 OIDC Identity Provider입니다:
# argocd-cm ConfigMap
data:
url: https://argocd.example.com
dex.config: |
connectors:
- type: github
id: github
name: GitHub
config:
clientID: YOUR_CLIENT_ID
clientSecret: $dex.github.clientSecret
orgs:
- name: my-org
teams:
- platform-team
- dev-team
OIDC 직접 연동 (Dex 없이)
Okta, Auth0, Keycloak 등과 직접 OIDC 연동도 가능합니다:
# argocd-cm ConfigMap
data:
oidc.config: |
name: Okta
issuer: https://my-org.okta.com/oauth2/default
clientID: YOUR_CLIENT_ID
clientSecret: $oidc.okta.clientSecret
requestedScopes:
- openid
- profile
- email
- groups
requestedIDTokenClaims:
groups:
essential: true
SAML 연동
data:
dex.config: |
connectors:
- type: saml
id: saml
name: SAML SSO
config:
ssoURL: https://idp.example.com/sso
caData: BASE64_ENCODED_CA_CERT
redirectURI: https://argocd.example.com/api/dex/callback
entityIssuer: https://argocd.example.com/api/dex/callback
usernameAttr: email
emailAttr: email
groupsAttr: groups
LDAP 연동
data:
dex.config: |
connectors:
- type: ldap
id: ldap
name: LDAP
config:
host: ldap.example.com:636
insecureNoSSL: false
insecureSkipVerify: false
rootCAData: BASE64_ENCODED_CA
bindDN: cn=admin,dc=example,dc=com
bindPW: $dex.ldap.bindPW
userSearch:
baseDN: ou=users,dc=example,dc=com
filter: "(objectClass=person)"
username: uid
idAttr: uid
emailAttr: mail
nameAttr: cn
groupSearch:
baseDN: ou=groups,dc=example,dc=com
filter: "(objectClass=groupOfNames)"
userMatchers:
- userAttr: DN
groupAttr: member
nameAttr: cn
인증 흐름 상세
SSO 로그인:
1. 사용자가 ArgoCD UI 접속
2. "Log in via SSO" 클릭
3. API Server -> Dex authorization endpoint로 리다이렉트
4. Dex -> 외부 IdP(GitHub/Okta/LDAP)로 리다이렉트
5. 사용자가 외부 IdP에서 인증
6. IdP -> Dex callback URL로 리다이렉트 (인증 코드)
7. Dex가 인증 코드로 토큰 교환
8. Dex가 ID Token 생성 (사용자 정보 + 그룹)
9. API Server가 ID Token 검증
10. ArgoCD JWT 발급 (그룹 정보 포함)
11. JWT를 브라우저 쿠키에 저장
3. 인가 (Authorization) - RBAC
RBAC 정책 구조
ArgoCD는 Casbin 라이브러리 기반의 RBAC을 사용합니다:
# argocd-rbac-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:readonly
policy.csv: |
# 역할 정의
p, role:admin, applications, *, */*, allow
p, role:admin, clusters, *, *, allow
p, role:admin, repositories, *, *, allow
p, role:admin, projects, *, *, allow
# 개발팀 역할
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, */*, allow
p, role:developer, applications, action/*, */*, allow
p, role:developer, logs, get, */*, allow
# 읽기 전용 역할
p, role:readonly, applications, get, */*, allow
p, role:readonly, projects, get, *, allow
p, role:readonly, clusters, get, *, allow
p, role:readonly, repositories, get, *, allow
# CI/CD 봇 역할
p, role:ci-bot, applications, sync, ci-project/*, allow
p, role:ci-bot, applications, get, ci-project/*, allow
# 그룹 매핑 (SSO 그룹 -> ArgoCD 역할)
g, platform-team, role:admin
g, dev-team, role:developer
g, viewers, role:readonly
g, ci-bot, role:ci-bot
scopes: '[groups, email]'
정책 문법
# 권한 정책 (p)
p, SUBJECT, RESOURCE, ACTION, OBJECT, EFFECT
# 그룹 매핑 (g)
g, GROUP, ROLE
리소스와 액션
| 리소스 | 액션 | 설명 |
|---|---|---|
| applications | get | Application 조회 |
| applications | create | Application 생성 |
| applications | update | Application 수정 |
| applications | delete | Application 삭제 |
| applications | sync | Application 동기화 |
| applications | override | Application 파라미터 오버라이드 |
| applications | action/* | 커스텀 액션 (restart 등) |
| clusters | get/create/update/delete | 클러스터 관리 |
| repositories | get/create/update/delete | 저장소 관리 |
| projects | get/create/update/delete | 프로젝트 관리 |
| logs | get | Pod 로그 조회 |
| exec | create | Pod exec 실행 |
AppProject RBAC
AppProject 내에서 더 세밀한 RBAC을 적용할 수 있습니다:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-alpha
spec:
roles:
- name: deployer
description: '배포 권한'
policies:
- p, proj:team-alpha:deployer, applications, sync, team-alpha/*, allow
- p, proj:team-alpha:deployer, applications, get, team-alpha/*, allow
groups:
- team-alpha-deployers
- name: viewer
description: '조회 권한'
policies:
- p, proj:team-alpha:viewer, applications, get, team-alpha/*, allow
groups:
- team-alpha-viewers
RBAC 디버깅
# 특정 사용자의 권한 확인
argocd admin settings rbac can role:developer get applications '*/*'
# 정책 검증
argocd admin settings rbac validate --policy-file policy.csv
4. 저장소 자격 증명 관리
HTTPS 자격 증명
apiVersion: v1
kind: Secret
metadata:
name: repo-creds
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: git
url: https://github.com/my-org/my-repo.git
username: git
password: ghp_XXXXXXXXXXXX # GitHub Personal Access Token
SSH 자격 증명
apiVersion: v1
kind: Secret
metadata:
name: repo-creds-ssh
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: git
url: git@github.com:my-org/my-repo.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
자격 증명 템플릿
같은 패턴의 여러 저장소에 공통 자격 증명을 적용합니다:
apiVersion: v1
kind: Secret
metadata:
name: repo-creds-template
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repo-creds
type: Opaque
stringData:
type: git
url: https://github.com/my-org # 이 URL로 시작하는 모든 저장소에 적용
username: git
password: ghp_XXXXXXXXXXXX
5. 클러스터 자격 증명 관리
클러스터 등록
# CLI로 클러스터 추가
argocd cluster add my-cluster-context --name production
ServiceAccount 토큰 방식
ArgoCD가 대상 클러스터에 접근할 때 사용하는 ServiceAccount:
# 대상 클러스터에 생성되는 리소스
apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-manager
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-manager-role
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin # 주의: 프로덕션에서는 최소 권한 적용
subjects:
- kind: ServiceAccount
name: argocd-manager
namespace: kube-system
최소 권한 원칙 적용
프로덕션 환경에서는 cluster-admin 대신 최소 권한을 적용합니다:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-manager-minimal
rules:
- apiGroups: ['*']
resources: ['*']
verbs: ['get', 'list', 'watch']
- apiGroups: ['apps']
resources: ['deployments', 'statefulsets', 'daemonsets', 'replicasets']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['']
resources: ['services', 'configmaps', 'secrets', 'serviceaccounts', 'namespaces', 'pods']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['networking.k8s.io']
resources: ['ingresses', 'networkpolicies']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['batch']
resources: ['jobs', 'cronjobs']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
6. 시크릿 관리 통합
Sealed Secrets
Sealed Secrets를 사용하면 암호화된 시크릿을 Git에 저장할 수 있습니다:
# 시크릿을 SealedSecret으로 암호화
kubeseal --format yaml --cert sealed-secrets-cert.pem \
< my-secret.yaml > sealed-secret.yaml
# Git에 저장되는 SealedSecret (암호화됨)
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-secret
namespace: default
spec:
encryptedData:
password: AgBy3i4OJSWK+... # 암호화된 값
template:
metadata:
name: my-secret
namespace: default
External Secrets Operator (ESO)
외부 시크릿 관리 시스템과 연동합니다:
# SecretStore 설정 (Vault 예시)
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: 'https://vault.example.com'
path: 'secret'
auth:
kubernetes:
mountPath: 'kubernetes'
role: 'argocd'
---
# ExternalSecret 정의
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: my-app-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: my-app/database
property: password
ArgoCD Vault Plugin (AVP)
ArgoCD의 Config Management Plugin으로 Vault와 직접 통합:
# AVP를 사용한 매니페스트 예시
apiVersion: v1
kind: Secret
metadata:
name: my-secret
annotations:
avp.kubernetes.io/path: 'secret/data/my-app'
type: Opaque
stringData:
password: <password> # Vault에서 자동으로 치환
api-key: <api-key>
SOPS (Secrets OPerationS)
SOPS로 YAML 값만 선택적으로 암호화:
# SOPS로 암호화된 파일 (키는 평문, 값은 암호화)
apiVersion: v1
kind: Secret
metadata:
name: my-secret
stringData:
password: ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
api-key: ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
sops:
kms: []
age:
- recipient: age1...
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
...
-----END AGE ENCRYPTED FILE-----
lastmodified: '2026-03-20T00:00:00Z'
version: 3.7.3
7. 네트워크 보안
TLS 설정
ArgoCD 컴포넌트 간 TLS 통신:
# argocd-cmd-params-cm ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cmd-params-cm
namespace: argocd
data:
server.insecure: 'false' # TLS 비활성화 금지
reposerver.tls.minversion: '1.2'
Ingress TLS
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: 'GRPC'
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
Network Policy
ArgoCD 네임스페이스에 Network Policy를 적용하여 접근을 제한합니다:
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-nginx
ports:
- port: 8080
protocol: TCP
- port: 8083
protocol: TCP
egress:
- to: [] # 모든 외부 접근 허용 (Git, 클러스터 등)
8. 감사 로깅 (Audit Logging)
ArgoCD 감사 로그
ArgoCD API Server는 모든 사용자 작업을 로그에 기록합니다:
로그 항목:
- 시간: 작업 수행 시각
- 사용자: 작업을 수행한 사용자 (SSO 그룹 포함)
- 액션: 수행된 작업 (sync, create, delete 등)
- 리소스: 대상 Application 또는 리소스
- 결과: 성공/실패
로그 수집 설정
# API Server 로그에서 감사 이벤트 필터링
kubectl logs -n argocd deployment/argocd-server | grep "level=info"
Prometheus 메트릭
ArgoCD는 보안 관련 메트릭도 노출합니다:
argocd_app_sync_total: 총 동기화 횟수
argocd_app_info: 애플리케이션 상태 정보
argocd_cluster_api_server_requests_total: 클러스터 API 요청 수
argocd_redis_request_total: Redis 요청 수
9. 보안 모범 사례
인증
- 프로덕션에서는 SSO를 필수로 사용
- 로컬 admin 계정 비활성화 또는 비밀번호 주기적 변경
- API 토큰에 만료 시간 설정
- MFA(Multi-Factor Authentication) 활성화
인가
- 기본 정책을
role:readonly로 설정 - 최소 권한 원칙 적용 (Least Privilege)
- AppProject로 팀별 격리
- 프로덕션 네임스페이스에 대한 sync 권한 제한
자격 증명
- SSH 키를 HTTPS 토큰보다 선호
- 토큰에 최소 scope 적용
- 주기적인 자격 증명 교체 (Key Rotation)
- 클러스터 접근에 최소 권한 RBAC 적용
시크릿
- 평문 시크릿을 Git에 절대 저장하지 않음
- Sealed Secrets 또는 External Secrets Operator 사용
- 시크릿 변경 시 자동 교체 메커니즘 구현
네트워크
- 모든 통신에 TLS 적용
- Network Policy로 ArgoCD 컴포넌트 접근 제한
- ArgoCD UI에 대한 접근을 VPN 또는 IP 화이트리스트로 제한
10. 정리
ArgoCD 보안 모델의 핵심 요소:
- 인증: SSO(OIDC/SAML/LDAP via Dex) + 로컬 사용자
- 인가: Casbin RBAC + AppProject 스코핑
- 저장소 자격 증명: HTTPS/SSH Secret으로 안전하게 관리
- 클러스터 자격 증명: ServiceAccount + 최소 권한 원칙
- 시크릿 관리: Sealed Secrets / ESO / AVP / SOPS
- 네트워크 보안: TLS + Network Policy
- 감사: API Server 로그 + Prometheus 메트릭
이러한 보안 계층을 적절히 구성하면 안전한 GitOps 운영 환경을 구축할 수 있습니다.
[ArgoCD] Security Model: Authentication, Authorization, and Secret Management
- 1. ArgoCD Security Architecture Overview
- 2. Authentication
- 3. Authorization - RBAC
- 4. Repository Credential Management
- 5. Cluster Credential Management
- 6. Secret Management Integration
- 7. Network Security
- 8. Audit Logging
- 9. Security Best Practices
- 10. Summary
1. ArgoCD Security Architecture Overview
ArgoCD holds broad access to clusters and Git repositories as a GitOps tool for Kubernetes. Security is therefore central to ArgoCD operations.
Security Layers
Layer 1: Authentication
- Who is accessing?
- Local Users, SSO (OIDC/SAML/LDAP via Dex)
Layer 2: Authorization
- What can they do?
- RBAC Policies, AppProject Scoping
Layer 3: Credential Management
- Git repository, cluster access credentials
- Stored securely as Kubernetes Secrets
Layer 4: Secret Management
- Safe handling of application secrets
- Sealed Secrets, External Secrets, Vault
Layer 5: Network Security
- TLS, Network Policy, access restrictions
2. Authentication
Local Users
ArgoCD provides built-in user accounts:
# argocd-cm ConfigMap
data:
accounts.alice: apiKey, login
accounts.bob: login
accounts.ci-bot: apiKey
| Capability | Description |
|---|---|
| login | Web UI and CLI login |
| apiKey | API token generation (for automation) |
SSO via Dex
Dex is the built-in OIDC Identity Provider:
data:
url: https://argocd.example.com
dex.config: |
connectors:
- type: github
id: github
name: GitHub
config:
clientID: YOUR_CLIENT_ID
clientSecret: $dex.github.clientSecret
orgs:
- name: my-org
teams:
- platform-team
- dev-team
Direct OIDC Integration (Without Dex)
Connect directly to Okta, Auth0, Keycloak:
data:
oidc.config: |
name: Okta
issuer: https://my-org.okta.com/oauth2/default
clientID: YOUR_CLIENT_ID
clientSecret: $oidc.okta.clientSecret
requestedScopes:
- openid
- profile
- email
- groups
requestedIDTokenClaims:
groups:
essential: true
LDAP Integration
data:
dex.config: |
connectors:
- type: ldap
id: ldap
name: LDAP
config:
host: ldap.example.com:636
insecureNoSSL: false
bindDN: cn=admin,dc=example,dc=com
bindPW: $dex.ldap.bindPW
userSearch:
baseDN: ou=users,dc=example,dc=com
filter: "(objectClass=person)"
username: uid
idAttr: uid
emailAttr: mail
nameAttr: cn
groupSearch:
baseDN: ou=groups,dc=example,dc=com
filter: "(objectClass=groupOfNames)"
userMatchers:
- userAttr: DN
groupAttr: member
nameAttr: cn
Authentication Flow
SSO Login:
1. User accesses ArgoCD UI
2. Clicks "Log in via SSO"
3. API Server redirects to Dex authorization endpoint
4. Dex redirects to external IdP (GitHub/Okta/LDAP)
5. User authenticates at external IdP
6. IdP redirects to Dex callback URL (auth code)
7. Dex exchanges auth code for tokens
8. Dex generates ID Token (user info + groups)
9. API Server validates ID Token
10. ArgoCD JWT issued (includes group info)
11. JWT stored in browser cookie
3. Authorization - RBAC
RBAC Policy Structure
ArgoCD uses Casbin-based RBAC:
# argocd-rbac-cm ConfigMap
data:
policy.default: role:readonly
policy.csv: |
# Admin role
p, role:admin, applications, *, */*, allow
p, role:admin, clusters, *, *, allow
p, role:admin, repositories, *, *, allow
p, role:admin, projects, *, *, allow
# Developer role
p, role:developer, applications, get, */*, allow
p, role:developer, applications, sync, */*, allow
p, role:developer, applications, action/*, */*, allow
p, role:developer, logs, get, */*, allow
# Read-only role
p, role:readonly, applications, get, */*, allow
p, role:readonly, projects, get, *, allow
# CI/CD bot role
p, role:ci-bot, applications, sync, ci-project/*, allow
p, role:ci-bot, applications, get, ci-project/*, allow
# Group mappings (SSO groups -> ArgoCD roles)
g, platform-team, role:admin
g, dev-team, role:developer
g, viewers, role:readonly
g, ci-bot, role:ci-bot
scopes: '[groups, email]'
Resources and Actions
| Resource | Actions | Description |
|---|---|---|
| applications | get, create, update, delete, sync, override, action/* | Application management |
| clusters | get, create, update, delete | Cluster management |
| repositories | get, create, update, delete | Repository management |
| projects | get, create, update, delete | Project management |
| logs | get | Pod log viewing |
| exec | create | Pod exec execution |
AppProject RBAC
Fine-grained RBAC within AppProjects:
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: team-alpha
spec:
roles:
- name: deployer
description: 'Deployment permissions'
policies:
- p, proj:team-alpha:deployer, applications, sync, team-alpha/*, allow
- p, proj:team-alpha:deployer, applications, get, team-alpha/*, allow
groups:
- team-alpha-deployers
- name: viewer
description: 'View permissions'
policies:
- p, proj:team-alpha:viewer, applications, get, team-alpha/*, allow
groups:
- team-alpha-viewers
4. Repository Credential Management
HTTPS Credentials
apiVersion: v1
kind: Secret
metadata:
name: repo-creds
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: git
url: https://github.com/my-org/my-repo.git
username: git
password: ghp_XXXXXXXXXXXX
SSH Credentials
apiVersion: v1
kind: Secret
metadata:
name: repo-creds-ssh
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: git
url: git@github.com:my-org/my-repo.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
Credential Templates
Apply common credentials to multiple repositories with the same pattern:
apiVersion: v1
kind: Secret
metadata:
name: repo-creds-template
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repo-creds
type: Opaque
stringData:
type: git
url: https://github.com/my-org
username: git
password: ghp_XXXXXXXXXXXX
5. Cluster Credential Management
Least Privilege Principle
For production, apply minimal permissions instead of cluster-admin:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-manager-minimal
rules:
- apiGroups: ['*']
resources: ['*']
verbs: ['get', 'list', 'watch']
- apiGroups: ['apps']
resources: ['deployments', 'statefulsets', 'daemonsets', 'replicasets']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['']
resources: ['services', 'configmaps', 'secrets', 'serviceaccounts', 'namespaces', 'pods']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['networking.k8s.io']
resources: ['ingresses', 'networkpolicies']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
- apiGroups: ['batch']
resources: ['jobs', 'cronjobs']
verbs: ['get', 'list', 'watch', 'create', 'update', 'patch', 'delete']
6. Secret Management Integration
Sealed Secrets
Encrypt secrets for safe Git storage:
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
name: my-secret
namespace: default
spec:
encryptedData:
password: AgBy3i4OJSWK+...
template:
metadata:
name: my-secret
namespace: default
External Secrets Operator (ESO)
Integration with external secret management systems:
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: 'https://vault.example.com'
path: 'secret'
auth:
kubernetes:
mountPath: 'kubernetes'
role: 'argocd'
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: my-app-secrets
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: my-app-secrets
creationPolicy: Owner
data:
- secretKey: database-password
remoteRef:
key: my-app/database
property: password
SOPS Integration
SOPS selectively encrypts YAML values:
apiVersion: v1
kind: Secret
metadata:
name: my-secret
stringData:
password: ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
api-key: ENC[AES256_GCM,data:...,iv:...,tag:...,type:str]
sops:
age:
- recipient: age1...
lastmodified: '2026-03-20T00:00:00Z'
version: 3.7.3
7. Network Security
TLS Configuration
# argocd-cmd-params-cm ConfigMap
data:
server.insecure: 'false'
reposerver.tls.minversion: '1.2'
Network Policy
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-nginx
ports:
- port: 8080
protocol: TCP
- port: 8083
protocol: TCP
egress:
- to: []
8. Audit Logging
ArgoCD API Server logs all user operations:
Log entries:
- Timestamp: When the action occurred
- User: Who performed the action (including SSO groups)
- Action: What was done (sync, create, delete, etc.)
- Resource: Target Application or resource
- Result: Success/failure
Prometheus Metrics
ArgoCD exposes security-related metrics:
argocd_app_sync_total: Total sync count
argocd_app_info: Application state information
argocd_cluster_api_server_requests_total: Cluster API request count
argocd_redis_request_total: Redis request count
9. Security Best Practices
Authentication
- Mandate SSO in production
- Disable or rotate local admin account password
- Set expiry on API tokens
- Enable MFA (Multi-Factor Authentication)
Authorization
- Set default policy to
role:readonly - Apply Least Privilege principle
- Isolate teams with AppProjects
- Restrict sync permissions for production namespaces
Credentials
- Prefer SSH keys over HTTPS tokens
- Apply minimal scope to tokens
- Implement periodic key rotation
- Apply minimal RBAC for cluster access
Secrets
- Never store plaintext secrets in Git
- Use Sealed Secrets or External Secrets Operator
- Implement auto-rotation mechanisms for secrets
Network
- Apply TLS to all communications
- Restrict ArgoCD component access with Network Policies
- Limit ArgoCD UI access via VPN or IP whitelisting
10. Summary
Key elements of the ArgoCD security model:
- Authentication: SSO (OIDC/SAML/LDAP via Dex) + local users
- Authorization: Casbin RBAC + AppProject scoping
- Repository Credentials: Secure management via HTTPS/SSH Secrets
- Cluster Credentials: ServiceAccount + Least Privilege
- Secret Management: Sealed Secrets / ESO / AVP / SOPS
- Network Security: TLS + Network Policy
- Audit: API Server logs + Prometheus metrics
Properly configuring these security layers enables building a secure GitOps operational environment.