diff --git a/docs/sources/enterprise/access-control/permissions.md b/docs/sources/enterprise/access-control/permissions.md index 5095df18837..e37a1604f4c 100644 --- a/docs/sources/enterprise/access-control/permissions.md +++ b/docs/sources/enterprise/access-control/permissions.md @@ -43,20 +43,20 @@ The following list contains fine-grained access control actions. | `teams.roles:list` | `teams:*` | List roles assigned directly to a team. | | `teams.roles:add` | `permissions:delegate` | Assign a role to a team. | | `teams.roles:remove` | `permissions:delegate` | Unassign a role from a team. | -| `users:read` | `global:users:*` | Read or search user profiles. | -| `users:write` | `global:users:*`
`global:users:id` | Update a user’s profile. | -| `users.teams:read` | `global:users:*`
`global:users:id:*` | Read a user’s teams. | -| `users.authtoken:list` | `global:users:*`
`global:users:id:*` | List authentication tokens that are assigned to a user. | -| `users.authtoken:update` | `global:users:*`
`global:users:id:*` | Update authentication tokens that are assigned to a user. | -| `users.password:update` | `global:users:*`
`global:users:id:*` | Update a user’s password. | -| `users:delete` | `global:users:*`
`global:users:id:*` | Delete a user. | +| `users:read` | `global.users:*` | Read or search user profiles. | +| `users:write` | `global.users:*`
`global.users:id:*` | Update a user’s profile. | +| `users.teams:read` | `global.users:*`
`global.users:id:*` | Read a user’s teams. | +| `users.authtoken:list` | `global.users:*`
`global.users:id:*` | List authentication tokens that are assigned to a user. | +| `users.authtoken:update` | `global.users:*`
`global.users:id:*` | Update authentication tokens that are assigned to a user. | +| `users.password:update` | `global.users:*`
`global.users:id:*` | Update a user’s password. | +| `users:delete` | `global.users:*`
`global.users:id:*` | Delete a user. | | `users:create` | n/a | Create a user. | -| `users:enable` | `global:users:*`
`global:users:id:*` | Enable a user. | -| `users:disable` | `global:users:*`
`global:users:id:*` | Disable a user. | -| `users.permissions:update` | `global:users:*`
`global:users:id:*` | Update a user’s organization-level permissions. | -| `users:logout` | `global:users:*`
`global:users:id:*` | Sign out a user. | -| `users.quotas:list` | `global:users:*`
`global:users:id:*` | List a user’s quotas. | -| `users.quotas:update` | `global:users:*`
`global:users:id:*` | Update a user’s quotas. | +| `users:enable` | `globa.users:*`
`global.users:id:*` | Enable a user. | +| `users:disable` | `global.users:*`
`global.users:id:*` | Disable a user. | +| `users.permissions:update` | `global.users:*`
`global.users:id:*` | Update a user’s organization-level permissions. | +| `users:logout` | `global.users:*`
`global.users:id:*` | Sign out a user. | +| `users.quotas:list` | `global.users:*`
`global.users:id:*` | List a user’s quotas. | +| `users.quotas:update` | `global.users:*`
`global.users:id:*` | Update a user’s quotas. | | `users.roles:list` | `users:*` | List roles assigned directly to a user. | | `users.roles:add` | `permissions:delegate` | Assign a role to a user. | | `users.roles:remove` | `permissions:delegate` | Unassign a role from a user. | @@ -124,7 +124,7 @@ The following list contains fine-grained access control scopes. | `roles:*`
`roles:uid:*` | Restrict an action to a set of roles. For example, `roles:*` matches any role and `roles:uid:randomuid` matches only the role whose UID is `randomuid`. | | `reports:*`
`reports:id:*` | Restrict an action to a set of reports. For example, `reports:*` matches any report and `reports:id:1` matches the report whose ID is `1`. | | `services:accesscontrol` | Restrict an action to target only the fine-grained access control service. You can use this in conjunction with the `status:accesscontrol` actions. | -| `global:users:*`
`global:users:id:*` | Restrict an action to a set of global users. For example, `global:users:*` matches any user and `global:users:id:1` matches the user whose ID is `1`. | +| `global.users:*`
`global.users:id:*` | Restrict an action to a set of global users. For example, `global.users:*` matches any user and `global.users:id:1` matches the user whose ID is `1`. | | `teams:*`
`teams:id:*` | Restrict an action to a set of teams from an organization. For example, `teams:*` matches any team and `teams:id:1` matches the team whose ID is `1`. | | `users:*`
`users:id:*` | Restrict an action to a set of users from an organization. For example, `users:*` matches any user and `users:id:1` matches the user whose ID is `1`. | | `orgs:*`
`orgs:id:*` | Restrict an action to a set of organizations. For example, `orgs:*` matches any organization and `orgs:id:1` matches the organization whose ID is `1`. | diff --git a/docs/sources/http_api/admin.md b/docs/sources/http_api/admin.md index fe57a085f25..b7d0f854711 100644 --- a/docs/sources/http_api/admin.md +++ b/docs/sources/http_api/admin.md @@ -376,7 +376,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | --------------------- | --------------- | -| users.password:update | global:users:\* | +| users.password:update | global.users:\* | **Example Request**: @@ -409,7 +409,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | ------------------------ | --------------- | -| users.permissions:update | global:users:\* | +| users.permissions:update | global.users:\* | **Example Request**: @@ -442,7 +442,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | ------------ | --------------- | -| users:delete | global:users:\* | +| users:delete | global.users:\* | **Example Request**: @@ -510,7 +510,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | -------------------- | --------------- | -| users.authtoken:list | global:users:\* | +| users.authtoken:list | global.users:\* | **Example Request**: @@ -569,7 +569,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | ---------------------- | --------------- | -| users.authtoken:update | global:users:\* | +| users.authtoken:update | global.users:\* | **Example Request**: @@ -609,7 +609,7 @@ See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation. | Action | Scope | | ------------ | --------------- | -| users.logout | global:users:\* | +| users.logout | global.users:\* | **Example Request**: diff --git a/docs/sources/http_api/user.md b/docs/sources/http_api/user.md index f989a906b50..3ad19641377 100644 --- a/docs/sources/http_api/user.md +++ b/docs/sources/http_api/user.md @@ -20,7 +20,7 @@ See note in the [introduction]({{< ref "#user-api" >}}) for an explanation. | Action | Scope | | ---------- | --------------- | -| users:read | global:users:\* | +| users:read | global.users:\* | **Example Request**: @@ -75,7 +75,7 @@ See note in the [introduction]({{< ref "#user-api" >}}) for an explanation. | Action | Scope | | ---------- | --------------- | -| users:read | global:users:\* | +| users:read | global.users:\* | **Example Request**: @@ -182,7 +182,7 @@ See note in the [introduction]({{< ref "#user-api" >}}) for an explanation. | Action | Scope | | ---------- | --------------- | -| users:read | global:users:\* | +| users:read | global.users:\* | **Example Request using the email as option**: diff --git a/pkg/api/api.go b/pkg/api/api.go index 0d669eb94d2..3eb19d216c6 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -174,7 +174,7 @@ func (hs *HTTPServer) registerRoutes() { }, reqSignedInNoAnonymous) apiRoute.Group("/users", func(usersRoute routing.RouteRegister) { - userIDScope := ac.Scope("global", "users", "id", ac.Parameter(":id")) + userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id")) usersRoute.Get("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll)), routing.Wrap(hs.searchUsersService.SearchUsers)) usersRoute.Get("/search", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll)), routing.Wrap(hs.searchUsersService.SearchUsersWithPaging)) usersRoute.Get("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(hs.GetUserByID)) @@ -516,7 +516,7 @@ func (hs *HTTPServer) registerRoutes() { // Administering users r.Group("/api/admin/users", func(adminUserRoute routing.RouteRegister) { - userIDScope := ac.Scope("global", "users", "id", ac.Parameter(":id")) + userIDScope := ac.Scope("global.users", "id", ac.Parameter(":id")) adminUserRoute.Post("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.AdminCreateUser)) adminUserRoute.Put("/:id/password", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPasswordUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPassword)) diff --git a/pkg/api/docs/definitions/admin_users.go b/pkg/api/docs/definitions/admin_users.go index bd8ef4a0b7f..92581b92b45 100644 --- a/pkg/api/docs/definitions/admin_users.go +++ b/pkg/api/docs/definitions/admin_users.go @@ -28,7 +28,7 @@ import ( // // Set password for user. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.password:update` and scope `global.users:*`. // // Security: // - basic: @@ -45,7 +45,7 @@ import ( // Set permissions for user. // // Only works with Basic Authentication (username and password). See introduction for an explanation. -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.permissions:update` and scope `global.users:*`. // // Responses: // 200: okResponse @@ -58,7 +58,7 @@ import ( // // Delete global User. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:delete` and scope `global.users:*`. // // Security: // - basic: @@ -74,7 +74,7 @@ import ( // // Disable user. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global:users:1` (userIDScope). +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:disable` and scope `global.users:1` (userIDScope). // // Security: // - basic: @@ -90,7 +90,7 @@ import ( // // Enable user. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global:users:1` (userIDScope). +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users:enable` and scope `global.users:1` (userIDScope). // // Security: // - basic: @@ -106,7 +106,7 @@ import ( // // Fetch user quota. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global:users:1` (userIDScope). +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:list` and scope `global.users:1` (userIDScope). // // Security: // - basic: @@ -122,7 +122,7 @@ import ( // // Update user quota. // -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global:users:1` (userIDScope). +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.quotas:update` and scope `global.users:1` (userIDScope). // // Security: // - basic: @@ -137,7 +137,7 @@ import ( // swagger:route GET /admin/users/{user_id}/auth-tokens admin_users getAuthTokens // // Return a list of all auth tokens (devices) that the user currently have logged in from. -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:list` and scope `global.users:*`. // // Security: // - basic: @@ -153,7 +153,7 @@ import ( // Revoke auth token for user. // // Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in and will be required to authenticate again upon next activity. -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.authtoken:update` and scope `global.users:*`. // // Security: // - basic: @@ -169,7 +169,7 @@ import ( // swagger:route POST /admin/users/{user_id}/logout admin_users logoutUser // // Logout user revokes all auth tokens (devices) for the user. User of issued auth tokens (devices) will no longer be logged in and will be required to authenticate again upon next activity. -// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global:users:*`. +// If you are running Grafana Enterprise and have Fine-grained access control enabled, you need to have a permission with action `users.logout` and scope `global.users:*`. // // Security: // - basic: diff --git a/pkg/api/user.go b/pkg/api/user.go index 25861433948..050a574413f 100644 --- a/pkg/api/user.go +++ b/pkg/api/user.go @@ -46,7 +46,7 @@ func (hs *HTTPServer) getUserUserProfile(c *models.ReqContext, userID int64) res query.Result.IsExternal = true } - query.Result.AccessControl = hs.getAccessControlMetadata(c, "global:users:id:", strconv.FormatInt(userID, 10)) + query.Result.AccessControl = hs.getAccessControlMetadata(c, "global.users:id:", strconv.FormatInt(userID, 10)) query.Result.AvatarUrl = dtos.GetGravatarUrl(query.Result.Email) return response.JSON(200, query.Result) diff --git a/pkg/services/accesscontrol/models.go b/pkg/services/accesscontrol/models.go index e54bbda14c1..90718fd12b3 100644 --- a/pkg/services/accesscontrol/models.go +++ b/pkg/services/accesscontrol/models.go @@ -296,7 +296,7 @@ const ( ActionPluginsManage = "plugins:manage" // Global Scopes - ScopeGlobalUsersAll = "global:users:*" + ScopeGlobalUsersAll = "global.users:*" // APIKeys scope ScopeAPIKeysAll = "apikeys:*" diff --git a/pkg/services/accesscontrol/roles.go b/pkg/services/accesscontrol/roles.go index 5bbb6b8a633..b8d20490a13 100644 --- a/pkg/services/accesscontrol/roles.go +++ b/pkg/services/accesscontrol/roles.go @@ -115,7 +115,7 @@ var ( DisplayName: "User reader", Description: "Read all users and their information, such as team memberships, authentication tokens, and quotas.", Group: "User administration (global)", - Version: 3, + Version: 4, Permissions: []Permission{ { Action: ActionUsersRead, @@ -141,7 +141,7 @@ var ( DisplayName: "User writer", Description: "Read and update all attributes and settings for all users in Grafana: update user information, read user information, create or enable or disable a user, make a user a Grafana administrator, sign out a user, update a user’s authentication token, or update quotas for all users.", Group: "User administration (global)", - Version: 3, + Version: 4, Permissions: ConcatPermissions(usersReaderRole.Permissions, []Permission{ { Action: ActionUsersPasswordUpdate,