Inconsistent RBAC deny behavior when policies refer to overlapping SSO groups
- Dominant language
- Go
- Stars
- 24.2k
- Forks
- 7.8k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 246
Description
Checklist:
* [x] I've searched in the docs and FAQ for my answer: https://bit.ly/argocd-faq.
* [x] I've included steps to reproduce the bug.
* [x] I've pasted the output of `argocd version`.
**Describe the bug**
When a SSO user A is member of multiple SSO groups G1 and G2, if one RBAC policy grants a specific permission to group G1 and another policy denies it for group G2 (or user A directly), the end result for user A is allow.
This seems to be inconsistent with the expected behavior based on [ArgoCD's Casbin policy effect](https://github.com/argoproj/argo-cd/blob/master/assets/model.conf#L11) where deny always overrides allow.
**To Reproduce**
With Okta configured with SAML connector in Dex and the following in `argocd-rbac-cm`:
```
policy.csv: |
g, k8s-admins, role:admin
p, role:test, projects, get, *, deny
g, userA@example.com, role:test
policy.default: ""
policy.matchMode: glob
scopes: '[email,groups]'
```
where user `userA@example.com` is member of `k8s-admins` and `userA@example.com` groups as verified in the User Info page in ArgoCD UI.
User `userA@example.com` can still view the projects in the UI.
I'm not 100% sure but this seems to be possibly caused by a premature return when looping over groups [here](https://github.com/argoproj/argo-cd/blob/master/server/rbacpolicy/rbacpolicy.go#L151).
It should probably evaluate all groups first and then implement a policy effect consistent with the Casbin model on the aggregate result.
**Expected behavior**
User `userA@example.com` should be denied as soon as any policy denies access to any of the groups it is a member of.
**Version**
```shell
argocd: v2.9.6+ba62a0a
BuildDate: 2024-02-02T19:36:48Z
GitCommit: ba62a0a86d19f71a65ec2b510a39ea55497e1580
GitTreeState: clean
GoVersion: go1.21.6
Compiler: gc
Platform: linux/amd64
argocd-server: v2.10.0+2175939
BuildDate: 2024-02-06T14:28:43Z
GitCommit: 2175939ed6156ddd743e60f427f7f48118c971bf
GitTreeState: clean
GoVersion: go1.21.3
Compiler: gc
Platform: linux/amd64
Kustomize Version: v5.2.1 2023-10-19T20:13:51Z
Helm Version: v3.14.0+g3fc9f4b
Kubectl Version: v0.26.11
Jsonnet Version: v0.20.0
```
**Logs**
Casbin logs with `ARGOCD_RBAC_DEBUG=1` set:
```
2024/03/14 18:31:19 Request: dXNlckFAZXhhbXBsZS5jb20gb2t0YQ, projects, get, default ---> false
Hit Policy:
2024/03/14 18:31:19 Request: userA@example.com, projects, get, default ---> false
Hit Policy:
2024/03/14 18:31:19 Request: k8s-admins, projects, get, default ---> true
Hit Policy:
2024/03/14 18:31:19 Request: dXNlckFAZXhhbXBsZS5jb20gb2t0YQ, projects, get, infrastructure ---> false
Hit Policy:
2024/03/14 18:31:19 Request: userA@example.com, projects, get, infrastructure ---> false
Hit Policy:
2024/03/14 18:31:19 Request: k8s-admins, projects, get, infrastructure ---> true
Hit Policy:
```
Contributor guide
Research direction
Start in server/rbacpolicy/rbacpolicy.go around the group loop near line 151, then compare its behavior with the Casbin policy effect in assets/model.conf. Reproduce with the provided argocd-rbac-cm policy.csv, overlapping SSO groups, and ARGOCD_RBAC_DEBUG=1. Done means a deny for any matching group or user overrides an allow consistently with the documented policy effect.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, kubernetes
- Domain
- authorization, backend, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100