Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions config/user-rbac/dashboard_editor.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# ClusterRole to bind to users who can also create, update and delete ClusterProfiles and
# Profiles from the Sveltos dashboard. Write access to ClusterProfiles is effectively admin on
# every cluster they select, because addon-controller deploys them with its own privileges.
# The ConfigMaps and Secrets a profile references are deliberately not covered here: grant them
# with a namespaced Role in the namespaces that hold the profile content.
# The dashboard stores the YAML of a profile in a ConfigMap, so the role also grants create,
# delete, get and update on ConfigMaps in every namespace. Secrets are deliberately not covered:
# grant them with a namespaced Role in the namespaces that hold the profile content.
# Keep in sync with the SubjectAccessReviews issued in internal/server/k8s-utils.go and the
# writes in internal/server/profile_writes.go.
apiVersion: rbac.authorization.k8s.io/v1
Expand Down Expand Up @@ -39,6 +40,15 @@ rules:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- delete
- get
- update
- apiGroups:
- lib.projectsveltos.io
resources:
Expand Down
30 changes: 25 additions & 5 deletions internal/server/dashboard_roles_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,37 @@ var _ = Describe("Dashboard ClusterRoles", func() {
Expect(isAllowed(user, verbUpdate, writableGroup, rbacClusterSummaries)).To(BeFalse())
})

It("neither role grants access to Secrets or ConfigMaps", func() {
It("sveltos-dashboard-editor allows the ConfigMap writes the dashboard sends and no others", func() {
user := randomString()
bindToUser(user, createShippedRole(editorRoleFile, dashboardEditor))

// Creating a profile from YAML creates the ConfigMap holding the YAML, and deletes it if the
// profile cannot be created. Editing a profile gets and updates the ConfigMap.
for _, verb := range []string{verbGet, verbCreate, verbUpdate, verbDelete} {
Eventually(func() bool {
return isAllowed(user, verb, "", configMapResource)
}).Should(BeTrue(), "%s %s", verb, configMapResource)
}

for _, verb := range []string{verbList, verbPatch} {
Expect(isAllowed(user, verb, "", configMapResource)).To(BeFalse(), "%s %s", verb, configMapResource)
}
})

It("neither role grants access to Secrets and the viewer does not grant access to ConfigMaps", func() {
viewer := randomString()
bindToUser(viewer, createShippedRole(viewerRoleFile, dashboardViewer))
editor := randomString()
bindToUser(editor, createShippedRole(editorRoleFile, dashboardEditor))

verbs := []string{verbGet, verbList, verbCreate, verbUpdate, verbDelete}
for _, verb := range verbs {
Expect(isAllowed(viewer, verb, "", configMapResource)).To(BeFalse(), "%s %s", verb, configMapResource)
}

for _, user := range []string{viewer, editor} {
for _, resource := range []string{secretsResource, configMapResource} {
for _, verb := range []string{verbGet, verbList, verbCreate, verbUpdate, verbDelete} {
Expect(isAllowed(user, verb, "", resource)).To(BeFalse(), "%s %s", verb, resource)
}
for _, verb := range verbs {
Expect(isAllowed(user, verb, "", secretsResource)).To(BeFalse(), "%s %s", verb, secretsResource)
}
}
})
Expand Down
9 changes: 9 additions & 0 deletions manifest/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,15 @@ rules:
- patch
- update
- watch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- delete
- get
- update
- apiGroups:
- lib.projectsveltos.io
resources:
Expand Down
Loading