Files
grafana/pkg/services/accesscontrol/roles.go
T
Alexander Zobnin 7476219b0c SAML: Configuration UI (#64054)
* Add initial authentication config page skeleton

* Add initial SAML config page WIP

* Add few more pages

* Add connect to IdP page

* Assertion mappings page stub and url params

* Able to save settings

* Some tweaks for authentication page

* Tweak behaviour

* Tweak provider name

* Move SAML config pages to enterprise

* minor refactor

* Able to reset settings

* Configure key and cert from UI

* Refactor WIP

* Tweak styles

* Optional save button

* Some tweaks for the page

* Don't show info popup when save settings

* Improve key/cert validation

* Fetch provider status and display on auth page

* Add settings list to the auth page

* Show call to action card if no auth configured

* clean up

* Show authentication page only if SAML available

* Add access control for SSO config page

* Add feature toggle for auth config UI

* Add code owners for auth config page

* Auth config UI disabled by default

* Fix feature toggle check

* Apply suggestions from review

* Refactor: use forms for steps

* Clean up

* Improve authentication page loading

* Fix CTA link

* Minor tweaks

* Fix page route

* Fix formatting

* Fix generated code formatting
2023-04-13 16:07:43 +02:00

344 lines
8.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package accesscontrol
import (
"fmt"
"strings"
"sync"
"github.com/grafana/grafana/pkg/services/org"
)
// Roles definition
var (
ldapReaderRole = RoleDTO{
Name: "fixed:ldap:reader",
DisplayName: "LDAP reader",
Description: "Read LDAP configuration and status.",
Group: "LDAP",
Permissions: []Permission{
{
Action: ActionLDAPUsersRead,
},
{
Action: ActionLDAPStatusRead,
},
},
}
ldapWriterRole = RoleDTO{
Name: "fixed:ldap:writer",
DisplayName: "LDAP writer",
Description: "Read and update LDAP configuration and read LDAP status.",
Group: "LDAP",
Permissions: ConcatPermissions(ldapReaderRole.Permissions, []Permission{
{
Action: ActionLDAPUsersSync,
},
{
Action: ActionLDAPConfigReload,
},
}),
}
orgUsersWriterRole = RoleDTO{
Name: "fixed:org.users:writer",
DisplayName: "Organization user writer",
Description: "Within a single organization, add a user, invite a user, read information about a user and their role, remove a user from that organization, or change the role of a user.",
Group: "User administration (organizational)",
Permissions: ConcatPermissions(orgUsersReaderRole.Permissions, []Permission{
{
Action: ActionOrgUsersAdd,
Scope: ScopeUsersAll,
},
{
Action: ActionOrgUsersWrite,
Scope: ScopeUsersAll,
},
{
Action: ActionOrgUsersRemove,
Scope: ScopeUsersAll,
},
}),
}
orgUsersReaderRole = RoleDTO{
Name: "fixed:org.users:reader",
DisplayName: "Organization user reader",
Description: "Read users within a single organization.",
Group: "User administration (organizational)",
Permissions: []Permission{
{
Action: ActionOrgUsersRead,
Scope: ScopeUsersAll,
},
{
Action: ActionUsersPermissionsRead,
Scope: ScopeUsersAll,
},
},
}
SettingsReaderRole = RoleDTO{
Name: "fixed:settings:reader",
DisplayName: "Setting reader",
Description: "Read Grafana instance settings.",
Group: "Settings",
Permissions: []Permission{
{
Action: ActionSettingsRead,
Scope: ScopeSettingsAll,
},
},
}
statsReaderRole = RoleDTO{
Name: "fixed:stats:reader",
DisplayName: "Statistics reader",
Description: "Read Grafana instance statistics.",
Group: "Statistics",
Permissions: []Permission{
{
Action: ActionServerStatsRead,
},
},
}
usersReaderRole = RoleDTO{
Name: "fixed:users:reader",
DisplayName: "User reader",
Description: "Read all users and their information, such as team memberships, authentication tokens, and quotas.",
Group: "User administration (global)",
Permissions: []Permission{
{
Action: ActionUsersRead,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersAuthTokenList,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersQuotasList,
Scope: ScopeGlobalUsersAll,
},
},
}
usersWriterRole = RoleDTO{
Name: "fixed:users:writer",
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)",
Permissions: ConcatPermissions(usersReaderRole.Permissions, []Permission{
{
Action: ActionUsersPasswordUpdate,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersCreate,
},
{
Action: ActionUsersWrite,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersDelete,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersEnable,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersDisable,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersPermissionsUpdate,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersLogout,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersAuthTokenUpdate,
Scope: ScopeGlobalUsersAll,
},
{
Action: ActionUsersQuotasUpdate,
Scope: ScopeGlobalUsersAll,
},
}),
}
authenticationConfigWriterRole = RoleDTO{
Name: "fixed:authentication.config:writer",
DisplayName: "Authentication config writer",
Description: "Read and update authentication configuration and access configuration UI.",
Group: "Settings",
Permissions: []Permission{
{
Action: ActionSettingsRead,
Scope: ScopeSettingsAuth,
},
{
Action: ActionSettingsRead,
Scope: ScopeSettingsSAML,
},
{
Action: ActionSettingsWrite,
Scope: ScopeSettingsAuth,
},
{
Action: ActionSettingsWrite,
Scope: ScopeSettingsSAML,
},
},
}
)
// Declare OSS roles to the accesscontrol service
func DeclareFixedRoles(service Service) error {
ldapReader := RoleRegistration{
Role: ldapReaderRole,
Grants: []string{RoleGrafanaAdmin},
}
ldapWriter := RoleRegistration{
Role: ldapWriterRole,
Grants: []string{RoleGrafanaAdmin},
}
orgUsersReader := RoleRegistration{
Role: orgUsersReaderRole,
Grants: []string{RoleGrafanaAdmin, string(org.RoleAdmin)},
}
orgUsersWriter := RoleRegistration{
Role: orgUsersWriterRole,
Grants: []string{RoleGrafanaAdmin, string(org.RoleAdmin)},
}
settingsReader := RoleRegistration{
Role: SettingsReaderRole,
Grants: []string{RoleGrafanaAdmin},
}
statsReader := RoleRegistration{
Role: statsReaderRole,
Grants: []string{RoleGrafanaAdmin},
}
usersReader := RoleRegistration{
Role: usersReaderRole,
Grants: []string{RoleGrafanaAdmin},
}
usersWriter := RoleRegistration{
Role: usersWriterRole,
Grants: []string{RoleGrafanaAdmin},
}
authenticationConfigWriter := RoleRegistration{
Role: authenticationConfigWriterRole,
Grants: []string{RoleGrafanaAdmin},
}
return service.DeclareFixedRoles(ldapReader, ldapWriter, orgUsersReader, orgUsersWriter,
settingsReader, statsReader, usersReader, usersWriter, authenticationConfigWriter)
}
func ConcatPermissions(permissions ...[]Permission) []Permission {
if permissions == nil {
return nil
}
perms := make([]Permission, 0)
for _, p := range permissions {
pCopy := make([]Permission, 0, len(p))
copy(pCopy, p)
perms = append(perms, p...)
}
return perms
}
// ValidateFixedRole errors when a fixed role does not match expected pattern
func ValidateFixedRole(role RoleDTO) error {
if !strings.HasPrefix(role.Name, FixedRolePrefix) {
return ErrFixedRolePrefixMissing
}
return nil
}
// ValidateBuiltInRoles errors when a built-in role does not match expected pattern
func ValidateBuiltInRoles(builtInRoles []string) error {
for _, br := range builtInRoles {
if !org.RoleType(br).IsValid() && br != RoleGrafanaAdmin {
return fmt.Errorf("'%s' %w", br, ErrInvalidBuiltinRole)
}
}
return nil
}
type RegistrationList struct {
mx sync.RWMutex
registrations []RoleRegistration
}
func (m *RegistrationList) Append(regs ...RoleRegistration) {
m.mx.Lock()
defer m.mx.Unlock()
m.registrations = append(m.registrations, regs...)
}
func (m *RegistrationList) Range(f func(registration RoleRegistration) bool) {
m.mx.RLock()
defer m.mx.RUnlock()
for _, registration := range m.registrations {
if ok := f(registration); !ok {
return
}
}
}
func BuildBasicRoleDefinitions() map[string]*RoleDTO {
return map[string]*RoleDTO{
string(org.RoleAdmin): {
Name: BasicRolePrefix + "admin",
UID: BasicRoleUIDPrefix + "admin",
OrgID: GlobalOrgID,
Version: 1,
DisplayName: string(org.RoleAdmin),
Description: "Admin role",
Group: "Basic",
Permissions: []Permission{},
Hidden: true,
},
string(org.RoleEditor): {
Name: BasicRolePrefix + "editor",
UID: BasicRoleUIDPrefix + "editor",
OrgID: GlobalOrgID,
Version: 1,
DisplayName: string(org.RoleEditor),
Description: "Editor role",
Group: "Basic",
Permissions: []Permission{},
Hidden: true,
},
string(org.RoleViewer): {
Name: BasicRolePrefix + "viewer",
UID: BasicRoleUIDPrefix + "viewer",
OrgID: GlobalOrgID,
Version: 1,
DisplayName: string(org.RoleViewer),
Description: "Viewer role",
Group: "Basic",
Permissions: []Permission{},
Hidden: true,
},
RoleGrafanaAdmin: {
Name: BasicRolePrefix + "grafana_admin",
UID: BasicRoleUIDPrefix + "grafana_admin",
OrgID: GlobalOrgID,
Version: 1,
DisplayName: RoleGrafanaAdmin,
Description: "Grafana Admin role",
Group: "Basic",
Permissions: []Permission{},
Hidden: true,
},
}
}