LAB 05 – Projects & RBAC: guard rails for teams¶
Story: A second team wants to use Argo CD. The security officer asks: "Can a developer deploy into
kube-system? Can the CI pipeline delete production?" Today the answer is yes. Projects and RBAC change that.
| Duration | ~40 min |
| You create | work/gitops/argocd/project-parcelpal.yaml; you edit env/argocd-values.yaml |
| Solution | solutions/LAB05/ (or ./bin/lab catchup 5) |
| Concept | Answers | Lives in |
|---|---|---|
| AppProject | What may an app deploy – from which repos, to which clusters/namespaces, which kinds? | AppProject resource |
| RBAC | Who may do what with apps, projects, repos, clusters… | argocd-rbac-cm |
| Project role | a machine identity (JWT) scoped to one project – for CI | inside the AppProject |
Step 1 – The project¶
cd work/gitops
cat > argocd/project-parcelpal.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: parcelpal
namespace: argocd
spec:
description: ParcelPal applications
sourceRepos: # where manifests may come from
- http://gitea:3000/student/*
- https://stefanprodan.github.io/podinfo
destinations: # where they may go
- server: https://kubernetes.default.svc
namespace: tracker
- server: https://kubernetes.default.svc
namespace: shop-*
- server: https://kubernetes.default.svc
namespace: status
- server: https://kubernetes.default.svc
namespace: orders
- server: https://kubernetes.default.svc
namespace: checkout
clusterResourceWhitelist: # cluster-scoped kinds allowed: only namespaces
- group: ""
kind: Namespace
namespaceResourceBlacklist: # teams may not touch quotas and limits
- group: ""
kind: ResourceQuota
- group: ""
kind: LimitRange
roles:
- name: ci
description: CI pipelines may sync, nothing else
policies:
- p, proj:parcelpal:ci, applications, get, parcelpal/*, allow
- p, proj:parcelpal:ci, applications, sync, parcelpal/*, allow
EOF
kubectl apply -f argocd/project-parcelpal.yaml
Move tracker, shop-dev, shop-prod and status into the project:
sed -i 's/^ project: default$/ project: parcelpal/' argocd/tracker.yaml argocd/shop-*.yaml argocd/status.yaml
git add argocd && git commit -m "ParcelPal project" && git push
kubectl apply -f argocd/
✅ Checkpoint: Settings → Projects → parcelpal lists the four apps; they stay Synced/Healthy.
Step 2 – The project says no¶
Try to escape the guard rails:
argocd app create escape --project parcelpal \
--repo http://gitea:3000/student/gitops.git --path apps/tracker \
--dest-server https://kubernetes.default.svc --dest-namespace kube-system
✅ Checkpoint: application destination … namespace kube-system is not permitted in project 'parcelpal'.
Now try a forbidden kind. Add a quota to the tracker and push:
kubectl create quota tracker-quota --hard=pods=10 -n tracker --dry-run=client -o yaml > apps/tracker/quota.yaml
git add -A && git commit -m "quota" && git push
argocd app get tracker --refresh | grep -i quota
✅ Checkpoint: the sync fails with resource :ResourceQuota is not permitted in project parcelpal. Remove the file again (git rm apps/tracker/quota.yaml, commit, push) – the app recovers.
Step 3 – A local user and RBAC¶
Users and policies are Argo CD configuration – so they belong in the Helm values. Add to env/argocd-values.yaml:
configs:
cm:
timeout.reconciliation: 60s
accounts.alice: login # local user for the UI and CLI
rbac:
policy.default: "" # no access unless granted below
policy.csv: |
p, role:parcelpal-dev, applications, get, parcelpal/*, allow
p, role:parcelpal-dev, applications, sync, parcelpal/*, allow
p, role:parcelpal-dev, logs, get, parcelpal/*, allow
p, role:parcelpal-dev, projects, get, parcelpal, allow
g, alice, role:parcelpal-dev
(Keep params as it is – merge, don't replace the whole configs block.)
./bin/lab install-argocd # helm upgrade with the new values
argocd login argocd.localtest.me --grpc-web --insecure --username admin --password 'ParcelPal-Admin-2026!'
argocd account update-password --account alice --current-password 'ParcelPal-Admin-2026!' --new-password 'Alice-Lab-2026!'
Policy format: p, <subject>, <resource>, <action>, <project>/<object>, allow|deny – and g, <user or SSO group>, <role> assigns roles.
Check before you trust it:
argocd admin settings rbac can alice sync applications parcelpal/tracker --namespace argocd
argocd admin settings rbac can alice delete applications parcelpal/tracker --namespace argocd
Log in as Alice in a private browser window (http://argocd.localtest.me, alice / Alice-Lab-2026!).
✅ Checkpoint: Alice sees the four ParcelPal apps (not default-project apps), can Sync and read Logs, but Delete fails with permission denied.
Since Argo CD 3.0
updateanddeleteon an application no longer include its resources: to let someone delete a pod inside an app, grantdelete/*explicitly. In productiong,lines map SSO groups (Entra ID, Okta, GitHub teams…) – not local users.
Step 4 – A token for CI¶
TOKEN=$(argocd proj role create-token parcelpal ci --token-only)
argocd app sync tracker --auth-token "$TOKEN" # allowed
argocd app delete tracker --auth-token "$TOKEN" --yes # denied
argocd proj role list parcelpal
✅ Checkpoint: the sync works, the delete returns permission denied. A pipeline holding this token can only do what the ci role allows, only in this project.
Revoke tokens with
argocd proj role delete-token parcelpal ci <issued-at>. Give them an expiry (--expires-in 24h).
Bonus¶
- Sync windows: in
project-parcelpal.yamladdsyncWindowsthat deny syncs on Saturdays and Sundays – andmanualSync: truefor emergencies. orphanedResources: { warn: true }in the project – create a ConfigMap by hand intrackerand look for the warning.argocd account can-i sync applications 'parcelpal/*'– as admin and as alice.
Troubleshooting¶
| Symptom | Likely cause |
|---|---|
| apps show Unknown after moving to the project | the project does not allow their repo or namespace – compare sourceRepos/destinations |
| Alice sees nothing | policy.default: "" + missing get permission, or the RBAC change has not been applied (./bin/lab install-argocd) |
account update-password: account alice does not exist |
accounts.alice: login missing in configs.cm |
create-token: permission denied |
you are logged in as Alice – log in as admin again |
Files for this lab: Think-Cube/argocd-labs/labs/LAB05-projects-rbac