Cloud

ArgoCD 접근제어 설정 방법

Hanhorang31 2025. 11. 16. 00:58
 

ArgoCD 접근 제어 학습 내용을 정리 합니다.

학습 내용은 CloudNet@ 가시다님이 진행하는 CI/CD스터디를 참고하였습니다.

ArgoCD 접근 제어 구성 내용은 다음과 같습니다.

 

  • 실습 환경 구성
  • Argo CD HTTPS 설정Argo CD 접근 제어
  • Keycloak SSO(OIDC) 연동

실습 환경 구성(Kind + NGINX)

클러스터 외부에서 Ingress를 통해 서비스에 접근할 수 있도록 하기 위해 80, 443 포트를 추가 설정합니다.

또한, ingress-ready 라벨이 있는 노드에 nginx ingress를 배포합니다.

# kind k8s 배포
kind create cluster --name myk8s --image kindest/node:v1.32.8 --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  labels:
    ingress-ready: true
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP
  - containerPort: 30000
    hostPort: 30000
  - containerPort: 30001
    hostPort: 30001
  - containerPort: 30002
    hostPort: 30002
  - containerPort: 30003
    hostPort: 30003
EOF

kind가 로컬 Docker 환경이라 정상적인 NodeIP를 쓸 수 없기에, 노드 IP대신 LocalHost IP를 쓸 수 있도록 옵션 설정(--publish-status-address=localhost)을 진행합니다.

#NGINX Ingress 배포 
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

# 배포 객체 확인 
kubectl get deploy,svc,ep ingress-nginx-controller -n ingress-nginx
---
NAME                                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-nginx-controller   1/1     1            1           2m

NAME                               TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/ingress-nginx-controller   LoadBalancer   10.96.250.135        80:32685/TCP,443:31457/TCP   2m

NAME                                 ENDPOINTS                      AGE
endpoints/ingress-nginx-controller   10.244.0.7:443,10.244.0.7:80   2m


# IP 매핑 설정 확인
kubectl describe -n ingress-nginx deployments/ingress-nginx-controller | grep publish 
      --publish-status-address=localhost
      
# IPtalbes 확인
# 호스트 IP 80, 443 포트로 접근시 endpoints/ingress-nginx-controller 로 접근 
docker exec -it myk8s-control-plane bash
root@myk8s-control-plane:/# iptables -t nat -L -n -v | grep '10.244.0.7'
    0     0 DNAT       6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:10.244.0.7:80
    0     0 DNAT       6    --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443 to:10.244.0.7:443
 

또한, ArgoCD가 TLS 직접 처리하기 위해 Nginx Ingress 컨트롤러 설정에서 SSL Passthrough Flag 활성화 합니다.

kubectl edit -n ingress-nginx deployments/ingress-nginx-controller
---
    spec:
      automountServiceAccountToken: true
      containers:
      - args:
        - /nginx-ingress-controller
        - --enable-ssl-passthrough # 추가 설정
        

 

 

ArgoCD 설치(TLS)

OpenSSL로 Self-signed 인증서 생성 및 Secrets 를 ArgoCD 인증서로 사용,

브라우저 → Ingress → ArgoCD Sever까지 HTTPS 유지 설정 가능합니다.

# TLS 키·인증서 생성 : 공통 이름이 argocd.example.com 이어야 합니다
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout argocd.example.com.key \
  -out argocd.example.com.crt \
  -subj "/CN=argocd.example.com/O=argocd"

ls -l argocd.example.com.*
-rw-r--r--@  1 hanseungho  staff  1184 11 15 20:37 argocd.example.com.crt # 인증서
-rw-------@  1 hanseungho  staff  1704 11 15 20:37 argocd.example.com.key # 비밀키

# 발급 주체 & 유효 기간 확인
openssl x509 -noout -text -in argocd.example.com.crt
...

        Issuer: CN=argocd.example.com, O=argocd
        Validity
            Not Before: Nov  8 14:10:14 2025 GMT
            Not After : Nov  8 14:10:14 2026 GMT
        Subject: CN=argocd.example.com, O=argocd
        ...
            X509v3 Basic Constraints: critical
                CA:TRUE

# Argo CD가 자신의 TLS를 쓰도록 argocd 네임스페이스에 tls 타입 시크릿 생성
kubectl create ns argocd

# tls 시크릿 생성 : key/crt 파일이 로컬에 있어야 함
kubectl -n argocd create secret tls argocd-server-tls \
  --cert=argocd.example.com.crt \
  --key=argocd.example.com.key

kubectl get secret -n argocd
NAME                TYPE                DATA   AGE
argocd-server-tls   kubernetes.io/tls   2      7s

# SSL-Passthrough : The 'tls: true' option will expect that the 'argocd-server-tls' secret exists as Argo CD server loads TLS certificates from this place.
cat < argocd-values.yaml
global:
  domain: argocd.example.com

server:
  ingress:
    enabled: true
    ingressClassName: nginx
    annotations:
      nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
      nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    tls: true
EOF

# 설치 : Argo CD v3.1.9 , (참고) 책 버전 Argo CD v2.1 ~ v2.2
# https://github.com/argoproj/argo-helm/blob/main/charts/argo-cd/values.yaml
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd --version 9.0.5 -f argocd-values.yaml --namespace argocd

# 각 구성요소 확인
kubectl get all -n argocd
kubectl get pod,ingress,svc,ep,secret,cm -n argocd

kubectl describe ingress -n argocd argocd-server
..
Default backend:  
TLS:
  argocd-server-tls terminates argocd.example.com
..


kubectl get ingress -n argocd argocd-server # 아래 address 에 localhost 는 배포 후 sync 까지 다소 시간 소요
NAME            CLASS   HOSTS                ADDRESS     PORTS     AGE
argocd-server   nginx   argocd.example.com   localhost   80, 443   6m42s

kubectl get ingress -n argocd argocd-server -o yaml  | grep nginx
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
  ...
  
kubectl get ingress -n argocd argocd-server -o yaml  | grep tls  
tls:
  secretName: argocd-server-tls


# 도메인 설정
## macOS의 /etc/hosts 파일 수정
echo "127.0.0.1 argocd.example.com" | sudo tee -a /etc/hosts
cat /etc/hosts


# 접속 확인
curl -vk https://argocd.example.com/
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller
kubectl -n argocd logs deploy/argocd-server

# 최초 접속 암호 확인
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d ;echo
7giLgw3mjTQC8alm

# Argo CD 웹 접속 주소 확인 : 초기 암호 입력 (admin 계정)
open "https://argocd.example.com"

 

 

ArgoCD 접근 제어

1. Local User/Account

ArgoCD 설치시 admin 유저 생성됨(전체 액세스 권한)

 

kubectl get secret -n argocd
NAME                           TYPE                 DATA   AGE
argocd-initial-admin-secret    Opaque               1      7m20s
argocd-notifications-secret    Opaque               0      7m21s
argocd-redis                   Opaque               1      7m24s
argocd-secret                  Opaque               3      7m21s
argocd-server-tls              kubernetes.io/tls    2      8m49s
sh.helm.release.v1.argocd.v1   helm.sh/release.v1   1      8m2s

kubectl get secret -n argocd argocd-initial-admin-secret 
NAME                          TYPE     DATA   AGE
argocd-initial-admin-secret   Opaque   1      52m

# 어드민 초기 비밀번호 확인 
kubectl get secret -n argocd argocd-initial-admin-secret --context kind-myk8s -o jsonpath='{.data.password}' | base64 -d


# 패스워드 변경 
argocd account update-password
*** Enter password of currently logged in user (admin): 
*** Enter new password for user admin: 
*** Confirm new password for user admin: 
Password updated
Context 'argocd.example.com' updated

# 패스워드 확인 
kubectl get secret argocd-secret -n argocd -o yaml
apiVersion: v1
data:
  admin.password: JDJhJDEwJDAyTXlDd0c3MEJSeW5lSzhkeTNNN2VaUWp5Z3Fod1JBYVpPN2pPS04uVTFTbWZiSFBScTJT
  admin.passwordMtime: MjAyNS0xMS0xNVQxMjozOTowMFo=
  server.secretkey: YXZzZyt6STFmOHcxcUNDQmN3U1FhZkNZVVA2ckR0bnQzbFhabkYxL0dWZz0=
  
# admin 패스워드 변경
kubectl -n argocd patch secret argocd-secret \
  -p '{"stringData": {
    "admin.password": "$2a$10$SAPKfIOUNkC8JjkGaFwDX.9zzLKHqaQlUcsGGWHM4eZ0FbAdzMGMq",
    "admin.passwordMtime": "'$(date +%FT%T%Z)'"
  }}'
  

# 관리자 비활성화 권장 설정
kubectl edit cm argocd-cm -n argocd
---
apiVersion: v1
data:
  admin.enabled: "false"
  application.instanceLabelKey: argocd.argoproj.io/instance

로컬 사용자 생성 및 애플리케이션 권한 설정 - DoC

# 로컬 사용자 생성
kubectl edit cm argocd-cm -n argocd 
---
apiVersion: v1
data:
    # add an additional local user with apiKey and login capabilities
  #   apiKey - allows generating API keys
  #   login - allows to login using UI
  accounts.alice: apiKey, login # 추가
  
 
 
argocd account list                
NAME   ENABLED  CAPABILITIES
admin  true     login
alice  true     apiKey, login


# if you are managing users as the admin user, <current-user-password> should be the current admin password.
argocd account update-password \
  --account alice \
  --current-password qwe12345 \
  --new-password alice12345
  
kubectl get secret -n argocd argocd-secret -o jsonpath='{.data}' | jq
{
  "accounts.alice.password": "JDJhJDEwJDZsWXdRdTRXaDhQdGJXeDZZSFJEaE84cHprdFVOU0hMQ2V6L1VRUC9KVGtUdU1jRmdDOXRD",
  "accounts.alice.passwordMtime": "MjAyNS0xMS0xNVQxMjo1ODozMVo=",
  "accounts.alice.tokens": "bnVsbA==",
  "admin.password": "JDJhJDEwJFNBUEtmSU9VTmtDOEpqa0dhRndEWC45enpMS0hxYVFsVWNzR0dXSE00ZVowRmJBZHpNR01x",
  "admin.passwordMtime": "MjAyNS0xMS0xNVQyMTo1NTo0NktTVA==",
  "server.secretkey": "YXZzZyt6STFmOHcxcUNDQmN3U1FhZkNZVVA2ckR0bnQzbFhabkYxL0dWZz0="
}
  

샘플 애플리케이션 배포 후 로컬 사용자 계정(alice) 조회

cat <https://github.com/argoproj/argocd-example-apps
    targetRevision: HEAD
  syncPolicy:
    automated:
      enabled: true
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
  destination:
    namespace: guestbook
    server: https://kubernetes.default.svc
EOF

Alice 계정 조회시 자원 확인 불가

 

 

RBAC 설정 - Doc

RBAC 기능은 Argo CD 리소스에 대한 액세스를 제한할 수 있도록 합니다.

Argo CD에는 두 가지 사전 정의된 역할이 있지만 RBAC 구성을 사용하면 역할과 그룹을 정의할 수 있습니다.

사전 정의 역할은 다음과 같습니다.

  • role:readonly: 모든 리소스에 대한 읽기 전용 액세스
  • role:admin : 모든 리소스에 대한 무제한 액세스

기본 ArgoCD 인증되면 지정된 역할로 설정

kubectl get cm -n argocd argocd-rbac-cm -o jsonpath='{.data}' | jq
{
  "policy.csv": "",
  "policy.default": "",
  "policy.matchMode": "glob",
  "scopes": "[groups]"
}
kubectl edit cm -n argocd argocd-rbac-cm
---
apiVersion: v1
data:
  policy.csv: ""
  policy.default: "role:readonly" # 업데이트 

2. 서비스 어카운트

서비스 어카운트는 CI/CD 파이프라인과 같은 자동화 시스템에 인증하는데 사용하는 계정이다.

위 사용자를 비활성화하거나 권한을 제어하면 파이프라인이 실패할 수 있기 때문에 사용자와 연결되어서는 안된다.

ArgoCD에서 서비스 어카운트를 생성하는 방법은 두가지이다.

  • 로그인 기능을 제거하고 API키 만을 사용하는 로컬 사용자
  • 프로젝트 역할을 사용하고 그 역할에 토큰 할당

 

2.1 로컬 서비스 어카운트 RBAC


kubectl edit cm -n argocd argocd-cm
 accounts.gitops-ci: apiKey
 
argocd account list
NAME       ENABLED  CAPABILITIES
admin      true     login
alice      true     apiKey, login
gitops-ci  true     apiKey

 
# 계정 토큰 생성 시도 (발급 가능) 
argocd account generate-token -a gitops-ci
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJnaXRvcHMtY2k6YXBpS2V5IiwibmJmIjoxNzYzMjEzMDE1LCJpYXQiOjE3NjMyMTMwMTUsImp0aSI6IjAxNDU0ZGU3LWU5NWUtNDE1ZS05ZDQ1LWFiN2Q0ODUyYTBmNiJ9.Unl90cS6Go8GHPlMjs97fAcftqjRA2hgqrJ4PHyDdRQ

# 토큰 작동 확인 
argocd account get-user-info --auth-token  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJhcmdvY2QiLCJzdWIiOiJnaXRvcHMtY2k6YXBpS2V5IiwibmJmIjoxNzYzMjEzMDE1LCJpYXQiOjE3NjMyMTMwMTUsImp0aSI6IjAxNDU0ZGU3LWU5NWUtNDE1ZS05ZDQ1LWFiN2Q0ODUyYTBmNiJ9.Unl90cS6Go8GHPlMjs97fAcftqjRA2hgqrJ4PHyDdRQ
Logged In: true
Username: gitops-ci
Issuer: argocd
Groups: 

 

 

2.2 프로젝트 역할과 토큰 할당

애플리케이션 프로젝트는 역할을 통해 애플리케이션 정의에 일부 제약 조건을 적용하는 방식이다.

상태를 가져오는 리포지터리, 대상 클러스터나 배포할 수 있는 네임스페이스를 지정할 수 있고, 설치할 수 있는 리소스 유형을 필터링할 수도 있다.

 

  • 기존 프로젝트에서는 애플리케이션에 대한 필터링이 설정되어 있지 않다.
# ‘*’ 표시로 모든 것에 대해서 허용돼 있다.
kubectl get appprojects.argoproj.io -n argocd default -o yaml | k neat | yq
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: default
  namespace: argocd
spec:
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'
  destinations:
    - namespace: '*'
      server: '*'
  sourceRepos:
    - '*'

예제 프로젝트와 앱을 배포합니다.

프로젝트 정책은 proj:sample-apps:read-sync 역할을 가진 사용자에게만 get, sync를 허용합니다.

# 프로젝트 배포
cat <https://kubernetes.default.svc
  sourceRepos:
    - https://github.com/argoproj/argocd-example-apps.git
EOF

# 프로젝트 앱 배포
cat <https://github.com/argoproj/argocd-example-apps
    targetRevision: master
  destination:
    namespace: test
    server: https://kubernetes.default.svc
  syncPolicy:
    automated:
      enabled: false
    syncOptions:
    - CreateNamespace=true
EOF

로컬 사용자(Alice) 계정에서 Sync 동작시 권한 부족으로 실패

 

 

추가 권한 설정 수행

Argocd 정책 구조는 다음과 같이 설정됩니다.

p, <subject>, <resource>, <action>, <object>, <effect>
- p 는 Policy, g는 매핑을 뜻함
  • role:user-update 역할에게 모든 어카운트에 대한 update/get 수행 권한과 프로젝트(sample-apps) 권한 부여
  • role:sample-apps-sync 역할에 sample-apps 애플리케이션 get/sync 역할 부여
  • ailice 사용자에 role:user-update & role:sample-apps-sync 역할 매핑

 

kubectl edit cm -n argocd argocd-rbac-cm
data:
apiVersion: v1
data:
  policy.csv: |
    p, role:user-update, accounts, update, *, allow
    p, role:user-update, accounts, get, *, allow
    p, role:user-update, projects, sync, sample-apps, allow
    p, role:sample-apps-sync, applications, get, sample-apps/*, allow
    p, role:sample-apps-sync, applications, sync, sample-apps/*, allow
    g, alice, role:user-update
    g, alice, role:sample-apps-sync

로컬 사용자 Sync 수행 확인

 

 

 

SSO

SSO를 사용하면 마스터 로그인을 할 수 있으며, 이를 기반으로 다른 독립적인 애플리케이션에 대한 권한을 부여받을 수 있습니다.

Argo CD는 두 가지 방법으로 SSO 기능을 제공합니다.

하나는 기본적으로 설치되는 Dex OIDC 공급자를 사용하는 것이고, 다른 하나는 dex 설치 없이 다른 OIDC 공급자를 통해 Argo CD를 직접 사용하는 것입니다.

이번 글에서는 Keycloak을 통해 SSO를 설정하겠습니다.

SSO 동작 : User — Application(ArgoCD, client 역할) — Keycloak(인증 서버 역할)

User는 Keycloak에서 한 번 로그인하면, Argo CD는 Keycloak이 발급한 신뢰 가능한 토큰을 기반으로 인증을 처리합니다.

 

 

keycloak 배포 및 기본 설정

--net host 로 설정해야 하지만, 필자는 공유기 환경으로 접근이 안되어 포트를 설정하였습니다.

포트를 설정하는 경우에는 ArgoCD에서 Keycloack 리다이릭트 URL을 인식하지 못하여 연동하지 못합니다.(후술)

docker run -d -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -p 8080:8080 --name dev-keycloak quay.io/keycloak/keycloak:22.0.0 start-dev

docker ps 
CONTAINER ID   IMAGE                              COMMAND                   CREATED         STATUS                 PORTS                                                                                                       NAMES
355733963ebb   quay.io/keycloak/keycloak:22.0.0   "/opt/keycloak/bin/k…"   5 seconds ago   Up 4 seconds     

# admin 웹 콘솔 접속 : admin / admin
open http://localhost:8080/admin

argoCD를 위한 client 생성

Client → Credential 에서 Secert 정보 확인

YCmoiHAp60J7W66s84Il4DOehjjnlFYo

ArgoCD OIDC 설정

  • 클라이언트 시크릿 설정
kubectl -n argocd patch secret argocd-secret --patch='{"stringData": { "oidc.keycloak.clientSecret": "YCmoiHAp60J7W66s84Il4DOehjjnlFYo" }}'
  • ArgoCD OIDC 활성화 및 keycloak 인증 활성화
kubectl edit cm -n argocd argocd-cm
...
data:
  url: https://argocd.example.com # 맨 아래 있음
  oidc.config: |
    name: Keycloak
    issuer: http://localhost:8080/realms/master
    clientID: argocd
    clientSecret: YCmoiHAp60J7W66s84Il4DOehjjnlFYo
    requestedScopes: ["openid", "profile", "email"]
    
# argocd 재시작
kubectl rollout restart deploy argocd-server -n argocd

ArgoCD 파드에서 localhost(로컬 맥) 를 인식을 못하여 생기는 오류입니다.

keycloak을 호스트 네트워크에 배포해야하지만, 필자의 경우 공유기 환경에 포트포워딩을 할 수 없는 환경이라 에러가 발생합니다.



'Cloud' 카테고리의 다른 글

KeyCloak SSO 실습  (0) 2025.11.23
ArgoCD로 멀티클러스터 관리하기  (0) 2025.11.23
ArgoCD 정리 (1)  (0) 2025.11.08
Gitops CI & CD 구성(Jenkins & ArgoCD)  (0) 2025.11.02
Helm 과 lgtm Stack 맛보기(Loki)  (0) 2025.10.26