Skip to content

Split View: ArgoCD 보안 모델: 인증, 인가, 시크릿 관리

|

ArgoCD 보안 모델: 인증, 인가, 시크릿 관리

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 키만)

계정 기능:

기능설명
loginWeb UI 및 CLI 로그인 가능
apiKeyAPI 토큰 생성 가능 (자동화용)

비밀번호 관리:

# 사용자 비밀번호 변경
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

리소스와 액션

리소스액션설명
applicationsgetApplication 조회
applicationscreateApplication 생성
applicationsupdateApplication 수정
applicationsdeleteApplication 삭제
applicationssyncApplication 동기화
applicationsoverrideApplication 파라미터 오버라이드
applicationsaction/*커스텀 액션 (restart 등)
clustersget/create/update/delete클러스터 관리
repositoriesget/create/update/delete저장소 관리
projectsget/create/update/delete프로젝트 관리
logsgetPod 로그 조회
execcreatePod 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 보안 모델의 핵심 요소:

  1. 인증: SSO(OIDC/SAML/LDAP via Dex) + 로컬 사용자
  2. 인가: Casbin RBAC + AppProject 스코핑
  3. 저장소 자격 증명: HTTPS/SSH Secret으로 안전하게 관리
  4. 클러스터 자격 증명: ServiceAccount + 최소 권한 원칙
  5. 시크릿 관리: Sealed Secrets / ESO / AVP / SOPS
  6. 네트워크 보안: TLS + Network Policy
  7. 감사: API Server 로그 + Prometheus 메트릭

이러한 보안 계층을 적절히 구성하면 안전한 GitOps 운영 환경을 구축할 수 있습니다.

[ArgoCD] Security Model: Authentication, Authorization, and Secret Management

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
CapabilityDescription
loginWeb UI and CLI login
apiKeyAPI 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

ResourceActionsDescription
applicationsget, create, update, delete, sync, override, action/*Application management
clustersget, create, update, deleteCluster management
repositoriesget, create, update, deleteRepository management
projectsget, create, update, deleteProject management
logsgetPod log viewing
execcreatePod 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:

  1. Authentication: SSO (OIDC/SAML/LDAP via Dex) + local users
  2. Authorization: Casbin RBAC + AppProject scoping
  3. Repository Credentials: Secure management via HTTPS/SSH Secrets
  4. Cluster Credentials: ServiceAccount + Least Privilege
  5. Secret Management: Sealed Secrets / ESO / AVP / SOPS
  6. Network Security: TLS + Network Policy
  7. Audit: API Server logs + Prometheus metrics

Properly configuring these security layers enables building a secure GitOps operational environment.