Argo CD 存取權限管理:用 Projects 與 RBAC 保護開發、測試與正式環境

Published on: | Last updated:

最近在玩 Argo CD,發現一個蠻...嗯,應該說是很關鍵但又容易被忽略的問題。就是當你團隊越來越大,環境越來越多,比如 dev、test、prod,整個 Argo CD 裡面會塞滿一堆 application。這時候,問題就來了:到底誰可以動誰的東西?

老實說,如果沒管好,一個開發團隊的成員,可能不小心就動到 production 環境的東西。這不是開玩笑的,真的會發生。所以,怎麼做到權限控管,讓對的人只能做對的事,就變得很重要。Argo CD 其實有內建一套機制來解決這個問題,就是用 ProjectsRBAC (Role-Based Access Control)。今天就來聊聊這個,把它們搞懂,你的 CI/CD 管線才能睡得安穩。

先說結論:不管控,就像把所有鑰匙都給同一個人

我自己是覺得,最簡單的理解方式就是:如果完全不用 Argo CD 的 Projects 功能,只用預設的那個 `default` project,那就等於你家裡所有房間——臥室、書房、廚房,甚至放著重要文件的保險箱——都用同一把鑰匙。

任何拿到這把「萬能鑰匙」(Argo CD 存取權)的人,都能進出所有房間,動任何東西。聽起來就很可怕吧?

所以,Projects 就是幫你打造不同的鎖,RBAC 則是決定要把哪把鑰匙給誰。下面這個對比,應該會更清楚。

作法 只用預設的 `default` Project 建立 dev / test / prod 各自的 Project
安全性 很低。基本上是個大洞,人人有功練,誰都能改到 Production。 高。可以把 Production 環境鎖起來,只有授權的人能動。
管理複雜度 表面上很簡單,但其實是混亂的開始。東西一多就找不到,也分不清誰是誰的。 初期設定多一點點,但後面會很清爽。每個團隊管好自己的一畝三分地。
適合情境 個人玩 side project,或剛裝好 Argo CD 測試一下的時候。千萬別在正式環境這樣搞。 只要是團隊協作,有超過一個環境(例如測試跟正式),就應該這樣做。
團隊感受 「欸,那個 prod-db 是誰改到的?」「我不知道啊,我只是想同步一下我的 feature-x...」 「我只能動 dev 的東西,prod 的我連 sync 按鈕都按不下去,很安心。」
權限混亂 vs. 權限分離的示意圖
權限混亂 vs. 權限分離的示意圖

怎麼做?一步步把權限設定好

好,理論講完了,我們來實際操作一下。整個流程大概是這樣:先把危險的 `default` project 廢掉,然後建立我們需要的 project,最後再建立使用者,把他們跟 project 綁定。聽起來步驟多,但其實觀念很直接。

第一步:廢掉 `default` project 的武功

剛裝好的 Argo CD,那個 `default` project 權限太大了,根本是超級管理員。所以第一件事,就是把它改成一個空殼子,讓它什麼事都不能做。這樣才不會有人不小心把新的 application 裝到這個「無人管」的 project 裡。

你就 apply 下面這個 YAML 檔。這段設定的意思是說,`default` project 不能從任何 Git repo 拉程式碼 (`sourceRepos: []`)、也不能部署到任何 Kubernetes 叢集或 namespace (`destinations: []`),基本上就是把它關進禁閉室。

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: default
  namespace: argocd
spec:
  # 把它能用的 repo 設為空,等於不能從任何地方同步
  sourceRepos: []
  # 能部署的目的地也設為空
  destinations: []
  # 甚至直接把所有資源都列入黑名單,確保萬無一失
  namespaceResourceBlacklist:
  - group: '*'
    kind: '*'

第二步:建立專屬的 Projects (dev, test, prod)

接下來,就是建立我們真正要用的 project 了。例如,我們先建一個 `dev-project`。這個 project 我們希望它只能部署到 `dev-` 開頭的 namespace,這樣才不會污染到其他環境。

你看這個 `destinations` 區塊,我們指定了 `namespace: 'dev*'`,這個星號就是萬用字元,代表所有 `dev-` 開頭的 namespace 都可以用。然後 `server` 就是你的 Kubernetes API server 位址。

# dev-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: dev-project
  namespace: argocd
spec:
  description: "給開發環境用的 Project"
  sourceRepos:
    - '*' # 為了方便,先允許所有 git repo,實務上應該指定你的專案 repo
  destinations:
    - namespace: 'dev*'
      server: https://kubernetes.default.svc
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'

同理,`test-project` 跟 `prod-project` 也是一樣的道理,只是把 `name` 跟 `namespace` 的規則改掉而已。例如 `prod-project` 就會長這樣:

# prod-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: prod-project
  namespace: argocd
spec:
  description: "正式環境,閒人勿近!"
  sourceRepos:
    - 'https://github.com/your-org/main-app.git' # Prod 環境最好明確指定 repo
  destinations:
    - namespace: 'prod*'
      server: https://kubernetes.default.svc
  clusterResourceWhitelist:
    - group: '*'
      kind: '*'

當你有了這些 project,之後在建立 application 的時候,就可以在 spec 裡面指定 `project: dev-project`,Argo CD 就會自動套用這個 project 的規則了。

RBAC 規則阻擋未授權操作的流程示意
RBAC 規則阻擋未授權操作的流程示意

第三步:建立使用者與角色 (RBAC)

好了,房間(Projects)隔好了,現在要發鑰匙(設定 User 和 Role)了。Argo CD 預設只有一個 `admin` user,我們總不能把 admin 密碼到處發吧。

這邊我們要動到兩個 ConfigMap:`argocd-cm` 用來建立本地使用者帳號,`argocd-rbac-cm` 用來設定權限。

首先,編輯 `argocd-cm`,在 `data` 區塊加上 `accounts.` 開頭的 key,來建立使用者。例如,我們建立三個使用者:developer、devops、tester。

# argocd-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # 格式是 accounts.[使用者名稱]: [能力]
  # apiKey, login 是最常見的組合,代表可以登入UI,也可以產生 API token
  accounts.developer: apiKey, login
  accounts.devops: apiKey, login
  accounts.tester: apiKey, login

建好帳號後,要幫他們設定密碼。這得用 CLI 來做。你要先拿到 admin 的密碼,然後用 admin 的身份去幫其他人設密碼。密碼千萬不要用 `developer123` 這種...我這只是範例啊。

# 先拿到 admin 的 current-password
argocd admin initial-password -n argocd

# 幫 developer 設定新密碼
argocd account update-password \
  --account developer \
  --current-password "把上面拿到的 admin 密碼貼上來" \
  --new-password "一個很安全的密碼"

第四步:分配權限,這才是重頭戲

最後一步,也是最關鍵的一步,就是編輯 `argocd-rbac-cm`。這裡面的 `policy.csv` 定義了誰能做什麼事。它的語法看起來有點怪,但拆開看就懂了。

`p` 開頭的是 policy rule,`g` 開頭的是 group/role 的綁定。規則是 `p, [sub], [res], [act], [obj], [eff]`,白話文就是「`sub` 這個主體,對於 `obj` 這個物件,可不可以 `eff` 執行 `act` 這個動作」。

例如,我們希望:

  • `devops` 這個使用者擁有管理員權限。
  • `developer` 這個使用者,只能對 `dev-project` 裡面的 application 執行 `sync` 動作。
  • 其他沒被定義到的人,預設只有 `readonly` 唯讀權限。

那 policy 就會長這樣:

# argocd-rbac-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  # policy.csv 裡的規則會被 Argo CD 讀取
  policy.csv: |
    # g, [user/group], [role]
    # 把 devops 這個使用者,綁定到內建的 admin 角色
    g, devops, role:admin

    # p, [sub], [res], [act], [obj], [eff]
    # 允許 developer,對 dev-project/* 裡面的 applications,執行 sync
    p, developer, applications, sync, dev-project/*, allow

  # 這是個很棒的保險。任何沒有在上面被定義到的使用者,預設都只有唯讀權限。
  policy.default: role:readonly

這樣一來,當 `developer` 這個使用者登入後,他會看到 `prod-project` 裡面的 application,但所有操作按鈕都是反灰的,他唯一能做的,就只有去 `dev-project` 按下 `Sync`。這就達到我們的目的了。

說到這個,其實這也跟 CNCF 提到的一些安全最佳實踐 (security best practices) 觀念是相通的,就是所謂的「最小權限原則」(Principle of Least Privilege)。不像我們在台灣很多團隊剛開始導入時,為了求快,常常是 `admin` 帳號大家共用...嗯,過來人都懂,但這樣真的不行,遲早會出事的。花點時間把 RBAC 設定好,絕對是值得的。

不同角色對應不同權限,就像不同鑰匙開不同的鎖
不同角色對應不同權限,就像不同鑰匙開不同的鎖

常見錯誤與修正

老實說,我自己剛開始玩的時候也踩過一些坑。這邊列幾個常見的錯誤,大家可以避開:

  • 忘了鎖 `default` project:很多人記得要建新的 project,卻忘了把預設的 `default` project 權限拿掉。結果新來的同事不知道,還是把 app 建在 `default` 裡,那前面做的都白費了。
  • RBAC 規則寫得太寬鬆:為了方便,在 `policy.csv` 裡寫了 `p, developer, *, *, */*, allow` 這種規則。這跟給他 admin 權限也差不多了。`*` 很好用,但也很危險,盡量把範圍縮小。
  • 使用者密碼管理混亂:用本地帳號很方便,但如果團隊大了,管理一堆人的密碼會是個災難。我自己是覺得,如果公司有 SSO 系統(像 Google Workspace, LDAP, OIDC),最好還是花點時間把 Argo CD 跟 SSO 整合起來,讓公司的帳號系統統一管理,會省事很多。

總結來說,Argo CD 的 Projects 跟 RBAC 功能真的很強大,是 GitOps 工作流程中不可或缺的一環。雖然初期設定有點繁瑣,需要動手寫一些 YAML,但這點投資絕對值得。它能確保你的 Kubernetes 叢集部署流程是安全、可控且有條理的。

所以,問題來了:你現在的團隊是用什麼方式來區分不同環境的部署權限呢?還在共用 admin 帳號嗎?或是有用到其他更有趣的方法?

Related to this topic:

Comments

  1. profile
    Guest 2025-08-11 Reply
    聽起來好像很複雜耶!權限管控真的有這麼困難嗎?我一直覺得開發團隊應該要更直接點,幹嘛搞這麼多限制?不過話說回來,安全性確實滿重要的...