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 Apr 14, 2024
1 parent 659f426 commit 4b35e53
Show file tree
Hide file tree
Showing 11 changed files with 743 additions and 57 deletions.
18 changes: 11 additions & 7 deletions cmd/argocd/commands/admin/settings_rbac.go
Expand Up @@ -281,11 +281,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 @@ -312,14 +312,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 (
userPolicy string
defaultRole string
Expand All @@ -338,12 +338,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
Expand Up @@ -241,6 +241,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.

## Anonymous Access

The anonymous access to Argo CD can be enabled using `users.anonymous.enabled` field in `argocd-cm` (see [argocd-cm.yaml](argocd-cm.yaml)).
Expand Down
65 changes: 65 additions & 0 deletions test/e2e/accounts_test.go
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"))
})

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

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"))
})
}

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

0 comments on commit 4b35e53

Please sign in to comment.