ArgoCDを複数ユーザで使う場合に権限を分けたい。
具体的には参照可能なApplicationリソースを以下のように分離したい。
Projectが同一 | Projectが異なる | |
---|---|---|
ゲスト | Read | Read |
開発者 | CRUD+Sync | なし |
管理者 | CRUD+Sync | CRUD+Sync |
※CRUD: Create, Read(Get), Update, Delete
これを実現する方法を検討した時のメモ。
なお、確認に利用したArgoCDのバージョンはv2.4.7であり、異なるバージョンで試す場合は方法が変わる可能性が有る点には注意すること。
やること
以下の仮想ユーザを用意し、それぞれ権限が適切に分けて付与できるかを確認する。
確認手順は以下となる。
- 前準備(Applicationが管理するManifestの準備)
- ArgoCD用ユーザアカウントの作成
- ArgoCDのProjectとRoleの作成
-
kind: Application
の適用 - 検証
前準備
ArgoCDのアプリケーション(game_app
、book_app
)が監視するManifestを作成してGitにpushする。
空のリポジトリを作成してcloneする。
export $MYREPO=https://mygitlab.info/myapp/apps.git
git clone $MYREPO
各プロジェクトで利用するManifestを格納するディレクトリを作成する。
mkdir -p apps/{game,book}
今回はアプリケーションそのものには価値を求めないため、ダミーでnginxが起動するManifestを作成する。
それぞれのディレクトリにダミーのManifestを作成してpushする。
NAME=game
kubectl run --image nginx nginx-$NAME -o yaml --dry-run=client | kubectl neat -f - > apps/$NAME/nginx-$NAME.yaml
NAME=book
kubectl run --image nginx nginx-$NAME -o yaml --dry-run=client | kubectl neat -f - > apps/$NAME/nginx-$NAME.yaml
git add *
git commit -m "nocomment"
git push
構成としては以下のようになる。
apps
├── README.md
├── book
│ └── nginx-book.yaml
└── game
└── nginx-game.yaml
ユーザアカウントの作成
ArgoCDはv2.4時点ではアカウントの作成がCLI/GUIから作成できず、ConfigMapで指定することでのみ作成できる。
作成するConfigMapも指定があり、argocd-cm
というConfigMapを必ず使うことになっているので、こちらを使用する。
なお、デフォルトでインストールされているargocd-cm
は初期状態では空なので、上書きしてもらって問題ない。
ArgoCDのユーザ管理のオフィシャルページを見つつ、アカウントの元となるyamlを作成し、applyする。
cat << EOF > ./argocd-account-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
accounts.alice: apiKey, login
accounts.bob: apiKey, login
accounts.mike: apiKey, login
EOF
kubectl apply -f argocd-account-cm.yaml
ユーザアカウント名はdata
フィールドにaccounts.<ユーザアカウント名>
で記載することで作成される。apiKeyはTokenによるアクセスを許可するかどうかであり、不要であれば外してもらって構わない。
反映されたことを確認する。
$ argocd account list
NAME ENABLED CAPABILITIES
admin true login
alice true apiKey, login
bob true apiKey, login
mike true apiKey, login
パスワードは設定されていないので、コマンドで変更する。なお、--current-password
にはadminのパスワードを指定する。
export ADMIN_PASSWORD='admin-password'
export PASSWORD='argocd-password'
argocd account update-password --account alice --current-password $ADMIN_PASSWORD --new-password $PASSWORD
argocd account update-password --account bob --current-password $ADMIN_PASSWORD --new-password $PASSWORD
argocd account update-password --account mike --current-password $ADMIN_PASSWORD --new-password $PASSWORD
ProjectとRoleの作成
次にProjectの作成とroleの作成をセットで行う。なおコマンドでProjectやroleも作成可能だが、Manifestで設定した方が全体を見渡せやすいので、今回はManifestにて作成する。
なお、Built-inのroleが存在するが、今回は利用しない(書き方の参考にはした)。
その他書き方を参考にしたページはこれとこれになる。
以下、Project:game
のManifest適用手順となる。book
に対しても同様に適用する(環境変数をbook
に変えて再実行する)。
export APP_PROJECT=game
cat <<EOF > ./${APP_PROJECT}-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: ${APP_PROJECT}
namespace: argocd
spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
destinations:
- namespace: '*'
server: '*'
sourceRepos:
- '*'
roles:
- name: guest
description: "guest role"
policies:
- p, proj:${APP_PROJECT}:guest, applications, get, */*, allow
- name: developer
description: "developer role"
policies:
- p, proj:${APP_PROJECT}:developer, applications, create, ${APP_PROJECT}/*, allow
- p, proj:${APP_PROJECT}:developer, applications, get, ${APP_PROJECT}/*, allow
- p, proj:${APP_PROJECT}:developer, applications, update, ${APP_PROJECT}/*, allow
- p, proj:${APP_PROJECT}:developer, applications, delete, ${APP_PROJECT}/*, allow
- p, proj:${APP_PROJECT}:developer, applications, sync, ${APP_PROJECT}/*, allow
- name: operator
description: "operator role"
policies:
- p, proj:${APP_PROJECT}:operator, applications, create, */*, allow
- p, proj:${APP_PROJECT}:operator, applications, get, */*, allow
- p, proj:${APP_PROJECT}:operator, applications, update, */*, allow
- p, proj:${APP_PROJECT}:operator, applications, delete, */*, allow
- p, proj:${APP_PROJECT}:operator, applications, sync, */*, allow
EOF
kubectl apply -f ./${APP_PROJECT}-project.yaml
clusterResourceWhitelist
、destinations
、sourceRepos
は今回チェックの対象外としている。必要な場合(クラスタやデプロイ先、利用するリポジトリに制限をかけたい場合)は
こちらを参照するとよい。
なお、policies
で指定しているポリシーの意味は以下となる。
- ポリシールールを定義:
p, subject, resource, action, object, effect
例)
p, my-org:team-alpha, applications, sync, my-project/*, allow
- ユーザとロールをbinding:
g, subject, inherited-subject
例)
g, my-org:team-beta, role:admin
ここではbindingまでは含めておらず、ロールの定義のみ実施しているため、g, xxxx
は記載していない。
適用後、argocd cliからProjectとRoleは以下のように見える。
$ argocd proj list
NAME DESCRIPTION DESTINATIONS SOURCES CLUSTER-RESOURCE-WHITELIST NAMESPACE-RESOURCE-BLACKLIST SIGNATURE-KEYS ORPHANED-RESOURCES
book *,* * */* <none> <none> disabled
default *,* * */* <none> <none> disabled
game *,* * */* <none> <none> disabled
$ argocd proj role list game
ROLE-NAME DESCRIPTION
guest guest role
developer developer role
operator operator role
$ argocd proj role get game developer
Role Name: developer
Description: developer role
Policies:
p, proj:game:guest, projects, get, game, allow
p, proj:game:guest, applications, get, */*, allow
p, proj:game:developer, projects, get, game, allow
p, proj:game:developer, applications, create, game/*, allow
p, proj:game:developer, applications, get, game/*, allow
p, proj:game:developer, applications, update, game/*, allow
p, proj:game:developer, applications, delete, game/*, allow
p, proj:game:developer, applications, sync, game/*, allow
p, proj:game:operator, projects, get, game, allow
p, proj:game:operator, applications, create, */*, allow
p, proj:game:operator, applications, get, */*, allow
p, proj:game:operator, applications, update, */*, allow
p, proj:game:operator, applications, delete, */*, allow
p, proj:game:operator, applications, sync, */*, allow
JWT Tokens:
ID ISSUED-AT EXPIRES-AT
次にオフィシャルサイトの記述を参考にユーザとロールをConfigMapを使ってbindingする。
こちらもアカウント作成時と同様にConfigMapに指定があり、argocd-rbac-cm
というConfigMapにpolicy.csv
というdataフィールドに追加することでbindingする。
適用したManifestは以下となる。
cat <<EOF > ./argocd-rbac-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
#policy.default: role:readonly
policy.csv: |
g, alice, proj:game:guest
g, alice, proj:book:guest
g, bob, proj:game:developer
g, mike, proj:game:operator
g, mike, proj:book:operator
EOF
kubectl apply -f ./argocd-rbac-cm.yaml
今回はroleは作成済みなので、policyの記載ではbindingに関するルールのg, xxxx
の方のみ記載した。
また、defaultのpolicyは検証の邪魔になるためコメントアウトした。
kind: Application
の適用
先程作成したManifestをデプロイするkind: Application
を作成する。
以下、Project:game
で動くアプリケーションとなる。Project:book
については環境変数を変更して流し直す。
export APP_PROJECT=game
cat <<EOF > ./${APP_PROJECT}-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: ${APP_PROJECT}-app
namespace: argocd
spec:
destination:
namespace: nginx-${APP_PROJECT}
server: https://kubernetes.default.svc
project: ${APP_PROJECT}
source:
path: ${APP_PROJECT}/
repoURL: https://mygitlab.info/myapp/apps.git
targetRevision: HEAD
syncPolicy:
syncOptions:
- CreateNamespace=true
EOF
kubectl apply -f ./${APP_PROJECT}-app.yaml
AutoSyncを書き忘れていたので、手動でsyncする。
argocd app sync game-app
argocd app sync book-app
実行後は以下となる。
$ argocd app list
NAME CLUSTER NAMESPACE PROJECT STATUS HEALTH SYNCPOLICY CONDITIONS REPO PATH TARGET
book-app https://kubernetes.default.svc nginx-book book Synced Healthy <none> <none> https://mygitlab.info/myapp/apps.git book/ HEAD
game-app https://kubernetes.default.svc nginx-game game Synced Healthy <none> <none> https://mygitlab.info/myapp/apps.git game/ HEAD
検証
作成したアカウントに適切に権限が設定されるかを確認する。
冒頭に載せた表をアカウント名に置き換えたものを再掲する。
Projectが同一 | Projectが異なる | |
---|---|---|
alice | Read | Read |
bob | CRUD+Sync | なし |
mike | CRUD+Sync | CRUD+Sync |
それぞれのアカウントでGUIからログインし、権限が適切に割り当たっていることを確認する。
alice(ゲスト)
それぞれのApplicationは表示される。
Syncしようとすると"permission denied"のエラーが表示される。
bob(開発者)
画面上にはgameのProjectのApplicationしか表示されず、リストも取得できない。
Syncは成功する。
mike(管理者)
画面上にはそれぞれのApplicationが表示される。
Syncはそれぞれ成功する。
まとめ
設定がCLIから出来ないところがあるのと、設定ルールを学習する必要があること、またドキュメントが散らばっていて分かりづらいところがあるのがやや難ではあるが、最低限のアクセスコントロールが出来ることは確認できた。