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 |