Skip to content

Commit

Permalink
Support for multiple ConfigMaps w/ policy.csv
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Melnick <meln5674@kettering.edu>
  • Loading branch information
meln5674 committed Nov 1, 2024
1 parent d761c94 commit 8884828
Show file tree
Hide file tree
Showing 11 changed files with 742 additions and 57 deletions.
18 changes: 11 additions & 7 deletions cmd/argocd/commands/admin/settings_rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,11 @@ func getPolicy(ctx context.Context, policyFile string, kubeClient kubernetes.Int
log.Fatalf("could not read policy file: %v", err)
}
} else {
cm, err := getPolicyConfigMap(ctx, kubeClient, namespace)
cm, extraCMs, err := getPolicyConfigMaps(ctx, kubeClient, namespace)
if err != nil {
log.Fatalf("could not get configmap: %v", err)
}
userPolicy, defaultRole, matchMode = getPolicyFromConfigMap(cm)
userPolicy, defaultRole, matchMode = getPolicyFromConfigMaps(cm, extraCMs...)
}

return userPolicy, defaultRole, matchMode
Expand All @@ -379,14 +379,14 @@ func getPolicyFromFile(policyFile string) (string, string, string, error) {
if err != nil {
userPolicy = string(upol)
} else {
userPolicy, defaultRole, matchMode = getPolicyFromConfigMap(upolCM)
userPolicy, defaultRole, matchMode = getPolicyFromConfigMaps(upolCM)
}

return userPolicy, defaultRole, matchMode, nil
}

// Retrieve policy information from a ConfigMap
func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string, string) {
func getPolicyFromConfigMaps(cm *corev1.ConfigMap, extraCMs ...corev1.ConfigMap) (string, string, string) {
var (
defaultRole string
ok bool
Expand All @@ -401,12 +401,16 @@ func getPolicyFromConfigMap(cm *corev1.ConfigMap) (string, string, string) {
}

// getPolicyConfigMap fetches the RBAC config map from K8s cluster
func getPolicyConfigMap(ctx context.Context, client kubernetes.Interface, namespace string) (*corev1.ConfigMap, error) {
func getPolicyConfigMaps(ctx context.Context, client kubernetes.Interface, namespace string) (*corev1.ConfigMap, []corev1.ConfigMap, error) {
cm, err := client.CoreV1().ConfigMaps(namespace).Get(ctx, common.ArgoCDRBACConfigMapName, v1.GetOptions{})
if err != nil {
return nil, err
return nil, nil, err
}
return cm, nil
extraCMs, err := client.CoreV1().ConfigMaps(namespace).List(ctx, v1.ListOptions{LabelSelector: rbac.ExtraConfigMapLabelSelector})
if err != nil {
return nil, nil, err
}
return cm, extraCMs.Items, nil
}

// checkPolicy checks whether given subject is allowed to execute specified
Expand Down
25 changes: 25 additions & 0 deletions docs/operator-manual/rbac.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,31 @@ data:
g, my-org:team-qa, role:tester
```
It is also possible to provide multiple configmaps by labeling those
configmaps with `argocd.argoproj.io/cm-type=policy-csv`. These extra
configmaps use the same rules for keys as the main `argocd-rbac-cm`
configmap. The output CSVs of these configmaps, along with the main
configmap, will be concatenated in alphabetical order of the configmap
name.

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: another-rbac-cm
namespace: argocd
labels:
argocd.argoproj.io/cm-type: policy-csv
data:
policy.yet-another.csv: |
p, role:another-tester, applications, *, */*, allow
p, role:another-tester, projects, *, *, allow
g, my-org:team-qa-2, role:another-tester
```

This can be used to create policies which exceed the size limit of a single configmap, which
may occurr in larger multi-tenant environments.

## Validating and testing your RBAC policies

If you want to ensure that your RBAC policies are working as expected, you can
Expand Down
65 changes: 65 additions & 0 deletions test/e2e/accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,71 @@ func TestCanIGetLogsAllowSwitchOn(t *testing.T) {
})
}

func TestCanIGetLogsAllowSwitchOnInExtraConfigMap(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Name("test").
Project(ProjectName).
When().
Create().
Login().
SetExtraPermissions([]ACL{
{
Resource: "logs",
Action: "get",
Scope: ProjectName + "/*",
},
{
Resource: "apps",
Action: "get",
Scope: ProjectName + "/*",
},
}, "log-viewer").
SetParamInSettingConfigMap("server.rbac.log.enforce.enable", "true").
CanIGetLogs().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(output, "yes"))

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Lint Go code

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings

Check failure on line 123 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings
})

accountFixture.GivenWithSameState(t).
When().
ClearExtraPermissions().
CanIGetLogs().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(output, "no"))

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Lint Go code

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings

Check failure on line 132 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings
})
}

func TestCanIGetLogsDenyAfterDeleteExtraConfigMap(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Name("test").
Project(ProjectName).
When().
Create().
Login().
SetExtraPermissions([]ACL{
{
Resource: "logs",
Action: "get",
Scope: ProjectName + "/*",
},
{
Resource: "apps",
Action: "get",
Scope: ProjectName + "/*",
},
}, "log-viewer").
SetParamInSettingConfigMap("server.rbac.log.enforce.enable", "true").
CanIGetLogs().
Then().
AndCLIOutput(func(output string, err error) {
assert.True(t, strings.Contains(output, "yes"))

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Lint Go code

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.31.0, true)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.30.4, false)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.29.8, false)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings

Check failure on line 160 in test/e2e/accounts_test.go

View workflow job for this annotation

GitHub Actions / Run end-to-end tests (v1.28.13, false)

undefined: strings
})
}

func TestCanIGetLogsAllowSwitchOff(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Expand Down
Loading

0 comments on commit 8884828

Please sign in to comment.